[gnome-system-monitor] pretty-table: prefer GIO to get application icons



commit 97fb0b3e3b27b0a26488df5e4e2612ce79f81d53
Author: Cosimo Cecchi <cosimo cecchi gmail com>
Date:   Mon Oct 1 23:11:51 2012 +0300

    pretty-table: prefer GIO to get application icons
    
    Prefer Gio::AppInfo over Wnck. We need to install file monitors in the
    application desktop file directories to make sure our cache is up to
    date when new applications are installed or upgraded, and we're still
    running.
    
    This ensures the icons we use are consistent with those displayed by the
    rest of the system.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=683762

 src/iconthemewrapper.cpp |   27 ++++++++++++++++++++++
 src/iconthemewrapper.h   |    2 +
 src/prettytable.cpp      |   55 ++++++++++++++++++++++++++++++++++++++++++++++
 src/prettytable.h        |   11 +++++++++
 4 files changed, 95 insertions(+), 0 deletions(-)
---
diff --git a/src/iconthemewrapper.cpp b/src/iconthemewrapper.cpp
index f2bf89b..9982975 100644
--- a/src/iconthemewrapper.cpp
+++ b/src/iconthemewrapper.cpp
@@ -27,3 +27,30 @@ procman::IconThemeWrapper::load_icon(const Glib::ustring& icon_name,
     }
 }
 
+Glib::RefPtr<Gdk::Pixbuf>
+procman::IconThemeWrapper::load_gicon(const Glib::RefPtr<Gio::Icon>& gicon,
+                                      int size, Gtk::IconLookupFlags flags) const
+{
+    Gtk::IconInfo icon_info;
+    icon_info = Gtk::IconTheme::get_default()->lookup_icon(gicon, size, flags);
+
+    if (!icon_info) {
+        return Glib::RefPtr<Gdk::Pixbuf>();
+    }
+
+    try
+    {
+        return icon_info.load_icon();
+    }
+    catch (Gtk::IconThemeError &error)
+    {
+        if (error.code() != Gtk::IconThemeError::ICON_THEME_NOT_FOUND)
+            g_error("Cannot load gicon from theme: %s", error.what().c_str());
+        return Glib::RefPtr<Gdk::Pixbuf>();
+    }
+    catch (Gio::Error &error)
+    {
+        g_debug("Could not load gicon: %s", error.what().c_str());
+        return Glib::RefPtr<Gdk::Pixbuf>();
+    }
+}
diff --git a/src/iconthemewrapper.h b/src/iconthemewrapper.h
index 81fb8d8..5e6c162 100644
--- a/src/iconthemewrapper.h
+++ b/src/iconthemewrapper.h
@@ -14,6 +14,8 @@ namespace procman
         // returns 0 instead of raising an exception
         Glib::RefPtr<Gdk::Pixbuf>
             load_icon(const Glib::ustring& icon_name, int size, Gtk::IconLookupFlags flags) const;
+        Glib::RefPtr<Gdk::Pixbuf>
+            load_gicon(const Glib::RefPtr<Gio::Icon>& gicon, int size, Gtk::IconLookupFlags flags) const;
 
         const IconThemeWrapper* operator->() const
         { return this; }
diff --git a/src/prettytable.cpp b/src/prettytable.cpp
index 25f6625..c201e4f 100644
--- a/src/prettytable.cpp
+++ b/src/prettytable.cpp
@@ -7,6 +7,10 @@
 #include <string.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <glibtop/procstate.h>
+#include <giomm/error.h>
+#include <giomm/file.h>
+#include <glibmm/miscutils.h>
+#include <iostream>
 
 #include <vector>
 
@@ -29,6 +33,20 @@ PrettyTable::PrettyTable()
 		   G_CALLBACK(PrettyTable::on_application_opened), this);
   g_signal_connect(G_OBJECT(screen), "application_closed",
 		   G_CALLBACK(PrettyTable::on_application_closed), this);
+
+  // init GIO apps cache
+  std::vector<std::string> dirs = Glib::get_system_data_dirs();
+  for (std::vector<std::string>::iterator it = dirs.begin(); it != dirs.end(); ++it) {
+    std::string path = (*it).append("/applications");
+    Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(path);
+    Glib::RefPtr<Gio::FileMonitor> monitor = file->monitor_directory();
+    monitor->set_rate_limit(1000); // 1 second
+
+    monitor->signal_changed().connect(sigc::mem_fun(this, &PrettyTable::file_monitor_event));
+    monitors[path] = monitor;
+  }
+
+  this->init_gio_app_cache();
 }
 
 
