[gnome-settings-daemon/412-do-not-notify-print-jobs] print-notifications: Allow ignoring of events for print jobs



commit bba7024cb63a34da0ba077ba6cc8ba32fdf71404
Author: Marek Kasik <mkasik redhat com>
Date:   Fri May 24 16:29:02 2019 +0200

    print-notifications: Allow ignoring of events for print jobs
    
    Adds DBus interface for ignoring of events related to print jobs.
    There is DBus method DoNotNotifyJob which takes job id
    and ignored events as parameters. If a job with the id is processed
    then the plugin checks whether the current event should be ignored
    from the notification point of view.
    
    The interface stores the ginored events as flags which values
    are determined as "1 << value" where value comes from ipp_jstate_t
    enum. Its values ranges from 3 to 9 so they fit into the 64 bits
    of the uint64. This allow us to ignore more events at once
    but this is not used yet.
    
    Fixes #412

 .../gsd-print-notifications-manager.c              | 287 +++++++++++++++++----
 1 file changed, 234 insertions(+), 53 deletions(-)
---
diff --git a/plugins/print-notifications/gsd-print-notifications-manager.c 
b/plugins/print-notifications/gsd-print-notifications-manager.c
index 53aaccff..6735110f 100644
--- a/plugins/print-notifications/gsd-print-notifications-manager.c
+++ b/plugins/print-notifications/gsd-print-notifications-manager.c
@@ -44,6 +44,14 @@
 #define CUPS_DBUS_PATH      "/org/cups/cupsd/Notifier"
 #define CUPS_DBUS_INTERFACE "org.cups.cupsd.Notifier"
 
+#define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
+#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
+#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon"
+
+#define GSD_PRINT_NOTIFICATIONS_DBUS_NAME         GSD_DBUS_NAME ".PrintNotifications"
+#define GSD_PRINT_NOTIFICATIONS_DBUS_PATH         GSD_DBUS_PATH "/PrintNotifications"
+#define GSD_PRINT_NOTIFICATIONS_DBUS_INTERFACE    GSD_DBUS_BASE_INTERFACE ".PrintNotifications"
+
 #define RENEW_INTERVAL                   3500
 #define SUBSCRIPTION_DURATION            3600
 #define CONNECTING_TIMEOUT               60
@@ -73,11 +81,26 @@ ippNextAttribute (ipp_t *ipp)
 }
 #endif
 
+/*
+ * Ignored events for print jobs are stored as "1 << value"
+ * where the value is from ipp_jstate_t enum which ranges from 3 to 9.
+ */
+static const gchar introspection_xml[] =
+"<node>"
+"  <interface name='org.gnome.SettingsDaemon.PrintNotifications'>"
+"    <method name='DoNotNotifyJob'>"
+"      <arg name='job-id'         direction='in' type='i'/>"
+"      <arg name='ignored-events' direction='in' type='t'/>"
+"    </method>"
+"  </interface>"
+"</node>";
+
 struct _GsdPrintNotificationsManager
 {
         GObject                       parent;
 
         GDBusConnection              *cups_bus_connection;
+        GDBusConnection              *session_bus_connection;
         gint                          subscription_id;
         cups_dest_t                  *dests;
         gint                          num_dests;
@@ -93,6 +116,10 @@ struct _GsdPrintNotificationsManager
         gint                          last_notify_sequence_number;
         guint                         start_idle_id;
         GList                        *held_jobs;
+
+        guint                         name_id;
+        GDBusNodeInfo                *introspection_data;
+        GList                        *ignored_jobs;
 };
 
 static void     gsd_print_notifications_manager_class_init  (GsdPrintNotificationsManagerClass *klass);
@@ -557,6 +584,38 @@ check_job_for_authentication (gpointer userdata)
         return G_SOURCE_REMOVE;
 }
 
