aboutsummaryrefslogtreecommitdiff
path: root/libqmenumodel/src/gtk/gtkmenutracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqmenumodel/src/gtk/gtkmenutracker.c')
-rw-r--r--libqmenumodel/src/gtk/gtkmenutracker.c245
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, &section->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 >