aboutsummaryrefslogtreecommitdiff
path: root/src/indicator-printers-menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/indicator-printers-menu.c')
-rw-r--r--src/indicator-printers-menu.c136
1 files changed, 112 insertions, 24 deletions
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 <gio/gio.h>
#include <cups/cups.h>
+#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);
}