+struct
+{
+        gint    job_id;
+        guint64 ignored_events;
+} typedef TIgnoredJob;
+
+static TIgnoredJob *
+find_ignored_job (GsdPrintNotificationsManager *manager,
+                  gint                          job_id)
+{
+        TIgnoredJob *ignored_job = NULL;
+        GList       *iter;
+
+        for (iter = manager->ignored_jobs; iter != NULL; iter = iter->next) {
+                if (((TIgnoredJob *) iter->data)->job_id == job_id) {
+                        ignored_job = (TIgnoredJob *) iter->data;
+                }
+        }
+
+        return ignored_job;
+}
+
+static void
+remove_ignored_job (GsdPrintNotificationsManager *manager,
+                    TIgnoredJob                  *ignored_job)
+{
+        if (ignored_job != NULL) {
+                manager->ignored_jobs = g_list_remove (manager->ignored_jobs, ignored_job);
+                g_free (ignored_job);
+        }
+}
+
 static void
 process_cups_notification (GsdPrintNotificationsManager *manager,
                            const char                   *notify_subscribed_event,
@@ -573,6 +632,7 @@ process_cups_notification (GsdPrintNotificationsManager *manager,
                            gint                          job_impressions_completed)
 {
         ipp_attribute_t *attr;
+        TIgnoredJob     *ignored_job = NULL;
         gboolean         my_job = FALSE;
         gboolean         known_reason;
         HeldJob         *held_job;
@@ -657,6 +717,8 @@ process_cups_notification (GsdPrintNotificationsManager *manager,
                         g_free (job_uri);
                         httpClose (http);
                 }
+
+                ignored_job = find_ignored_job (manager, notify_job_id);
         }
 
         if (g_strcmp0 (notify_subscribed_event, "printer-added") == 0) {
@@ -683,72 +745,102 @@ process_cups_notification (GsdPrintNotificationsManager *manager,
                         case IPP_JOB_PROCESSING:
                                 break;
                         case IPP_JOB_STOPPED:
-                                /* Translators: A print job has been stopped */
-                                primary_text = g_strdup (C_("print job state", "Printing stopped"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_STOPPED))) {
+                                        /* Translators: A print job has been stopped */
+                                        primary_text = g_strdup (C_("print job state", "Printing stopped"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                }
                                 break;
                         case IPP_JOB_CANCELED:
-                                /* Translators: A print job has been canceled */
-                                primary_text = g_strdup (C_("print job state", "Printing canceled"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_CANCELED))) {
+                                        /* Translators: A print job has been canceled */
+                                        primary_text = g_strdup (C_("print job state", "Printing canceled"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                } else {
+                                        remove_ignored_job (manager, ignored_job);
+                                }
                                 break;
                         case IPP_JOB_ABORTED:
-                                /* Translators: A print job has been aborted */
-                                primary_text = g_strdup (C_("print job state", "Printing aborted"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_ABORTED))) {
+                                        /* Translators: A print job has been aborted */
+                                        primary_text = g_strdup (C_("print job state", "Printing aborted"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                } else {
+                                        remove_ignored_job (manager, ignored_job);
+                                }
                                 break;
                         case IPP_JOB_COMPLETED:
-                                /* Translators: A print job has been completed */
-                                primary_text = g_strdup (C_("print job state", "Printing completed"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_COMPLETED))) {
+                                        /* Translators: A print job has been completed */
+                                        primary_text = g_strdup (C_("print job state", "Printing 
completed"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                } else {
+                                        remove_ignored_job (manager, ignored_job);
+                                }
                                 break;
                 }
         } else if (g_strcmp0 (notify_subscribed_event, "job-state-changed") == 0 && my_job) {
                 switch (job_state) {
                         case IPP_JOB_PROCESSING:
-                                g_hash_table_insert (manager->printing_printers,
-                                                     g_strdup (printer_name), NULL);
-
-                                /* Translators: A job is printing */
-                                primary_text = g_strdup (C_("print job state", "Printing"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_PROCESSING))) {
+                                        g_hash_table_insert (manager->printing_printers,
+                                                             g_strdup (printer_name), NULL);
+
+                                        /* Translators: A job is printing */
+                                        primary_text = g_strdup (C_("print job state", "Printing"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                }
                                 break;
                         case IPP_JOB_STOPPED:
-                                g_hash_table_remove (manager->printing_printers,
-                                                     printer_name);
-                                /* Translators: A print job has been stopped */
-                                primary_text = g_strdup (C_("print job state", "Printing stopped"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_STOPPED))) {
+                                        g_hash_table_remove (manager->printing_printers,
+                                                             printer_name);
+                                        /* Translators: A print job has been stopped */
+                                        primary_text = g_strdup (C_("print job state", "Printing stopped"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                }
                                 break;
                         case IPP_JOB_CANCELED:
-                                g_hash_table_remove (manager->printing_printers,
-                                                     printer_name);
-                                /* Translators: A print job has been canceled */
-                                primary_text = g_strdup (C_("print job state", "Printing canceled"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_CANCELED))) {
+                                        g_hash_table_remove (manager->printing_printers,
+                                                             printer_name);
+                                        /* Translators: A print job has been canceled */
+                                        primary_text = g_strdup (C_("print job state", "Printing canceled"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                } else {
+                                        remove_ignored_job (manager, ignored_job);
+                                }
                                 break;
                         case IPP_JOB_ABORTED:
-                                g_hash_table_remove (manager->printing_printers,
-                                                     printer_name);
-                                /* Translators: A print job has been aborted */
-                                primary_text = g_strdup (C_("print job state", "Printing aborted"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_ABORTED))) {
+                                        g_hash_table_remove (manager->printing_printers,
+                                                             printer_name);
+                                        /* Translators: A print job has been aborted */
+                                        primary_text = g_strdup (C_("print job state", "Printing aborted"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                } else {
+                                        remove_ignored_job (manager, ignored_job);
+                                }
                                 break;
                         case IPP_JOB_COMPLETED:
-                                g_hash_table_remove (manager->printing_printers,
-                                                     printer_name);
-                                /* Translators: A print job has been completed */
-                                primary_text = g_strdup (C_("print job state", "Printing completed"));
-                                /* Translators: "print-job xy" on a printer */
-                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_COMPLETED))) {
+                                        g_hash_table_remove (manager->printing_printers,
+                                                             printer_name);
+                                        /* Translators: A print job has been completed */
+                                        primary_text = g_strdup (C_("print job state", "Printing 
completed"));
+                                        /* Translators: "print-job xy" on a printer */
+                                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), 
job_name, printer_name);
+                                } else {
+                                        remove_ignored_job (manager, ignored_job);
+                                }
                                 break;
                         case IPP_JOB_HELD:
                                 held_job = g_new (HeldJob, 1);
@@ -766,13 +858,15 @@ process_cups_notification (GsdPrintNotificationsManager *manager,
                 }
         } else if (g_strcmp0 (notify_subscribed_event, "job-created") == 0 && my_job) {
                 if (job_state == IPP_JOB_PROCESSING) {
-                        g_hash_table_insert (manager->printing_printers,
-                                             g_strdup (printer_name), NULL);
+                        if (ignored_job == NULL || !(ignored_job->ignored_events & (1 << 
IPP_JOB_PROCESSING))) {
+                                g_hash_table_insert (manager->printing_printers,
+                                                     g_strdup (printer_name), NULL);
 
-                        /* Translators: A job is printing */
-                        primary_text = g_strdup (C_("print job state", "Printing"));
-                        /* Translators: "print-job xy" on a printer */
-                        secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                                /* Translators: A job is printing */
+                                primary_text = g_strdup (C_("print job state", "Printing"));
+                                /* Translators: "print-job xy" on a printer */
+                                secondary_text = g_strdup_printf (C_("print job", "“%s” on %s"), job_name, 
printer_name);
+                        }
                 }
         } else if (g_strcmp0 (notify_subscribed_event, "printer-state-changed") == 0) {
                 cups_dest_t  *dest = NULL;
@@ -1514,6 +1608,73 @@ gsd_print_notifications_manager_got_dbus_connection (GObject      *source_object
         }
 }
 
+static void
+handle_method_call (GDBusConnection       *connection,
+                    const gchar           *sender,
+                    const gchar           *object_path,
+                    const gchar           *interface_name,
+                    const gchar           *method_name,
+                    GVariant              *parameters,
+                    GDBusMethodInvocation *invocation,
+                    gpointer               user_data)
+{
+        GsdPrintNotificationsManager *manager = GSD_PRINT_NOTIFICATIONS_MANAGER (user_data);
+
+        if (g_strcmp0 (method_name, "DoNotNotifyJob") == 0) {
+                TIgnoredJob *ignored_job;
+                guint64      events = 0;
+                gint         job_id = 0;
+
+                g_variant_get (parameters, "(it)", &job_id, &events);
+
+                if (job_id > 0 && events > 0) {
+                        ignored_job = g_new (TIgnoredJob, 1);
+                        ignored_job->job_id = job_id;
+                        ignored_job->ignored_events = events;
+                        manager->ignored_jobs = g_list_prepend (manager->ignored_jobs, ignored_job);
+                }
+
+                g_dbus_method_invocation_return_value (invocation, NULL);
+        } else {
+                g_assert_not_reached ();
+        }
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+        handle_method_call,
+        NULL,
+        NULL
+};
+
+static void
+gsd_print_notifications_manager_got_session_dbus_connection (GObject      *source_object,
+                                                             GAsyncResult *res,
+                                                             gpointer      user_data)
+{
+        GsdPrintNotificationsManager *manager = (GsdPrintNotificationsManager *) user_data;
+        GError                       *error = NULL;
+
+        manager->session_bus_connection = g_bus_get_finish (res, &error);
+        if (manager->session_bus_connection != NULL) {
+                g_dbus_connection_register_object (manager->session_bus_connection,
+                                                   GSD_PRINT_NOTIFICATIONS_DBUS_PATH,
+                                                   manager->introspection_data->interfaces[0],
+                                                   &interface_vtable,
+                                                   manager,
+                                                   NULL,
+                                                   NULL);
+
+                manager->name_id = g_bus_own_name_on_connection (manager->session_bus_connection,
+                                                                 GSD_PRINT_NOTIFICATIONS_DBUS_NAME,
+                                                                 G_BUS_NAME_OWNER_FLAGS_NONE,
+                                                                 NULL, NULL, NULL, NULL);
+        } else {
+                g_warning ("Connection to message bus failed: %s", error->message);
+                g_error_free (error);
+        }
+}
+
 static gboolean
 gsd_print_notifications_manager_start_idle (gpointer data)
 {
@@ -1523,6 +1684,11 @@ gsd_print_notifications_manager_start_idle (gpointer data)
 
         manager->printing_printers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
+        g_bus_get (G_BUS_TYPE_SESSION,
+                   NULL,
+                   gsd_print_notifications_manager_got_session_dbus_connection,
+                   data);
+
         /*
          * Set a password callback which cancels authentication
          * before we prepare a correct solution (see bug #725440).
@@ -1569,6 +1735,10 @@ gsd_print_notifications_manager_start (GsdPrintNotificationsManager *manager,
         manager->cups_connection_timeout_id = 0;
         manager->last_notify_sequence_number = -1;
         manager->held_jobs = NULL;
+        manager->ignored_jobs = NULL;
+        manager->session_bus_connection = NULL;
+        manager->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+        g_assert (manager->introspection_data != NULL);
 
         manager->start_idle_id = g_idle_add (gsd_print_notifications_manager_start_idle, manager);
         g_source_set_name_by_id (manager->start_idle_id, "[gnome-settings-daemon] 
gsd_print_notifications_manager_start_idle");
@@ -1588,6 +1758,17 @@ gsd_print_notifications_manager_stop (GsdPrintNotificationsManager *manager)
 
         g_debug ("Stopping print-notifications manager");
 
+        if (manager->name_id != 0) {
+                g_bus_unown_name (manager->name_id);
+                manager->name_id = 0;
+        }
+
+        g_clear_object (&manager->session_bus_connection);
+
+        g_clear_pointer (&manager->introspection_data, g_dbus_node_info_unref);
+
+        g_list_free_full (manager->ignored_jobs, g_free);
+
         cupsFreeDests (manager->num_dests, manager->dests);
         manager->num_dests = 0;
         manager->dests = NULL;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]