Mercurial > projects > package-update-indicator
comparison pui-application.c @ 55:24cba399757f
Add new setting "always-active"
The setting determines whether the indicator status is set to "active" when
packages are up to date, i.e. whether it is visible and/or can be interacted
with. It defaults to true which reflects the previous behavior.
author | Guido Berhoerster <guido+pui@berhoerster.name> |
---|---|
date | Wed, 17 Aug 2022 16:55:17 +0200 |
parents | c4b8785d0b75 |
children | 08747f3a718b |
comparison
equal
deleted
inserted
replaced
54:b4b36627c1c1 | 55:24cba399757f |
---|---|
46 GtkWidget *about_dialog; | 46 GtkWidget *about_dialog; |
47 GIcon *icons[PUI_STATE_LAST]; | 47 GIcon *icons[PUI_STATE_LAST]; |
48 PuiState state; | 48 PuiState state; |
49 gchar *update_command; | 49 gchar *update_command; |
50 gchar *error_message; | 50 gchar *error_message; |
51 gboolean always_active; | |
51 }; | 52 }; |
52 | 53 |
53 G_DEFINE_TYPE(PuiApplication, pui_application, G_TYPE_APPLICATION) | 54 G_DEFINE_TYPE(PuiApplication, pui_application, G_TYPE_APPLICATION) |
54 | 55 |
55 enum { | 56 enum { |
56 PROP_0, | 57 PROP_0, |
57 PROP_UPDATE_COMMAND, | 58 PROP_UPDATE_COMMAND, |
59 PROP_ALWAYS_ACTIVE, | |
58 PROP_LAST | 60 PROP_LAST |
59 }; | 61 }; |
60 | 62 |
61 extern gboolean restart; | 63 extern gboolean restart; |
62 | 64 |
187 g_error_free(error); | 189 g_error_free(error); |
188 } | 190 } |
189 } | 191 } |
190 | 192 |
191 static void | 193 static void |
194 update_indicator(PuiApplication *self, const gchar *title) | |
195 { | |
196 switch (self->state) { | |
197 case PUI_STATE_INITIAL: | |
198 app_indicator_set_status(self->indicator, | |
199 APP_INDICATOR_STATUS_PASSIVE); | |
200 break; | |
201 case PUI_STATE_UP_TO_DATE: | |
202 app_indicator_set_status(self->indicator, self->always_active ? | |
203 APP_INDICATOR_STATUS_ACTIVE : | |
204 APP_INDICATOR_STATUS_PASSIVE); | |
205 break; | |
206 case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
207 case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
208 case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ | |
209 case PUI_STATE_SYSTEM_RESTART_REQUIRED: /* FALLTHGROUGH */ | |
210 case PUI_STATE_ERROR: | |
211 app_indicator_set_status(self->indicator, | |
212 APP_INDICATOR_STATUS_ACTIVE); | |
213 break; | |
214 } | |
215 app_indicator_set_icon_full(self->indicator, icon_names[self->state], | |
216 title); | |
217 } | |
218 | |
219 static void | |
220 update_notification(PuiApplication *self, const gchar *title, const gchar *body) | |
221 { | |
222 GSimpleAction *install_updates_action; | |
223 GApplication *application = G_APPLICATION(self); | |
224 GNotification *notification = NULL; | |
225 | |
226 install_updates_action = | |
227 G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(self), | |
228 "install-updates")); | |
229 | |
230 switch (self->state) { | |
231 case PUI_STATE_INITIAL: /* FALLTHGROUGH */ | |
232 case PUI_STATE_UP_TO_DATE: /* FALLTHGROUGH */ | |
233 case PUI_STATE_ERROR: | |
234 /* withdraw exisiting notification */ | |
235 g_application_withdraw_notification(application, | |
236 "package-updates-or-restart-required"); | |
237 break; | |
238 case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
239 case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
240 case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ | |
241 case PUI_STATE_SYSTEM_RESTART_REQUIRED: | |
242 /* create notification */ | |
243 notification = g_notification_new(title); | |
244 g_notification_set_body(notification, body); | |
245 g_notification_set_icon(notification, self->icons[self->state]); | |
246 g_notification_set_priority(notification, | |
247 G_NOTIFICATION_PRIORITY_NORMAL); | |
248 if (g_action_get_enabled(G_ACTION(install_updates_action))) { | |
249 g_notification_add_button(notification, | |
250 _("Install Updates"), | |
251 "app.install-updates"); | |
252 } | |
253 g_application_send_notification(application, | |
254 "package-updates-or-restart-required", notification); | |
255 break; | |
256 } | |
257 | |
258 if (notification != NULL) { | |
259 g_object_unref(notification); | |
260 } | |
261 } | |
262 | |
263 static void | |
192 update_ui(PuiApplication *self) | 264 update_ui(PuiApplication *self) |
193 { | 265 { |
194 GSimpleAction *install_updates_action; | 266 GSimpleAction *install_updates_action; |
195 guint important_updates = 0; | 267 guint important_updates = 0; |
196 guint normal_updates = 0; | 268 guint normal_updates = 0; |
197 gchar *title = NULL; | 269 gchar *title = NULL; |
198 gchar *body = NULL; | 270 gchar *body = NULL; |
199 GApplication *application = G_APPLICATION(self); | 271 GApplication *application = G_APPLICATION(self); |
200 GNotification *notification = NULL; | |
201 | 272 |
202 install_updates_action = | 273 install_updates_action = |
203 G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(self), | 274 G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(self), |
204 "install-updates")); | 275 "install-updates")); |
205 | 276 |
283 case PUI_STATE_ERROR: | 354 case PUI_STATE_ERROR: |
284 title = g_strdup(self->error_message); | 355 title = g_strdup(self->error_message); |
285 break; | 356 break; |
286 } | 357 } |
287 | 358 |
288 /* indicator */ | 359 update_indicator(self, title); |
289 switch (self->state) { | 360 update_notification(self, title, body); |
290 case PUI_STATE_INITIAL: | |
291 app_indicator_set_status(self->indicator, | |
292 APP_INDICATOR_STATUS_PASSIVE); | |
293 break; | |
294 case PUI_STATE_UP_TO_DATE: /* FALLTHGROUGH */ | |
295 case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
296 case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
297 case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ | |
298 case PUI_STATE_SYSTEM_RESTART_REQUIRED: /* FALLTHGROUGH */ | |
299 case PUI_STATE_ERROR: | |
300 app_indicator_set_status(self->indicator, | |
301 APP_INDICATOR_STATUS_ACTIVE); | |
302 break; | |
303 } | |
304 app_indicator_set_icon_full(self->indicator, icon_names[self->state], | |
305 title); | |
306 | |
307 /* notification */ | |
308 switch (self->state) { | |
309 case PUI_STATE_INITIAL: /* FALLTHGROUGH */ | |
310 case PUI_STATE_UP_TO_DATE: /* FALLTHGROUGH */ | |
311 case PUI_STATE_ERROR: | |
312 /* withdraw exisiting notification */ | |
313 g_application_withdraw_notification(application, | |
314 "package-updates-or-restart-required"); | |
315 break; | |
316 case PUI_STATE_NORMAL_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
317 case PUI_STATE_IMPORTANT_UPDATES_AVAILABLE: /* FALLTHGROUGH */ | |
318 case PUI_STATE_SESSION_RESTART_REQUIRED: /* FALLTHGROUGH */ | |
319 case PUI_STATE_SYSTEM_RESTART_REQUIRED: | |
320 /* create notification */ | |
321 notification = g_notification_new(title); | |
322 g_notification_set_body(notification, body); | |
323 g_notification_set_icon(notification, self->icons[self->state]); | |
324 g_notification_set_priority(notification, | |
325 G_NOTIFICATION_PRIORITY_NORMAL); | |
326 if (g_action_get_enabled(G_ACTION(install_updates_action))) { | |
327 g_notification_add_button(notification, | |
328 _("Install Updates"), | |
329 "app.install-updates"); | |
330 } | |
331 g_application_send_notification(application, | |
332 "package-updates-or-restart-required", notification); | |
333 break; | |
334 } | |
335 | |
336 if (notification != NULL) { | |
337 g_object_unref(notification); | |
338 } | |
339 | 361 |
340 g_debug("indicator icon: %s, notification title: \"%s\", " | 362 g_debug("indicator icon: %s, notification title: \"%s\", " |
341 "notification body: \"%s\"", icon_names[self->state], title, body); | 363 "notification body: \"%s\"", icon_names[self->state], title, body); |
342 | 364 |
343 g_free(body); | 365 g_free(body); |
476 /* load icons */ | 498 /* load icons */ |
477 for (i = 0; i < G_N_ELEMENTS(self->icons); i++) { | 499 for (i = 0; i < G_N_ELEMENTS(self->icons); i++) { |
478 self->icons[i] = g_themed_icon_new(icon_names[i]); | 500 self->icons[i] = g_themed_icon_new(icon_names[i]); |
479 } | 501 } |
480 | 502 |
481 /* create settings */ | 503 /* create settings backend */ |
482 self->settings = pui_settings_new(); | 504 self->settings = pui_settings_new(); |
483 g_settings_bind(self->settings, "update-command", self, | |
484 "update-command", G_SETTINGS_BIND_GET); | |
485 | 505 |
486 /* start instantiating backend */ | 506 /* start instantiating backend */ |
487 pui_backend_new_async(self->cancellable, on_pui_backend_finished, self); | 507 pui_backend_new_async(self->cancellable, on_pui_backend_finished, self); |
488 | 508 |
489 /* create indicator */ | 509 /* create indicator */ |
498 menu = GTK_WIDGET(gtk_builder_get_object(builder, "menu")); | 518 menu = GTK_WIDGET(gtk_builder_get_object(builder, "menu")); |
499 gtk_widget_insert_action_group(menu, "app", G_ACTION_GROUP(self)); | 519 gtk_widget_insert_action_group(menu, "app", G_ACTION_GROUP(self)); |
500 gtk_widget_show_all(menu); | 520 gtk_widget_show_all(menu); |
501 app_indicator_set_menu(self->indicator, GTK_MENU(menu)); | 521 app_indicator_set_menu(self->indicator, GTK_MENU(menu)); |
502 | 522 |
523 /* | |
524 * bind settings to properties after indicator with its menu are | |
525 * initialized, if the setting "always-active" is set by the user the | |
526 * corresponding property is set accordingly which in turn invokes | |
527 * update_ui() so order matters here | |
528 */ | |
529 g_settings_bind(self->settings, "update-command", self, | |
530 "update-command", G_SETTINGS_BIND_GET); | |
531 g_settings_bind(self->settings, "always-active", self, | |
532 "always-active", G_SETTINGS_BIND_GET); | |
533 | |
534 /* ensure the ui reflects the current state */ | |
503 update_ui(self); | 535 update_ui(self); |
504 | 536 |
505 /* keep GApplication running */ | 537 /* keep GApplication running */ |
506 g_application_hold(application); | 538 g_application_hold(application); |
507 | 539 |
601 g_free(self->update_command); | 633 g_free(self->update_command); |
602 self->update_command = g_value_dup_string(value); | 634 self->update_command = g_value_dup_string(value); |
603 g_debug("property \"update-command\" set to \"%s\"", | 635 g_debug("property \"update-command\" set to \"%s\"", |
604 self->update_command); | 636 self->update_command); |
605 break; | 637 break; |
638 case PROP_ALWAYS_ACTIVE: | |
639 self->always_active = g_value_get_boolean(value); | |
640 g_debug("property \"always-active\" set to \"%s\"", | |
641 self->always_active ? "TRUE" : "FALSE"); | |
642 update_ui(self); | |
643 break; | |
606 default: | 644 default: |
607 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); | 645 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); |
608 break; | 646 break; |
609 } | 647 } |
610 } | 648 } |
617 | 655 |
618 switch (property_id) { | 656 switch (property_id) { |
619 case PROP_UPDATE_COMMAND: | 657 case PROP_UPDATE_COMMAND: |
620 g_value_set_string(value, self->update_command); | 658 g_value_set_string(value, self->update_command); |
621 break; | 659 break; |
660 case PROP_ALWAYS_ACTIVE: | |
661 g_value_set_boolean(value, self->always_active); | |
662 break; | |
622 default: | 663 default: |
623 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); | 664 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); |
624 break; | 665 break; |
625 } | 666 } |
626 } | 667 } |
648 if (self->indicator != NULL) { | 689 if (self->indicator != NULL) { |
649 g_clear_object(&self->indicator); | 690 g_clear_object(&self->indicator); |
650 } | 691 } |
651 | 692 |
652 if (self->about_dialog != NULL) { | 693 if (self->about_dialog != NULL) { |
653 g_clear_pointer(&self->about_dialog, | 694 g_clear_pointer(&self->about_dialog, gtk_widget_destroy); |
654 (GDestroyNotify)(gtk_widget_destroy)); | |
655 } | 695 } |
656 | 696 |
657 for (i = 0; i < G_N_ELEMENTS(self->icons); i++) { | 697 for (i = 0; i < G_N_ELEMENTS(self->icons); i++) { |
658 if (self->icons[i] != NULL) { | 698 if (self->icons[i] != NULL) { |
659 g_clear_object(&self->icons[i]); | 699 g_clear_object(&self->icons[i]); |
686 object_class->finalize = pui_application_finalize; | 726 object_class->finalize = pui_application_finalize; |
687 | 727 |
688 properties[PROP_UPDATE_COMMAND] = g_param_spec_string("update-command", | 728 properties[PROP_UPDATE_COMMAND] = g_param_spec_string("update-command", |
689 "Update command", "Command for installing updates", NULL, | 729 "Update command", "Command for installing updates", NULL, |
690 G_PARAM_READWRITE); | 730 G_PARAM_READWRITE); |
731 properties[PROP_ALWAYS_ACTIVE] = g_param_spec_boolean("always-active", | |
732 "Whether the indicator is always active", | |
733 "Whether the indicator is active even when packages are up to date", | |
734 TRUE, G_PARAM_READWRITE); | |
691 | 735 |
692 g_object_class_install_properties(object_class, PROP_LAST, properties); | 736 g_object_class_install_properties(object_class, PROP_LAST, properties); |
693 | 737 |
694 application_class->startup = pui_application_startup; | 738 application_class->startup = pui_application_startup; |
695 application_class->shutdown = pui_application_shutdown; | 739 application_class->shutdown = pui_application_shutdown; |