Merge lp:~larsu/indicator-messages/watch-desktop-files into lp:indicator-messages/12.10

Proposed by Lars Karlitski
Status: Merged
Merge reported by: Lars Karlitski
Merged at revision: not available
Proposed branch: lp:~larsu/indicator-messages/watch-desktop-files
Merge into: lp:indicator-messages/12.10
Diff against target: 325 lines (+131/-52)
3 files modified
src/app-section.c (+108/-40)
src/app-section.h (+0/-2)
src/messages-service.c (+23/-10)
To merge this branch: bzr merge lp:~larsu/indicator-messages/watch-desktop-files
Reviewer Review Type Date Requested Status
jenkins (community) continuous-integration Needs Fixing
Charles Kerr (community) Approve
Review via email: mp+122873@code.launchpad.net
To post a comment you must log in.
Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

Overall this is a good patch as usual. :)

Needs Fixing:

  * in app-section.c, the file-scope variable destroy_count should be static

  * the new function app_section_get_name() is not used anywhere, was this included by accident?

Comment:

  * in remove_application(), the new call to g_hash_table_remove() added when (section == NULL) should be removed.

  * remove_section() is wrapped in a g_hash_table_lookup() safety check when called from remove_application(), but not when called from the destroy callback. Both this and the previous bullet point could be addressed by moving the g_hash_table_lookup() + g_warning() from remove_application() to remove_section().

review: Needs Fixing
Revision history for this message
Lars Karlitski (larsu) wrote :

> Overall this is a good patch as usual. :)
>
> Needs Fixing:
>
> * in app-section.c, the file-scope variable destroy_count should be static

Fixed in r311. (you meant destroy_signal, right?)

> * the new function app_section_get_name() is not used anywhere, was this
> included by accident?

That's a very old function. Removed it anyway in r312.

> Comment:
>
> * in remove_application(), the new call to g_hash_table_remove() added when
> (section == NULL) should be removed.

Right, fixed in r313.

> * remove_section() is wrapped in a g_hash_table_lookup() safety check when
> called from remove_application(), but not when called from the destroy
> callback. Both this and the previous bullet point could be addressed by moving
> the g_hash_table_lookup() + g_warning() from remove_application() to
> remove_section().

I didn't do this because remove_section is called from the "destroy" signal from the AppSection. There's no need to look up the AppSection again in the hash table, because we already have it. That said, are you okay with keeping this as it is for now? I plan on refactoring thatq bit starting next cycle anyway.

Thanks for reviewing!

Revision history for this message
jenkins (martin-mrazik+qa) wrote :
review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

Yes, I'm fine with that part as-is, especially if it's getting refactored away :)

review: Approve
Revision history for this message
jenkins (martin-mrazik+qa) wrote :

FAILED: Autolanding.
No commit message was specified.
http://jenkins.qa.ubuntu.com/job/indicator-messages-autolanding/7/

