diff options
Diffstat (limited to 'libqmenumodel/src/gtk/gtkmenutracker.c')
| -rw-r--r-- | libqmenumodel/src/gtk/gtkmenutracker.c | 245 |
1 files changed, 61 insertions, 184 deletions
diff --git a/libqmenumodel/src/gtk/gtkmenutracker.c b/libqmenumodel/src/gtk/gtkmenutracker.c index 95e08bc..8b72965 100644 --- a/libqmenumodel/src/gtk/gtkmenutracker.c +++ b/libqmenumodel/src/gtk/gtkmenutracker.c @@ -12,7 +12,9 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. * * Author: Ryan Lortie <desrt@desrt.ca> */ @@ -21,7 +23,7 @@ #include "gtkmenutracker.h" -/*< private > +/** * SECTION:gtkmenutracker * @Title: GtkMenuTracker * @Short_description: A helper class for interpreting #GMenuModel @@ -46,11 +48,11 @@ * * Certain properties on the #GtkMenuTrackerItem are mutable, and you must * listen for changes in the item. For more details, see the documentation - * for #GtkMenuTrackerItem along with https://wiki.gnome.org/Projects/GLib/GApplication/GMenuModel. + * for #GtkMenuTrackerItem along with https://live.gnome.org/GApplication/GMenuModel. * * The idea of @with_separators is for special cases where menu models may * be tracked in places where separators are not available, like in toplevel - * "File", “Edit” menu bars. Ignoring separator items is wrong, as #GtkMenuTracker + * "File", "Edit" menu bars. Ignoring separator items is wrong, as #GtkMenuTracker * expects the position to change, so we must tell #GtkMenuTracker to ignore * separators itself. */ @@ -60,8 +62,6 @@ typedef struct _GtkMenuTrackerSection GtkMenuTrackerSection; struct _GtkMenuTracker { GtkActionObservable *observable; - guint merge_sections : 1; - guint mac_os_mode : 1; GtkMenuTrackerInsertFunc insert_func; GtkMenuTrackerRemoveFunc remove_func; gpointer user_data; @@ -71,14 +71,12 @@ struct _GtkMenuTracker struct _GtkMenuTrackerSection { - gpointer model; /* may be a GtkMenuTrackerItem or a GMenuModel */ + GMenuModel *model; GSList *items; gchar *action_namespace; - guint separator_label : 1; guint with_separators : 1; guint has_separator : 1; - guint is_fake : 1; gulong handler; }; @@ -86,7 +84,6 @@ struct _GtkMenuTrackerSection static GtkMenuTrackerSection * gtk_menu_tracker_section_new (GtkMenuTracker *tracker, GMenuModel *model, gboolean with_separators, - gboolean separator_label, gint offset, const gchar *action_namespace, GPtrArray *items_already_created); @@ -94,7 +91,7 @@ static void gtk_menu_tracker_section_free (GtkMenuTrackerS static GtkMenuTrackerSection * gtk_menu_tracker_section_find_model (GtkMenuTrackerSection *section, - gpointer model, + GMenuModel *model, gint *offset) { GSList *item; @@ -122,7 +119,7 @@ gtk_menu_tracker_section_find_model (GtkMenuTrackerSection *section, (*offset)++; } - return NULL; + return FALSE; } /* this is responsible for syncing the showing of a separator for a @@ -130,7 +127,7 @@ gtk_menu_tracker_section_find_model (GtkMenuTrackerSection *section, * * we only ever show separators if we have _actual_ children (ie: we do * not show a separator if the section contains only empty child - * sections). it’s difficult to determine this on-the-fly, so we have + * sections). it's difficult to determine this on-the-fly, so we have * this separate function to come back later and figure it out. * * 'section' is that section. @@ -145,11 +142,11 @@ gtk_menu_tracker_section_find_model (GtkMenuTrackerSection *section, * * could_have_separator is true in two situations: * - * - our parent section had with_separators defined and there are items - * before us (ie: we should add a separator if we have content in + * - our parent section had with_separators defined and we are not the + * first section (ie: we should add a separator if we have content in * order to divide us from the items above) * - * - if we had a “label” attribute set for this section + * - if we had a 'label' attribute set for this section * * parent_model and parent_index are passed in so that we can give them * to the insertion callback so that it can see the label (and anything @@ -171,7 +168,6 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section, gboolean should_have_separator; gint n_items = 0; GSList *item; - GPtrArray *items = g_ptr_array_new (); gint i = 0; for (item = section->items; item; item = item->next) @@ -180,15 +176,13 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section, if (subsection) { - gboolean separator; + gboolean could_have_separator; - separator = (section->with_separators && n_items > 0) || subsection->separator_label; + could_have_separator = (section->with_separators && i > 0) || + g_menu_model_get_item_attribute (section->model, i, "label", "s", NULL); - /* Only pass the parent_model and parent_index in case they may be used to create the separator. */ n_items += gtk_menu_tracker_section_sync_separators (subsection, tracker, offset + n_items, - separator, - separator ? section->model : NULL, - separator ? i : 0); + could_have_separator, section->model, i); } else n_items++; @@ -196,18 +190,19 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section, i++; } - should_have_separator = !section->is_fake && could_have_separator && n_items != 0; + should_have_separator = could_have_separator && n_items != 0; if (should_have_separator > section->has_separator) { /* Add a separator */ - GtkMenuTrackerItem *separator; + GtkMenuTrackerItem *item; + GPtrArray *items = g_ptr_array_new (); - separator = _gtk_menu_tracker_item_new (tracker->observable, parent_model, parent_index, FALSE, NULL, TRUE); - g_ptr_array_add (items, (gpointer) separator); + item = _gtk_menu_tracker_item_new (tracker->observable, parent_model, parent_index, NULL, TRUE); + g_ptr_array_add (items, (gpointer) item); (* tracker->insert_func) (items, offset, tracker->user_data); g_ptr_array_unref (items); - g_object_unref (separator); + g_object_unref (item); section->has_separator = TRUE; } @@ -223,41 +218,6 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section, return n_items; } -static void -gtk_menu_tracker_item_visibility_changed (GtkMenuTrackerItem *item, - GParamSpec *pspec, - gpointer user_data) -{ - GtkMenuTracker *tracker = user_data; - GtkMenuTrackerSection *section; - gboolean is_now_visible; - gboolean was_visible; - gint offset = 0; - - is_now_visible = gtk_menu_tracker_item_get_is_visible (item); - - /* remember: the item is our model */ - section = gtk_menu_tracker_section_find_model (tracker->toplevel, item, &offset); - - was_visible = section->items != NULL; - - if (is_now_visible == was_visible) - return; - - if (is_now_visible) - { - section->items = g_slist_prepend (NULL, NULL); - (* tracker->insert_func) (section->model, offset, tracker->user_data); - } - else - { - section->items = g_slist_delete_link (section->items, section->items); - (* tracker->remove_func) (offset, 1, tracker->user_data); - } - - gtk_menu_tracker_section_sync_separators (tracker->toplevel, tracker, 0, FALSE, NULL, 0); -} - static gint gtk_menu_tracker_section_measure (GtkMenuTrackerSection *section) { @@ -298,7 +258,6 @@ gtk_menu_tracker_remove_items (GtkMenuTracker *tracker, n = gtk_menu_tracker_section_measure (subsection); gtk_menu_tracker_section_free (subsection); - while (n--) n_total_items += n; } @@ -316,32 +275,28 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker, GMenuModel *model, gint position, gint n_items, - GPtrArray *items_already_created) + GPtrArray *items_already_created + ) { - GPtrArray *items; - if (items_already_created) - { - items = items_already_created; - } - else - { - items = g_ptr_array_new (); - } + GPtrArray *items; + if (items_already_created) + { + items = items_already_created; + } + else + { + items = g_ptr_array_new (); + } while (n_items--) { GMenuModel *submenu; submenu = g_menu_model_get_item_link (model, position + n_items, G_MENU_LINK_SECTION); g_assert (submenu != model); - - if (submenu != NULL && tracker->merge_sections) + if (submenu != NULL) { GtkMenuTrackerSection *subsection; gchar *action_namespace = NULL; - gboolean has_label; - - has_label = g_menu_model_get_item_attribute (model, position + n_items, - G_MENU_ATTRIBUTE_LABEL, "s", NULL); g_menu_model_get_item_attribute (model, position + n_items, G_MENU_ATTRIBUTE_ACTION_NAMESPACE, "s", &action_namespace); @@ -351,11 +306,11 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker, gchar *namespace; namespace = g_strjoin (".", section->action_namespace, action_namespace, NULL); - subsection = gtk_menu_tracker_section_new (tracker, submenu, FALSE, has_label, offset, namespace, items_already_created); + subsection = gtk_menu_tracker_section_new (tracker, submenu, FALSE, offset, namespace, items_already_created); g_free (namespace); } else - subsection = gtk_menu_tracker_section_new (tracker, submenu, FALSE, has_label, offset, action_namespace, items_already_created); + subsection = gtk_menu_tracker_section_new (tracker, submenu, FALSE, offset, section->action_namespace, items_already_created); *change_point = g_slist_prepend (*change_point, subsection); g_free (action_namespace); @@ -366,76 +321,22 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker, GtkMenuTrackerItem *item; item = _gtk_menu_tracker_item_new (tracker->observable, model, position + n_items, - tracker->mac_os_mode, - section->action_namespace, submenu != NULL); - - /* In the case that the item may disappear we handle that by - * treating the item that we just created as being its own - * subsection. This happens as so: - * - * - the subsection is created without the possibility of - * showing a separator - * - * - the subsection will have either 0 or 1 item in it at all - * times: either the shown item or not (in the case it is - * hidden) - * - * - the created item acts as the "model" for this section - * and we use its "visiblity-changed" signal in the same - * way that we use the "items-changed" signal from a real - * GMenuModel - * - * We almost never use the '->model' stored in the section for - * anything other than lookups and for dropped the ref and - * disconnecting the signal when we destroy the menu, and we - * need to do exactly those things in this case as well. - * - * The only other thing that '->model' is used for is in the - * case that we want to show a separator, but we will never do - * that because separators are not shown for this fake section. - */ - if (gtk_menu_tracker_item_may_disappear (item)) - { - GtkMenuTrackerSection *fake_section; - - fake_section = g_slice_new0 (GtkMenuTrackerSection); - fake_section->is_fake = TRUE; - fake_section->model = g_object_ref (item); - fake_section->handler = g_signal_connect (item, "notify::is-visible", - G_CALLBACK (gtk_menu_tracker_item_visibility_changed), - tracker); - *change_point = g_slist_prepend (*change_point, fake_section); - - if (gtk_menu_tracker_item_get_is_visible (item)) - { - (* tracker->insert_func) (items, offset, tracker->user_data); - fake_section->items = g_slist_prepend (NULL, NULL); - } - } - else - { - /* In the normal case, we store NULL in the linked list. - * The measurement and lookup code count NULL always as - * exactly 1: an item that will always be there. - */ - g_ptr_array_insert (items, 0, (gpointer) item); - *change_point = g_slist_prepend (*change_point, NULL); - } + section->action_namespace, FALSE); + g_ptr_array_insert (items, 0, (gpointer) item); - g_object_unref (item); + *change_point = g_slist_prepend (*change_point, NULL); } } - if (!items_already_created) - { - if (items->len) - { - (* tracker->insert_func) (items, offset, tracker->user_data); - for (gint i = 0; i < items->len; ++i) - g_object_unref(g_ptr_array_index(items, i)); - } - g_ptr_array_unref (items); - } + { + if (items->len) + { + (* tracker->insert_func) (items, offset, tracker->user_data); + for (gint i = 0; i < items->len; ++i) + g_object_unref(g_ptr_array_index(items, i)); + } + g_ptr_array_unref (items); + } } static void @@ -505,7 +406,6 @@ static GtkMenuTrackerSection * gtk_menu_tracker_section_new (GtkMenuTracker *tracker, GMenuModel *model, gboolean with_separators, - gboolean separator_label, gint offset, const gchar *action_namespace, GPtrArray *items_already_created) @@ -516,7 +416,6 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker, section->model = g_object_ref (model); section->with_separators = with_separators; section->action_namespace = g_strdup (action_namespace); - section->separator_label = separator_label; gtk_menu_tracker_add_items (tracker, section, §ion->items, offset, model, 0, g_menu_model_get_n_items (model), items_already_created); section->handler = g_signal_connect (model, "items-changed", G_CALLBACK (gtk_menu_tracker_model_changed), tracker); @@ -529,10 +428,6 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker, * @model: the model to flatten * @with_separators: if the toplevel should have separators (ie: TRUE * for menus, FALSE for menubars) - * @merge_sections: if sections should have their items merged in the - * usual way or reported only as separators (which can be queried to - * manually handle the items) - * @mac_os_mode: if this is on behalf of the Mac OS menubar * @action_namespace: the passed-in action namespace * @insert_func: insert callback * @remove_func: remove callback @@ -563,7 +458,7 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker, * information about the menu item to insert. @action_namespace is the * action namespace that actions referred to from that item should place * themselves in. Note that if the item is a submenu and the - * “action-namespace” attribute is defined on the item, it will _not_ be + * "action-namespace" attribute is defined on the item, it will _not_ be * applied to the @action_namespace argument as it is meant for the * items inside of the submenu, not the submenu item itself. * @@ -571,7 +466,7 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker, * separator. @model and @item_index will still be meaningfully set in * this case -- to the section menu item corresponding to the separator. * This is useful if the section specifies a label, for example. If - * there is an “action-namespace” attribute on this menu item then it + * there is an "action-namespace" attribute on this menu item then it * should be ignored by the consumer because #GtkMenuTracker has already * handled it. * @@ -583,10 +478,7 @@ GtkMenuTracker * gtk_menu_tracker_new (GtkActionObservable *observable, GMenuModel *model, gboolean with_separators, - gboolean merge_sections, - gboolean mac_os_mode, const gchar *action_namespace, - GPtrArray *items_already_created, GtkMenuTrackerInsertFunc insert_func, GtkMenuTrackerRemoveFunc remove_func, gpointer user_data) @@ -594,43 +486,28 @@ gtk_menu_tracker_new (GtkActionObservable *observable, GtkMenuTracker *tracker; tracker = g_slice_new (GtkMenuTracker); - tracker->merge_sections = merge_sections; - tracker->mac_os_mode = mac_os_mode; tracker->observable = g_object_ref (observable); tracker->insert_func = insert_func; tracker->remove_func = remove_func; tracker->user_data = user_data; - tracker->toplevel = gtk_menu_tracker_section_new (tracker, model, with_separators, FALSE, 0, action_namespace, NULL); + tracker->toplevel = gtk_menu_tracker_section_new (tracker, model, with_separators, 0, action_namespace, NULL); gtk_menu_tracker_section_sync_separators (tracker->toplevel, tracker, 0, FALSE, NULL, 0); return tracker; } GtkMenuTracker * -gtk_menu_tracker_new_for_item_link (GtkMenuTrackerItem *item, - const gchar *link_name, - gboolean merge_sections, - gboolean mac_os_mode, - GtkMenuTrackerInsertFunc insert_func, - GtkMenuTrackerRemoveFunc remove_func, - gpointer user_data) +gtk_menu_tracker_new_for_item_submenu (GtkMenuTrackerItem *item, + GtkMenuTrackerInsertFunc insert_func, + GtkMenuTrackerRemoveFunc remove_func, + gpointer user_data) { - GtkMenuTracker *tracker; - GMenuModel *submenu; - gchar *namespace; - - submenu = _gtk_menu_tracker_item_get_link (item, link_name); - namespace = _gtk_menu_tracker_item_get_link_namespace (item); - - tracker = gtk_menu_tracker_new (_gtk_menu_tracker_item_get_observable (item), submenu, - TRUE, merge_sections, mac_os_mode, - namespace, NULL, insert_func, remove_func, user_data); - - g_object_unref (submenu); - g_free (namespace); - - return tracker; + return gtk_menu_tracker_new (_gtk_menu_tracker_item_get_observable (item), + _gtk_menu_tracker_item_get_submenu (item), + TRUE, + _gtk_menu_tracker_item_get_submenu_namespace (item), + insert_func, remove_func, user_data); } /*< private > |
