aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Astals Cid <albert.astals@canonical.com>2017-03-16 16:55:18 +0000
committerBileto Bot <ci-train-bot@canonical.com>2017-03-16 16:55:18 +0000
commite2b335b0ccb0b156283a320c2e1b7a2f4063b70b (patch)
treefd4c974396446dc7efcfe9858974b27e6a845a63
parent2eaa36e38c910a0ee2450ac7ccae6473d359eb58 (diff)
parent4216eb744d580195628611f0aab698cd483a8675 (diff)
downloadqmenumodel-e2b335b0ccb0b156283a320c2e1b7a2f4063b70b.tar.gz
qmenumodel-e2b335b0ccb0b156283a320c2e1b7a2f4063b70b.tar.bz2
qmenumodel-e2b335b0ccb0b156283a320c2e1b7a2f4063b70b.zip
Batch add and removes into the model
Works much better with Qt Quick views to have all the insert/removes at once (LP: #1666701)
-rw-r--r--libqmenumodel/src/gtk/gtkmenutracker.c58
-rw-r--r--libqmenumodel/src/gtk/gtkmenutracker.h3
-rw-r--r--libqmenumodel/src/unitymenumodel.cpp39
-rw-r--r--libqmenumodel/src/unitymenumodelevents.cpp20
-rw-r--r--libqmenumodel/src/unitymenumodelevents.h8
5 files changed, 84 insertions, 44 deletions
diff --git a/libqmenumodel/src/gtk/gtkmenutracker.c b/libqmenumodel/src/gtk/gtkmenutracker.c
index ab369ab..8b72965 100644
--- a/libqmenumodel/src/gtk/gtkmenutracker.c
+++ b/libqmenumodel/src/gtk/gtkmenutracker.c
@@ -85,7 +85,8 @@ static GtkMenuTrackerSection * gtk_menu_tracker_section_new (GtkMenuTracker
GMenuModel *model,
gboolean with_separators,
gint offset,
- const gchar *action_namespace);
+ const gchar *action_namespace,
+ GPtrArray *items_already_created);
static void gtk_menu_tracker_section_free (GtkMenuTrackerSection *section);
static GtkMenuTrackerSection *
@@ -195,9 +196,12 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section,
{
/* Add a separator */
GtkMenuTrackerItem *item;
+ GPtrArray *items = g_ptr_array_new ();
item = _gtk_menu_tracker_item_new (tracker->observable, parent_model, parent_index, NULL, TRUE);
- (* tracker->insert_func) (item, offset, tracker->user_data);
+ g_ptr_array_add (items, (gpointer) item);
+ (* tracker->insert_func) (items, offset, tracker->user_data);
+ g_ptr_array_unref (items);
g_object_unref (item);
section->has_separator = TRUE;
@@ -205,7 +209,7 @@ gtk_menu_tracker_section_sync_separators (GtkMenuTrackerSection *section,
else if (should_have_separator < section->has_separator)
{
/* Remove a separator */
- (* tracker->remove_func) (offset, tracker->user_data);
+ (* tracker->remove_func) (offset, 1, tracker->user_data);
section->has_separator = FALSE;
}
@@ -241,6 +245,7 @@ gtk_menu_tracker_remove_items (GtkMenuTracker *tracker,
gint n_items)
{
gint i;
+ gint n_total_items = 0;
for (i = 0; i < n_items; i++)
{
@@ -253,8 +258,12 @@ gtk_menu_tracker_remove_items (GtkMenuTracker *tracker,
n = gtk_menu_tracker_section_measure (subsection);
gtk_menu_tracker_section_free (subsection);
- while (n--)
- (* tracker->remove_func) (offset, tracker->user_data);
+ n_total_items += n;
+ }
+
+ if (n_total_items)
+ {
+ (* tracker->remove_func) (offset, n_total_items, tracker->user_data);
}
}
@@ -265,8 +274,19 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker,
gint offset,
GMenuModel *model,
gint position,
- gint n_items)
+ gint n_items,
+ GPtrArray *items_already_created
+ )
{
+ GPtrArray *items;
+ if (items_already_created)
+ {
+ items = items_already_created;
+ }
+ else
+ {
+ items = g_ptr_array_new ();
+ }
while (n_items--)
{
GMenuModel *submenu;
@@ -286,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, offset, namespace);
+ 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, offset, section->action_namespace);
+ 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);
@@ -302,12 +322,21 @@ gtk_menu_tracker_add_items (GtkMenuTracker *tracker,
item = _gtk_menu_tracker_item_new (tracker->observable, model, position + n_items,
section->action_namespace, FALSE);
- (* tracker->insert_func) (item, offset, tracker->user_data);
- g_object_unref (item);
+ g_ptr_array_insert (items, 0, (gpointer) 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);
+ }
}
static void
@@ -352,7 +381,7 @@ gtk_menu_tracker_model_changed (GMenuModel *model,
* would do by appending.
*/
gtk_menu_tracker_remove_items (tracker, change_point, offset, removed);
- gtk_menu_tracker_add_items (tracker, section, change_point, offset, model, position, added);
+ gtk_menu_tracker_add_items (tracker, section, change_point, offset, model, position, added, NULL);
/* The offsets for insertion/removal of separators will be all over
* the place, however...
@@ -378,7 +407,8 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
GMenuModel *model,
gboolean with_separators,
gint offset,
- const gchar *action_namespace)
+ const gchar *action_namespace,
+ GPtrArray *items_already_created)
{
GtkMenuTrackerSection *section;
@@ -387,7 +417,7 @@ gtk_menu_tracker_section_new (GtkMenuTracker *tracker,
section->with_separators = with_separators;
section->action_namespace = g_strdup (action_namespace);
- gtk_menu_tracker_add_items (tracker, section, &section->items, offset, model, 0, g_menu_model_get_n_items (model));
+ 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);
return section;
@@ -461,7 +491,7 @@ gtk_menu_tracker_new (GtkActionObservable *observable,
tracker->remove_func = remove_func;
tracker->user_data = user_data;
- tracker->toplevel = gtk_menu_tracker_section_new (tracker, model, with_separators, 0, action_namespace);
+ 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;
diff --git a/libqmenumodel/src/gtk/gtkmenutracker.h b/libqmenumodel/src/gtk/gtkmenutracker.h
index 96370ad..1ade63f 100644
--- a/libqmenumodel/src/gtk/gtkmenutracker.h
+++ b/libqmenumodel/src/gtk/gtkmenutracker.h
@@ -26,11 +26,12 @@
typedef struct _GtkMenuTracker GtkMenuTracker;
-typedef void (* GtkMenuTrackerInsertFunc) (GtkMenuTrackerItem *item,
+typedef void (* GtkMenuTrackerInsertFunc) (GPtrArray *items,
gint position,
gpointer user_data);
typedef void (* GtkMenuTrackerRemoveFunc) (gint position,
+ gint n_items,
gpointer user_data);
diff --git a/libqmenumodel/src/unitymenumodel.cpp b/libqmenumodel/src/unitymenumodel.cpp
index 192ee46..658fdca 100644
--- a/libqmenumodel/src/unitymenumodel.cpp
+++ b/libqmenumodel/src/unitymenumodel.cpp
@@ -89,8 +89,8 @@ public:
static void nameAppeared(GDBusConnection *connection, const gchar *name, const gchar *owner, gpointer user_data);
static void nameVanished(GDBusConnection *connection, const gchar *name, gpointer user_data);
- static void menuItemInserted(GtkMenuTrackerItem *item, gint position, gpointer user_data);
- static void menuItemRemoved(gint position, gpointer user_data);
+ static void menuItemInserted(GPtrArray *items, gint position, gpointer user_data);
+ static void menuItemRemoved(gint position, gint n_items, gpointer user_data);
static void menuItemChanged(GObject *object, GParamSpec *pspec, gpointer user_data);
static void registeredActionAdded(GtkSimpleActionObserver *observer_item,
@@ -250,19 +250,19 @@ void UnityMenuModelPrivate::nameVanished(GDBusConnection *connection, const gcha
priv->clearName();
}
-void UnityMenuModelPrivate::menuItemInserted(GtkMenuTrackerItem *item, gint position, gpointer user_data)
+void UnityMenuModelPrivate::menuItemInserted(GPtrArray *items, gint position, gpointer user_data)
{
UnityMenuModelPrivate *priv = (UnityMenuModelPrivate *)user_data;
- UnityMenuModelAddRowEvent ummare(item, position);
+ UnityMenuModelAddRowEvent ummare(items, position);
QCoreApplication::sendEvent(priv->model, &ummare);
}
-void UnityMenuModelPrivate::menuItemRemoved(gint position, gpointer user_data)
+void UnityMenuModelPrivate::menuItemRemoved(gint position, gint n_items, gpointer user_data)
{
UnityMenuModelPrivate *priv = (UnityMenuModelPrivate *)user_data;
- UnityMenuModelRemoveRowEvent ummrre(position);
+ UnityMenuModelRemoveRowEvent ummrre(position, n_items);
QCoreApplication::sendEvent(priv->model, &ummrre);
}
@@ -797,26 +797,29 @@ bool UnityMenuModel::event(QEvent* e)
GSequenceIter *it;
it = g_sequence_get_iter_at_pos (priv->items, ummrce->position);
- beginInsertRows(QModelIndex(), ummrce->position, ummrce->position);
+ beginInsertRows(QModelIndex(), ummrce->position, ummrce->position + ummrce->items->len - 1);
- it = g_sequence_insert_before (it, g_object_ref (ummrce->item));
- g_object_set_qdata (G_OBJECT (ummrce->item), unity_menu_model_quark (), this);
- g_signal_connect (ummrce->item, "notify", G_CALLBACK (UnityMenuModelPrivate::menuItemChanged), it);
+ for (gint i = ummrce->items->len - 1; i >= 0; --i) {
+ GtkMenuTrackerItem *item = (GtkMenuTrackerItem*)g_ptr_array_index(ummrce->items, i);
+ it = g_sequence_insert_before (it, g_object_ref (item));
+ g_object_set_qdata (G_OBJECT (item), unity_menu_model_quark (), this);
+ g_signal_connect (item, "notify", G_CALLBACK (UnityMenuModelPrivate::menuItemChanged), it);
+ }
endInsertRows();
return true;
} else if (e->type() == UnityMenuModelRemoveRowEvent::eventType) {
UnityMenuModelRemoveRowEvent *ummrre = static_cast<UnityMenuModelRemoveRowEvent*>(e);
- GSequenceIter *it;
- it = g_sequence_get_iter_at_pos (priv->items, ummrre->position);
- if (!g_sequence_iter_is_end (it)) {
- beginRemoveRows(QModelIndex(), ummrre->position, ummrre->position);
-
- g_sequence_remove (it);
-
- endRemoveRows();
+ beginRemoveRows(QModelIndex(), ummrre->position, ummrre->position + ummrre->nItems - 1);
+ for (int i = 0; i < ummrre->nItems; ++i) {
+ GSequenceIter *it = g_sequence_get_iter_at_pos (priv->items, ummrre->position);
+ if (!g_sequence_iter_is_end (it)) {
+ g_sequence_remove (it);
+ }
}
+ endRemoveRows();
+
return true;
} else if (e->type() == UnityMenuModelDataChangeEvent::eventType) {
UnityMenuModelDataChangeEvent *ummdce = static_cast<UnityMenuModelDataChangeEvent*>(e);
diff --git a/libqmenumodel/src/unitymenumodelevents.cpp b/libqmenumodel/src/unitymenumodelevents.cpp
index e03d1c7..68dacde 100644
--- a/libqmenumodel/src/unitymenumodelevents.cpp
+++ b/libqmenumodel/src/unitymenumodelevents.cpp
@@ -35,26 +35,30 @@ UnityMenuModelClearEvent::UnityMenuModelClearEvent(bool _reset)
reset(_reset)
{}
-UnityMenuModelAddRowEvent::UnityMenuModelAddRowEvent(GtkMenuTrackerItem *_item, int _position)
+UnityMenuModelAddRowEvent::UnityMenuModelAddRowEvent(GPtrArray *_items, int _position)
: QEvent(UnityMenuModelAddRowEvent::eventType),
- item(_item),
+ items(_items),
position(_position)
{
- if (item) {
- g_object_ref(item);
+ if (items) {
+ for (gint i = 0; i < items->len; ++i)
+ g_object_ref(g_ptr_array_index(items, i));
+ g_ptr_array_ref(items);
}
}
UnityMenuModelAddRowEvent::~UnityMenuModelAddRowEvent()
{
- if (item) {
- g_object_unref(item);
+ if (items) {
+ for (gint i = 0; i < items->len; ++i)
+ g_object_unref(g_ptr_array_index(items, i));
+ g_ptr_array_unref(items);
}
}
-UnityMenuModelRemoveRowEvent::UnityMenuModelRemoveRowEvent(int _position)
+UnityMenuModelRemoveRowEvent::UnityMenuModelRemoveRowEvent(int _position, int _nItems)
: QEvent(UnityMenuModelRemoveRowEvent::eventType),
- position(_position)
+ position(_position), nItems(_nItems)
{}
UnityMenuModelDataChangeEvent::UnityMenuModelDataChangeEvent(int _position)
diff --git a/libqmenumodel/src/unitymenumodelevents.h b/libqmenumodel/src/unitymenumodelevents.h
index dcb27ff..d860f0e 100644
--- a/libqmenumodel/src/unitymenumodelevents.h
+++ b/libqmenumodel/src/unitymenumodelevents.h
@@ -21,6 +21,7 @@
#define UNITYMENUMODELEVENTS_H
#include <QEvent>
+#include <glib.h>
typedef struct _GtkMenuTrackerItem GtkMenuTrackerItem;
@@ -39,10 +40,10 @@ class UnityMenuModelAddRowEvent : public QEvent
{
public:
static const QEvent::Type eventType;
- UnityMenuModelAddRowEvent(GtkMenuTrackerItem *item, int position);
+ UnityMenuModelAddRowEvent(GPtrArray *_items, int position);
~UnityMenuModelAddRowEvent();
- GtkMenuTrackerItem *item;
+ GPtrArray *items;
int position;
};
@@ -51,9 +52,10 @@ class UnityMenuModelRemoveRowEvent : public QEvent
{
public:
static const QEvent::Type eventType;
- UnityMenuModelRemoveRowEvent(int position);
+ UnityMenuModelRemoveRowEvent(int position, int nItems);
int position;
+ int nItems;
};
/* Event for a row data change for unitymenumodel */