[Xfce4-commits] <xfce4-settings:nick/mime-settings> Add chooser dialog to mime editor.

Nick Schermer noreply at xfce.org
Sat Jan 21 16:02:01 CET 2012


Updating branch refs/heads/nick/mime-settings
         to ff3c30edf9aaddedf184de35311f5165a656d649 (commit)
       from ae016a96bfa282f93504837ade857ea33ead806d (commit)

commit ff3c30edf9aaddedf184de35311f5165a656d649
Author: Nick Schermer <nick at xfce.org>
Date:   Sat Jan 21 16:00:00 2012 +0100

    Add chooser dialog to mime editor.

 dialogs/mime-settings/Makefile.am                  |    5 +-
 dialogs/mime-settings/xfce-mime-chooser.c          |  608 ++++++++++++++++++++
 dialogs/mime-settings/xfce-mime-chooser.h          |   45 ++
 dialogs/mime-settings/xfce-mime-window.c           |   79 +++-
 .../mime-settings/xfce4-mime-settings.desktop.in   |    2 +-
 po/POTFILES.in                                     |    1 +
 6 files changed, 727 insertions(+), 13 deletions(-)

diff --git a/dialogs/mime-settings/Makefile.am b/dialogs/mime-settings/Makefile.am
index 9b806a5..29a79be 100644
--- a/dialogs/mime-settings/Makefile.am
+++ b/dialogs/mime-settings/Makefile.am
@@ -1,8 +1,7 @@
 
 INCLUDES = \
 	-I${top_srcdir} \
-	-DDATADIR=\"$(datadir)\" \
-	-DSRCDIR=\"$(top_srcdir)\" \
+	-DBINDIR=\"$(bindir)\" \
 	-DLOCALEDIR=\"$(localedir)\" \
 	-DG_LOG_DOMAIN=\"xfce4-mime-settings\" \
 	$(PLATFORM_CPPFLAGS)
@@ -12,6 +11,8 @@ bin_PROGRAMS = \
 
 xfce4_mime_settings_SOURCES = \
 	main.c \
+	xfce-mime-chooser.c \
+	xfce-mime-chooser.h \
 	xfce-mime-window.c \
 	xfce-mime-window.h
 
diff --git a/dialogs/mime-settings/xfce-mime-chooser.c b/dialogs/mime-settings/xfce-mime-chooser.c
new file mode 100644
index 0000000..149ac4b
--- /dev/null
+++ b/dialogs/mime-settings/xfce-mime-chooser.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * 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.
+ *
+ * Parts of the code were takes from Thunar's chooser dialog and model:
+ * Copyright (c) 2005-2006 Benedikt Meurer <benny at xfce.org>
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <libxfce4util/libxfce4util.h>
+#include <libxfce4ui/libxfce4ui.h>
+#include <gio/gdesktopappinfo.h>
+
+#include "xfce-mime-chooser.h"
+
+
+
+static void     xfce_mime_chooser_finalize          (GObject          *object);
+static void     xfce_mime_chooser_update_accept     (XfceMimeChooser  *chooser);
+static void     xfce_mime_chooser_notify_expanded   (GtkExpander      *expander,
+                                                     GParamSpec       *pspec,
+                                                     XfceMimeChooser  *chooser);
+static void     xfce_mime_chooser_browse_command    (GtkWidget        *button,
+                                                     XfceMimeChooser  *chooser);
+
+
+
+struct _XfceMimeChooserClass
+{
+    GtkDialogClass __parent__;
+};
+
+struct _XfceMimeChooser
+{
+    GtkDialog  __parent__;
+
+    GtkTreeStore *model;
+
+    GtkWidget    *image;
+    GtkWidget    *label;
+    GtkWidget    *treeview;
+    GtkWidget    *expander;
+    GtkWidget    *entry;
+};
+
+enum
+{
+    CHOOSER_COLUMN_NAME,
+    CHOOSER_COLUMN_APP_INFO,
+    CHOOSER_COLUMN_GICON,
+    CHOOSER_COLUMN_ATTRS,
+    N_CHOOSER_COLUMNS
+};
+
+
+
+G_DEFINE_TYPE (XfceMimeChooser, xfce_mime_chooser, GTK_TYPE_DIALOG)
+
+
+
+static void
+xfce_mime_chooser_class_init (XfceMimeChooserClass *klass)
+{
+    GObjectClass *gobject_class;
+
+    gobject_class = G_OBJECT_CLASS (klass);
+    gobject_class->finalize = xfce_mime_chooser_finalize;
+}
+
+
+
+static void
+xfce_mime_chooser_init (XfceMimeChooser *chooser)
+{
+    GtkWidget         *vbox;
+    GtkWidget         *scroll;
+    GtkWidget         *area;
+    GtkWidget         *expander;
+    GtkWidget         *hbox;
+    GtkWidget         *entry;
+    GtkWidget         *image;
+    GtkWidget         *label;
+    GtkWidget         *button;
+    GtkWidget         *treeview;
+    GtkTreeViewColumn *column;
+    GtkTreeSelection  *selection;
+    GtkCellRenderer   *renderer;
+
+    chooser->model = gtk_tree_store_new (N_CHOOSER_COLUMNS,
+                                         G_TYPE_STRING,
+                                         G_TYPE_APP_INFO,
+                                         G_TYPE_ICON,
+                                         PANGO_TYPE_ATTR_LIST);
+
+    gtk_window_set_title (GTK_WINDOW (chooser), _("Select Application"));
+    gtk_window_set_icon_name (GTK_WINDOW (chooser), "application-default-icon");
+    gtk_window_set_default_size (GTK_WINDOW (chooser), 400, 350);
+    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+
+    gtk_dialog_add_button (GTK_DIALOG (chooser),
+                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
+    button = gtk_dialog_add_button (GTK_DIALOG (chooser),
+                                    GTK_STOCK_OPEN, GTK_RESPONSE_YES);
+    gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_YES);
+    gtk_widget_set_sensitive (button, FALSE);
+
+    vbox = gtk_vbox_new (FALSE, 6);
+    area = gtk_dialog_get_content_area (GTK_DIALOG (chooser));
+    gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
+    gtk_box_pack_start (GTK_BOX (area), vbox, TRUE, TRUE, 0);
+    gtk_widget_show (vbox);
+
+    hbox = gtk_hbox_new (FALSE, 6);
+    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
+    gtk_widget_show (hbox);
+
+    chooser->image = image = gtk_image_new ();
+    gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0);
+    gtk_widget_show (image);
+
+    chooser->label = label = gtk_label_new ("");
+    gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+    gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+    gtk_widget_set_size_request (label, 350, -1);
+    gtk_widget_show (label);
+
+    scroll = gtk_scrolled_window_new (NULL, NULL);
+    gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+                                    GTK_POLICY_AUTOMATIC,
+                                    GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_ETCHED_IN);
+    gtk_widget_show (scroll);
+
+    treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (chooser->model));
+    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+    gtk_tree_view_set_show_expanders (GTK_TREE_VIEW (treeview), FALSE);
+    gtk_tree_view_set_level_indentation (GTK_TREE_VIEW (treeview), 24);
+    gtk_container_add (GTK_CONTAINER (scroll), treeview);
+    gtk_widget_show (treeview);
+    chooser->treeview = treeview;
+
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+    g_signal_connect_swapped (G_OBJECT (selection), "changed",
+        G_CALLBACK (xfce_mime_chooser_update_accept), chooser);
+
+    column = gtk_tree_view_column_new ();
+    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+    gtk_tree_view_column_set_spacing (column, 2);
+    gtk_tree_view_column_set_expand (column, TRUE);
+
+    renderer = gtk_cell_renderer_pixbuf_new ();
+    g_object_set (G_OBJECT (renderer), "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
+    gtk_tree_view_column_pack_start (column, renderer, FALSE);
+    gtk_tree_view_column_set_attributes (column, renderer,
+                                         "gicon", CHOOSER_COLUMN_GICON,
+                                         NULL);
+
+    renderer = gtk_cell_renderer_text_new ();
+    gtk_tree_view_column_pack_start (column, renderer, TRUE);
+    gtk_tree_view_column_set_attributes (column, renderer,
+                                         "text", CHOOSER_COLUMN_NAME,
+                                         "attributes", CHOOSER_COLUMN_ATTRS,
+                                         NULL);
+
+    chooser->expander = expander = gtk_expander_new_with_mnemonic (_("Use a c_ustom command:"));
+    gtk_widget_set_tooltip_text (expander, _("Use a custom command for an application that is not "
+                                             "available from the above application list."));
+    g_signal_connect (G_OBJECT (expander), "notify::expanded",
+        G_CALLBACK (xfce_mime_chooser_notify_expanded), chooser);
+    gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, TRUE, 0);
+    gtk_expander_set_expanded (GTK_EXPANDER (expander), FALSE);
+    gtk_widget_show (expander);
+
+    hbox = gtk_hbox_new (FALSE, 6);
+    gtk_container_add (GTK_CONTAINER (expander), hbox);
+    gtk_widget_show (hbox);
+
+    chooser->entry = entry = gtk_entry_new ();
+    gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
+    g_signal_connect_swapped (G_OBJECT (entry), "changed",
+        G_CALLBACK (xfce_mime_chooser_update_accept), chooser);
+    gtk_widget_show (entry);
+
+    button = gtk_button_new_with_mnemonic (_("_Browse..."));
+    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+    g_signal_connect (G_OBJECT (button), "clicked",
+         G_CALLBACK (xfce_mime_chooser_browse_command), chooser);
+    gtk_widget_show (button);
+}
+
+
+
+static void
+xfce_mime_chooser_finalize (GObject *object)
+{
+    XfceMimeChooser *chooser = XFCE_MIME_CHOOSER (object);
+
+    g_object_unref (G_OBJECT (chooser->model));
+
+    (*G_OBJECT_CLASS (xfce_mime_chooser_parent_class)->finalize) (object);
+}
+
+
+
+static GAppInfo *
+xfce_mime_chooser_get_selected (XfceMimeChooser *chooser)
+{
+    GtkTreeIter       iter;
+    GAppInfo         *app_info = NULL;
+    GtkTreeSelection *selection;
+
+    g_return_val_if_fail (XFCE_IS_MIME_CHOOSER (chooser), NULL);
+
+    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (chooser->treeview));
+    if (gtk_tree_selection_get_selected (selection, NULL, &iter))
+    {
+        gtk_tree_model_get (GTK_TREE_MODEL (chooser->model), &iter,
+                            CHOOSER_COLUMN_APP_INFO, &app_info, -1);
+
+    }
+
+    return app_info;
+}
+
+
+
+static void
+xfce_mime_chooser_update_accept (XfceMimeChooser *chooser)
+{
+    gboolean     can_open = FALSE;
+    GAppInfo    *app_info;
+    const gchar *text;
+
+    if (gtk_expander_get_expanded (GTK_EXPANDER (chooser->expander)))
+    {
+        text = gtk_entry_get_text (GTK_ENTRY (chooser->entry));
+        can_open = (text != NULL && *text != '\0');
+    }
+    else
+    {
+        app_info = xfce_mime_chooser_get_selected (chooser);
+        if (app_info != NULL)
+        {
+            can_open = TRUE;
+            g_object_unref (G_OBJECT (app_info));
+        }
+    }
+
+    gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser), GTK_RESPONSE_YES, can_open);
+}
+
+
+
+static void
+xfce_mime_chooser_notify_expanded (GtkExpander     *expander,
+                                   GParamSpec      *pspec,
+                                   XfceMimeChooser *chooser)
+{
+    gboolean          expanded;
+    GtkTreeSelection *selection;
+    GAppInfo         *app_info;
+    const gchar      *exec;
+
+    expanded = gtk_expander_get_expanded (expander);
+    gtk_widget_set_sensitive (chooser->treeview, !expanded);
+
+    if (expanded)
+    {
+        /* use the command of the selected item */
+        app_info = xfce_mime_chooser_get_selected (chooser);
+        if (app_info != NULL)
+        {
+            exec = g_app_info_get_executable (app_info);
+            if (G_LIKELY (exec != NULL && g_utf8_validate (exec, -1, NULL)))
+                gtk_entry_set_text (GTK_ENTRY (chooser->entry), exec);
+
+            g_object_unref (G_OBJECT (app_info));
+        }
+
+        /* unselect all item in the treeview */
+        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (chooser->treeview));
+        gtk_tree_selection_unselect_all (selection);
+    }
+
+    xfce_mime_chooser_update_accept (chooser);
+}
+
+
+
+static void
+xfce_mime_chooser_browse_command (GtkWidget       *button,
+                                  XfceMimeChooser *dialog)
+{
+    GtkWidget     *chooser;
+    GtkFileFilter *filter;
+    gchar         *filename;
+    gchar         *s;
+
+    chooser = gtk_file_chooser_dialog_new (_("Select an Application"),
+                                           GTK_WINDOW (dialog),
+                                           GTK_FILE_CHOOSER_ACTION_OPEN,
+                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                           GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                           NULL);
+    gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
+
+    /* add file chooser filters */
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("All Files"));
+    gtk_file_filter_add_pattern (filter, "*");
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("Executable Files"));
+    gtk_file_filter_add_mime_type (filter, "application/x-csh");
+    gtk_file_filter_add_mime_type (filter, "application/x-executable");
+    gtk_file_filter_add_mime_type (filter, "application/x-perl");
+    gtk_file_filter_add_mime_type (filter, "application/x-python");
+    gtk_file_filter_add_mime_type (filter, "application/x-ruby");
+    gtk_file_filter_add_mime_type (filter, "application/x-shellscript");
+    gtk_file_filter_add_pattern (filter, "*.pl");
+    gtk_file_filter_add_pattern (filter, "*.py");
+    gtk_file_filter_add_pattern (filter, "*.rb");
+    gtk_file_filter_add_pattern (filter, "*.sh");
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+    gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("Perl Scripts"));
+    gtk_file_filter_add_mime_type (filter, "application/x-perl");
+    gtk_file_filter_add_pattern (filter, "*.pl");
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("Python Scripts"));
+    gtk_file_filter_add_mime_type (filter, "application/x-python");
+    gtk_file_filter_add_pattern (filter, "*.py");
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("Ruby Scripts"));
+    gtk_file_filter_add_mime_type (filter, "application/x-ruby");
+    gtk_file_filter_add_pattern (filter, "*.rb");
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+    filter = gtk_file_filter_new ();
+    gtk_file_filter_set_name (filter, _("Shell Scripts"));
+    gtk_file_filter_add_mime_type (filter, "application/x-csh");
+    gtk_file_filter_add_mime_type (filter, "application/x-shellscript");
+    gtk_file_filter_add_pattern (filter, "*.sh");
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter);
+
+    /* use the bindir as default folder */
+    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), BINDIR);
+
+    /* setup the currently selected file */
+    filename = gtk_editable_get_chars (GTK_EDITABLE (dialog->entry), 0, -1);
+    if (G_LIKELY (filename != NULL))
+    {
+        /* use only the first argument */
+        s = strchr (filename, ' ');
+        if (G_UNLIKELY (s != NULL))
+            *s = '\0';
+
+        /* check if we have a file name */
+        if (G_LIKELY (*filename != '\0'))
+        {
+            /* check if the filename is not an absolute path */
+            if (G_LIKELY (!g_path_is_absolute (filename)))
+            {
+                /* try to lookup the filename in $PATH */
+                s = g_find_program_in_path (filename);
+                if (G_LIKELY (s != NULL))
+                {
+                    /* use the absolute path instead */
+                    g_free (filename);
+                    filename = s;
+                }
+            }
+
+            /* check if we have an absolute path now */
+            if (G_LIKELY (g_path_is_absolute (filename)))
+                gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (chooser), filename);
+        }
+
+        /* release the filename */
+        g_free (filename);
+    }
+
+    /* run the chooser dialog */
+    if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
+    {
+        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
+        gtk_entry_set_text (GTK_ENTRY (dialog->entry), filename);
+        g_free (filename);
+    }
+
+    gtk_widget_destroy (chooser);
+}
+
+
+
+static void
+xfce_mime_chooser_model_append (GtkTreeStore *model,
+                                const gchar  *title,
+                                const gchar  *icon_name,
+                                GList        *app_infos)
+{
+    GIcon         *icon;
+    GtkTreeIter    child_iter;
+    GtkTreeIter    parent_iter;
+    GList         *li;
+    PangoAttrList *attrs;
+
+    attrs = pango_attr_list_new ();
+    pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+
+    icon = g_themed_icon_new (icon_name);
+    gtk_tree_store_append (model, &parent_iter, NULL);
+    gtk_tree_store_set (model, &parent_iter,
+                        CHOOSER_COLUMN_NAME, title,
+                        CHOOSER_COLUMN_GICON, icon,
+                        CHOOSER_COLUMN_ATTRS, attrs, -1);
+    g_object_unref (G_OBJECT (icon));
+    pango_attr_list_unref (attrs);
+
+    if (G_LIKELY (app_infos != NULL))
+    {
+        /* insert the program items */
+        for (li = app_infos; li != NULL; li = li->next)
+        {
+            /* append the tree row with the program data */
+            gtk_tree_store_append (model, &child_iter, &parent_iter);
+            gtk_tree_store_set (model, &child_iter,
+                                CHOOSER_COLUMN_NAME, g_app_info_get_name (li->data),
+                                CHOOSER_COLUMN_GICON, g_app_info_get_icon (li->data),
+                                CHOOSER_COLUMN_APP_INFO, li->data,
+                                -1);
+        }
+    }
+    else
+    {
+        attrs = pango_attr_list_new ();
+        pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_ITALIC));
+
+        /* tell the user that we don't have any applications for this category */
+        gtk_tree_store_append (model, &child_iter, &parent_iter);
+        gtk_tree_store_set (model, &child_iter,
+                            CHOOSER_COLUMN_NAME, _("None available"),
+                            CHOOSER_COLUMN_ATTRS, attrs, -1);
+        pango_attr_list_unref (attrs);
+    }
+}
+
+
+
+static gint
+xfce_mime_chooser_compare_app_info (gconstpointer a,
+                                    gconstpointer b)
+{
+    return !g_app_info_equal (G_APP_INFO (a), G_APP_INFO (b));
+}
+
+
+
+static gint
+xfce_mime_chooser_sort_app_info (gconstpointer a,
+                                 gconstpointer b)
+{
+    return g_utf8_collate (g_app_info_get_name (G_APP_INFO (a)),
+                           g_app_info_get_name (G_APP_INFO (b)));
+}
+
+
+
+void
+xfce_mime_chooser_set_mime_type (XfceMimeChooser *chooser,
+                                 const gchar     *mime_type)
+{
+    GList *recommended;
+    GList *all, *li;
+    GList *other = NULL;
+    GIcon *icon;
+    gchar *label;
+    gchar *description;
+
+    g_return_if_fail (XFCE_IS_MIME_CHOOSER (chooser));
+    g_return_if_fail (mime_type != NULL);
+    g_return_if_fail (GTK_IS_TREE_STORE (chooser->model));
+
+    gtk_tree_store_clear (chooser->model);
+
+    /* add recommended types */
+    recommended = g_app_info_get_all_for_type (mime_type);
+    xfce_mime_chooser_model_append (chooser->model,
+                                    _("Recommended Applications"),
+                                    "preferences-desktop-default-applications",
+                                    recommended);
+
+    /* filter out recommended apps from all apps */
+    all = g_app_info_get_all ();
+    for (li = all; li != NULL; li = li->next)
+    {
+        if (g_list_find_custom (recommended, li->data,
+                                xfce_mime_chooser_compare_app_info) == NULL)
+        {
+            other = g_list_prepend (other, li->data);
+        }
+    }
+
+    /* add the other applications */
+    other = g_list_sort (other, xfce_mime_chooser_sort_app_info);
+    xfce_mime_chooser_model_append (chooser->model,
+                                    _("Other Applications"),
+                                    "gnome-applications",
+                                    other);
+
+    /* open all */
+    gtk_tree_view_expand_all (GTK_TREE_VIEW (chooser->treeview));
+
+    /* cleanup */
+    g_list_foreach (recommended, (GFunc) g_object_unref, NULL);
+    g_list_foreach (all, (GFunc) g_object_unref, NULL);
+    g_list_free (recommended);
+    g_list_free (all);
+    g_list_free (other);
+
+    /* set label and icon */
+    icon = g_content_type_get_icon (mime_type);
+    gtk_image_set_from_gicon (GTK_IMAGE (chooser->image), icon, GTK_ICON_SIZE_DIALOG);
+    g_object_unref (G_OBJECT (icon));
+
+    description = g_content_type_get_description (mime_type);
+    label = g_strdup_printf (_("Open <i>%s</i> and other files of type \"%s\" with:"),
+                             mime_type, description);
+    gtk_label_set_markup (GTK_LABEL (chooser->label), label);
+    g_free (label);
+    g_free (description);
+}
+
+
+
+GAppInfo *
+xfce_mime_chooser_get_app_info (XfceMimeChooser *chooser)
+{
+    const gchar *exec;
+    GAppInfo    *app_info;
+    gchar       *path;
+    gchar       *name;
+    gchar       *s;
+    GError      *error = NULL;
+
+    if (gtk_expander_get_expanded (GTK_EXPANDER (chooser->expander)))
+    {
+        exec = gtk_entry_get_text (GTK_ENTRY (chooser->entry));
+
+        /* determine the path for the custom command */
+        path = g_strdup (exec);
+        s = strchr (path, ' ');
+        if (G_UNLIKELY (s != NULL))
+            *s = '\0';
+
+        /* determine the name from the path of the custom command */
+        name = g_path_get_basename (path);
+
+        /* try to add an application for the custom command */
+        app_info = g_app_info_create_from_commandline (exec, name, G_APP_INFO_CREATE_NONE, &error);
+        if (G_UNLIKELY (app_info == NULL))
+        {
+            xfce_dialog_show_error (GTK_WINDOW (chooser), error, _("Failed to add new application \"%s\""), name);
+            g_error_free (error);
+        }
+
+        g_free (path);
+        g_free (name);
+
+        return app_info;
+    }
+    else
+    {
+        return xfce_mime_chooser_get_selected (chooser);
+    }
+}
diff --git a/dialogs/mime-settings/xfce-mime-chooser.h b/dialogs/mime-settings/xfce-mime-chooser.h
new file mode 100644
index 0000000..eb7790b
--- /dev/null
+++ b/dialogs/mime-settings/xfce-mime-chooser.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 Nick Schermer <nick at xfce.org>
+ *
+ * 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 __XFCE_MIME_CHOOSER_H__
+#define __XFCE_MIME_CHOOSER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _XfceMimeChooserClass XfceMimeChooserClass;
+typedef struct _XfceMimeChooser      XfceMimeChooser;
+
+#define XFCE_TYPE_MIME_CHOOSER            (xfce_mime_chooser_get_type ())
+#define XFCE_MIME_CHOOSER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MIME_CHOOSER, XfceMimeChooser))
+#define XFCE_MIME_CHOOSER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MIME_CHOOSER, XfceMimeChooserClass))
+#define XFCE_IS_MIME_CHOOSER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MIME_CHOOSER))
+#define XFCE_IS_MIME_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MIME_CHOOSER))
+#define XFCE_MIME_CHOOSER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MIME_CHOOSER, XfceMimeChooserClass))
+
+GType      xfce_mime_chooser_get_type      (void) G_GNUC_CONST;
+
+void       xfce_mime_chooser_set_mime_type (XfceMimeChooser *chooser,
+                                            const gchar     *mime_type);
+
+GAppInfo  *xfce_mime_chooser_get_app_info  (XfceMimeChooser *chooser);
+
+G_END_DECLS
+
+#endif /* !__XFCE_MIME_CHOOSER_H__ */
diff --git a/dialogs/mime-settings/xfce-mime-window.c b/dialogs/mime-settings/xfce-mime-window.c
index e2775df..c6a550f 100644
--- a/dialogs/mime-settings/xfce-mime-window.c
+++ b/dialogs/mime-settings/xfce-mime-window.c
@@ -31,6 +31,8 @@
 #include <gio/gdesktopappinfo.h>
 
 #include "xfce-mime-window.h"
+#include "xfce-mime-chooser.h"
+
 
 
 static void     xfce_mime_window_finalize          (GObject              *object);
@@ -253,10 +255,12 @@ xfce_mime_window_init (XfceMimeWindow *window)
     renderer = gtk_cell_renderer_combo_new ();
     g_signal_connect (G_OBJECT (renderer), "editing-started",
         G_CALLBACK (xfce_mime_window_combo_populate), window);
-    g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
     gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column), renderer, TRUE);
-    g_object_set (renderer, "text-column", COLUMN_APP_NAME,
-                  "has-entry", FALSE, "editable", TRUE, NULL);
+    g_object_set (renderer,
+                  "text-column", COLUMN_APP_NAME,
+                  "ellipsize", PANGO_ELLIPSIZE_END,
+                  "has-entry", FALSE,
+                  "editable", TRUE, NULL);
     gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column), renderer,
                                     "attributes", COLUMN_MIME_ATTRS,
                                     "text", COLUMN_MIME_DEFAULT, NULL);
@@ -309,7 +313,7 @@ xfce_mime_window_mime_user (void)
             if (G_LIKELY (mimes != NULL))
             {
                 for (i = 0; mimes[i] != NULL; i++)
-                    g_hash_table_insert (table, mimes[i], mimes[i]);
+                    g_hash_table_insert (table, mimes[i], GINT_TO_POINTER (TRUE));
                 g_free (mimes);
             }
         }