@@ -105,7 +123,24 @@ PrettyTable::unregister_application(pid_t pid)
     this->apps.erase(it);
 }
 
+void PrettyTable::init_gio_app_cache ()
+{
+  this->gio_apps.clear();
+
+  Glib::ListHandle<Glib::RefPtr<Gio::AppInfo> > apps = Gio::AppInfo::get_all();
+  for (Glib::ListHandle<Glib::RefPtr<Gio::AppInfo> >::const_iterator it = apps.begin();
+       it != apps.end(); ++it) {
+    Glib::RefPtr<Gio::AppInfo> app = *it;
+    this->gio_apps[app->get_executable()] = app;
+  }
+}
 
+void PrettyTable::file_monitor_event(Glib::RefPtr<Gio::File>,
+                                     Glib::RefPtr<Gio::File>,
+                                     Gio::FileMonitorEvent)
+{
+  this->init_gio_app_cache();
+}
 
 Glib::RefPtr<Gdk::Pixbuf>
 PrettyTable::get_icon_from_theme(const ProcInfo &info)
@@ -153,7 +188,26 @@ PrettyTable::get_icon_from_default(const ProcInfo &info)
   return pix;
 }
 
+Glib::RefPtr<Gdk::Pixbuf>
+PrettyTable::get_icon_from_gio(const ProcInfo &info)
+{
+  gchar **cmdline = g_strsplit(info.name, " ", 2);
+  const gchar *executable = cmdline[0];
+  Glib::RefPtr<Gdk::Pixbuf> icon;
+
+  if (executable) {
+    Glib::RefPtr<Gio::AppInfo> app = this->gio_apps[executable];
+    Glib::RefPtr<Gio::Icon> gicon;
+
+    if (app)
+      gicon = app->get_icon();
 
+    if (gicon)
+      icon = this->theme->load_gicon(gicon, APP_ICON_SIZE, Gtk::ICON_LOOKUP_USE_BUILTIN);
+  }
+
+  return icon;
+}
 
 Glib::RefPtr<Gdk::Pixbuf>
 PrettyTable::get_icon_from_wnck(const ProcInfo &info)
@@ -223,6 +277,7 @@ PrettyTable::set_icon(ProcInfo &info)
 
   if (getters.empty())
     {
+      getters.push_back(&PrettyTable::get_icon_from_gio);
       getters.push_back(&PrettyTable::get_icon_from_wnck);
       getters.push_back(&PrettyTable::get_icon_from_theme);
       getters.push_back(&PrettyTable::get_icon_from_default);
diff --git a/src/prettytable.h b/src/prettytable.h
index eb44723..74efe84 100644
--- a/src/prettytable.h
+++ b/src/prettytable.h
@@ -4,6 +4,8 @@
 #include <glib.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <glibmm/refptr.h>
+#include <giomm/filemonitor.h>
+
 #include <gdkmm/pixbuf.h>
 
 #include <map>
@@ -41,18 +43,27 @@ private:
 
     Glib::RefPtr<Gdk::Pixbuf> get_icon_from_theme(const ProcInfo &);
     Glib::RefPtr<Gdk::Pixbuf> get_icon_from_default(const ProcInfo &);
+    Glib::RefPtr<Gdk::Pixbuf> get_icon_from_gio(const ProcInfo &);
     Glib::RefPtr<Gdk::Pixbuf> get_icon_from_wnck(const ProcInfo &);
     Glib::RefPtr<Gdk::Pixbuf> get_icon_from_name(const ProcInfo &);
     Glib::RefPtr<Gdk::Pixbuf> get_icon_for_kernel(const ProcInfo &);
     Glib::RefPtr<Gdk::Pixbuf> get_icon_dummy(const ProcInfo &);
 
     bool get_default_icon_name(const string &cmd, string &name);
+    void file_monitor_event (Glib::RefPtr<Gio::File>,
+                             Glib::RefPtr<Gio::File>,
+                             Gio::FileMonitorEvent);
+    void init_gio_app_cache ();
 
     typedef std::map<string, Glib::RefPtr<Gdk::Pixbuf> > IconCache;
     typedef std::map<pid_t, Glib::RefPtr<Gdk::Pixbuf> > IconsForPID;
+    typedef std::map<string, Glib::RefPtr<Gio::AppInfo> > AppCache;
+    typedef std::map<string, Glib::RefPtr<Gio::FileMonitor> > DesktopDirMonitors;
 
     IconsForPID apps;
     IconCache defaults;
+    DesktopDirMonitors monitors;
+    AppCache gio_apps;
     procman::IconThemeWrapper theme;
 };
 



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