review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app-section.c'
2--- src/app-section.c 2012-08-27 15:34:30 +0000
3+++ src/app-section.c 2012-09-05 19:31:19 +0000
4@@ -37,7 +37,7 @@
5 struct _AppSectionPrivate
6 {
7 GDesktopAppInfo * appinfo;
8- guint unreadcount;
9+ GFileMonitor *desktop_file_monitor;
10
11 IndicatorDesktopShortcuts * ids;
12
13@@ -64,6 +64,7 @@
14 };
15
16 static GParamSpec *properties[NUM_PROPERTIES];
17+static guint destroy_signal;
18
19 /* Prototypes */
20 static void app_section_class_init (AppSectionClass *klass);
21@@ -98,6 +99,11 @@
22 const gchar *action_name,
23 gpointer user_data);
24 static gboolean action_draws_attention (GVariant *state);
25+static void desktop_file_changed_cb (GFileMonitor *monitor,
26+ GFile *file,
27+ GFile *other_file,
28+ GFileMonitorEvent event,
29+ gpointer user_data);
30
31 /* GObject Boilerplate */
32 G_DEFINE_TYPE (AppSection, app_section, G_TYPE_OBJECT);
33@@ -138,6 +144,14 @@
34 G_PARAM_READABLE);
35
36 g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
37+
38+ destroy_signal = g_signal_new ("destroy",
39+ APP_SECTION_TYPE,
40+ G_SIGNAL_RUN_FIRST,
41+ 0,
42+ NULL, NULL,
43+ g_cclosure_marshal_VOID__VOID,
44+ G_TYPE_NONE, 0);
45 }
46
47 static void
48@@ -151,7 +165,6 @@
49 priv = self->priv;
50
51 priv->appinfo = NULL;
52- priv->unreadcount = 0;
53
54 priv->menu = g_menu_new ();
55 priv->static_shortcuts = g_simple_action_group_new ();
56@@ -209,12 +222,18 @@
57 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
58 }
59 }
60+
61 static void
62 app_section_dispose (GObject *object)
63 {
64 AppSection * self = APP_SECTION(object);
65 AppSectionPrivate * priv = self->priv;
66
67+ if (priv->desktop_file_monitor) {
68+ g_signal_handlers_disconnect_by_func (priv->desktop_file_monitor, desktop_file_changed_cb, self);
69+ g_clear_object (&priv->desktop_file_monitor);
70+ }
71+
72 g_clear_object (&priv->menu);
73 g_clear_object (&priv->static_shortcuts);
74
75@@ -289,6 +308,9 @@
76 G_KEY_FILE_DESKTOP_GROUP,
77 "X-MessagingMenu-UsesChatSection",
78 &error);
79+
80+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
81+
82 if (error) {
83 if (error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
84 g_warning ("could not read X-MessagingMenu-UsesChatSection: %s",
85@@ -298,34 +320,48 @@
86 goto out;
87 }
88
89- if (self->priv->uses_chat_status)
90- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_USES_CHAT_STATUS]);
91-
92 out:
93 g_key_file_free (keyfile);
94 g_free (contents);
95 }
96
97 static void
98-app_section_set_app_info (AppSection *self,
99- GDesktopAppInfo *appinfo)
100+g_menu_clear (GMenu *menu)
101+{
102+ gint n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu));
103+
104+ while (n_items--)
105+ g_menu_remove (menu, 0);
106+}
107+
108+static void
109+g_simple_action_group_clear (GSimpleActionGroup *group)
110+{
111+ gchar **actions;
112+ gchar **it;
113+
114+ actions = g_action_group_list_actions (G_ACTION_GROUP (group));
115+ for (it = actions; *it; it++)
116+ g_simple_action_group_remove (group, *it);
117+
118+ g_strfreev (actions);
119+}
120+
121+static void
122+app_section_update_menu (AppSection *self)
123 {
124 AppSectionPrivate *priv = self->priv;
125 GSimpleAction *launch;
126 GFile *keyfile;
127 GMenuItem *item;
128 gchar *iconstr;
129-
130- g_return_if_fail (priv->appinfo == NULL);
131-
132- if (appinfo == NULL) {
133- g_warning ("appinfo must not be NULL");
134- return;
135- }
136-
137- priv->appinfo = g_object_ref (appinfo);
138-
139- launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (FALSE));
140+ gboolean is_running;
141+
142+ g_menu_clear (priv->menu);
143+ g_simple_action_group_clear (priv->static_shortcuts);
144+
145+ is_running = priv->name_watch_id > 0;
146+ launch = g_simple_action_new_stateful ("launch", NULL, g_variant_new_boolean (is_running));
147 g_signal_connect (launch, "activate", G_CALLBACK (activate_cb), self);
148 g_signal_connect (launch, "change-state", G_CALLBACK (launch_action_change_state), self);
149 g_simple_action_group_insert (priv->static_shortcuts, G_ACTION (launch));
150@@ -366,12 +402,63 @@
151
152 keyfile = g_file_new_for_path (g_desktop_app_info_get_filename (priv->appinfo));
153 g_file_load_contents_async (keyfile, NULL, keyfile_loaded, self);
154+
155+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
156+
157 g_object_unref (keyfile);
158+ g_object_unref (launch);
159+}
160+
161+static void
162+desktop_file_changed_cb (GFileMonitor *monitor,
163+ GFile *file,
164+ GFile *other_file,
165+ GFileMonitorEvent event,
166+ gpointer user_data)
167+{
168+ AppSection *self = user_data;
169+
170+ if (event == G_FILE_MONITOR_EVENT_CHANGED) {
171+ app_section_update_menu (self);
172+ }
173+ else if (event == G_FILE_MONITOR_EVENT_DELETED ||
174+ event == G_FILE_MONITOR_EVENT_UNMOUNTED) {
175+ g_signal_emit (self, destroy_signal, 0);
176+ }
177+}
178+
179+static void
180+app_section_set_app_info (AppSection *self,
181+ GDesktopAppInfo *appinfo)
182+{
183+ AppSectionPrivate *priv = self->priv;
184+ GFile *desktop_file;
185+ GError *error = NULL;
186+
187+ g_return_if_fail (priv->appinfo == NULL);
188+ g_return_if_fail (priv->desktop_file_monitor == NULL);
189+
190+ if (appinfo == NULL) {
191+ g_warning ("appinfo must not be NULL");
192+ return;
193+ }
194+
195+ priv->appinfo = g_object_ref (appinfo);
196+
197+ desktop_file = g_file_new_for_path (g_desktop_app_info_get_filename (appinfo));
198+ priv->desktop_file_monitor = g_file_monitor (desktop_file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
199+ if (priv->desktop_file_monitor == NULL) {
200+ g_warning ("unable to watch desktop file: %s", error->message);
201+ g_error_free (error);
202+ }
203+ g_signal_connect (priv->desktop_file_monitor, "changed",
204+ G_CALLBACK (desktop_file_changed_cb), self);
205
206 g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_APPINFO]);
207- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIONS]);
208-
209- g_object_unref (launch);
210+
211+ app_section_update_menu (self);
212+
213+ g_object_unref (desktop_file);
214 }
215
216 AppSection *
217@@ -407,25 +494,6 @@
218 g_simple_action_set_state (action, value);
219 }
220
221-guint
222-app_section_get_count (AppSection * self)
223-{
224- AppSectionPrivate * priv = self->priv;
225-
226- return priv->unreadcount;
227-}
228-
229-const gchar *
230-app_section_get_name (AppSection * self)
231-{
232- AppSectionPrivate * priv = self->priv;
233-
234- if (priv->appinfo) {
235- return g_app_info_get_name(G_APP_INFO(priv->appinfo));
236- }
237- return NULL;
238-}
239-
240 const gchar *
241 app_section_get_desktop (AppSection * self)
242 {
243
244=== modified file 'src/app-section.h'
245--- src/app-section.h 2012-08-19 20:41:23 +0000
246+++ src/app-section.h 2012-09-05 19:31:19 +0000
247@@ -51,8 +51,6 @@
248
249 GType app_section_get_type (void);
250 AppSection * app_section_new (GDesktopAppInfo *appinfo);
251-guint app_section_get_count (AppSection * appitem);
252-const gchar * app_section_get_name (AppSection * appitem);
253 const gchar * app_section_get_desktop (AppSection * appitem);
254 GActionGroup * app_section_get_actions (AppSection *self);
255 GMenuModel * app_section_get_menu (AppSection *appitem);
256
257=== modified file 'src/messages-service.c'
258--- src/messages-service.c 2012-08-27 13:38:04 +0000
259+++ src/messages-service.c 2012-09-05 19:31:19 +0000
260@@ -45,7 +45,6 @@
261 static GMenuModel *chat_section;
262 static GSettings *settings;
263
264-
265 static gchar *
266 g_app_info_get_simple_id (GAppInfo *appinfo)
267 {
268@@ -138,6 +137,23 @@
269 g_object_unref (first_section);
270 }
271
272+static void
273+remove_section (AppSection *section,
274+ const gchar *id)
275+{
276+ int pos = g_menu_find_section (menu, app_section_get_menu (section));
277+ if (pos >= 0)
278+ g_menu_remove (menu, pos);
279+ g_action_muxer_remove (action_muxer, id);
280+
281+ g_signal_handlers_disconnect_by_func (section, actions_changed, NULL);
282+ g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL);
283+ g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL);
284+ g_signal_handlers_disconnect_by_func (section, remove_section, NULL);
285+
286+ g_hash_table_remove (applications, id);
287+}
288+
289 static AppSection *
290 add_application (const gchar *desktop_id)
291 {
292@@ -167,6 +183,11 @@
293 G_CALLBACK (draws_attention_changed), NULL);
294 g_signal_connect (section, "notify::uses-chat-status",
295 G_CALLBACK (uses_chat_status_changed), NULL);
296+ g_signal_connect_data (section, "destroy",
297+ G_CALLBACK (remove_section),
298+ g_strdup (id),
299+ (GClosureNotify) g_free,
300+ 0);
301
302 /* TODO insert it at the right position (alphabetically by application name) */
303 menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section));
304@@ -197,20 +218,12 @@
305
306 section = g_hash_table_lookup (applications, id);
307 if (section) {
308- int pos = g_menu_find_section (menu, app_section_get_menu (section));
309- if (pos >= 0)
310- g_menu_remove (menu, pos);
311- g_action_muxer_remove (action_muxer, id);
312-
313- g_signal_handlers_disconnect_by_func (section, actions_changed, NULL);
314- g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL);
315- g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL);
316+ remove_section (section, id);
317 }
318 else {
319 g_warning ("could not remove '%s', it's not registered", desktop_id);
320 }
321
322- g_hash_table_remove (applications, id);
323 g_free (id);
324 g_object_unref (appinfo);
325 }

Subscribers

People subscribed via source and target branches