[gnome-software/wip/launcher: 5/7] Add update monitoring



commit 8955fa31561d4fcd659538e0b8237e20f90ea0cb
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Sep 15 22:19:20 2013 -0400

    Add update monitoring
    
    Move some of the g-s-d updates plugin functionality over here.
    
    The service is now monitoring available offline updates itself,
    and notifies about them.

 src/Makefile.am         |    2 +
 src/gs-application.c    |   23 ++++--
 src/gs-update-monitor.c |  191 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gs-update-monitor.h |   47 ++++++++++++
 4 files changed, 257 insertions(+), 6 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 1150028..bd4c0eb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -96,6 +96,8 @@ gnome_software_service_SOURCES =                      \
        gs-shell-updates.h                              \
        gs-shell-search.c                               \
        gs-shell-search.h                               \
+       gs-update-monitor.c                             \
+       gs-update-monitor.h                             \
        gs-plugin-loader.c                              \
        gs-plugin-loader.h                              \
        gs-plugin-loader-sync.c                         \
diff --git a/src/gs-application.c b/src/gs-application.c
index 186ebc4..422fb6d 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -31,17 +31,19 @@
 
 #include "gs-box.h"
 #include "gs-shell.h"
+#include "gs-update-monitor.h"
 #include "gs-plugin-loader.h"
 
 struct _GsApplication {
        GtkApplication parent;
 
-       GCancellable        *cancellable;
-       GtkApplication    *application;
-       GtkCssProvider    *provider;
-       GsPluginLoader    *plugin_loader;
-       gint                 pending_apps;
-       GsShell          *shell;
+       GCancellable    *cancellable;
+       GtkApplication  *application;
+       GtkCssProvider  *provider;
+       GsPluginLoader  *plugin_loader;
+       gint             pending_apps;
+       GsShell         *shell;
+       GsUpdateMonitor *monitor;
 };
 
 struct _GsApplicationClass {
@@ -56,6 +58,12 @@ gs_application_init (GsApplication *application)
 }
 
 static void
+gs_application_monitor_updates (GsApplication *app)
+{
+       app->monitor = gs_update_monitor_new (app);
+}
+
+static void
 gs_application_initialize_ui (GsApplication *app)
 {
        static gboolean initialized = FALSE;
@@ -246,6 +254,8 @@ gs_application_startup (GApplication *application)
        g_action_map_add_action_entries (G_ACTION_MAP (application),
                                         actions, G_N_ELEMENTS (actions),
                                         application);
+
+       gs_application_monitor_updates (GS_APPLICATION (application));
 }
 
 static void
@@ -263,6 +273,7 @@ gs_application_finalize (GObject *object)
        g_clear_object (&app->cancellable);
        g_clear_object (&app->shell);
        g_clear_object (&app->provider);
+       g_clear_object (&app->monitor);
 
        G_OBJECT_CLASS (gs_application_parent_class)->finalize (object);
 }
