[packagekit] Software Update Icon for non-GNOME desktops

Ikey Doherty ikey at solusos.com
Thu Sep 5 07:21:45 PDT 2013


Hello all,

I recently got thinking again about the removal of the update icon from 
gnome-packagekit. Recently in SolusOS we moved away from using a GNOME 
desktop by default, and for now we're using Xfce.

So I set about looking for a simple Xfce solution, and actually found a 
disturbing amount of repeated efforts, used in LXDE, Xfce, etc, on 
multiple distros. So considering we use the PiSi backend of PackageKit 
in SolusOS, I wanted a simple pk-based gpk-using icon. Alas, none were 
what I wanted.

That said, it took me about 20 minutes to write an icon that "does the 
job". Those not using GNOME by default don't have the joy of the little 
banner telling them to update. Sometimes, we just need a GtkStatusIcon :)

If others are in agreement (others meaning Richard mainly :)) I'm happy 
to maintain a small Gtk update notification icon. Eventually I'd want it 
to also support AppIndicator by default over GtkStatusIcon (multiple 
reasons, not being X dependant being a large factor) with StatusIcon a 
fallback option.

A key note here is that it does not in any way implement its own update 
logic, it's an incredibly trivial utility. It currently pulls an update 
count from PackageKitGlib, and when clicked just calls gpk-update-viewer 
into action. I'd also like to (when this is all ready) integrate with 
gnome-software, which I see is scheduled to make an arrival in Fedora.

I've placed the script at the bottom for a quick overview. Essentially 
those of us using it would just need to have a notification system in 
place such as notification-daemon, notify-osd, etc. The idea here is 
passive notifications, and click the icon to actually go about updating.

Kind Regards,
Ikey Doherty
  - SolusOS Founder

diff --git a/software-update-icon.py b/software-update-icon.py
new file mode 100755
index 0000000..019f564
--- /dev/null
+++ b/software-update-icon.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+#  update-icon.py - Simple update notification system
+#
+#  Copyright 2013 Ikey Doherty <ikey at solusos.com>
+#
+#  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.
+#
+#
+import gi.repository
+
+from gi.repository import Gtk, GObject, Notify
+from gi.repository import PackageKitGlib as PackageKit
+import gettext
+import os
+
+gettext.install("update-icon", "/usr/share/locale")
+
+
+class UpdateIcon:
+
+    def __init__(self):
+        # in future we must support appindicators so that we're not X 
dependent
+        self.icon = Gtk.StatusIcon()
+        self.icon.set_from_icon_name("system-software-install")
+        self.icon.set_title(_("Software Update"))
+        self.icon.connect("popup-menu", self.popup)
+        self.icon.connect("activate", self.open_client)
+
+        # our menu
+        self.menu = Gtk.Menu()
+        reload = Gtk.MenuItem(_("Reload"))
+        reload.connect("activate", self.refresh)
+        self.menu.append(reload)
+
+        quit = Gtk.MenuItem(_("Quit"))
+        quit.connect("activate", Gtk.main_quit)
+        self.menu.append(quit)
+
+        self.menu.show_all()
+
+        # We'll reload our icon every 3 minutes
+        GObject.timeout_add (3 * (60 * 1000), self.refresh)
+
+        self.reported = False
+
+
+        try:
+            Notify.init('update-icon')
+        except:
+            # Should probably log this
+            print "Notification daemon could not be reached"
+
+        self.client = PackageKit.Client()
+        self.refresh()
+
+    def popup(self, source, button, time):
+        self.menu.popup(None, None, Gtk.StatusIcon.position_menu, 
self.icon, button, time)
+
+    def open_client(self, widg, user=None):
+        self.icon.set_visible(False)
+        GObject.idle_add(self._open_client)
+
+    def _open_client(self):
+        os.system("gpk-update-viewer")
+        # Essentially blocked until we return from the process
+        self._reload()
+
+    def refresh(self, wid=None):
+        ''' Refresh possible updates '''
+        GObject.idle_add(self._reload)
+
+        return True
+
+    def _reload(self):
+        result = self.client.get_updates(PackageKit.FilterEnum.NONE, 
None, self.progress, None)
+        security = 0
+        packages = result.get_package_array()
+        updates = len(packages)
+        for package in packages:
+            name = package.get_name()
+            print name
+            version = package.get_version()
+            if package.get_info() == PackageKit.InfoEnum.SECURITY:
+                security += 1
+        if security >= 1:
+            self.icon.set_from_icon_name("software-update-urgent")
+            self.icon.set_visible(True)
+
+            # Show notification
+            update_str = _("There is a new security update") if 
security == 1 else \
+                         _("There are %d security updates available") % 
security
+            self.icon.set_tooltip_text(update_str)
+            if not self.reported:
+                notif = Notify.Notification.new(_('Security update'), 
update_str, 'software-update-urgent')
+                notif.show()
+                self.reported = True
+        else:
+            if updates >= 1:
+                self.icon.set_from_icon_name("software-update-available")
+                self.icon.set_visible(True)
+
+                # Show notification
+                update_str = _("There is a new software update") if 
updates == 1 else \
+                             _("There are %d software updates 
available") % updates
+                self.icon.set_tooltip_text(update_str)
+                if not self.reported:
+                    notif = Notify.Notification.new(_('Software 
update'), update_str, 'software-update-available')
+                    notif.show()
+                    self.reported = True
+
+            else:
+                self.icon.set_tooltip_text(_("All software is up to date"))
+                self.icon.set_visible(False)
+
+    def progress(self, progress, type, user_data=None):
+        pass
+
+if __name__ == "__main__":
+    icon = UpdateIcon()
+    Gtk.main()
-- 
1.7.10.4


More information about the PackageKit mailing list