Back to index

indicator-appmenu  12.10.0
Classes | Functions
gtkmodelmenu.c File Reference
#include "config.h"
#include "gtkmodelmenu.h"
#include "gtkmodelmenuitem.h"

Go to the source code of this file.

Classes

struct  GtkModelMenuBinding

Functions

static void gtk_model_menu_binding_items_changed (GMenuModel *model, gint position, gint removed, gint added, gpointer user_data)
static void gtk_model_menu_binding_append_model (GtkModelMenuBinding *binding, GMenuModel *model, gboolean with_separators)
static void gtk_model_menu_binding_free (gpointer data)
static void gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding, GMenuModel *model, gint item_index, gchar **heading)
static void gtk_model_menu_binding_populate (GtkModelMenuBinding *binding)
static gboolean gtk_model_menu_binding_handle_changes (gpointer user_data)
static void gtk_model_menu_bind (GtkMenuShell *shell, GMenuModel *model, gboolean with_separators)
static void gtk_model_menu_populate (GtkMenuShell *shell, GActionObservable *actions, GtkAccelGroup *accels)
GtkWidget * gtk_model_menu_create_menu (GMenuModel *model, GActionObservable *actions, GtkAccelGroup *accels)

Class Documentation

struct GtkModelMenuBinding

Definition at line 26 of file gtkmodelmenu.c.

Class Members
GtkAccelGroup * accels
GActionObservable * actions
GSList * connected
GMenuModel * model
gint n_items
GtkMenuShell * shell
guint update_idle
gboolean with_separators

Function Documentation

static void gtk_model_menu_bind ( GtkMenuShell *  shell,
GMenuModel *  model,
gboolean  with_separators 
) [static]

Definition at line 222 of file gtkmodelmenu.c.

