Merge lp:~ted/indicator-applet/indicator-sorting into lp:indicator-applet/0.4

Proposed by Ted Gould
Status: Merged
Merged at revision: not available
Proposed branch: lp:~ted/indicator-applet/indicator-sorting
Merge into: lp:indicator-applet/0.4
Diff against target: 208 lines (+154/-4)
1 file modified
src/applet-main.c (+154/-4)
To merge this branch: bzr merge lp:~ted/indicator-applet/indicator-sorting
Reviewer Review Type Date Requested Status
David Barth Approve
Review via email: mp+17644@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

This branch adds support for indicators being placed inside the applet
in a specific order. It also does entries from each indicator.

Revision history for this message
David Barth (dbarth) wrote :

Looks good to me.

However, I feel the loops, positioning tests and ordering support in libindicator would benefit from a few more unit tests.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/applet-main.c'
2--- src/applet-main.c 2010-01-04 19:21:21 +0000
3+++ src/applet-main.c 2010-01-19 05:36:18 +0000
4@@ -25,7 +25,20 @@
5
6 #include "libindicator/indicator-object.h"
7
8-#define ENTRY_DATA_NAME "indicator-custom-entry-data"
9+
10+static gchar * indicator_order[] = {
11+ "libapplication.so",
12+ "libmessaging.so",
13+ "libdatetime.so",
14+ "libme.so",
15+ "libsession.so",
16+ NULL
17+};
18+
19+#define MENU_DATA_INDICATOR_OBJECT "indicator-object"
20+#define MENU_DATA_INDICATOR_ENTRY "indicator-entry"
21+
22+#define IO_DATA_ORDER_NUMBER "indicator-order-number"
23
24 static gboolean applet_fill_cb (PanelApplet * applet, const gchar * iid, gpointer data);
25
26@@ -62,6 +75,78 @@
27 /*************
28 * init function
29 * ***********/
30+
31+static gint
32+name2order (const gchar * name) {
33+ int i;
34+
35+ for (i = 0; indicator_order[i] != NULL; i++) {
36+ if (g_strcmp0(name, indicator_order[i]) == 0) {
37+ return i;
38+ }
39+ }
40+
41+ return -1;
42+}
43+
44+typedef struct _incoming_position_t incoming_position_t;
45+struct _incoming_position_t {
46+ gint objposition;
47+ gint entryposition;
48+ gint menupos;
49+ gboolean found;
50+};
51+
52+/* This function helps by determining where in the menu list
53+ this new entry should be placed. It compares the objects
54+ that they're on, and then the individual entries. Each
55+ is progressively more expensive. */
56+static void
57+place_in_menu (GtkWidget * widget, gpointer user_data)
58+{
59+ incoming_position_t * position = (incoming_position_t *)user_data;
60+ if (position->found) {
61+ /* We've already been placed, just finish the foreach */
62+ return;
63+ }
64+
65+ IndicatorObject * io = INDICATOR_OBJECT(g_object_get_data(G_OBJECT(widget), MENU_DATA_INDICATOR_OBJECT));
66+ g_assert(io != NULL);
67+
68+ gint objposition = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(io), IO_DATA_ORDER_NUMBER));
69+ /* We've already passed it, well, then this is where
70+ we should be be. Stop! */
71+ if (objposition > position->objposition) {
72+ position->found = TRUE;
73+ return;
74+ }
75+
76+ /* The objects don't match yet, keep looking */
77+ if (objposition < position->objposition) {
78+ position->menupos++;
79+ return;
80+ }
81+
82+ /* The objects are the same, let's start looking at entries. */
83+ IndicatorObjectEntry * entry = (IndicatorObjectEntry *)g_object_get_data(G_OBJECT(widget), MENU_DATA_INDICATOR_ENTRY);
84+ gint entryposition = indicator_object_get_location(io, entry);
85+
86+ if (entryposition > position->entryposition) {
87+ position->found = TRUE;
88+ return;
89+ }
90+
91+ if (entryposition < position->entryposition) {
92+ position->menupos++;
93+ return;
94+ }
95+
96+ /* We've got the same object and the same entry. Well,
97+ let's just put it right here then. */
98+ position->found = TRUE;
99+ return;
100+}
101+
102 static void
103 entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, GtkWidget * menu)
104 {
105@@ -83,10 +168,19 @@
106 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(entry->menu));
107 }
108
109- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
110+ incoming_position_t position;
111+ position.objposition = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(io), IO_DATA_ORDER_NUMBER));
112+ position.entryposition = indicator_object_get_location(io, entry);
113+ position.menupos = 0;
114+ position.found = FALSE;
115+
116+ gtk_container_foreach(GTK_CONTAINER(menu), place_in_menu, &position);
117+
118+ gtk_menu_shell_insert(GTK_MENU_SHELL(menu), menuitem, position.menupos);
119 gtk_widget_show(menuitem);
120
121- g_object_set_data(G_OBJECT(menuitem), ENTRY_DATA_NAME, entry);
122+ g_object_set_data(G_OBJECT(menuitem), MENU_DATA_INDICATOR_ENTRY, entry);
123+ g_object_set_data(G_OBJECT(menuitem), MENU_DATA_INDICATOR_OBJECT, io);
124
125 return;
126 }
127@@ -94,7 +188,7 @@
128 static void
129 entry_removed_cb (GtkWidget * widget, gpointer userdata)
130 {
131- gpointer data = g_object_get_data(G_OBJECT(widget), ENTRY_DATA_NAME);
132+ gpointer data = g_object_get_data(G_OBJECT(widget), MENU_DATA_INDICATOR_ENTRY);
133
134 if (data != userdata) {
135 return;
136@@ -114,6 +208,58 @@
137 return;
138 }
139
140+static void
141+entry_moved_find_cb (GtkWidget * widget, gpointer userdata)
142+{
143+ gpointer * array = (gpointer *)userdata;
144+ if (array[1] != NULL) {
145+ return;
146+ }
147+
148+ gpointer data = g_object_get_data(G_OBJECT(widget), MENU_DATA_INDICATOR_ENTRY);
149+
150+ if (data != array[0]) {
151+ return;
152+ }
153+
154+ array[1] = widget;
155+ return;
156+}
157+
158+/* Gets called when an entry for an object was moved. */
159+static void
160+entry_moved (IndicatorObject * io, IndicatorObjectEntry * entry, gint old, gint new, gpointer user_data)
161+{
162+ GtkWidget * menu = GTK_WIDGET(user_data);
163+
164+ gpointer array[2];
165+ array[0] = entry;
166+ array[1] = NULL;
167+
168+ gtk_container_foreach(GTK_CONTAINER(user_data), entry_moved_find_cb, array);
169+ if (array[1] == NULL) {
170+ g_warning("Moving an entry that isn't in our menus.");
171+ return;
172+ }
173+
174+ GtkWidget * mi = GTK_WIDGET(array[1]);
175+ g_object_ref(G_OBJECT(mi));
176+ gtk_container_remove(GTK_CONTAINER(user_data), mi);
177+
178+ incoming_position_t position;
179+ position.objposition = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(io), IO_DATA_ORDER_NUMBER));
180+ position.entryposition = indicator_object_get_location(io, entry);
181+ position.menupos = 0;
182+ position.found = FALSE;
183+
184+ gtk_container_foreach(GTK_CONTAINER(menu), place_in_menu, &position);
185+
186+ gtk_menu_shell_insert(GTK_MENU_SHELL(menu), mi, position.menupos);
187+ g_object_unref(G_OBJECT(mi));
188+
189+ return;
190+}
191+
192 static gboolean
193 load_module (const gchar * name, GtkWidget * menu)
194 {
195@@ -131,9 +277,13 @@
196 IndicatorObject * io = indicator_object_new_from_file(fullpath);
197 g_free(fullpath);
198
199+ /* Attach the 'name' to the object */
200+ g_object_set_data(G_OBJECT(io), IO_DATA_ORDER_NUMBER, GINT_TO_POINTER(name2order(name)));
201+
202 /* Connect to it's signals */
203 g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_added), menu);
204 g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(entry_removed), menu);
205+ g_signal_connect(G_OBJECT(io), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, G_CALLBACK(entry_moved), menu);
206
207 /* Work on the entries */
208 GList * entries = indicator_object_get_entries(io);

Subscribers

People subscribed via source and target branches

to status/vote changes: