Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > 13ce869a0181d88dc955d6eb70d0fe99 > files > 5

libdesktop-agnostic-0.3.90-13.fc15.src.rpm

=== modified file 'debian/control'
--- debian/control	2010-04-18 20:00:06 +0000
+++ debian/control	2011-01-22 11:35:11 +0000
@@ -9,9 +9,9 @@
                intltool,
                valac (>= 0.7.10),
                gobject-introspection (>= 0.6.3),
-               gobject-introspection-glib-2.0,
-               gobject-introspection-freedesktop,
-               gobject-introspection-repository,
+               gir-repository-dev (>= 0.6.3) | gobject-introspection-glib-2.0,
+               gir-repository-dev (>= 0.6.3) | gobject-introspection-freedesktop,
+               gir-repository-dev (>= 0.6.3) | gobject-introspection-repository,
                libgirepository1.0-dev (>= 0.6.3),
                libglib2.0-dev (>= 2.16.0),
                libgtk2.0-dev,

=== modified file 'docs/known-issues.rst'
--- docs/known-issues.rst	2009-08-18 17:29:21 +0000
+++ docs/known-issues.rst	2011-01-22 11:35:11 +0000
@@ -19,7 +19,7 @@
     config-bridge.vala:164: warning: pointer targets in passing argument 2 of ‘g_object_class_list_properties’ differ in signedness
     desktop-entry-impl-glib.c:306: warning: pointer targets in passing argument 4 of ‘g_key_file_get_string_list’ differ in signedness
 
-.. [1] See `GNOME Bug #582092`_.
+.. [1] See `GNOME Bug #582092`_ (fixed in Vala 0.9.1).
 .. [2] See `GNOME Bug #529866`_ (fixed in Vala 0.7.6).
 .. [3] See `GNOME Bug #592108`_ (fixed in Vala 0.7.6).
 

=== modified file 'libdesktop-agnostic/config-bridge.vala'
--- libdesktop-agnostic/config-bridge.vala	2010-03-31 20:31:44 +0000
+++ libdesktop-agnostic/config-bridge.vala	2011-01-22 11:35:11 +0000
@@ -202,14 +202,13 @@
                                         string key, ParamSpec spec,
                                         NotifyFuncHandler func) throws GLib.Error
     {
-      unowned BindingNotifier notifier;
-      notifier = (BindingNotifier*) config.get_data ("lda-binding-notifier");
+      unowned BindingNotifier? notifier;
+      notifier = config.get_data ("lda-binding-notifier");
       if (notifier == null)
       {
         BindingNotifier new_notifier = new BindingNotifier (config);
         notifier = new_notifier;
-        config.set_data_full ("lda-binding-notifier", notifier.@ref (),
-                              Object.unref);
+        config.set_data ("lda-binding-notifier", notifier);
       }
 
       if (spec.value_type == typeof (bool) ||
@@ -353,8 +352,7 @@
       uint pos = -1;
       string binding_key;
 
-      unowned BindingListWrapper? obj_bindings = 
-        (BindingListWrapper*) obj.get_data ("lda-bindings");
+      unowned BindingListWrapper? obj_bindings = obj.get_data ("lda-bindings");
       binding_key = "%s/%s/%s".printf (config.instance_id, group, key);
       bindings_list = this.bindings.get_data (binding_key);
       bindings_to_remove = new SList<uint> ();

=== modified file 'libdesktop-agnostic/config-client.vala'
--- libdesktop-agnostic/config-client.vala	2010-04-07 22:45:37 +0000
+++ libdesktop-agnostic/config-client.vala	2011-01-22 11:35:11 +0000
@@ -101,13 +101,12 @@
     // constructors
     public Client (string schema_filename)
     {
-      this.schema_filename = schema_filename;
+      GLib.Object (schema_filename: schema_filename);
     }
     public Client.for_instance (string schema_filename,
                                 string instance_id) throws GLib.Error
     {
-      this.schema_filename = schema_filename;
-      this.instance_id = instance_id;
+      GLib.Object (schema_filename: schema_filename, instance_id: instance_id);
     }
     /**
      * Auto-determines whether an instance config object should be created.

=== modified file 'libdesktop-agnostic/config-impl-gconf.vala'
--- libdesktop-agnostic/config-impl-gconf.vala	2010-02-04 22:08:30 +0000
+++ libdesktop-agnostic/config-impl-gconf.vala	2011-01-22 11:35:11 +0000
@@ -654,7 +654,6 @@
   }
 }
 
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/config-impl-keyfile.vala'
--- libdesktop-agnostic/config-impl-keyfile.vala	2009-10-21 18:48:42 +0000
+++ libdesktop-agnostic/config-impl-keyfile.vala	2011-01-22 11:35:11 +0000
@@ -697,6 +697,10 @@
 
       if (value.n_values == 0)
       {
+        if (!this._data.has_group (group))
+        {
+          return;
+        }
         if (this._data.has_key (group, key))
         {
           // set_*_list() doesn't like NULL lists, so just unset the key.
@@ -764,7 +768,6 @@
     }
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/config-impl-memory.vala'
--- libdesktop-agnostic/config-impl-memory.vala	2009-08-15 18:26:33 +0000
+++ libdesktop-agnostic/config-impl-memory.vala	2011-01-22 11:35:11 +0000
@@ -226,7 +226,6 @@
     }
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/config-impl-null.vala'
--- libdesktop-agnostic/config-impl-null.vala	2009-08-06 06:38:30 +0000
+++ libdesktop-agnostic/config-impl-null.vala	2011-01-22 11:35:11 +0000
@@ -121,7 +121,6 @@
     }
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/config-schema.vala'
--- libdesktop-agnostic/config-schema.vala	2009-09-26 20:13:40 +0000
+++ libdesktop-agnostic/config-schema.vala	2011-01-22 11:35:11 +0000
@@ -188,7 +188,8 @@
      */
     public Schema (string filename) throws GLib.Error
     {
-      this.filename = filename;
+      GLib.Object (filename: filename);
+
       unowned HashTable<string,Value?> backend_metadata_keys;
       this.options = Datalist<SchemaOption> ();
       this.keys = new HashTable<string,List<string>> (str_hash, str_equal);

=== modified file 'libdesktop-agnostic/config-type-color.vala'
--- libdesktop-agnostic/config-type-color.vala	2009-07-31 06:50:20 +0000
+++ libdesktop-agnostic/config-type-color.vala	2011-01-22 11:35:11 +0000
@@ -120,7 +120,6 @@
     dest_value = ct.deserialize ((string)src_value);
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== added file 'libdesktop-agnostic/desktop-entry-impl-gio.vala'
--- libdesktop-agnostic/desktop-entry-impl-gio.vala	1970-01-01 00:00:00 +0000
+++ libdesktop-agnostic/desktop-entry-impl-gio.vala	2011-01-22 11:35:11 +0000
@@ -0,0 +1,394 @@
+/*
+ * Desktop Agnostic Library: Desktop Entry implementation using GLib.
+ *
+ * Copyright (C) 2010 Michal Hruby <michal.mhr@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author : Michal Hruby <michal.mhr@gmail.com>
+ */
+
+using DesktopAgnostic;
+
+namespace DesktopAgnostic.FDO
+{
+  private const string GROUP = "Desktop Entry";
+  public class DesktopEntryGio : DesktopEntry, Object
+  {
+    private KeyFile _keyfile = new KeyFile ();
+    private bool loaded = false;
+    private VFS.File _file = null;
+
+    public VFS.File? file
+    {
+      get
+      {
+        return this._file;
+      }
+      set construct
+      {
+        if (value != null)
+        {
+          if (this.loaded)
+          {
+            warning ("The desktop entry has already been initialized.");
+          }
+          else if (value.exists ())
+          {
+            string? path;
+
+            this._file = value;
+            path = value.path;
+            if (path == null)
+            {
+              string data;
+              size_t data_len;
+
+              this._file.load_contents (out data, out data_len);
+              this._keyfile.load_from_data (data, data_len,
+                                            KeyFileFlags.KEEP_TRANSLATIONS);
+            }
+            else
+            {
+              this._keyfile.load_from_file (path, KeyFileFlags.KEEP_TRANSLATIONS);
+            }
+            this.loaded = true;
+          }
+        }
+      }
+    }
+
+    public KeyFile keyfile
+    {
+      get
+      {
+        return this._keyfile;
+      }
+      set construct
+      {
+        if (value != null)
+        {
+          if (this.loaded)
+          {
+            warning ("The desktop entry has already been initialized.");
+          }
+          else
+          {
+            string data;
+            size_t length;
+
+            data = value.to_data (out length);
+            this._keyfile.load_from_data (data, length,
+                                          KeyFileFlags.KEEP_TRANSLATIONS);
+            this.loaded = true;
+          }
+        }
+      }
+    }
+
+    public string data
+    {
+      set construct
+      {
+        if (value != null && value != "")
+        {
+          if (this.loaded)
+          {
+            warning ("The desktop entry has already been initialized.");
+          }
+          else
+          {
+            this._keyfile.load_from_data (value, value.size (),
+                                          KeyFileFlags.KEEP_TRANSLATIONS);
+            this.loaded = true;
+          }
+        }
+      }
+    }
+
+    public DesktopEntryType entry_type
+    {
+      get
+      {
+        string type = this.get_string ("Type");
+        switch (type)
+        {
+          case "Application":
+            return DesktopEntryType.APPLICATION;
+          case "Link":
+            return DesktopEntryType.LINK;
+          case "Directory":
+            return DesktopEntryType.DIRECTORY;
+          default:
+            return DesktopEntryType.UNKNOWN;
+        }
+      }
+      set
+      {
+        this.set_string ("Type", desktop_entry_type_to_string (value));
+      }
+    }
+
+    public string name
+    {
+      owned get
+      {
+        return this.get_string ("Name");
+      }
+      set
+      {
+        this.set_string ("Name", value);
+      }
+    }
+
+    public string? icon
+    {
+      /**
+       * If a path is provided then return the given value. Otherwise,
+       * strip any extension (.xpm, .svg, .png).
+       */
+      owned get
+      {
+        string? icon_name = this.get_string ("Icon");
+
+        if (icon_name != null && Path.get_basename (icon_name) == icon_name)
+        {
+          icon_name = icon_name.split (".png", 2)[0];
+          icon_name = icon_name.split (".svg", 2)[0];
+          icon_name = icon_name.split (".xpm", 2)[0];
+        }
+
+        return icon_name;
+      }
+      set
+      {
+        if (value == null)
+        {
+          warning ("Cannot set a NULL value for 'Icon'.");
+        }
+        else
+        {
+          this.set_string ("Icon", value);
+        }
+      }
+    }
+
+    public bool
+    key_exists (string key)
+    {
+      return this._keyfile.has_group (GROUP) &&
+             this._keyfile.has_key (GROUP, key);
+    }
+
+    public bool
+    get_boolean (string key)
+    {
+      try
+      {
+        return this._keyfile.get_boolean (GROUP, key);
+      }
+      catch (KeyFileError err)
+      {
+        warning ("Error trying to retrieve '%s': %s", key, err.message);
+        return false;
+      }
+    }
+
+    public void
+    set_boolean (string key, bool value)
+    {
+      this._keyfile.set_boolean (GROUP, key, value);
+    }
+
+    public string?
+    get_string (string key)
+    {
+      try
+      {
+        return this._keyfile.get_string (GROUP, key);
+      }
+      catch (KeyFileError err)
+      {
+        warning ("Error trying to retrieve '%s': %s", key, err.message);
+        return null;
+      }
+    }
+
+    public void
+    set_string (string key, string value)
+    {
+      this._keyfile.set_string (GROUP, key, value);
+    }
+
+    public string?
+    get_localestring (string key, string? locale)
+    {
+      try
+      {
+        return this._keyfile.get_locale_string (GROUP, key, locale);
+      }
+      catch (KeyFileError err)
+      {
+        warning ("Error trying to retrieve '%s[%s]': %s", key, locale,
+                 err.message);
+        return null;
+      }
+    }
+
+    public void
+    set_localestring (string key, string locale, string value)
+    {
+      this._keyfile.set_locale_string (GROUP, key, locale, value);
+    }
+
+    [CCode (array_length = false, array_null_terminated = true)]
+    public string[]?
+    get_string_list (string key)
+    {
+      try
+      {
+        return this._keyfile.get_string_list (GROUP, key);
+      }
+      catch (KeyFileError err)
+      {
+        warning ("Error trying to retrieve '%s': %s", key, err.message);
+        return null;
+      }
+    }
+
+    public void
+    set_string_list (string key, [CCode (array_length = false, array_null_terminated = true)] string[] value)
+    {
+      this._keyfile.set_string_list (GROUP, key, value);
+    }
+
+    /**
+     * Based on EggDesktopFile's egg_desktop_file_can_launch().
+     */
+    public bool
+    exists ()
+    {
+      switch (this.entry_type)
+      {
+        case DesktopEntryType.APPLICATION:
+          if (this._keyfile.has_key (GROUP, "TryExec"))
+          {
+            if (Environment.find_program_in_path (this.get_string ("TryExec")) != null)
+            {
+              return true;
+            }
+          }
+          string? exec;
+          string[] argv = null;;
+          exec = this.get_string ("Exec");
+          if (exec == null || !Shell.parse_argv (exec, out argv))
+          {
+            return false;
+          }
+          return Environment.find_program_in_path (argv[0]) != null;
+        case DesktopEntryType.LINK:
+          if (this._keyfile.has_key (GROUP, "URL"))
+          {
+            string uri = this._keyfile.get_string (GROUP, "URL");
+            VFS.File file = VFS.file_new_for_uri (uri);
+            return file.exists ();
+          }
+          else
+          {
+            return false;
+          }
+        default:
+          return false;
+      }
+    }
+
+    /**
+     * Launch desktop entry.
+     * @return always zero.
+     */
+    public Pid
+    launch (DesktopEntryLaunchFlags flags,
+            SList<string>? documents) throws GLib.Error
+    {
+      List<unowned string> uris = new List<unowned string> ();
+      foreach (unowned string s in documents)
+      {
+        uris.append (s);
+      }
+
+      // interesting that GIO 2.26 supports only APPLICATION
+      switch (this.entry_type)
+      {
+        case DesktopEntryType.APPLICATION:
+          AppInfo info;
+          if (this._file != null)
+          {
+            info = new DesktopAppInfo.from_filename (this._file.path);
+          }
+          else
+          {
+            info = new DesktopAppInfo.from_keyfile (this._keyfile);
+          }
+
+          //var context = new AppLaunchContext ();
+          info.launch_uris (uris, null);
+
+          break;
+        case DesktopEntryType.LINK:
+          if (this._keyfile.has_key (GROUP, "URL"))
+          {
+            string uri = this._keyfile.get_string (GROUP, "URL");
+            AppInfo.launch_default_for_uri (uri, null);
+          }
+          else
+          {
+            throw new DesktopEntryError.NOT_LAUNCHABLE ("Invalid desktop entry.");
+          }
+          break;
+        default:
+          throw new DesktopEntryError.NOT_LAUNCHABLE ("Unknown desktop entry type.");
+      }
+
+      return (Pid) 0;
+    }
+
+    public void
+    save (VFS.File? new_file) throws GLib.Error
+    {
+      VFS.File? file = null;
+      if (new_file != null)
+      {
+        file = new_file;
+      }
+      else if (this._file != null)
+      {
+        file = this._file;
+      }
+      else
+      {
+        throw new DesktopEntryError.INVALID_FILE ("No filename specified.");
+      }
+      file.replace_contents (this._keyfile.to_data ());
+    }
+  }
+}
+
+public Type
+register_plugin ()
+{
+  return typeof (DesktopAgnostic.FDO.DesktopEntryGio);
+}
+
+// vim: set ts=2 sts=2 sw=2 et ai cindent :

=== modified file 'libdesktop-agnostic/desktop-entry-impl-glib.vala'
--- libdesktop-agnostic/desktop-entry-impl-glib.vala	2010-03-26 22:45:36 +0000
+++ libdesktop-agnostic/desktop-entry-impl-glib.vala	2011-01-22 11:35:11 +0000
@@ -531,6 +531,59 @@
         throw new DesktopEntryError.NOT_LAUNCHABLE ("Could not parse Exec key.");
       }
 
+      if (this._keyfile.has_key (GROUP, "Terminal") &&
+          this.get_boolean ("Terminal"))
+      {
+        string[] term_argv = new string[argv.length + 2];
+
+        // based on the code for GDesktopAppInfo
+        string? check = null;
+        check = Environment.find_program_in_path ("gnome-terminal");
+        if (check != null)
+        {
+          term_argv[0] = check;
+          term_argv[1] = "-x";
+        }
+        else
+        {
+          if (check == null)
+          {
+            check = Environment.find_program_in_path ("nxterm");
+          }
+          if (check == null)
+          {
+            check = Environment.find_program_in_path ("color-xterm");
+          }
+          if (check == null)
+          {
+            check = Environment.find_program_in_path ("rxvt");
+          }
+          if (check == null)
+          {
+            check = Environment.find_program_in_path ("xterm");
+          }
+          if (check == null)
+          {
+            check = Environment.find_program_in_path ("dtterm");
+          }
+          if (check == null)
+          {
+            check = "xterm";
+            warning ("couldn't find a terminal, falling back to xterm");
+          }
+
+          term_argv[0] = check;
+          term_argv[1] = "-e";
+        }
+
+        for (int i = 0; i < argv.length; i++)
+        {
+          term_argv[i+2] = argv[i];
+        }
+
+        argv = (owned) term_argv;
+      }
+
       Process.spawn_async_with_pipes (working_dir, argv, null, flags, null, out pid);
       return pid;
     }
@@ -614,7 +667,6 @@
   }
 }
 
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/desktop-entry-impl-gnome.vala'
--- libdesktop-agnostic/desktop-entry-impl-gnome.vala	2010-03-26 22:45:36 +0000
+++ libdesktop-agnostic/desktop-entry-impl-gnome.vala	2011-01-22 11:35:11 +0000
@@ -305,7 +305,6 @@
   }
 }
 
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/ui-color-button.vala'
--- libdesktop-agnostic/ui-color-button.vala	2009-10-29 05:26:26 +0000
+++ libdesktop-agnostic/ui-color-button.vala	2011-01-22 11:35:11 +0000
@@ -38,7 +38,7 @@
       this.on_color_set ();
     }
 
-    private override void
+    protected override void
     constructed ()
     {
       this.use_alpha = true;

=== modified file 'libdesktop-agnostic/ui-icon-chooser-dialog.vala'
--- libdesktop-agnostic/ui-icon-chooser-dialog.vala	2010-02-04 22:24:49 +0000
+++ libdesktop-agnostic/ui-icon-chooser-dialog.vala	2011-01-22 11:35:11 +0000
@@ -35,13 +35,40 @@
     FILE
   }
 
+  private class LazyPixbufRenderer : CellRendererPixbuf
+  {
+    public bool item_ready { get; set; default = false; }
+
+    public signal void prepare_pixbuf (TreePath path);
+
+    public override void render (Gdk.Window window,
+                                 Gtk.Widget widget,
+                                 Gdk.Rectangle background_area,
+                                 Gdk.Rectangle cell_area,
+                                 Gdk.Rectangle expose_area,
+                                 Gtk.CellRendererState flags)
+    {
+      if (!item_ready)
+      {
+        int x, y;
+        var view = widget as Gtk.IconView;
+        x = cell_area.x + cell_area.width / 2;
+        y = cell_area.y + cell_area.height / 2;
+        var path = view.get_path_at_pos (x, y);
+        prepare_pixbuf (path);
+      }
+      base.render (window, widget,
+                   background_area, cell_area, expose_area, flags);
+    }
+  }
+
   public class IconChooserDialog : Dialog
   {
     private RadioButton _file;
     private RadioButton _themed;
     private FileChooserButton _directory;
     private ComboBox _themed_context;
-    private IconView _file_viewer;
+    private IconView? _file_viewer = null;
     private IconView? _themed_viewer = null;
     private unowned IconView _viewer;
     public string selected_icon { get; private set; default = null; }
@@ -53,16 +80,26 @@
       PIXBUF,
       NAME,
       DATA,
+      PIXBUF_READY,
       COUNT
     }
 
     public signal void icon_selected ();
 
+    private static Gdk.Pixbuf NO_ICON;
+
+    static construct
+    {
+      var flags = IconLookupFlags.FORCE_SIZE | IconLookupFlags.GENERIC_FALLBACK;
+      NO_ICON = IconTheme.get_default ().load_icon ("gtk-file", 48, flags);
+    }
+
     construct
     {
       this.response.connect (this.on_response);
       this.title = _ ("Select Icon");
       this.icon_name = STOCK_FIND;
+      this.set_default_size (375, 375);
       this.create_ui ();
     }
 
@@ -72,27 +109,17 @@
       HBox choices;
 
       choices = new HBox (false, 5);
-      this._file = new RadioButton.with_mnemonic (null, _ ("From File"));
+      this._themed = new RadioButton.with_mnemonic (null, _ ("From Theme"));
+      choices.add (this._themed);
+      this._file = new RadioButton.with_mnemonic_from_widget (this._themed,
+                                                              _ ("From File"));
+      this._themed.active = true;
+      this._themed.toggled.connect (this.on_icon_type_toggled);
       choices.add (this._file);
-      this._themed = new RadioButton.with_mnemonic_from_widget (this._file,
-                                                                _ ("From Theme"));
-      this._themed.active = false;
-      this._themed.toggled.connect (this.on_icon_type_toggled);
-      choices.add (this._themed);
       this.vbox.pack_start (choices, false, false, 5);
       choices.show_all ();
 
-      this._directory = new FileChooserButton (_ ("Select icon folder"),
-                                               FileChooserAction.SELECT_FOLDER);
-      this._directory.current_folder_changed.connect (this.on_folder_changed);
-      this.vbox.pack_start (this._directory, false, false, 5);
-      this._directory.show ();
-
-      this.add_icon_viewer (ref this._file_viewer, false);
-      this._file_viewer.parent.show_all ();
-      this._viewer = this._file_viewer;
-
-      this.on_folder_changed (this._directory);
+      this.on_icon_type_toggled ();
 
       this.add_buttons (STOCK_CANCEL, ResponseType.CANCEL,
                         STOCK_OK, ResponseType.OK);
@@ -115,30 +142,64 @@
     create_icon_viewer (bool themed)
     {
       IconView viewer;
-      CellRendererPixbuf cell_pixbuf;
+      LazyPixbufRenderer cell_pixbuf;
       CellRendererText cell_text;
 
       viewer = new IconView.with_model (this.create_model ());
-      viewer.item_width = 72;
-      viewer.columns = 4;
-      viewer.column_spacing = 5;
-      viewer.set_size_request (325, 300);
-      viewer.tooltip_column = Column.DATA;
-      cell_pixbuf = new CellRendererPixbuf ();
+      // without this the IconView is not shrinkable after expanding it
+      viewer.set_size_request (108, -1);
+      viewer.set_item_width (108);
+      viewer.set_column_spacing (5);
+      viewer.set_tooltip_column (Column.DATA);
+
+      cell_pixbuf = new LazyPixbufRenderer ();
       cell_pixbuf.xalign = 0.5f;
       cell_pixbuf.yalign = 0.5f;
       cell_pixbuf.width = 48;
+
       viewer.pack_start (cell_pixbuf, false);
       viewer.add_attribute (cell_pixbuf, "pixbuf", Column.PIXBUF);
+      viewer.add_attribute (cell_pixbuf, "item-ready", Column.PIXBUF_READY);
+
+      cell_pixbuf.prepare_pixbuf.connect ((p) =>
+      {
+        TreeIter iter;
+        Value val;
+        var store = this._viewer.model as ListStore;
+        store.get_iter (out iter, p);
+        store.get_value (iter, Column.DATA, out val);
+
+        string icon_name = val.get_string ();
+        IconTheme icon_theme = IconTheme.get_default ();
+        var info = icon_theme.lookup_icon (icon_name, 48, 0);
+        string? name = info.get_display_name ();
+        if (name == null)
+        {
+          name = icon_name.replace ("-", " ");
+        }
+        try
+        {
+          var pixbuf = info.load_icon ();
+          store.set (iter, Column.NAME, name, Column.PIXBUF, pixbuf,
+                     Column.PIXBUF_READY, true, -1);
+        }
+        catch (Error err)
+        {
+          warning ("Could not load %s: %s", icon_name, err.message);
+          store.set (iter, Column.NAME, name, Column.PIXBUF_READY, true, -1);
+        }
+      });
+
       cell_text = new CellRendererText ();
       cell_text.xalign = 0.5f;
-      cell_text.yalign = 0;
+      cell_text.yalign = 0.0f;
       cell_text.wrap_mode = Pango.WrapMode.WORD;
-      cell_text.wrap_width = 72;
-      cell_text.width = 72;
-      cell_text.ellipsize = Pango.EllipsizeMode.START;
+      int wrap_width = viewer.item_width - viewer.item_padding * 2;
+      cell_text.wrap_width = wrap_width;
+      cell_text.width = wrap_width;
+      cell_text.ellipsize = Pango.EllipsizeMode.MIDDLE;
       viewer.pack_start (cell_text, true);
-      viewer.add_attribute (cell_text, "text", 1);
+      viewer.add_attribute (cell_text, "text", Column.NAME);
       viewer.selection_mode = SelectionMode.SINGLE;
 
       return viewer;
@@ -148,20 +209,24 @@
     create_model ()
     {
       // icon, name, data
-      return new ListStore (Column.COUNT, typeof (Gdk.Pixbuf), typeof (string),
-                            typeof (string));
+      return new ListStore (Column.COUNT,
+                            typeof (Gdk.Pixbuf),
+                            typeof (string),
+                            typeof (string),
+                            typeof (bool));
     }
 
     private void
-    on_icon_type_toggled (ToggleButton themed)
+    on_icon_type_toggled ()
     {
       if (this._themed.active)
       {
         if (this._themed_viewer == null)
         {
           unowned IconTheme icon_theme;
-          unowned List<string> context_list;
+          List<string> context_list;
 
+          // "From Theme" widgets -> context combobox + icon view
           this._themed_context = new ComboBox.text ();
           this._themed_context.changed.connect (this.on_icon_context_changed);
           this.vbox.pack_start (this._themed_context, false, false, 5);
@@ -171,21 +236,52 @@
           icon_theme = IconTheme.get_default ();
           context_list = icon_theme.list_contexts ();
           context_list.sort ((CompareFunc)strcmp);
+
+          int active_index = 0;
+          int cur_index = 0;
           foreach (unowned string context in context_list)
           {
             this._themed_context.append_text (context);
+            // try to make "Applications" context active by default
+            if (context == "Applications")
+            {
+              active_index = cur_index;
+            }
+            cur_index++;
           }
-        }
-        this._file_viewer.parent.hide ();
-        this._directory.hide ();
+          this._themed_context.set_active (active_index);
+        }
+
+        if (this._file_viewer != null)
+        {
+          this._file_viewer.parent.hide ();
+          this._directory.hide ();
+        }
         this._themed_viewer.parent.show ();
         this._themed_context.show ();
         this._viewer = this._themed_viewer;
       }
       else
       {
-        this._themed_viewer.parent.hide ();
-        this._themed_context.hide ();
+        if (this._file_viewer == null)
+        {
+          // "From File" widgets -> directory chooser + icon view
+          this._directory = new FileChooserButton (_ ("Select icon folder"),
+                                                   FileChooserAction.SELECT_FOLDER);
+          this._directory.current_folder_changed.connect (this.on_folder_changed);
+          this.vbox.pack_start (this._directory, false, false, 5);
+          this._directory.show ();
+
+          this.add_icon_viewer (ref this._file_viewer, false);
+
+          this.on_folder_changed (this._directory);
+        }
+
+        if (this._themed_viewer != null)
+        {
+          this._themed_viewer.parent.hide ();
+          this._themed_context.hide ();
+        }
         this._file_viewer.parent.show ();
         this._directory.show ();
         this._viewer = this._file_viewer;
@@ -225,7 +321,9 @@
             pixbuf = new Gdk.Pixbuf.from_file_at_scale (path, 48, -1, true);
 
             model.append (out iter);
-            model.set (iter, Column.PIXBUF, pixbuf,
+            model.set (iter,
+                       Column.PIXBUF, pixbuf,
+                       Column.PIXBUF_READY, true,
                        Column.NAME, Path.get_basename (path),
                        Column.DATA, path);
           }
@@ -246,7 +344,7 @@
     {
       unowned ListStore model;
       unowned IconTheme icon_theme;
-      unowned List<string> icon_list;
+      List<string> icon_list;
 
       model = this._themed_viewer.model as ListStore;
       model.clear ();
@@ -256,29 +354,14 @@
       icon_list.sort ((CompareFunc)strcmp);
       foreach (unowned string icon_name in icon_list)
       {
-        try
-        {
-          IconInfo info;
-          Gdk.Pixbuf pixbuf;
-          string? name;
-          TreeIter iter;
+        TreeIter iter;
 
-          info = icon_theme.lookup_icon (icon_name, 48, 0);
-          pixbuf = info.load_icon ();
-          name = info.get_display_name ();
-          if (name == null)
-          {
-            name = icon_name.replace ("-", " ");
-          }
-          model.append (out iter);
-          model.set (iter, Column.PIXBUF, pixbuf,
-                     Column.NAME, name,
-                     Column.DATA, icon_name);
-        }
-        catch (Error err)
-        {
-          warning ("Could not load %s: %s", icon_name, err.message);
-        }
+        model.append (out iter);
+        model.set (iter,
+                   Column.PIXBUF, NO_ICON,
+                   Column.PIXBUF_READY, false,
+                   Column.NAME, icon_name,
+                   Column.DATA, icon_name);
       }
     }
 
@@ -297,7 +380,7 @@
 
           msg = _ ("Please select an icon.");
           dialog = new MessageDialog (this, DialogFlags.MODAL, MessageType.ERROR,
-                                      ButtonsType.OK, msg);
+                                      ButtonsType.OK, "%s", msg);
           dialog.title = _ ("Error");
           dialog.run ();
           dialog.destroy ();

=== modified file 'libdesktop-agnostic/ui-launcher-editor-dialog.vala'
--- libdesktop-agnostic/ui-launcher-editor-dialog.vala	2009-10-27 07:36:10 +0000
+++ libdesktop-agnostic/ui-launcher-editor-dialog.vala	2011-01-22 11:35:11 +0000
@@ -53,51 +53,45 @@
       this.attach (widget, left_attach, right_attach, top_attach, bottom_attach,
                    AttachOptions.FILL, 0, 0, 0);
     }
+
+    public void
+    attach_expand (Widget widget, uint left_attach, uint right_attach,
+                   uint top_attach, uint bottom_attach)
+    {
+      this.attach (widget, left_attach, right_attach, top_attach, bottom_attach,
+                   AttachOptions.FILL | AttachOptions.EXPAND, 0, 0, 0);
+    }
   }
 
   public class LauncherEditorDialog : Dialog
   {
+    private ComboBox _type_combo;
     private IconButton _icon;
     private Entry _name;
     private Entry _desc;
     private Entry _exec;
+    private Expander _advanced;
     private CheckButton _terminal;
     private CheckButton _startup_notification;
+    private unowned Label _command_label;
     public unowned VFS.File file { get; construct; }
     public VFS.File? output { get; construct; }
-    private bool _standalone;
+    public bool entry_type_sensitive { get; construct set; default = false; }
     private DesktopEntry _entry;
 
-    public LauncherEditorDialog (VFS.File file, VFS.File? output, bool standalone)
+    public LauncherEditorDialog (VFS.File file, VFS.File? output = null,
+                                 bool entry_type_sensitive = true)
     {
-      WindowType type;
-
-      if (standalone)
-      {
-        type = WindowType.TOPLEVEL;
-      }
-      else
-      {
-        type = WindowType.POPUP;
-      }
-      this.type = type;
-      this._standalone = standalone;
-      this.file = file;
-      this.output = output;
+      GLib.Object (file: file, output: output,
+                   border_width: 4,
+                   entry_type_sensitive: entry_type_sensitive);
     }
 
-    private override void
+    protected override void
     constructed ()
     {
       this.title = _ ("Desktop Entry Editor");
       this.icon_name = "gtk-preferences";
-      if (this._standalone)
-      {
-        this.delete_event.connect((widget, event) => {
-          main_quit ();
-          return true;
-        });
-      }
       if (this._output == null)
       {
         this._output = file;
@@ -113,10 +107,10 @@
       string icon;
       Button exec_button;
       Image exec_image;
-      Label name_label, desc_label, exec_label;
+      Label type_label, name_label, desc_label, exec_label;
       HBox exec_hbox;
-      Expander advanced;
       VBox advanced_vbox;
+      bool is_application = true;
 
       // Action bar
       this.add_buttons (STOCK_CANCEL, ResponseType.CANCEL,
@@ -125,12 +119,12 @@
       this.response.connect (this.on_response);
 
       // Form container
-      table = new FixedTable (4, 3);
+      table = new FixedTable (3, 5);
       // FIXME Table.row_spacing needs [NoAccessorMethod] in the VAPI, in
       // Vala 0.7.6
       //table.row_spacing = 5;
       table.set_row_spacings (5);
-      table.column_spacing = 5;
+      table.column_spacing = 6;
 
       // Icon
       if (this._entry.key_exists ("Icon"))
@@ -143,11 +137,48 @@
       }
       this._icon = new IconButton (icon);
       this._icon.icon_selected.connect (this.on_icon_changed);
-      table.attach_defaults (this._icon, 0, 1, 0, 3);
+      table.attach_defaults (this._icon, 0, 1, 0, 4);
+
+      // Entry Type
+      if (this._entry.key_exists ("Type"))
+      {
+        is_application = this._entry.entry_type == DesktopEntryType.APPLICATION;
+      }
+      else
+      {
+        // if type is unset, use application
+        this._entry.entry_type = DesktopEntryType.APPLICATION;
+      }
+      type_label = new Label.with_mnemonic (_ ("T_ype:"));
+      type_label.xalign = 1.0f;
+      table.attach_defaults (type_label, 1, 2, 0, 1);
+      this._type_combo = new ComboBox.text ();
+      this._type_combo.append_text (_ ("Application"));
+      this._type_combo.append_text (_ ("Location"));
+      type_label.set_mnemonic_widget (this._type_combo);
+
+      int active_index = -1;
+      switch (this._entry.entry_type)
+      {
+        case DesktopEntryType.APPLICATION:
+          active_index = 0;
+          break;
+        case DesktopEntryType.LINK:
+          active_index = 1;
+          break;
+      }
+      this._type_combo.set_active (active_index);
+      this._type_combo.set_sensitive (entry_type_sensitive);
+      this.notify["entry-type-sensitive"].connect (
+        () => { this._type_combo.set_sensitive (this.entry_type_sensitive); }
+      );
+      this._type_combo.changed.connect (this.on_type_changed);
+      table.attach_expand (this._type_combo, 2, 3, 0, 1);
 
       // Name
       name_label = new Label.with_mnemonic (_ ("_Name:"));
-      table.attach_defaults (name_label, 1, 2, 0, 1);
+      name_label.xalign = 1.0f;
+      table.attach_defaults (name_label, 1, 2, 1, 2);
       this._name = new Entry ();
       name_label.set_mnemonic_widget (this._name);
       if (this._entry.key_exists ("Name"))
@@ -155,11 +186,12 @@
         this._name.set_text (this._entry.name);
       }
       this._name.changed.connect (this.on_name_changed);
-      table.attach_defaults (this._name, 2, 3, 0, 1);
+      table.attach_expand (this._name, 2, 3, 1, 2);
 
       // Description
       desc_label = new Label.with_mnemonic (_ ("_Description:"));
-      table.attach_defaults (desc_label, 1, 2, 1, 2);
+      desc_label.xalign = 1.0f;
+      table.attach_defaults (desc_label, 1, 2, 2, 3);
       this._desc = new Entry ();
       desc_label.set_mnemonic_widget (this._desc);
       if (this._entry.key_exists ("Comment"))
@@ -167,31 +199,36 @@
         this._desc.set_text (this._entry.get_string ("Comment"));
       }
       this._desc.changed.connect (this.on_desc_changed);
-      table.attach_defaults (this._desc, 2, 3, 1, 2);
+      table.attach_expand (this._desc, 2, 3, 2, 3);
 
       // Exec
       exec_label = new Label.with_mnemonic (_ ("_Command:"));
-      table.attach_defaults (exec_label, 1, 2, 2, 3);
+      _command_label = exec_label;
+      exec_label.xalign = 1.0f;
+      table.attach_defaults (exec_label, 1, 2, 3, 4);
       exec_hbox = new HBox (false, 5);
       this._exec = new Entry ();
       exec_label.set_mnemonic_widget (this._exec);
-      if (this._entry.key_exists ("Exec"))
+
+      string key_name = is_application ? "Exec" : "URL";
+      if (this._entry.key_exists (key_name))
       {
-        this._exec.set_text (this._entry.get_string ("Exec"));
+        this._exec.set_text (this._entry.get_string (key_name));
       }
+
       this._exec.changed.connect (this.on_exec_changed);
-      exec_hbox.add (this._exec);
+      exec_hbox.pack_start (this._exec, true);
       exec_button = new Button.with_mnemonic (_ ("_Browse..."));
       exec_image = new Image.from_stock (STOCK_OPEN, IconSize.BUTTON);
       exec_button.set_image (exec_image);
       exec_button.clicked.connect (this.on_exec_browse);
-      exec_hbox.add (exec_button);
-      table.attach_defaults (exec_hbox, 2, 3, 2, 3);
+      exec_hbox.pack_start (exec_button, false);
+      table.attach_expand (exec_hbox, 2, 3, 3, 4);
 
       // Advanced options
       // TODO look into ResizeMode so that the window shrinks when the expander
       // is un-expanded.
-      advanced = new Expander.with_mnemonic (_ ("_Advanced"));
+      this._advanced = new Expander.with_mnemonic (_ ("_Advanced"));
       advanced_vbox = new VBox (false, 5);
       this._terminal = new CheckButton.with_mnemonic (_ ("Run in _terminal"));
       if (this._entry.key_exists ("Terminal"))
@@ -207,8 +244,20 @@
       }
       this._startup_notification.toggled.connect (this.on_startup_notification_toggled);
       advanced_vbox.add (this._startup_notification);
-      advanced.add (advanced_vbox);
-      table.attach_fill (advanced, 0, 3, 3, 4);
+      this._advanced.add (advanced_vbox);
+      table.attach_expand (this._advanced, 0, 3, 4, 5);
+
+      // make sure widgets are properly set up
+      on_type_changed (this._type_combo);
+
+      List<unowned Widget> focus_chain_list = new List<unowned Widget> ();
+      focus_chain_list.append (this._type_combo);
+      focus_chain_list.append (this._name);
+      focus_chain_list.append (this._desc);
+      focus_chain_list.append (exec_hbox);
+      focus_chain_list.append (this._icon);
+      focus_chain_list.append (this._advanced);
+      table.set_focus_chain (focus_chain_list);
 
       this.vbox.add (table);
     }
@@ -220,6 +269,29 @@
     }
 
     private void
+    on_type_changed (ComboBox combo)
+    {
+      switch (combo.get_active ())
+      {
+        case 0: this._entry.entry_type = DesktopEntryType.APPLICATION; break;
+        case 1: this._entry.entry_type = DesktopEntryType.LINK; break;
+      }
+
+      if (this._entry.entry_type == DesktopEntryType.LINK)
+      {
+        this._command_label.set_markup_with_mnemonic (_ ("_Location:"));
+        this._advanced.hide ();
+        this._advanced.set_no_show_all (true);
+      }
+      else
+      {
+        this._command_label.set_markup_with_mnemonic (_ ("_Command:"));
+        this._advanced.set_no_show_all (false);
+        this._advanced.show ();
+      }
+    }
+
+    private void
     on_name_changed (Editable editable)
     {
       Entry entry = editable as Entry;
@@ -237,7 +309,9 @@
     on_exec_changed (Editable editable)
     {
       Entry entry = editable as Entry;
-      this._entry.set_string ("Exec", entry.text);
+      string key_name =
+        this._entry.entry_type == DesktopEntryType.LINK ? "URL" : "Exec";
+      this._entry.set_string (key_name, entry.text);
     }
 
     private void
@@ -246,14 +320,17 @@
       FileChooserDialog dialog;
       int response;
 
-      dialog = new FileChooserDialog (_ ("Locate Command"), this,
+      bool is_link = this._entry.entry_type == DesktopEntryType.LINK;
+      string title = is_link ? _ ("Locate a file") : _ ("Locate Command");
+
+      dialog = new FileChooserDialog (title, this,
                                       FileChooserAction.OPEN,
                                       STOCK_CANCEL, ResponseType.CANCEL,
                                       STOCK_OK, ResponseType.OK);
       response = dialog.run ();
       if (response == ResponseType.OK)
       {
-        this._exec.text = dialog.get_filename ();
+        this._exec.text = is_link ? dialog.get_uri () : dialog.get_filename ();
       }
       dialog.destroy ();
     }
@@ -345,14 +422,7 @@
           }
         }
       }
-      if (this._standalone)
-      {
-        main_quit ();
-      }
-      else
-      {
-        this.hide ();
-      }
+      this.hide ();
     }
   }
 }

=== modified file 'libdesktop-agnostic/vfs-bookmarks-gtk.vala'
--- libdesktop-agnostic/vfs-bookmarks-gtk.vala	2009-07-18 08:06:58 +0000
+++ libdesktop-agnostic/vfs-bookmarks-gtk.vala	2011-01-22 11:35:11 +0000
@@ -77,7 +77,7 @@
      */
     public GtkBookmarks (File? file = null, bool monitor = true)
     {
-      this.file = file;
+      GLib.Object (file: file);
       if (this._file.exists ())
       {
         this.parse ();

=== modified file 'libdesktop-agnostic/vfs-file-impl-gio.vala'
--- libdesktop-agnostic/vfs-file-impl-gio.vala	2010-03-26 22:45:36 +0000
+++ libdesktop-agnostic/vfs-file-impl-gio.vala	2011-01-22 11:35:11 +0000
@@ -239,6 +239,71 @@
       }
       return this._file.delete (null);
     }
+
+    public override bool is_native ()
+    {
+      return this._file.is_native ();
+    }
+
+    public override string get_mime_type () throws Error
+    {
+      var fi = this._file.query_info (FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                                      0, null);
+      return fi.get_content_type ();
+    }
+
+    public override string[] get_icon_names () throws Error
+    {
+      var fi = this._file.query_info (FILE_ATTRIBUTE_STANDARD_ICON,
+                                      0, null);
+      GLib.Icon icon = fi.get_icon ();
+      if (icon != null)
+      {
+        if (icon is ThemedIcon)
+        {
+          // wow! Vala sucks!
+          Value v = Value (typeof (string[]));
+          icon.get_property ("names", ref v);
+          string[] names = (string[]) v;
+          
+          // this should be fixed in vala 0.12
+          //names = (icon as ThemedIcon).get_names ();
+
+          return names;
+        }
+
+        if (icon is FileIcon)
+        {
+          string path = (icon as FileIcon).get_file ().get_path ();
+          string[] result = { path };
+
+          return result;
+        }
+      }
+
+      // hmm... what now?
+      string[] unknown = {};
+      return unknown;
+    }
+
+    public override string?
+    get_thumbnail_path ()
+    {
+      try
+      {
+        var fi = this._file.query_info (FILE_ATTRIBUTE_THUMBNAIL_PATH,
+                                        0, null);
+        if (fi.has_attribute (FILE_ATTRIBUTE_THUMBNAIL_PATH))
+        {
+          return fi.get_attribute_byte_string (FILE_ATTRIBUTE_THUMBNAIL_PATH);
+        }
+      }
+      catch (GLib.Error err)
+      {
+        warning ("%s", err.message);
+      }
+      return null;
+    }
   }
 }
 

=== modified file 'libdesktop-agnostic/vfs-file-impl-gnome-vfs.vala'
--- libdesktop-agnostic/vfs-file-impl-gnome-vfs.vala	2010-03-26 22:45:36 +0000
+++ libdesktop-agnostic/vfs-file-impl-gnome-vfs.vala	2011-01-22 11:35:11 +0000
@@ -322,6 +322,24 @@
       }
       return (GnomeVFS.unlink_from_uri (this._uri) == GnomeVFS.Result.OK);
     }
+
+    public override bool
+    is_native ()
+    {
+      return this._uri_str.has_prefix ("file:");
+    }
+
+    public override string
+    get_mime_type () throws Error
+    {
+      return GnomeVFS.get_mime_type_from_uri (this._uri);
+    }
+
+    public override string[]
+    get_icon_names () throws Error
+    {
+      return get_icon_names_for_mime_type (this.get_mime_type ());
+    }
   }
 }
 

=== modified file 'libdesktop-agnostic/vfs-file-impl-thunar-vfs.vala'
--- libdesktop-agnostic/vfs-file-impl-thunar-vfs.vala	2009-10-27 07:29:55 +0000
+++ libdesktop-agnostic/vfs-file-impl-thunar-vfs.vala	2011-01-22 11:35:11 +0000
@@ -247,6 +247,24 @@
       }
       return (FileUtils.unlink (this.impl_path) == 0);
     }
+
+    public override bool
+    is_native ()
+    {
+      return this._uri.has_prefix ("file:");
+    }
+
+    public override string
+    get_mime_type () throws Error
+    {
+      return this._info.mime_info.get_name ();
+    }
+
+    public override string[]
+    get_icon_names () throws Error
+    {
+      return get_icon_names_for_mime_type (this.get_mime_type ());
+    }
   }
 }
 

=== modified file 'libdesktop-agnostic/vfs-file.vala'
--- libdesktop-agnostic/vfs-file.vala	2009-10-27 07:29:55 +0000
+++ libdesktop-agnostic/vfs-file.vala	2011-01-22 11:35:11 +0000
@@ -190,6 +190,34 @@
      * @return %TRUE on success, %FALSE on failure.
      */
     public abstract bool remove () throws Error;
+
+    /**
+     * Checks to see if a file is native to the platform.
+     * @return %TRUE if file is native, %FALSE otherwise.
+     */
+    public abstract bool is_native ();
+
+    /**
+     * Gets the file's mime type. (might block)
+     * @return String containing file's mime type.
+     */
+    public abstract string get_mime_type () throws Error;
+
+    /**
+     * Gets list of possible icon names representing this file. (might block)
+     * @return List of possible icon names.
+     */
+    public abstract string[] get_icon_names () throws Error;
+
+    /**
+     * Get path to thumbnail representing this file. (might block)
+     * @return Path to file with thumbnail or %null if thumbnail cannot be
+     * found or backend doesn't support it.
+     */
+    public virtual string? get_thumbnail_path ()
+    {
+      return null;
+    }
   }
 
   public File?
@@ -219,6 +247,20 @@
       return (File)Object.new (vfs.file_type, "uri", uri);
     }
   }
+
+  public static string[]
+  get_icon_names_for_mime_type (string mime_type)
+  {
+    string[] names = null;
+
+    return_val_if_fail (mime_type != "", null);
+
+    names += mime_type.replace ("/", "-");
+    names += "gnome-mime-%s".printf (names[0]);
+    names += "%s-x-generic".printf (Regex.split_simple ("/.*", mime_type)[0]);
+
+    return names;
+  }
 }
 
 // vim: set et ts=2 sts=2 sw=2 ai :

=== modified file 'libdesktop-agnostic/vfs-impl-gio.vala'
--- libdesktop-agnostic/vfs-impl-gio.vala	2009-07-18 02:12:37 +0000
+++ libdesktop-agnostic/vfs-impl-gio.vala	2011-01-22 11:35:11 +0000
@@ -89,7 +89,6 @@
     }
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/vfs-impl-gnome-vfs.vala'
--- libdesktop-agnostic/vfs-impl-gnome-vfs.vala	2009-07-18 02:12:37 +0000
+++ libdesktop-agnostic/vfs-impl-gnome-vfs.vala	2011-01-22 11:35:11 +0000
@@ -92,7 +92,6 @@
     }
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/vfs-impl-thunar-vfs.vala'
--- libdesktop-agnostic/vfs-impl-thunar-vfs.vala	2009-07-18 02:12:37 +0000
+++ libdesktop-agnostic/vfs-impl-thunar-vfs.vala	2011-01-22 11:35:11 +0000
@@ -92,7 +92,6 @@
     }
   }
 }
-[ModuleInit]
 public Type
 register_plugin ()
 {

=== modified file 'libdesktop-agnostic/vfs-trash-impl-gio.vala'
--- libdesktop-agnostic/vfs-trash-impl-gio.vala	2009-11-02 06:42:05 +0000
+++ libdesktop-agnostic/vfs-trash-impl-gio.vala	2011-01-22 11:35:11 +0000
@@ -77,7 +77,7 @@
 
       try
       {
-        file_info = dir.query_info_finish (res);
+        file_info = dir.query_info_async.end (res);
         this._file_count = file_info.get_attribute_uint32 (FILE_ATTRIBUTE_TRASH_ITEM_COUNT);
         this.file_count_changed ();
       }

=== modified file 'libdesktop-agnostic/vfs-trash-impl-thunar-vfs.vala'
--- libdesktop-agnostic/vfs-trash-impl-thunar-vfs.vala	2009-09-21 17:53:13 +0000
+++ libdesktop-agnostic/vfs-trash-impl-thunar-vfs.vala	2011-01-22 11:35:11 +0000
@@ -53,7 +53,7 @@
     {
       Monitor monitor;
       this.trash = ThunarVfs.Path.get_for_trash ();
-      this.dbus = Bus.get (BusType.SESSION);
+      this.dbus = DBus.Bus.get (DBus.BusType.SESSION);
       this.xfce_trash =
         (Xfce.Trash)this.dbus.get_object ("org.xfce.Thunar",
                                           "/org/xfce/FileManager");

=== modified file 'libdesktop-agnostic/vfs-volume-impl-gio.vala'
--- libdesktop-agnostic/vfs-volume-impl-gio.vala	2009-09-24 16:36:40 +0000
+++ libdesktop-agnostic/vfs-volume-impl-gio.vala	2011-01-22 11:35:11 +0000
@@ -121,7 +121,7 @@
       bool result = false;
       try
       {
-        result = this.vol.mount_finish (this.async_result);
+        result = this.vol.mount.end (this.async_result);
       }
       catch (GLib.Error err)
       {
@@ -156,7 +156,7 @@
       bool result = false;
       try
       {
-        result = this.vol.get_mount ().unmount_finish (this.async_result);
+        result = this.vol.get_mount ().unmount.end (this.async_result);
       }
       catch (GLib.Error err)
       {
@@ -192,7 +192,7 @@
       bool result = false;
       try
       {
-        result = this.vol.eject_finish (this.async_result);
+        result = this.vol.eject.end (this.async_result);
       }
       catch (GLib.Error err)
       {
@@ -211,7 +211,7 @@
       this.monitor = GLib.VolumeMonitor.get ();
       this._volumes = new HashTable<GLib.Volume,VFS.Volume> (direct_hash,
                                                              direct_equal);
-      unowned List<GLib.Volume> vols = this.monitor.get_volumes ();
+      List<GLib.Volume> vols = this.monitor.get_volumes ();
       foreach (unowned GLib.Volume gvol in vols)
       {
         VFS.Volume vol = this.create_volume (gvol);

=== modified file 'libdesktop-agnostic/vfs-volume-impl-gnome-vfs.vala'
--- libdesktop-agnostic/vfs-volume-impl-gnome-vfs.vala	2009-09-24 16:36:40 +0000
+++ libdesktop-agnostic/vfs-volume-impl-gnome-vfs.vala	2011-01-22 11:35:11 +0000
@@ -190,8 +190,7 @@
       this.monitor = GnomeVFS.get_volume_monitor ();
       this._volumes = new HashTable<GnomeVFS.Drive,VFS.Volume> (direct_hash,
                                                                 direct_equal);
-      unowned List<GnomeVFS.Drive> drives =
-        this.monitor.get_connected_drives ();
+      List<GnomeVFS.Drive> drives = this.monitor.get_connected_drives ();
       foreach (unowned GnomeVFS.Drive drive in drives)
       {
         VFS.Volume vol = this.create_volume (drive);

=== modified file 'libdesktop-agnostic/vfs-volume-impl-thunar-vfs.vala'
--- libdesktop-agnostic/vfs-volume-impl-thunar-vfs.vala	2009-09-24 16:36:40 +0000
+++ libdesktop-agnostic/vfs-volume-impl-thunar-vfs.vala	2011-01-22 11:35:11 +0000
@@ -63,7 +63,7 @@
     }
     public VolumeThunarVFS.for_implementation (ThunarVfs.Volume impl)
     {
-      this.implementation = impl;
+      GLib.Object (implementation: impl);
     }
     public bool
     is_mounted ()

=== modified file 'libdesktop-agnostic/wscript'
--- libdesktop-agnostic/wscript	2010-04-10 23:17:55 +0000
+++ libdesktop-agnostic/wscript	2011-01-22 11:35:11 +0000
@@ -34,6 +34,10 @@
         }
     },
     'fdo': {
+        'gio': {
+            'uselib': 'GIO_UNIX',
+            'packages': 'gio-unix-2.0',
+        },
         'gnome': {
             'uselib': 'GNOME_DESKTOP',
             'packages': 'gnome-desktop-2.0',
@@ -113,7 +117,7 @@
         ])
     lib.packages = 'gdk-2.0 gmodule-2.0'
     lib.target = 'desktop-agnostic'
-    lib.gir = 'DesktopAgnostic-1.0'
+    if bld.env['INTROSPECTION']: lib.gir = 'DesktopAgnostic-1.0'
     lib.uselib = 'M GDK GMODULE'
     lib.packages_private = 'build'
     lib.includes = '..'
@@ -133,7 +137,7 @@
     vfs.packages = 'desktop-agnostic posix'
     vfs.target = 'desktop-agnostic-vfs'
     vfs.header = 'vfs'
-    vfs.gir = 'DesktopAgnosticVFS-1.0'
+    if bld.env['INTROSPECTION']: vfs.gir = 'DesktopAgnosticVFS-1.0'
     vfs.uselib_local = 'desktop-agnostic'
     vfs.packages_private = 'posix-glob'
     vfs.includes = '..'
@@ -152,7 +156,7 @@
     cfg.packages = 'desktop-agnostic-vfs'
     cfg.target = 'desktop-agnostic-cfg'
     cfg.header = 'config'
-    cfg.gir = 'DesktopAgnosticConfig-1.0'
+    if bld.env['INTROSPECTION']: cfg.gir = 'DesktopAgnosticConfig-1.0'
     cfg.uselib_local = 'desktop-agnostic-vfs'
     cfg.packages_private = 'hashtable-gtype-key'
     cfg.includes = '..'
@@ -166,7 +170,7 @@
     fdo.packages = 'desktop-agnostic-vfs'
     fdo.target = 'desktop-agnostic-fdo'
     fdo.header = 'fdo'
-    fdo.gir = 'DesktopAgnosticFDO-1.0'
+    if bld.env['INTROSPECTION']: fdo.gir = 'DesktopAgnosticFDO-1.0'
     fdo.uselib_local = 'desktop-agnostic-vfs'
     fdo.vapi_dirs = '.'
     fdo.includes = '..'
@@ -183,7 +187,7 @@
     ui.packages_private = 'build'
     ui.target = 'desktop-agnostic-ui'
     ui.header = 'ui'
-    ui.gir = 'DesktopAgnosticUI-1.0'
+    if bld.env['INTROSPECTION']: ui.gir = 'DesktopAgnosticUI-1.0'
     ui.uselib = 'GTK'
     ui.uselib_local = 'desktop-agnostic-fdo'
     ui.vapi_dirs = '. ../vapi'

=== modified file 'python/desktopagnostic.override'
--- python/desktopagnostic.override	2009-08-25 22:11:31 +0000
+++ python/desktopagnostic.override	2011-01-22 11:35:11 +0000
@@ -98,19 +98,23 @@
 _wrap_desktop_agnostic_color_from_values (PyObject *self, PyObject *args,
                                           PyObject *kwargs)
 {
-    static char *kwlist[] = { "red", "green", "blue", "alpha", NULL };
-    int red, green, blue, alpha;
-    DesktopAgnosticColor *ret;
-
-    if (!PyArg_ParseTupleAndKeywords (args, kwargs,
-                                      "iiii:color_new_from_values", kwlist,
-                                      &red, &green, &blue, &alpha))
-        return NULL;
-
-    ret = desktop_agnostic_color_new_from_values (red, green, blue, alpha);
-
-    /* pygobject_new handles NULL checking */
-    return pygobject_new ((GObject *)ret);
+  static char *kwlist[] = { "red", "green", "blue", "alpha", NULL };
+  int red, green, blue, alpha;
+  DesktopAgnosticColor *ret;
+  PyObject *py_ret;
+
+  if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+                                    "iiii:color_new_from_values", kwlist,
+                                    &red, &green, &blue, &alpha))
+    return NULL;
+
+  ret = desktop_agnostic_color_new_from_values (red, green, blue, alpha);
+
+  /* pygobject_new handles NULL checking */
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+      g_object_unref (ret);
+  return py_ret;
 }
 %%
 define DesktopAgnosticColor.from_string kwargs staticmethod
@@ -122,6 +126,7 @@
   char *spec;
   GError *error = NULL;
   DesktopAgnosticColor *ret;
+  PyObject *py_ret;
 
   if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:color_new_from_string",
                                     kwlist, &spec))
@@ -137,7 +142,10 @@
   }
 
   /* pygobject_new handles NULL checking */
-  return pygobject_new ((GObject *)ret);
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+    g_object_unref (ret);
+  return py_ret;
 }
 %%
 override-slot DesktopAgnosticColor.tp_str

=== modified file 'python/fdo.override'
--- python/fdo.override	2009-10-06 18:53:45 +0000
+++ python/fdo.override	2011-01-22 11:35:11 +0000
@@ -197,6 +197,7 @@
 {
   DesktopAgnosticFDODesktopEntry *ret;
   GError *error = NULL;
+  PyObject *py_ret;
 
   ret = desktop_agnostic_fdo_desktop_entry_new (&error);
 
@@ -206,7 +207,10 @@
   }
 
   /* pygobject_new handles NULL checking */
-  return pygobject_new ((GObject *)ret);
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+      g_object_unref (ret);
+  return py_ret;
 }
 %%
 define DesktopAgnosticFDODesktopEntry.for_data kwargs staticmethod
@@ -218,6 +222,7 @@
   static char *kwlist[] = { "data", NULL };
   char *data;
   DesktopAgnosticFDODesktopEntry *ret;
+  PyObject *py_ret;
   GError *error = NULL;
 
   if (!PyArg_ParseTupleAndKeywords (args, kwargs,
@@ -235,7 +240,10 @@
   }
 
   /* pygobject_new handles NULL checking */
-  return pygobject_new ((GObject *)ret);
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+      g_object_unref (ret);
+  return py_ret;
 }
 %%
 define DesktopAgnosticFDODesktopEntry.for_file onearg staticmethod
@@ -244,6 +252,7 @@
                                                      PyGObject *file)
 {
   DesktopAgnosticFDODesktopEntry *ret;
+  PyObject *py_ret;
   GError *error = NULL;
 
   ret = desktop_agnostic_fdo_desktop_entry_new_for_file (DESKTOP_AGNOSTIC_VFS_FILE(file->obj),
@@ -255,7 +264,10 @@
   }
 
   /* pygobject_new handles NULL checking */
-  return pygobject_new ((GObject *)ret);
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+      g_object_unref (ret);
+  return py_ret;
 }
 %%
 define DesktopAgnosticFDODesktopEntry.type_to_string onearg staticmethod

=== modified file 'python/ui.override'
--- python/ui.override	2009-10-21 22:09:04 +0000
+++ python/ui.override	2011-01-22 11:35:11 +0000
@@ -46,9 +46,13 @@
                                                     PyGObject *color)
 {
     DesktopAgnosticUIColorButton *ret;
+    PyObject *py_ret;
 
     ret = desktop_agnostic_ui_color_button_new_with_color (DESKTOP_AGNOSTIC_COLOR(color->obj));
 
     /* pygobject_new handles NULL checking */
-    return pygobject_new((GObject *)ret);
+    py_ret = pygobject_new ((GObject *)ret);
+    if (ret != NULL)
+        g_object_unref (ret);
+    return py_ret;
 }

=== modified file 'python/vfs.defs'
--- python/vfs.defs	2009-09-08 03:28:50 +0000
+++ python/vfs.defs	2011-01-22 11:35:11 +0000
@@ -199,6 +199,36 @@
   )
 )
 
+(define-method is_native
+  (of-object "DesktopAgnosticVFSFile")
+  (c-name "desktop_agnostic_vfs_file_is_native")
+  (return-type "gboolean")
+)
+
+(define-method get_mime_type
+  (of-object "DesktopAgnosticVFSFile")
+  (c-name "desktop_agnostic_vfs_file_get_mime_type")
+  (return-type "char*")
+  (parameters
+    '("GError**" "error")
+  )
+)
+
+(define-method get_icon_names
+  (of-object "DesktopAgnosticVFSFile")
+  (c-name "desktop_agnostic_vfs_file_get_icon_names")
+  (return-type "GStrv")
+  (parameters
+    '("GError**" "error")
+  )
+)
+
+(define-method get_thumbnail_path
+  (of-object "DesktopAgnosticVFSFile")
+  (c-name "desktop_agnostic_vfs_file_get_thumbnail_path")
+  (return-type "char*")
+)
+
 (define-function file_new_for_path
   (c-name "desktop_agnostic_vfs_file_new_for_path")
   (return-type "DesktopAgnosticVFSFile*")
@@ -217,6 +247,14 @@
   )
 )
 
+(define-function get_icon_names_for_mime_type
+  (c-name "desktop_agnostic_vfs_get_icon_names_for_mime_type")
+  (return-type "char*")
+  (parameters
+    '("const-char*" "mime_type")
+  )
+)
+
 (define-method changed
   (of-object "DesktopAgnosticVFSFileMonitor")
   (c-name "desktop_agnostic_vfs_file_monitor_emit")

=== modified file 'python/vfs.override'
--- python/vfs.override	2009-09-08 03:28:50 +0000
+++ python/vfs.override	2011-01-22 11:35:11 +0000
@@ -117,6 +117,7 @@
 {
   char *path;
   DesktopAgnosticVFSFile *ret;
+  PyObject *py_ret;
   GError *error = NULL;
 
   if (!PyString_Check (arg))
@@ -136,16 +137,20 @@
   }
 
   /* pygobject_new handles NULL checking */
-  return pygobject_new ((GObject *)ret);
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+      g_object_unref (ret);
+  return py_ret;
 }
 %%
 define DesktopAgnosticVFSFile.for_uri onearg staticmethod
 static PyObject *
 _wrap_desktop_agnostic_v_f_s_file_for_uri (PyObject *self, PyObject *arg)
 {
-    char *uri;
-    DesktopAgnosticVFSFile *ret;
-    GError *error = NULL;
+  char *uri;
+  DesktopAgnosticVFSFile *ret;
+  PyObject *py_ret;
+  GError *error = NULL;
 
   if (!PyString_Check (arg))
   {
@@ -164,8 +169,39 @@
   }
 
   /* pygobject_new handles NULL checking */
-  return pygobject_new ((GObject *)ret);
-}
+  py_ret = pygobject_new ((GObject *)ret);
+  if (ret != NULL)
+      g_object_unref (ret);
+  return py_ret;
+}
+%%
+override desktop_agnostic_vfs_get_icon_names_for_mime_type kwargs
+static PyObject *
+_wrap_desktop_agnostic_vfs_get_icon_names_for_mime_type(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "mime_type", NULL };
+    char *mime_type;
+    gchar **ret;
+    int ret_length = 0;
+    int i;
+    PyObject *py_ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:get_icon_names_for_mime_type", kwlist, &mime_type))
+        return NULL;
+
+    ret = desktop_agnostic_vfs_get_icon_names_for_mime_type(mime_type, &ret_length);
+
+    py_ret = PyList_New (ret_length);
+    if (ret) {
+        for (i=0; i<ret_length; i++) {
+            PyList_SetItem (py_ret, i, PyString_FromString (ret[i]));
+            g_free (ret[i]);
+        }
+        g_free(ret);
+    }
+    return py_ret;
+}
+
 %%
 override desktop_agnostic_vfs_file_enumerate_children noargs
 static PyObject *
@@ -209,6 +245,34 @@
   return PyString_FromStringAndSize (data, length);
 }
 %%
+override desktop_agnostic_vfs_file_get_icon_names noargs
+static PyObject *
+_wrap_desktop_agnostic_vfs_file_get_icon_names (PyGObject *self)
+{
+  int i, res_length;
+  char **result;
+  PyObject *py_result;
+  GError *error = NULL;
+
+  result = desktop_agnostic_vfs_file_get_icon_names (DESKTOP_AGNOSTIC_VFS_FILE (self->obj),
+                                                     &res_length, &error);
+
+  if (pyg_error_check (&error))
+  {
+    return NULL;
+  }
+
+  py_result = PyList_New (res_length);
+  for (i=0; i<res_length; i++)
+  {
+    PyList_SetItem (py_result, i, PyString_FromString (result[i]));
+    g_free (result[i]);
+  }
+  if (result != NULL) g_free (result);
+
+  return py_result;
+}
+%%
 define DesktopAgnosticVFSTrash.get_default noargs staticmethod
 static PyObject *
 _wrap_desktop_agnostic_v_f_s_trash_get_default (PyObject *self)

=== modified file 'tools/lda-desktop-entry-editor.vala'
--- tools/lda-desktop-entry-editor.vala	2009-10-21 22:09:04 +0000
+++ tools/lda-desktop-entry-editor.vala	2011-01-22 11:35:11 +0000
@@ -51,9 +51,9 @@
     {
       output = VFS.file_new_for_path (args[2]);
     }
-    editor = new LauncherEditorDialog (file, output, true);
+    editor = new LauncherEditorDialog (file, output);
     editor.show_all ();
-    Gtk.main ();
+    editor.run ();
 
     VFS.shutdown ();
   }

=== modified file 'wscript'
--- wscript	2010-04-18 20:00:06 +0000
+++ wscript	2011-01-22 11:35:11 +0000
@@ -70,6 +70,8 @@
                    dest='profiling', default=False,
                    help='Enables the library to be built so that it is '
                         'instrumented to measure performance.')
+    opt.add_option('--disable-gi', action='store_true',
+                   dest='no_gi', default=False)
 
 
 def configure(conf):
@@ -88,12 +90,13 @@
     conf.env['DEBUG'] = Options.options.debug
     conf.env['EXTRA_WARNINGS'] = Options.options.extra_warnings
     conf.env['PROFILING'] = Options.options.profiling
+    conf.env['INTROSPECTION'] = not Options.options.no_gi
     conf.env['VNUM'] = str(VNUM)
 
     conf.check_tool('gnu_dirs')
     conf.check_tool('compiler_cc intltool misc python vala')
 
-    MIN_VALA_VERSION = (0, 7, 10)
+    MIN_VALA_VERSION = (0, 8, 1)
 
     conf.check_cfg(package='gmodule-2.0', uselib_store='GMODULE',
                    atleast_version='2.6.0', mandatory=True,
@@ -131,12 +134,16 @@
         conf.check_cfg(package='gnome-vfs-2.0', uselib_store='GNOME_VFS',
                        atleast_version='2.6.0', mandatory=True,
                        args='--cflags --libs')
+    if 'gio' in conf.env['BACKENDS_DE']:
+        conf.check_cfg(package='gio-unix-2.0', uselib_store='GIO_UNIX',
+                       atleast_version='2.18.0', mandatory=True,
+                       args='--cflags --libs')
     if 'gnome' in conf.env['BACKENDS_DE']:
         conf.check_cfg(package='gnome-desktop-2.0',
                        uselib_store='GNOME_DESKTOP', mandatory=True,
                        args='--cflags --libs')
     # make sure we have the proper Vala version
-    if conf.env['VALAC_VERSION'] != MIN_VALA_VERSION and \
+    if conf.env['VALAC_VERSION'] < MIN_VALA_VERSION and \
         not os.path.isdir(os.path.join(conf.curdir, GEN_SRC_DIR)):
         conf.fatal('''\
 Your Vala compiler version %s is too old. The project requires