Merge lp:~charlesk/libindicator/lp-1045372 into lp:libindicator/12.10

Proposed by Charles Kerr on 2012-09-12
Status: Merged
Approved by: Lars Karlitski on 2012-09-12
Approved revision: 473
Merged at revision: 471
Proposed branch: lp:~charlesk/libindicator/lp-1045372
Merge into: lp:libindicator/12.10
Diff against target: 287 lines (+66/-103)
4 files modified
libindicator/indicator-object.c (+2/-62)
tests/dummy-indicator-visible.c (+10/-2)
tests/test-loader.c (+13/-11)
tools/indicator-loader.c (+41/-28)
To merge this branch: bzr merge lp:~charlesk/libindicator/lp-1045372
Reviewer Review Type Date Requested Status
Lars Karlitski (community) 2012-09-12 Approve on 2012-09-12
jenkins (community) continuous-integration Approve on 2012-09-12
Review via email: mp+123876@code.launchpad.net

Commit Message

In libindicator, remove the cloak/decloak code in IndicatorObject to address Bug #1045372.

In indicator-loader, support hiding & re-showing IndicatorObjectEntries by caching their menuitems and using gtk_widget_hide / gtk_widget_show.

In tests/test-loader and tests/dummy-indicator-visible.c, support hiding & re-showing IndicatorObjectEntries by caching their parent widgetry instead of using gtk_widget_destroy().

Description of the Change

The cloak/decloak code existed to ensure that the IndicatorObjectEntry's widgets were not destroyed by client code on the "entry-removed" signal. Instead, let's fix the client code to understand that IOEs' visibility can be toggled and re-toggled.

See also: https://code.launchpad.net/~charlesk/indicator-applet/lp-1045372

To post a comment you must log in.
jenkins (martin-mrazik+qa) wrote :
review: Needs Fixing (continuous-integration)
lp:~charlesk/libindicator/lp-1045372 updated on 2012-09-12
473. By Charles Kerr on 2012-09-12

In tests/test-loader and tests/dummy-indicator-visible.c, support hiding & re-showing IndicatorObjectEntries by caching their parent widgetry instead of using gtk_widget_destroy()

jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Lars Karlitski (larsu) wrote :