diff --git a/src/gs-update-monitor.c b/src/gs-update-monitor.c
new file mode 100644
index 0000000..4e20d16
--- /dev/null
+++ b/src/gs-update-monitor.c
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n.h>
+#include <libnotify/notify.h>
+
+#include "gs-update-monitor.h"
+
+#define GSD_UPDATES_ICON_NORMAL "software-update-available-symbolic"
+
+struct _GsUpdateMonitor {
+       GObject          parent;
+
+       GsApplication   *application;
+       GFile           *offline_update_file;
+       GFileMonitor    *offline_update_monitor;
+       gboolean         offline_update_notified;
+};
+
+struct _GsUpdateMonitorClass {
+       GObjectClass     parent_class;
+};
+
+G_DEFINE_TYPE (GsUpdateMonitor, gs_update_monitor, G_TYPE_OBJECT)
+
+static void
+offline_update_action_cb (NotifyNotification *notification,
+                         gchar              *action,
+                         gpointer            user_data)
+{
+       GsUpdateMonitor *monitor = user_data;
+
+       notify_notification_close (notification, NULL);
+
+       if (g_strcmp0 (action, "view") == 0) {
+               g_action_group_activate_action (G_ACTION_GROUP (monitor->application),
+                                               "set-mode",
+                                               g_variant_new_string ("updates"));
+       }
+}
+
+static gboolean
+reenable_offline_update (gpointer data)
+{
+       GsUpdateMonitor *monitor = data;
+
+       monitor->offline_update_notified = FALSE;
+
+       return G_SOURCE_REMOVE;
+}
+
+static void
+on_notification_closed (NotifyNotification *notification, gpointer data)
+{
+       g_object_unref (notification);
+}
+
+static void
+notify_offline_update_available (GsUpdateMonitor *monitor)
+{
+       NotifyNotification *notification;
+       const gchar *title;
+       const gchar *body;
+       gboolean ret;
+       GError *error = NULL;
+
+       if (!g_file_query_exists (monitor->offline_update_file, NULL))
+               return;
+
+       if (monitor->offline_update_notified)
+               return;
+
+       monitor->offline_update_notified = TRUE;
+
+       /* don't notify more often than every 5 minutes */
+       g_timeout_add_seconds (300, reenable_offline_update, monitor);
+
+       title = _("Software Updates available");
+       body = _("Important OS and application updates are ready to be installed");
+       notification = notify_notification_new (title, body,
+                                               GSD_UPDATES_ICON_NORMAL);
+       notify_notification_set_hint_string (notification, "desktop-entry", "gnome-software");
+       notify_notification_set_timeout (notification, NOTIFY_EXPIRES_NEVER);
+       notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
+       notify_notification_add_action (notification, "ignore",
+                                       /* TRANSLATORS: don't install updates now */
+                                       _("Not Now"),
+                                       offline_update_action_cb,
+                                       monitor, NULL);
+       notify_notification_add_action (notification, "view",
+                                               /* TRANSLATORS: view available updates */
+                                       _("View"),
+                                       offline_update_action_cb,
+                                       monitor, NULL);
+       g_signal_connect (notification, "closed",
+                         G_CALLBACK (on_notification_closed), NULL);
+       ret = notify_notification_show (notification, &error);
+       if (!ret) {
+               g_warning ("error: %s", error->message);
+               g_error_free (error);
+       }
+}
+
+static void
+offline_update_cb (GFileMonitor      *file_monitor,
+                  GFile             *file,
+                  GFile             *other_file,
+                  GFileMonitorEvent  event_type,
+                  GsUpdateMonitor   *monitor)
+{
+       notify_offline_update_available (monitor);
+}
+
+static gboolean
+initial_offline_update_check (gpointer data)
+{
+       GsUpdateMonitor *monitor = data;
+
+        notify_offline_update_available (monitor);
+
+        return G_SOURCE_REMOVE;
+}
+
+static void
+gs_update_monitor_init (GsUpdateMonitor *monitor)
+{
+       monitor->offline_update_file = g_file_new_for_path ("/var/lib/PackageKit/prepared-update");
+       monitor->offline_update_monitor = g_file_monitor_file (monitor->offline_update_file, 0, NULL, NULL);
+
+       g_signal_connect (monitor->offline_update_monitor, "changed",
+                         G_CALLBACK (offline_update_cb), monitor);
+
+       g_timeout_add_seconds (300,
+                              initial_offline_update_check,
+                              monitor);
+}
+
+static void
+gs_update_monitor_finalize (GObject *object)
+{
+       GsUpdateMonitor *monitor = GS_UPDATE_MONITOR (object);
+
+       g_clear_object (&monitor->offline_update_file);
+       g_clear_object (&monitor->offline_update_monitor);
+       g_application_release (G_APPLICATION (monitor->application));
+
+       G_OBJECT_CLASS (gs_update_monitor_parent_class)->finalize (object);
+}
+
+static void
+gs_update_monitor_class_init (GsUpdateMonitorClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       object_class->finalize = gs_update_monitor_finalize;
+}
+
+GsUpdateMonitor *
+gs_update_monitor_new (GsApplication *application)
+{
+       GsUpdateMonitor *monitor;
+
+       monitor = GS_UPDATE_MONITOR (g_object_new (GS_TYPE_UPDATE_MONITOR, NULL));
+       monitor->application = application;
+       g_application_hold (G_APPLICATION (application));
+
+       return monitor;
+}
+
+/* vim: set noexpandtab: */
diff --git a/src/gs-update-monitor.h b/src/gs-update-monitor.h
new file mode 100644
index 0000000..3ecf7fe
--- /dev/null
+++ b/src/gs-update-monitor.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GS_UPDATE_MONITOR_H
+#define __GS_UPDATE_MONITOR_H
+
+#include <glib-object.h>
+#include "gs-application.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_UPDATE_MONITOR         (gs_update_monitor_get_type ())
+#define GS_UPDATE_MONITOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GS_TYPE_UPDATE_MONITOR, 
GsUpdateMonitor))
+#define GS_UPDATE_MONITOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GS_TYPE_UPDATE_MONITOR, 
GsUpdateMonitorClass))
+#define GS_IS_UPDATE_MONITOR(o)                (G_TYPE_CHECK_INSTANCE_TYPE ((o), GS_TYPE_UPDATE_MONITOR))
+#define GS_IS_UPDATE_MONITOR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GS_TYPE_UPDATE_MONITOR))
+#define GS_UPDATE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GS_TYPE_UPDATE_MONITOR, 
GsUpdateMonitorClass))
+
+typedef struct _GsUpdateMonitor                GsUpdateMonitor;
+typedef struct _GsUpdateMonitorClass   GsUpdateMonitorClass;
+
+GType           gs_update_monitor_get_type     (void);
+GsUpdateMonitor        *gs_update_monitor_new          (GsApplication *app);
+
+G_END_DECLS
+
+#endif /* __GS_UPDATE_MONITOR_H */
+
+/* vim: set noexpandtab: */


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