@@ -572,19 +576,65 @@ xfce_mime_window_combo_unref_data (gpointer user_data)
 
 
 static void
+xfce_mime_window_chooser_response (GtkWidget       *chooser,
+                                   gint             response_id,
+                                   MimeChangedData *data)
+{
+    GAppInfo    *app_info;
+    GtkTreeIter  iter;
+    GError      *error = NULL;
+
+    gtk_widget_hide (chooser);
+
+    if (response_id == GTK_RESPONSE_YES)
+    {
+        if (!gtk_tree_model_get_iter (data->window->mime_model, &iter, data->path))
+            return;
+
+        app_info = xfce_mime_chooser_get_app_info (XFCE_MIME_CHOOSER (chooser));
+        if (G_LIKELY (app_info != NULL))
+        {
+            if (g_app_info_set_as_default_for_type (app_info, data->mime_type, &error))
+            {
+                gtk_list_store_set (GTK_LIST_STORE (data->window->mime_model), &iter,
+                                    COLUMN_MIME_DEFAULT, g_app_info_get_name (app_info),
+                                    COLUMN_MIME_STATUS, _("User Set"),
+                                    COLUMN_MIME_ATTRS, data->window->attrs_bold,
+                                    -1);
+            }
+            else
+            {
+                xfce_dialog_show_error (GTK_WINDOW (data->window), error,
+                    _("Failed to set application \"%s\" for mime type \"%s\"."),
+                    g_app_info_get_name (app_info), data->mime_type);
+                g_error_free (error);
+            }
+
+            g_object_unref (G_OBJECT (app_info));
+        }
+    }
+
+    xfce_mime_window_combo_unref_data (data);
+
+    gtk_widget_destroy (chooser);
+}
+
+
+
+static void
 xfce_mime_window_reset_response (GtkWidget       *dialog,
                                  gint             response_id,
                                  MimeChangedData *data)
 {
-    GAppInfo       *app_default;
-    const gchar    *app_name;
-    GtkTreeIter     mime_iter;
+    GAppInfo    *app_default;
+    const gchar *app_name;
+    GtkTreeIter  iter;
 
     gtk_widget_destroy (dialog);
 
     if (response_id == GTK_RESPONSE_YES)
     {
-        if (!gtk_tree_model_get_iter (data->window->mime_model, &mime_iter, data->path))
+        if (!gtk_tree_model_get_iter (data->window->mime_model, &iter, data->path))
             return;
 
         /* reset the user's default */
@@ -597,7 +647,7 @@ xfce_mime_window_reset_response (GtkWidget       *dialog,
         else
           app_name = NULL;
 
-        gtk_list_store_set (GTK_LIST_STORE (data->window->mime_model), &mime_iter,
+        gtk_list_store_set (GTK_LIST_STORE (data->window->mime_model), &iter,
                             COLUMN_MIME_DEFAULT, app_name,
                             COLUMN_MIME_STATUS, _("Default"),
                             COLUMN_MIME_ATTRS, NULL,
@@ -660,7 +710,16 @@ xfce_mime_window_combo_changed (GtkWidget       *combo,
     }
     else if (type == APP_TYPE_CHOOSER)
     {
-        g_message ("todo");
+        dialog = g_object_new (XFCE_TYPE_MIME_CHOOSER, NULL);
+        gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
+        xfce_mime_chooser_set_mime_type (XFCE_MIME_CHOOSER (dialog), data->mime_type);
+
+        /* ref data */
+        data->ref_count++;
+
+        g_signal_connect (G_OBJECT (dialog), "response",
+            G_CALLBACK (xfce_mime_window_chooser_response), data);
+        gtk_window_present (GTK_WINDOW (dialog));
     }
     else if (type == APP_TYPE_RESET)
     {
diff --git a/dialogs/mime-settings/xfce4-mime-settings.desktop.in b/dialogs/mime-settings/xfce4-mime-settings.desktop.in
index 7bc6b93..a3e5770 100644
--- a/dialogs/mime-settings/xfce4-mime-settings.desktop.in
+++ b/dialogs/mime-settings/xfce4-mime-settings.desktop.in
@@ -1,6 +1,6 @@
 [Desktop Entry]
 Version=1.0
-_Name=Mime Settings
+_Name=Mime Type Editor
 _Comment=Configure the default application for mime types
 Exec=xfce4-mime-settings
 Icon=application-default-icon
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6e0774d..d5bdc63 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -21,6 +21,7 @@ dialogs/keyboard-settings/xfce-keyboard-settings.c
 dialogs/keyboard-settings/xfce-keyboard-settings.desktop.in
 
 dialogs/mime-settings/main.c
+dialogs/mime-settings/xfce-mime-chooser.c
 dialogs/mime-settings/xfce-mime-window.c
 dialogs/mime-settings/xfce-mime-settings.desktop.in
 


More information about the Xfce4-commits mailing list