Looks good, that cloaking thing was indeed a bit weird. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libindicator/indicator-object.c'
2--- libindicator/indicator-object.c 2012-02-29 20:58:03 +0000
3+++ libindicator/indicator-object.c 2012-09-12 04:29:16 +0000
4@@ -113,9 +113,7 @@
5 /* entries' visibility */
6 static GList * get_entries_default (IndicatorObject*);
7 static GList * get_all_entries (IndicatorObject*);
8-static void entry_being_removed_default (IndicatorObject*, IndicatorObjectEntry*);
9 static void indicator_object_entry_being_removed (IndicatorObject*, IndicatorObjectEntry*);
10-static void entry_was_added_default (IndicatorObject*, IndicatorObjectEntry*);
11 static void indicator_object_entry_was_added (IndicatorObject*, IndicatorObjectEntry*);
12 static IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject*, IndicatorObjectEntry*);
13
14@@ -141,8 +139,8 @@
15 klass->get_accessible_desc = NULL;
16 klass->get_entries = get_entries_default;
17 klass->get_location = NULL;
18- klass->entry_being_removed = entry_being_removed_default;
19- klass->entry_was_added = entry_was_added_default;
20+ klass->entry_being_removed = NULL;
21+ klass->entry_was_added = NULL;
22
23 klass->entry_activate = NULL;
24 klass->entry_activate_window = NULL;
25@@ -937,61 +935,3 @@
26 }
27 }
28
29-/***
30-****
31-***/
32-
33-/* Cloaked entries are ones which are hidden but may be re-added later.
34- They are reffed + unparented so that they'll survive even if the
35- rest of the widgetry is destroyed */
36-#define CLOAKED_KEY "entry-is-cloaked"
37-
38-static void
39-decloak_widget (gpointer w)
40-{
41- if (w != NULL) {
42- GObject * o = G_OBJECT(w);
43- if (g_object_steal_data (o, CLOAKED_KEY) != NULL) {
44- g_object_unref (o);
45- }
46- }
47-}
48-
49-static void
50-entry_was_added_default (IndicatorObject * io, IndicatorObjectEntry * entry)
51-{
52- decloak_widget (entry->image);
53- decloak_widget (entry->label);
54- decloak_widget (entry->menu);
55-}
56-
57-static void
58-cloak_widget (gpointer w)
59-{
60- if (w != NULL) {
61- GtkWidget * parent;
62-
63- /* tag this object as cloaked */
64- GObject * o = G_OBJECT(w);
65- g_object_ref (o);
66- g_object_set_data (o, CLOAKED_KEY, GINT_TO_POINTER(1));
67-
68- /* remove it from its surrounding widgetry */
69- if(GTK_IS_MENU(w)) {
70- if (gtk_menu_get_attach_widget (GTK_MENU(w)) != NULL) {
71- gtk_menu_detach (GTK_MENU(w));
72- }
73- }
74- else if((parent = gtk_widget_get_parent(w))) {
75- gtk_container_remove(GTK_CONTAINER(parent), w);
76- }
77- }
78-}
79-
80-static void
81-entry_being_removed_default (IndicatorObject * io, IndicatorObjectEntry * entry)
82-{
83- cloak_widget (entry->image);
84- cloak_widget (entry->label);
85- cloak_widget (entry->menu);
86-}
87
88=== modified file 'tests/dummy-indicator-visible.c'
89--- tests/dummy-indicator-visible.c 2012-01-23 11:39:50 +0000
90+++ tests/dummy-indicator-visible.c 2012-09-12 04:29:16 +0000
91@@ -88,17 +88,25 @@
92 static void
93 dummy_indicator_entry_being_removed (IndicatorObject * io, IndicatorObjectEntry * entry)
94 {
95+ IndicatorObjectClass * indicator_object_class = INDICATOR_OBJECT_CLASS (dummy_indicator_visible_parent_class);
96+
97 g_object_set_data(G_OBJECT(entry->label), "is-hidden", GINT_TO_POINTER(1));
98
99- INDICATOR_OBJECT_CLASS(dummy_indicator_visible_parent_class)->entry_being_removed (io, entry);
100+ if (indicator_object_class->entry_being_removed != NULL) {
101+ indicator_object_class->entry_being_removed (io, entry);
102+ }
103 }
104
105 static void
106 dummy_indicator_entry_was_added (IndicatorObject * io, IndicatorObjectEntry * entry)
107 {
108+ IndicatorObjectClass * indicator_object_class = INDICATOR_OBJECT_CLASS (dummy_indicator_visible_parent_class);
109+
110 g_object_steal_data(G_OBJECT(entry->label), "is-hidden");
111
112- INDICATOR_OBJECT_CLASS(dummy_indicator_visible_parent_class)->entry_was_added (io, entry);
113+ if (indicator_object_class->entry_was_added != NULL) {
114+ indicator_object_class->entry_was_added (io, entry);
115+ }
116 }
117
118 static void
119
120=== modified file 'tests/test-loader.c'
121--- tests/test-loader.c 2012-01-25 17:11:43 +0000
122+++ tests/test-loader.c 2012-09-12 04:29:16 +0000
123@@ -156,22 +156,24 @@
124 static void
125 visible_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer box)
126 {
127- // make a frame for the entry, and add the frame to the box
128- GtkWidget * frame = gtk_frame_new (NULL);
129- GtkWidget * child = GTK_WIDGET(entry->label);
130+ GtkWidget * child = GTK_WIDGET (entry->label);
131 g_assert (child != NULL);
132- gtk_container_add (GTK_CONTAINER(frame), child);
133- gtk_box_pack_start (GTK_BOX(box), frame, FALSE, FALSE, 0);
134- g_object_set_data (G_OBJECT(child), "frame-parent", frame);
135+
136+ if (g_object_get_data (G_OBJECT(child), "frame-parent") == NULL)
137+ {
138+ GtkWidget * frame = gtk_frame_new (NULL);
139+ gtk_container_add (GTK_CONTAINER(frame), child);
140+ gtk_box_pack_start (GTK_BOX(box), frame, FALSE, FALSE, 0);
141+ g_object_set_data (G_OBJECT(child), "frame-parent", frame);
142+ }
143 }
144
145 static void
146 visible_entry_removed (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer box)
147 {
148- // destroy this entry's frame
149- gpointer parent = g_object_steal_data (G_OBJECT(entry->label), "frame-parent");
150- if (GTK_IS_WIDGET(parent))
151- gtk_widget_destroy(GTK_WIDGET(parent));
152+ GtkWidget * child = GTK_WIDGET (entry->label);
153+ g_assert (child != NULL);
154+ g_assert (g_object_get_data (G_OBJECT(child), "frame-parent") != NULL);
155 }
156
157 void
158@@ -218,7 +220,7 @@
159 g_assert(GTK_IS_LABEL(label));
160 g_assert(g_object_get_qdata(G_OBJECT(label), is_hidden_quark) != NULL);
161 list = gtk_container_get_children (GTK_CONTAINER(box));
162- g_assert(g_list_length(list) == 0);
163+ g_assert(g_list_length(list) == 1);
164 g_list_free(list);
165
166 // restore the entries and confirm that the label survived
167
168=== modified file 'tools/indicator-loader.c'
169--- tools/indicator-loader.c 2012-01-19 17:48:32 +0000
170+++ tools/indicator-loader.c 2012-09-12 04:29:16 +0000
171@@ -25,6 +25,8 @@
172 #include <gtk/gtk.h>
173 #include <libindicator/indicator-object.h>
174
175+static GHashTable * entry_to_menuitem = NULL;
176+
177 #define ENTRY_DATA_NAME "indicator-custom-entry-data"
178
179 static void
180@@ -40,20 +42,18 @@
181 return;
182 }
183
184-static void
185-entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data)
186+static GtkWidget*
187+create_menu_item (IndicatorObjectEntry * entry)
188 {
189- g_debug("Signal: Entry Added");
190-
191- if (entry->parent_object == NULL) {
192- g_warning("Entry '%p' does not have a parent object", entry);
193- }
194-
195- GtkWidget * menuitem = gtk_menu_item_new();
196+ GtkWidget * hbox;
197+ GtkWidget * menuitem;
198+
199+ menuitem = gtk_menu_item_new();
200+
201 #if GTK_CHECK_VERSION(3,0,0)
202- GtkWidget * hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
203+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3);
204 #else
205- GtkWidget * hbox = gtk_hbox_new(FALSE, 3);
206+ hbox = gtk_hbox_new(FALSE, 3);
207 #endif
208
209 if (entry->image != NULL) {
210@@ -69,26 +69,34 @@
211 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(entry->menu));
212 }
213
214- g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(activate_entry), io);
215-
216- gtk_menu_shell_append(GTK_MENU_SHELL(user_data), menuitem);
217- gtk_widget_show(menuitem);
218-
219- g_object_set_data(G_OBJECT(menuitem), ENTRY_DATA_NAME, entry);
220-
221- return;
222+ return menuitem;
223 }
224
225 static void
226-entry_removed_cb (GtkWidget * widget, gpointer userdata)
227+entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data)
228 {
229- gpointer data = g_object_get_data(G_OBJECT(widget), ENTRY_DATA_NAME);
230-
231- if (data != userdata) {
232- return;
233- }
234-
235- gtk_widget_destroy(widget);
236+ GtkWidget * menuitem;
237+
238+ g_debug("Signal: Entry Added");
239+
240+ if (entry->parent_object == NULL) {
241+ g_warning("Entry '%p' does not have a parent object", entry);
242+ }
243+
244+ menuitem = g_hash_table_lookup (entry_to_menuitem, entry);
245+ if (menuitem == NULL) {
246+ g_debug ("This is the first time this entry's been added -- creating a new menuitem for it");
247+ menuitem = create_menu_item (entry);
248+ g_hash_table_insert (entry_to_menuitem, entry, menuitem);
249+
250+ g_object_set_data(G_OBJECT(menuitem), ENTRY_DATA_NAME, entry);
251+ g_signal_connect (G_OBJECT(menuitem), "activate", G_CALLBACK(activate_entry), io);
252+
253+ gtk_menu_shell_append (GTK_MENU_SHELL(user_data), menuitem);
254+
255+ }
256+ gtk_widget_show (menuitem);
257+
258 return;
259 }
260
261@@ -97,7 +105,9 @@
262 {
263 g_debug("Signal: Entry Removed");
264
265- gtk_container_foreach(GTK_CONTAINER(user_data), entry_removed_cb, entry);
266+ GtkWidget * menuitem = g_hash_table_lookup (entry_to_menuitem, entry);
267+ if (menuitem != NULL)
268+ gtk_widget_hide (menuitem);
269
270 return;
271 }
272@@ -162,6 +172,8 @@
273
274 gtk_init(&argc, &argv);
275
276+ entry_to_menuitem = g_hash_table_new (g_direct_hash, g_direct_equal);
277+
278 if (argc != 2) {
279 g_error("Need filename");
280 return 1;
281@@ -183,5 +195,6 @@
282
283 gtk_main();
284
285+ g_hash_table_destroy (entry_to_menuitem);
286 return 0;
287 }

Subscribers

People subscribed via source and target branches