{
  GtkModelMenuBinding *binding;

  binding = g_slice_new (GtkModelMenuBinding);
  binding->model = g_object_ref (model);
  binding->actions = NULL;
  binding->accels = NULL;
  binding->shell = shell;
  binding->update_idle = 0;
  binding->connected = NULL;
  binding->with_separators = with_separators;

  g_object_set_data_full (G_OBJECT (shell), "gtk-model-menu-binding", binding, gtk_model_menu_binding_free);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_model_menu_binding_append_item ( GtkModelMenuBinding binding,
GMenuModel *  model,
gint  item_index,
gchar **  heading 
) [static]

Definition at line 69 of file gtkmodelmenu.c.

{
  GMenuModel *section;

  if ((section = g_menu_model_get_item_link (model, item_index, "section")))
    {
      g_menu_model_get_item_attribute (model, item_index, "label", "s", heading);
      gtk_model_menu_binding_append_model (binding, section, FALSE);
    }
  else
    {
      GtkMenuItem *item;

      item = gtk_model_menu_item_new (model, item_index, binding->actions, binding->accels);
      gtk_menu_shell_append (binding->shell, GTK_WIDGET (item));
      gtk_widget_show (GTK_WIDGET (item));
      binding->n_items++;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_model_menu_binding_append_model ( GtkModelMenuBinding binding,
GMenuModel *  model,
gboolean  with_separators 
) [static]

Definition at line 93 of file gtkmodelmenu.c.

{
  gint n, i;

  g_signal_connect (model, "items-changed", G_CALLBACK (gtk_model_menu_binding_items_changed), binding);
  binding->connected = g_slist_prepend (binding->connected, g_object_ref (model));

  /* Deciding if we should show a separator is a bit difficult.  There
   * are two types of separators:
   *
   *  - section headings (when sections have 'label' property)
   *
   *  - normal separators automatically put between sections
   *
   * The easiest way to think about it is that a section usually has a
   * separator (or heading) immediately before it.
   *
   * There are three exceptions to this general rule:
   *
   *  - empty sections don't get separators or headings
   *
   *  - sections only get separators and headings at the toplevel of a
   *    menu (ie: no separators on nested sections or in menubars)
   *
   *  - the first section in the menu doesn't get a normal separator,
   *    but it can get a header (if it's not empty)
   *
   * Unfortunately, we cannot simply check the size of the section in
   * order to determine if we should place a header: the section may
   * contain other sections that are themselves empty.  Instead, we need
   * to append the section, and check if we ended up with any actual
   * content.  If we did, then we need to insert before that content.
   * We use 'our_position' to keep track of this.
   */

  n = g_menu_model_get_n_items (model);

  for (i = 0; i < n; i++)
    {
      gint our_position = binding->n_items;
      gchar *heading = NULL;

      gtk_model_menu_binding_append_item (binding, model, i, &heading);

      if (with_separators && our_position < binding->n_items)
        {
          GtkWidget *separator = NULL;

          if (heading)
            {
              separator = gtk_menu_item_new_with_label (heading);
              gtk_widget_set_sensitive (separator, FALSE);
            }
          else if (our_position > 0)
            separator = gtk_separator_menu_item_new ();

          if (separator)
            {
              gtk_menu_shell_insert (binding->shell, separator, our_position);
              gtk_widget_show (separator);
              binding->n_items++;
            }
        }

      g_free (heading);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_model_menu_binding_free ( gpointer  data) [static]

Definition at line 48 of file gtkmodelmenu.c.

{
  GtkModelMenuBinding *binding = data;

  /* disconnect all existing signal handlers */
  while (binding->connected)
    {
      g_signal_handlers_disconnect_by_func (binding->connected->data, gtk_model_menu_binding_items_changed, binding);
      g_object_unref (binding->connected->data);

      binding->connected = g_slist_delete_link (binding->connected, binding->connected);
    }

  if (binding->actions)
    g_object_unref (binding->actions);
  g_object_unref (binding->model);

  g_slice_free (GtkModelMenuBinding, binding);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean gtk_model_menu_binding_handle_changes ( gpointer  user_data) [static]

Definition at line 183 of file gtkmodelmenu.c.

{
  GtkModelMenuBinding *binding = user_data;

  /* disconnect all existing signal handlers */
  while (binding->connected)
    {
      g_signal_handlers_disconnect_by_func (binding->connected->data, gtk_model_menu_binding_items_changed, binding);
      g_object_unref (binding->connected->data);

      binding->connected = g_slist_delete_link (binding->connected, binding->connected);
    }

  gtk_model_menu_binding_populate (binding);

  binding->update_idle = 0;

  g_object_unref (binding->shell);

  return G_SOURCE_REMOVE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_model_menu_binding_items_changed ( GMenuModel *  model,
gint  position,
gint  removed,
gint  added,
gpointer  user_data 
) [static]

Definition at line 206 of file gtkmodelmenu.c.

{
  GtkModelMenuBinding *binding = user_data;

  if (binding->update_idle == 0)
    {
      binding->update_idle = gdk_threads_add_idle (gtk_model_menu_binding_handle_changes, user_data);
      g_object_ref (binding->shell);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_model_menu_binding_populate ( GtkModelMenuBinding binding) [static]

Definition at line 164 of file gtkmodelmenu.c.

{
  GList *children;

  /* remove current children */
  children = gtk_container_get_children (GTK_CONTAINER (binding->shell));
  while (children)
    {
      gtk_container_remove (GTK_CONTAINER (binding->shell), children->data);
      children = g_list_delete_link (children, children);
    }

  binding->n_items = 0;

  /* add new items from the model */
  gtk_model_menu_binding_append_model (binding, binding->model, binding->with_separators);
}

Here is the call graph for this function:

Here is the caller graph for this function:

GtkWidget* gtk_model_menu_create_menu ( GMenuModel *  model,
GActionObservable *  actions,
GtkAccelGroup *  accels 
)

Definition at line 257 of file gtkmodelmenu.c.

{
  GtkWidget *menu;

  menu = gtk_menu_new ();

  gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, TRUE);
  gtk_model_menu_populate (GTK_MENU_SHELL (menu), actions, accels);

  return menu;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gtk_model_menu_populate ( GtkMenuShell *  shell,
GActionObservable *  actions,
GtkAccelGroup *  accels 
) [static]

Definition at line 242 of file gtkmodelmenu.c.

{
  GtkModelMenuBinding *binding;

  binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding");

  binding->actions = g_object_ref (actions);
  binding->accels = accels;

  gtk_model_menu_binding_populate (binding);
}

Here is the call graph for this function:

Here is the caller graph for this function: