From 0d7de7c0cd1b2d9939bbaabe9c93e4d86f2018ad Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 2 Feb 2012 15:49:11 +0100 Subject: Listen to cups dbus messages to update menu when jobs are added / done --- .bzrignore | 1 + src/Makefile.am | 18 ++++- src/indicator-printers-menu.c | 136 ++++++++++++++++++++++++++++++------- src/org.cups.cupsd.Notifier.xml | 147 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 25 deletions(-) create mode 100644 src/org.cups.cupsd.Notifier.xml diff --git a/.bzrignore b/.bzrignore index e54d376..8c71946 100644 --- a/.bzrignore +++ b/.bzrignore @@ -25,4 +25,5 @@ src/Makefile.in src/indicator-printers-service src/*.la src/*.lo +src/cups-notifier.[ch] diff --git a/src/Makefile.am b/src/Makefile.am index 5684e70..7b66b1b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,13 +12,29 @@ libprintersmenu_la_LIBADD = $(APPLET_LIBS) libprintersmenu_la_LDFLAGS = -module -avoid-version +cups_notifier_sources = \ + cups-notifier.c \ + cups-notifier.h + +$(cups_notifier_sources): org.cups.cupsd.Notifier.xml + gdbus-codegen \ + --interface-prefix org.cups.cupsd \ + --c-namespace Cups \ + --generate-c-code cups-notifier \ + $^ + + libexec_PROGRAMS = indicator-printers-service indicator_printers_service_SOURCES = \ indicator-printers-service.c \ indicator-printers-service.h \ indicator-printers-menu.c \ - indicator-printers-menu.h + indicator-printers-menu.h \ + $(cups_notifier_sources) indicator_printers_service_CPPFLAGS = $(SERVICE_CFLAGS) indicator_printers_service_LDADD = $(SERVICE_LIBS) + +BUILT_SOURCES = $(cups_notifier_sources) + diff --git a/src/indicator-printers-menu.c b/src/indicator-printers-menu.c index e0cfd4b..8aa4c62 100644 --- a/src/indicator-printers-menu.c +++ b/src/indicator-printers-menu.c @@ -4,6 +4,8 @@ #include #include +#include "cups-notifier.h" + G_DEFINE_TYPE (IndicatorPrintersMenu, indicator_printers_menu, G_TYPE_OBJECT) @@ -15,6 +17,7 @@ struct _IndicatorPrintersMenuPrivate { DbusmenuMenuitem *root; GHashTable *printers; /* printer name -> dbusmenuitem */ + CupsNotifier *cups_notifier; }; @@ -29,6 +32,7 @@ dispose (GObject *object) } g_clear_object (&priv->root); + g_clear_object (&priv->cups_notifier); G_OBJECT_CLASS (indicator_printers_menu_parent_class)->dispose (object); } @@ -45,6 +49,19 @@ indicator_printers_menu_class_init (IndicatorPrintersMenuClass *klass) } +static int +get_number_of_active_jobs (const gchar *printer) +{ + int njobs; + cups_job_t *jobs; + + njobs = cupsGetJobs (&jobs, printer, 1, CUPS_WHICHJOBS_ACTIVE); + cupsFreeJobs (njobs, jobs); + + return njobs; +} + + static void show_system_settings (DbusmenuMenuitem *menuitem, guint timestamp, @@ -79,19 +96,35 @@ show_system_settings (DbusmenuMenuitem *menuitem, g_object_unref (appinfo); } + static void -add_printer_menuitem (IndicatorPrintersMenu *self, - const char *printer, - int state, - int njobs) +update_printer_menuitem (IndicatorPrintersMenu *self, + const char *printer, + int state, + int njobs) { IndicatorPrintersMenuPrivate *priv = PRINTERS_MENU_PRIVATE (self); DbusmenuMenuitem *item; - item = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (item, "type", "indicator-item"); - dbusmenu_menuitem_property_set (item, "indicator-icon-name", "printer"); - dbusmenu_menuitem_property_set (item, "indicator-label", printer); + item = g_hash_table_lookup (priv->printers, printer); + + if (!item) { + item = dbusmenu_menuitem_new (); + dbusmenu_menuitem_property_set (item, "type", "indicator-item"); + dbusmenu_menuitem_property_set (item, "indicator-icon-name", "printer"); + g_signal_connect_data (item, "item-activated", + G_CALLBACK (show_system_settings), + g_strdup (printer), (GClosureNotify) g_free, 0); + + dbusmenu_menuitem_child_append(priv->root, item); + g_hash_table_insert (priv->printers, g_strdup (printer), item); + } + + if (njobs == 0) { + dbusmenu_menuitem_property_set_bool (item, "visible", FALSE); + return; + } + dbusmenu_menuitem_property_set_bool (item, "visible", TRUE); switch (state) { @@ -108,13 +141,49 @@ add_printer_menuitem (IndicatorPrintersMenu *self, break; } } +} + + +static void +update_job (CupsNotifier *cups_notifier, + const gchar *text, + const gchar *printer_uri, + const gchar *printer_name, + guint printer_state, + const gchar *printer_state_reasons, + gboolean printer_is_accepting_jobs, + guint job_id, + guint job_state, + const gchar *job_state_reasons, + const gchar *job_name, + guint job_impressions_completed, + gpointer user_data) +{ + IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (user_data); + + update_printer_menuitem (self, + printer_name, + printer_state, + get_number_of_active_jobs (printer_name)); +} + - g_signal_connect_data (item, "item-activated", - G_CALLBACK (show_system_settings), - g_strdup (printer), (GClosureNotify) g_free, 0); +static void +on_printer_state_changed (CupsNotifier *object, + const gchar *text, + const gchar *printer_uri, + const gchar *printer_name, + guint printer_state, + const gchar *printer_state_reasons, + gboolean printer_is_accepting_jobs, + gpointer user_data) +{ + IndicatorPrintersMenu *self = INDICATOR_PRINTERS_MENU (user_data); - dbusmenu_menuitem_child_append(priv->root, item); - g_hash_table_insert (priv->printers, g_strdup (printer), item); + update_printer_menuitem (self, + printer_name, + printer_state, + get_number_of_active_jobs (printer_name)); } @@ -122,9 +191,9 @@ static void indicator_printers_menu_init (IndicatorPrintersMenu *self) { IndicatorPrintersMenuPrivate *priv = PRINTERS_MENU_PRIVATE (self); - int ndests, njobs, i, state; + int ndests, i; cups_dest_t *dests; - cups_job_t *jobs; + GError *error = NULL; priv->root = dbusmenu_menuitem_new (); @@ -133,18 +202,37 @@ indicator_printers_menu_init (IndicatorPrintersMenu *self) g_free, g_object_unref); + priv->cups_notifier = cups_notifier_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + 0, + NULL, + "/org/cups/cupsd/Notifier", + NULL, + &error); + if (error) { + g_warning ("Error creating cups notify handler: %s", error->message); + g_clear_error (&error); + } + else { + g_signal_connect (priv->cups_notifier, "job-created", + G_CALLBACK (update_job), self); + g_signal_connect (priv->cups_notifier, "job-state", + G_CALLBACK (update_job), self); + g_signal_connect (priv->cups_notifier, "job-completed", + G_CALLBACK (update_job), self); + g_signal_connect (priv->cups_notifier, "printer-state-changed", + G_CALLBACK (on_printer_state_changed), self); + } + /* create initial menu items */ ndests = cupsGetDests (&dests); for (i = 0; i < ndests; i++) { - njobs = cupsGetJobs (&jobs, dests[i].name, 1, CUPS_WHICHJOBS_ACTIVE); - state = atoi (cupsGetOption ("printer-state", - dests[i].num_options, - dests[i].options)); - - if (njobs > 0) - add_printer_menuitem (self, dests[i].name, state, njobs); - - cupsFreeJobs (njobs, jobs); + int state = atoi (cupsGetOption ("printer-state", + dests[i].num_options, + dests[i].options)); + update_printer_menuitem (self, + dests[i].name, + state, + get_number_of_active_jobs (dests[i].name)); } cupsFreeDests (ndests, dests); } diff --git a/src/org.cups.cupsd.Notifier.xml b/src/org.cups.cupsd.Notifier.xml new file mode 100644 index 0000000..e70a5c3 --- /dev/null +++ b/src/org.cups.cupsd.Notifier.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3