[Goodies-commits] r3399 - thunar-svn-plugin/trunk/tsp-svn-helper
Peter de Ridder
peter at xfce.org
Fri Oct 19 00:30:16 CEST 2007
Author: peter
Date: 2007-10-18 22:30:16 +0000 (Thu, 18 Oct 2007)
New Revision: 3399
Added:
thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.c
thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.h
thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.c
thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.h
Modified:
thunar-svn-plugin/trunk/tsp-svn-helper/Makefile.am
thunar-svn-plugin/trunk/tsp-svn-helper/main.c
thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout.c
thunar-svn-plugin/trunk/tsp-svn-helper/tsh-file-dialog.c
Log:
made a start on the checkout dialog
Modified: thunar-svn-plugin/trunk/tsp-svn-helper/Makefile.am
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/Makefile.am 2007-10-16 23:05:17 UTC (rev 3398)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/Makefile.am 2007-10-18 22:30:16 UTC (rev 3399)
@@ -20,6 +20,8 @@
tsh-update.c \
tsh-checkout.h \
tsh-checkout.c \
+ gtkfilechooserentry.h \
+ gtkfilechooserentry.c \
tsh-dialog-common.h \
tsh-dialog-common.c \
tsh-login-dialog.h \
@@ -29,7 +31,9 @@
tsh-trust-dialog.h \
tsh-trust-dialog.c \
tsh-notify-dialog.h \
- tsh-notify-dialog.c
+ tsh-notify-dialog.c \
+ tsh-checkout-dialog.h \
+ tsh-checkout-dialog.c
tsp_svn_helper_CPPFLAGS = \
-DG_LOG_DOMAIN=\"tsp-svn-helper\"
Added: thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.c
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.c (rev 0)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.c 2007-10-18 22:30:16 UTC (rev 3399)
@@ -0,0 +1,2985 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*- */
+
+/* GTK+: gtkfilechooserentry.c
+ *
+ * Copyright (c) 2004 James M. Cape <jcape at ignore-your.tv>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <string.h>
+
+#define GTK_FILE_CHOOSER_ENABLE_UNSUPPORTED
+#define GTK_FILE_SYSTEM_ENABLE_UNSUPPORTED
+#include "gtkintl.h"
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkcellrendererpixbuf.h>
+#include <gtk/gtkcomboboxentry.h>
+#include <gtk/gtkdnd.h>
+#include <gtk/gtkicontheme.h>
+#include <gtk/gtkiconfactory.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtktreemodelfilter.h>
+#include <gtk/gtkvseparator.h>
+#include <gtk/gtkfilechooserdialog.h>
+#include <gtk/gtkfilechooserprivate.h>
+#include <gtk/gtkfilechooserutils.h>
+#include "gtkmarshalers.h"
+
+#include "gtkfilechooserentry.h"
+
+#ifdef G_OS_WIN32
+#include <gtk/gtkfilesystemwin32.h>
+#endif
+
+#include <gtk/gtkprivate.h>
+//#include <gtk/gtkalias.h>
+
+/* **************** *
+ * Private Macros *
+ * **************** */
+
+#define GTK_FILE_CHOOSER_ENTRY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_FILE_CHOOSER_ENTRY, GtkFileChooserEntryPrivate))
+
+#define DEFAULT_TITLE N_("Select A File")
+#define DESKTOP_DISPLAY_NAME N_("Desktop")
+#define FALLBACK_DISPLAY_NAME N_("(None)")
+#define FALLBACK_ICON_NAME "stock_unknown"
+#define FALLBACK_ICON_SIZE 16
+
+
+/* ********************** *
+ * Private Enumerations *
+ * ********************** */
+
+/* Property IDs */
+enum
+{
+ PROP_0,
+
+ PROP_DIALOG,
+ PROP_FOCUS_ON_CLICK,
+ PROP_TITLE,
+ PROP_WIDTH_CHARS
+};
+
+/* Signals */
+enum
+{
+ FILE_SET,
+ LAST_SIGNAL
+};
+
+/* TreeModel Columns */
+enum
+{
+ ICON_COLUMN,
+ DISPLAY_NAME_COLUMN,
+ PATH_COLUMN,
+ TYPE_COLUMN,
+ DATA_COLUMN,
+ IS_FOLDER_COLUMN,
+ HANDLE_COLUMN,
+ NUM_COLUMNS
+};
+
+/* TreeModel Row Types */
+typedef enum
+{
+ ROW_TYPE_SPECIAL,
+ ROW_TYPE_VOLUME,
+ ROW_TYPE_SHORTCUT,
+ ROW_TYPE_BOOKMARK_SEPARATOR,
+ ROW_TYPE_BOOKMARK,
+ ROW_TYPE_CURRENT_FOLDER_SEPARATOR,
+ ROW_TYPE_CURRENT_FOLDER,
+ ROW_TYPE_OTHER_SEPARATOR,
+ ROW_TYPE_OTHER,
+
+ ROW_TYPE_INVALID = -1
+}
+RowType;
+
+
+/* ******************** *
+ * Private Structures *
+ * ******************** */
+
+struct _GtkFileChooserEntryPrivate
+{
+ GtkWidget *dialog;
+ GtkWidget *button;
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *combo_box;
+ GtkCellRenderer *icon_cell;
+ GtkCellRenderer *name_cell;
+
+ GtkTreeModel *model;
+ GtkTreeModel *filter_model;
+
+ gchar *backend;
+ GtkFileSystem *fs;
+ GtkFilePath *old_path;
+
+ gulong combo_box_changed_id;
+ gulong dialog_file_activated_id;
+ gulong dialog_folder_changed_id;
+ gulong dialog_selection_changed_id;
+ gulong fs_volumes_changed_id;
+ gulong fs_bookmarks_changed_id;
+
+ GtkFileSystemHandle *dnd_select_folder_handle;
+ GtkFileSystemHandle *update_entry_handle;
+ GSList *change_icon_theme_handles;
+
+ gint icon_size;
+
+ guint8 n_special;
+ guint8 n_volumes;
+ guint8 n_shortcuts;
+ guint8 n_bookmarks;
+ guint8 has_bookmark_separator : 1;
+ guint8 has_current_folder_separator : 1;
+ guint8 has_current_folder : 1;
+ guint8 has_other_separator : 1;
+
+ /* Used for hiding/showing the dialog when the entry is hidden */
+ guint8 active : 1;
+
+ /* Used to track whether we need to set a default current folder on ::map() */
+ guint8 folder_has_been_set : 1;
+
+ guint8 focus_on_click : 1;
+};
+
+
+/* ************* *
+ * DnD Support *
+ * ************* */
+
+enum
+{
+ TEXT_PLAIN,
+ TEXT_URI_LIST
+};
+
+
+/* ********************* *
+ * Function Prototypes *
+ * ********************* */
+
+/* GtkFileChooserIface Functions */
+static void gtk_file_chooser_entry_file_chooser_iface_init (GtkFileChooserIface *iface);
+static gboolean gtk_file_chooser_entry_add_shortcut_folder (GtkFileChooser *chooser,
+ const GtkFilePath *path,
+ GError **error);
+static gboolean gtk_file_chooser_entry_remove_shortcut_folder (GtkFileChooser *chooser,
+ const GtkFilePath *path,
+ GError **error);
+
+/* GObject Functions */
+static GObject *gtk_file_chooser_entry_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params);
+static void gtk_file_chooser_entry_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_file_chooser_entry_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gtk_file_chooser_entry_finalize (GObject *object);
+
+/* GtkObject Functions */
+static void gtk_file_chooser_entry_destroy (GtkObject *object);
+
+/* GtkWidget Functions */
+static void gtk_file_chooser_entry_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint type,
+ guint drag_time);
+static void gtk_file_chooser_entry_show_all (GtkWidget *widget);
+static void gtk_file_chooser_entry_hide_all (GtkWidget *widget);
+static void gtk_file_chooser_entry_show (GtkWidget *widget);
+static void gtk_file_chooser_entry_hide (GtkWidget *widget);
+static void gtk_file_chooser_entry_map (GtkWidget *widget);
+static gboolean gtk_file_chooser_entry_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling);
+static void gtk_file_chooser_entry_style_set (GtkWidget *widget,
+ GtkStyle *old_style);
+static void gtk_file_chooser_entry_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen);
+
+/* Utility Functions */
+static GtkIconTheme *get_icon_theme (GtkWidget *widget);
+static void set_info_for_path_at_iter (GtkFileChooserEntry *fs,
+ const GtkFilePath *path,
+ GtkTreeIter *iter);
+
+static gint model_get_type_position (GtkFileChooserEntry *entry,
+ RowType row_type);
+static void model_free_row_data (GtkFileChooserEntry *entry,
+ GtkTreeIter *iter);
+static inline void model_add_special (GtkFileChooserEntry *entry);
+static inline void model_add_other (GtkFileChooserEntry *entry);
+static void model_add_volumes (GtkFileChooserEntry *entry,
+ GSList *volumes);
+static void model_add_bookmarks (GtkFileChooserEntry *entry,
+ GSList *bookmarks);
+static void model_update_current_folder (GtkFileChooserEntry *entry,
+ const GtkFilePath *path);
+static void model_remove_rows (GtkFileChooserEntry *entry,
+ gint pos,
+ gint n_rows);
+
+static gboolean filter_model_visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+
+static gboolean combo_box_row_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static void name_cell_data_func (GtkCellLayout *layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static void open_dialog (GtkFileChooserEntry *entry);
+static void update_combo_box (GtkFileChooserEntry *entry);
+static void update_label_and_image (GtkFileChooserEntry *entry);
+
+/* Child Object Callbacks */
+static void fs_volumes_changed_cb (GtkFileSystem *fs,
+ gpointer user_data);
+static void fs_bookmarks_changed_cb (GtkFileSystem *fs,
+ gpointer user_data);
+
+static void combo_box_changed_cb (GtkComboBox *combo_box,
+ gpointer user_data);
+
+static void button_clicked_cb (GtkButton *real_button,
+ gpointer user_data);
+
+static void dialog_update_preview_cb (GtkFileChooser *dialog,
+ gpointer user_data);
+static void dialog_selection_changed_cb (GtkFileChooser *dialog,
+ gpointer user_data);
+static void dialog_file_activated_cb (GtkFileChooser *dialog,
+ gpointer user_data);
+static void dialog_current_folder_changed_cb (GtkFileChooser *dialog,
+ gpointer user_data);
+static void dialog_notify_cb (GObject *dialog,
+ GParamSpec *pspec,
+ gpointer user_data);
+static gboolean dialog_delete_event_cb (GtkWidget *dialog,
+ GdkEvent *event,
+ gpointer user_data);
+static void dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ gpointer user_data);
+
+static guint file_chooser_entry_signals[LAST_SIGNAL] = { 0 };
+
+/* ******************* *
+ * GType Declaration *
+ * ******************* */
+
+G_DEFINE_TYPE_WITH_CODE (GtkFileChooserEntry, gtk_file_chooser_entry, GTK_TYPE_HBOX, { \
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER, gtk_file_chooser_entry_file_chooser_iface_init) \
+})
+
+
+/* ***************** *
+ * GType Functions *
+ * ***************** */
+
+static void
+gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass * class)
+{
+ GObjectClass *gobject_class;
+ GtkObjectClass *gtkobject_class;
+ GtkWidgetClass *widget_class;
+
+ gobject_class = G_OBJECT_CLASS (class);
+ gtkobject_class = GTK_OBJECT_CLASS (class);
+ widget_class = GTK_WIDGET_CLASS (class);
+
+ gobject_class->constructor = gtk_file_chooser_entry_constructor;
+ gobject_class->set_property = gtk_file_chooser_entry_set_property;
+ gobject_class->get_property = gtk_file_chooser_entry_get_property;
+ gobject_class->finalize = gtk_file_chooser_entry_finalize;
+
+ gtkobject_class->destroy = gtk_file_chooser_entry_destroy;
+
+ widget_class->drag_data_received = gtk_file_chooser_entry_drag_data_received;
+ widget_class->show_all = gtk_file_chooser_entry_show_all;
+ widget_class->hide_all = gtk_file_chooser_entry_hide_all;
+ widget_class->show = gtk_file_chooser_entry_show;
+ widget_class->hide = gtk_file_chooser_entry_hide;
+ widget_class->map = gtk_file_chooser_entry_map;
+ widget_class->style_set = gtk_file_chooser_entry_style_set;
+ widget_class->screen_changed = gtk_file_chooser_entry_screen_changed;
+ widget_class->mnemonic_activate = gtk_file_chooser_entry_mnemonic_activate;
+
+ /**
+ * GtkFileChooserEntrys::file-set:
+ * @widget: the object which received the signal.
+ *
+ * The ::file-set signal is emitted when the user selects a file.
+ *
+ * Note that this signal is only emitted when the <emphasis>user</emphasis>
+ * changes the file.
+ *
+ * Since: 2.12
+ */
+ file_chooser_entry_signals[FILE_SET] =
+ g_signal_new (I_("file-set"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkFileChooserEntryClass, file_set),
+ NULL, NULL,
+ _gtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
+ * GtkFileChooserEntry:dialog:
+ *
+ * Instance of the #GtkFileChooserDialog associated with the entry.
+ *
+ * Since: 2.6
+ */
+ g_object_class_install_property (gobject_class, PROP_DIALOG,
+ g_param_spec_object ("dialog",
+ P_("Dialog"),
+ P_("The file chooser dialog to use."),
+ GTK_TYPE_FILE_CHOOSER,
+ (GTK_PARAM_WRITABLE |
+ G_PARAM_CONSTRUCT_ONLY)));
+
+ /**
+ * GtkFileChooserEntry:focus-on-click:
+ *
+ * Whether the #GtkFileChooserEntry entry grabs focus when it is clicked
+ * with the mouse.
+ *
+ * Since: 2.10
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_FOCUS_ON_CLICK,
+ g_param_spec_boolean ("focus-on-click",
+ P_("Focus on click"),
+ P_("Whether the entry grabs focus when it is clicked with the mouse"),
+ TRUE,
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkFileChooserEntry:title:
+ *
+ * Title to put on the #GtkFileChooserDialog associated with the entry.
+ *
+ * Since: 2.6
+ */
+ g_object_class_install_property (gobject_class, PROP_TITLE,
+ g_param_spec_string ("title",
+ P_("Title"),
+ P_("The title of the file chooser dialog."),
+ _(DEFAULT_TITLE),
+ GTK_PARAM_READWRITE));
+
+ /**
+ * GtkFileChooserEntry:width-chars:
+ *
+ * The width of the entry and label inside the entry, in characters.
+ *
+ * Since: 2.6
+ */
+ g_object_class_install_property (gobject_class, PROP_WIDTH_CHARS,
+ g_param_spec_int ("width-chars",
+ P_("Width In Characters"),
+ P_("The desired width of the entry widget, in characters."),
+ -1, G_MAXINT, -1,
+ GTK_PARAM_READWRITE));
+
+ _gtk_file_chooser_install_properties (gobject_class);
+
+ g_type_class_add_private (class, sizeof (GtkFileChooserEntryPrivate));
+}
+
+static void
+gtk_file_chooser_entry_init (GtkFileChooserEntry *entry)
+{
+ GtkFileChooserEntryPrivate *priv;
+ GtkWidget *box, *image, *sep;
+ GtkTargetList *target_list;
+ GList *list, *iter;
+
+ priv = entry->priv = GTK_FILE_CHOOSER_ENTRY_GET_PRIVATE (entry);
+
+ priv->icon_size = FALLBACK_ICON_SIZE;
+ priv->focus_on_click = TRUE;
+
+ gtk_widget_push_composite_child ();
+
+ /* Button */
+ priv->button = gtk_button_new ();
+ g_signal_connect (priv->button, "clicked", G_CALLBACK (button_clicked_cb),
+ entry);
+ //gtk_container_add (GTK_CONTAINER (entry), priv->button);
+ gtk_widget_show (priv->button);
+
+ box = gtk_hbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (priv->button), box);
+ gtk_widget_show (box);
+
+ priv->image = gtk_image_new ();
+ gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
+ gtk_widget_show (priv->image);
+
+ priv->label = gtk_label_new (_(FALLBACK_DISPLAY_NAME));
+ gtk_label_set_ellipsize (GTK_LABEL (priv->label), PANGO_ELLIPSIZE_END);
+ gtk_misc_set_alignment (GTK_MISC (priv->label), 0.0, 0.5);
+ gtk_container_add (GTK_CONTAINER (box), priv->label);
+ gtk_widget_show (priv->label);
+
+ sep = gtk_vseparator_new ();
+ gtk_box_pack_start (GTK_BOX (box), sep, FALSE, FALSE, 0);
+ gtk_widget_show (sep);
+
+ image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
+ GTK_ICON_SIZE_MENU);
+ gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 0);
+ gtk_widget_show (image);
+
+ /* Combo Box */
+ /* Keep in sync with columns enum, line 88 */
+ priv->model =
+ GTK_TREE_MODEL (gtk_list_store_new (NUM_COLUMNS,
+ GDK_TYPE_PIXBUF, /* Icon */
+ G_TYPE_STRING, /* Display Name */
+ G_TYPE_STRING,
+ G_TYPE_CHAR, /* Row Type */
+ G_TYPE_POINTER /* Volume || Path */,
+ G_TYPE_BOOLEAN /* Is Folder? */,
+ G_TYPE_POINTER /* handle */));
+
+ priv->combo_box = gtk_combo_box_entry_new ();
+ priv->combo_box_changed_id =
+ g_signal_connect (priv->combo_box, "changed",
+ G_CALLBACK (combo_box_changed_cb), entry);
+ gtk_container_add (GTK_CONTAINER (entry), priv->combo_box);
+
+ //gtk_cell_layout_clear (GTK_CELL_LAYOUT (priv->combo_box));
+ list = iter = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->combo_box));
+ while(iter)
+ {
+ g_object_set (iter->data, "visible", FALSE, NULL);
+ iter = g_list_next (iter);
+ }
+ g_list_free (list);
+
+ priv->icon_cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->combo_box),
+ priv->icon_cell, FALSE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->combo_box),
+ priv->icon_cell, "pixbuf", ICON_COLUMN);
+
+ priv->name_cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->combo_box),
+ priv->name_cell, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (priv->combo_box),
+ priv->name_cell, "text", DISPLAY_NAME_COLUMN);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->combo_box),
+ priv->name_cell, name_cell_data_func,
+ NULL, NULL);
+
+ gtk_widget_pop_composite_child ();
+
+ /* DnD */
+ gtk_drag_dest_set (GTK_WIDGET (entry),
+ (GTK_DEST_DEFAULT_ALL),
+ NULL, 0,
+ GDK_ACTION_COPY);
+ target_list = gtk_target_list_new (NULL, 0);
+ gtk_target_list_add_uri_targets (target_list, TEXT_URI_LIST);
+ gtk_target_list_add_text_targets (target_list, TEXT_PLAIN);
+ gtk_drag_dest_set_target_list (GTK_WIDGET (entry), target_list);
+ gtk_target_list_unref (target_list);
+}
+
+
+/* ******************************* *
+ * GtkFileChooserIface Functions *
+ * ******************************* */
+static void
+gtk_file_chooser_entry_file_chooser_iface_init (GtkFileChooserIface *iface)
+{
+ _gtk_file_chooser_delegate_iface_init (iface);
+
+ iface->add_shortcut_folder = gtk_file_chooser_entry_add_shortcut_folder;
+ iface->remove_shortcut_folder = gtk_file_chooser_entry_remove_shortcut_folder;
+}
+
+static gboolean
+gtk_file_chooser_entry_add_shortcut_folder (GtkFileChooser *chooser,
+ const GtkFilePath *path,
+ GError **error)
+{
+ GtkFileChooser *delegate;
+ gboolean retval;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+ retval = _gtk_file_chooser_add_shortcut_folder (delegate, path, error);
+
+ if (retval)
+ {
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (chooser);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GtkTreeIter iter;
+ gint pos;
+
+ pos = model_get_type_position (entry, ROW_TYPE_SHORTCUT);
+ pos += priv->n_shortcuts;
+
+ gtk_list_store_insert (GTK_LIST_STORE (priv->model), &iter, pos);
+ gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME),
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ TYPE_COLUMN, ROW_TYPE_SHORTCUT,
+ DATA_COLUMN, gtk_file_path_copy (path),
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+ set_info_for_path_at_iter (entry, path, &iter);
+ priv->n_shortcuts++;
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+ }
+
+ return retval;
+}
+
+static gboolean
+gtk_file_chooser_entry_remove_shortcut_folder (GtkFileChooser *chooser,
+ const GtkFilePath *path,
+ GError **error)
+{
+ GtkFileChooser *delegate;
+ gboolean retval;
+
+ delegate = g_object_get_qdata (G_OBJECT (chooser),
+ GTK_FILE_CHOOSER_DELEGATE_QUARK);
+
+ retval = _gtk_file_chooser_remove_shortcut_folder (delegate, path, error);
+
+ if (retval)
+ {
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (chooser);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GtkTreeIter iter;
+ gint pos;
+ gchar type;
+
+ pos = model_get_type_position (entry, ROW_TYPE_SHORTCUT);
+ gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos);
+
+ do
+ {
+ gpointer data;
+
+ gtk_tree_model_get (priv->model, &iter,
+ TYPE_COLUMN, &type,
+ DATA_COLUMN, &data,
+ -1);
+
+ if (type == ROW_TYPE_SHORTCUT &&
+ data &&
+ gtk_file_path_compare (data, path) == 0)
+ {
+ model_free_row_data (GTK_FILE_CHOOSER_ENTRY (chooser), &iter);
+ gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter);
+ priv->n_shortcuts--;
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+ update_combo_box (GTK_FILE_CHOOSER_ENTRY (chooser));
+ break;
+ }
+ }
+ while (type == ROW_TYPE_SHORTCUT &&
+ gtk_tree_model_iter_next (priv->model, &iter));
+ }
+
+ return retval;
+}
+
+
+/* ******************* *
+ * GObject Functions *
+ * ******************* */
+
+static GObject *
+gtk_file_chooser_entry_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
+{
+ GObject *object;
+ GtkFileChooserEntry *entry;
+ GtkFileChooserEntryPrivate *priv;
+ GSList *list;
+ char *current_folder;
+
+ object = (*G_OBJECT_CLASS (gtk_file_chooser_entry_parent_class)->constructor) (type,
+ n_params,
+ params);
+ entry = GTK_FILE_CHOOSER_ENTRY (object);
+ priv = entry->priv;
+
+ if (!priv->dialog)
+ {
+ if (priv->backend)
+ priv->dialog = gtk_file_chooser_dialog_new_with_backend (NULL, NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ priv->backend,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ else
+ priv->dialog = gtk_file_chooser_dialog_new (NULL, NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (priv->dialog),
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (priv->dialog),
+ GTK_RESPONSE_ACCEPT,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gtk_file_chooser_entry_set_title (entry, _(DEFAULT_TITLE));
+ }
+ else if (!GTK_WINDOW (priv->dialog)->title)
+ {
+ gtk_file_chooser_entry_set_title (entry, _(DEFAULT_TITLE));
+ }
+
+ current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (priv->dialog));
+ if (current_folder != NULL)
+ {
+ priv->folder_has_been_set = TRUE;
+ g_free (current_folder);
+ }
+
+ g_free (priv->backend);
+ priv->backend = NULL;
+
+ g_signal_connect (priv->dialog, "delete_event",
+ G_CALLBACK (dialog_delete_event_cb), object);
+ g_signal_connect (priv->dialog, "response",
+ G_CALLBACK (dialog_response_cb), object);
+
+ /* This is used, instead of the standard delegate, to ensure that signals are only
+ * delegated when the OK button is pressed. */
+ g_object_set_qdata (object, GTK_FILE_CHOOSER_DELEGATE_QUARK, priv->dialog);
+ priv->dialog_folder_changed_id =
+ g_signal_connect (priv->dialog, "current-folder-changed",
+ G_CALLBACK (dialog_current_folder_changed_cb), object);
+ priv->dialog_file_activated_id =
+ g_signal_connect (priv->dialog, "file-activated",
+ G_CALLBACK (dialog_file_activated_cb), object);
+ priv->dialog_selection_changed_id =
+ g_signal_connect (priv->dialog, "selection-changed",
+ G_CALLBACK (dialog_selection_changed_cb), object);
+ g_signal_connect (priv->dialog, "update-preview",
+ G_CALLBACK (dialog_update_preview_cb), object);
+ g_signal_connect (priv->dialog, "notify",
+ G_CALLBACK (dialog_notify_cb), object);
+ g_object_add_weak_pointer (G_OBJECT (priv->dialog),
+ (gpointer) (&priv->dialog));
+
+ priv->fs =
+ g_object_ref (_gtk_file_chooser_get_file_system (GTK_FILE_CHOOSER (priv->dialog)));
+
+ model_add_special (entry);
+
+ list = gtk_file_system_list_volumes (priv->fs);
+ model_add_volumes (entry, list);
+ g_slist_free (list);
+
+ list = gtk_file_system_list_bookmarks (priv->fs);
+ model_add_bookmarks (entry, list);
+ gtk_file_paths_free (list);
+
+ model_add_other (entry);
+
+ priv->filter_model = gtk_tree_model_filter_new (priv->model, NULL);
+ gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (priv->filter_model),
+ filter_model_visible_func,
+ object, NULL);
+
+ gtk_combo_box_set_model (GTK_COMBO_BOX (priv->combo_box), priv->filter_model);
+ gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (priv->combo_box), PATH_COLUMN);
+ gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (priv->combo_box),
+ combo_box_row_separator_func,
+ NULL, NULL);
+
+ /* set up the action for a user-provided dialog, this also updates
+ * the label, image and combobox
+ */
+ g_object_set (object,
+ "action", gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)),
+ NULL);
+
+ priv->fs_volumes_changed_id =
+ g_signal_connect (priv->fs, "volumes-changed",
+ G_CALLBACK (fs_volumes_changed_cb), object);
+ priv->fs_bookmarks_changed_id =
+ g_signal_connect (priv->fs, "bookmarks-changed",
+ G_CALLBACK (fs_bookmarks_changed_cb), object);
+
+ return object;
+}
+
+static void
+gtk_file_chooser_entry_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (object);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ switch (param_id)
+ {
+ case PROP_DIALOG:
+ /* Construct-only */
+ priv->dialog = g_value_get_object (value);
+ break;
+ case PROP_FOCUS_ON_CLICK:
+ gtk_file_chooser_entry_set_focus_on_click (entry, g_value_get_boolean (value));
+ break;
+ case PROP_WIDTH_CHARS:
+ gtk_file_chooser_entry_set_width_chars (GTK_FILE_CHOOSER_ENTRY (object),
+ g_value_get_int (value));
+ break;
+ case GTK_FILE_CHOOSER_PROP_ACTION:
+ switch (g_value_get_enum (value))
+ {
+ case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
+ case GTK_FILE_CHOOSER_ACTION_SAVE:
+ {
+ GEnumClass *eclass;
+ GEnumValue *eval;
+
+ eclass = g_type_class_peek (GTK_TYPE_FILE_CHOOSER_ACTION);
+ eval = g_enum_get_value (eclass, g_value_get_enum (value));
+ g_warning ("%s: Choosers of type `%s' do not support `%s'.",
+ G_STRFUNC, G_OBJECT_TYPE_NAME (object), eval->value_name);
+
+ g_value_set_enum ((GValue *) value, GTK_FILE_CHOOSER_ACTION_OPEN);
+ }
+ break;
+ }
+
+ g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value);
+ update_label_and_image (GTK_FILE_CHOOSER_ENTRY (object));
+ update_combo_box (GTK_FILE_CHOOSER_ENTRY (object));
+
+ switch (g_value_get_enum (value))
+ {
+ case GTK_FILE_CHOOSER_ACTION_OPEN:
+ gtk_widget_hide (priv->combo_box);
+ gtk_widget_show (priv->button);
+ break;
+ case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ gtk_widget_hide (priv->button);
+ gtk_widget_show (priv->combo_box);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ break;
+
+ case PROP_TITLE:
+ case GTK_FILE_CHOOSER_PROP_FILTER:
+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
+ case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
+ case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
+ case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
+ g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value);
+ break;
+
+ case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
+ g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value);
+ fs_volumes_changed_cb (priv->fs, entry);
+ fs_bookmarks_changed_cb (priv->fs, entry);
+ break;
+
+ case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
+ /* Construct-only */
+ priv->backend = g_value_dup_string (value);
+ break;
+
+ case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
+ g_warning ("%s: Choosers of type `%s` do not support selecting multiple files.",
+ G_STRFUNC, G_OBJECT_TYPE_NAME (object));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_file_chooser_entry_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (object);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ switch (param_id)
+ {
+ case PROP_WIDTH_CHARS:
+ g_value_set_int (value,
+ gtk_label_get_width_chars (GTK_LABEL (priv->label)));
+ break;
+ case PROP_FOCUS_ON_CLICK:
+ g_value_set_boolean (value,
+ gtk_file_chooser_entry_get_focus_on_click (entry));
+ break;
+
+ case PROP_TITLE:
+ case GTK_FILE_CHOOSER_PROP_ACTION:
+ case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
+ case GTK_FILE_CHOOSER_PROP_FILTER:
+ case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
+ case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
+ case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
+ case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
+ case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
+ g_object_get_property (G_OBJECT (priv->dialog), pspec->name, value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_file_chooser_entry_finalize (GObject *object)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (object);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ if (priv->old_path)
+ gtk_file_path_free (priv->old_path);
+
+ if (G_OBJECT_CLASS (gtk_file_chooser_entry_parent_class)->finalize != NULL)
+ (*G_OBJECT_CLASS (gtk_file_chooser_entry_parent_class)->finalize) (object);
+}
+
+/* ********************* *
+ * GtkObject Functions *
+ * ********************* */
+
+static void
+gtk_file_chooser_entry_destroy (GtkObject *object)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (object);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GtkTreeIter iter;
+ GSList *l;
+
+ if (priv->dialog != NULL)
+ {
+ gtk_widget_destroy (priv->dialog);
+ priv->dialog = NULL;
+ }
+
+ if (priv->model && gtk_tree_model_get_iter_first (priv->model, &iter)) do
+ {
+ model_free_row_data (entry, &iter);
+ }
+ while (gtk_tree_model_iter_next (priv->model, &iter));
+
+ if (priv->dnd_select_folder_handle)
+ {
+ gtk_file_system_cancel_operation (priv->dnd_select_folder_handle);
+ priv->dnd_select_folder_handle = NULL;
+ }
+
+ if (priv->update_entry_handle)
+ {
+ gtk_file_system_cancel_operation (priv->update_entry_handle);
+ priv->update_entry_handle = NULL;
+ }
+
+ if (priv->change_icon_theme_handles)
+ {
+ for (l = priv->change_icon_theme_handles; l; l = l->next)
+ {
+ GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data);
+ gtk_file_system_cancel_operation (handle);
+ }
+ g_slist_free (priv->change_icon_theme_handles);
+ priv->change_icon_theme_handles = NULL;
+ }
+
+ if (priv->model)
+ {
+ g_object_unref (priv->model);
+ priv->model = NULL;
+ }
+
+ if (priv->filter_model)
+ {
+ g_object_unref (priv->filter_model);
+ priv->filter_model = NULL;
+ }
+
+ if (priv->fs)
+ {
+ g_signal_handler_disconnect (priv->fs, priv->fs_volumes_changed_id);
+ g_signal_handler_disconnect (priv->fs, priv->fs_bookmarks_changed_id);
+ g_object_unref (priv->fs);
+ priv->fs = NULL;
+ }
+
+ if (GTK_OBJECT_CLASS (gtk_file_chooser_entry_parent_class)->destroy != NULL)
+ (*GTK_OBJECT_CLASS (gtk_file_chooser_entry_parent_class)->destroy) (object);
+}
+
+
+/* ********************* *
+ * GtkWidget Functions *
+ * ********************* */
+
+struct DndSelectFolderData
+{
+ GtkFileChooserEntry *entry;
+ GtkFileChooserAction action;
+ GtkFilePath *path;
+ gchar **uris;
+ guint i;
+ gboolean selected;
+};
+
+static void
+dnd_select_folder_get_info_cb (GtkFileSystemHandle *handle,
+ const GtkFileInfo *info,
+ const GError *error,
+ gpointer user_data)
+{
+ gboolean cancelled = handle->cancelled;
+ struct DndSelectFolderData *data = user_data;
+
+ if (handle != data->entry->priv->dnd_select_folder_handle)
+ {
+ g_object_unref (data->entry);
+ gtk_file_path_free (data->path);
+ g_strfreev (data->uris);
+ g_free (data);
+
+ g_object_unref (handle);
+ return;
+ }
+
+ data->entry->priv->dnd_select_folder_handle = NULL;
+
+ if (!cancelled && !error && info != NULL)
+ {
+ data->selected =
+ (((data->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
+ gtk_file_info_get_is_folder (info)) ||
+ (data->action == GTK_FILE_CHOOSER_ACTION_OPEN &&
+ !gtk_file_info_get_is_folder (info))) &&
+ _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (data->entry->priv->dialog),
+ data->path, NULL));
+ }
+ else
+ data->selected = FALSE;
+
+ if (data->selected || data->uris[++data->i] == NULL)
+ {
+ g_object_unref (data->entry);
+ gtk_file_path_free (data->path);
+ g_strfreev (data->uris);
+ g_free (data);
+
+ g_object_unref (handle);
+ return;
+ }
+
+ if (data->path)
+ gtk_file_path_free (data->path);
+
+ data->path = gtk_file_system_uri_to_path (handle->file_system,
+ data->uris[data->i]);
+
+ data->entry->priv->dnd_select_folder_handle =
+ gtk_file_system_get_info (handle->file_system, data->path,
+ GTK_FILE_INFO_IS_FOLDER,
+ dnd_select_folder_get_info_cb, user_data);
+
+ g_object_unref (handle);
+}
+
+static void
+gtk_file_chooser_entry_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *data,
+ guint type,
+ guint drag_time)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (widget);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GtkFilePath *path;
+ gchar *text;
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->drag_data_received != NULL)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->drag_data_received) (widget,
+ context,
+ x, y,
+ data, type,
+ drag_time);
+
+ if (widget == NULL || context == NULL || data == NULL || data->length < 0)
+ return;
+
+ switch (type)
+ {
+ case TEXT_URI_LIST:
+ {
+ gchar **uris;
+ struct DndSelectFolderData *info;
+
+ uris = gtk_selection_data_get_uris (data);
+
+ if (uris == NULL)
+ break;
+
+ info = g_new0 (struct DndSelectFolderData, 1);
+ info->entry = g_object_ref (entry);
+ info->i = 0;
+ info->uris = uris;
+ info->selected = FALSE;
+ g_object_get (priv->dialog, "action", &info->action, NULL);
+
+ info->path = gtk_file_system_uri_to_path (priv->fs,
+ info->uris[info->i]);
+
+ if (priv->dnd_select_folder_handle)
+ gtk_file_system_cancel_operation (priv->dnd_select_folder_handle);
+
+ priv->dnd_select_folder_handle =
+ gtk_file_system_get_info (priv->fs, info->path,
+ GTK_FILE_INFO_IS_FOLDER,
+ dnd_select_folder_get_info_cb, info);
+ }
+ break;
+
+ case TEXT_PLAIN:
+ text = (char*) gtk_selection_data_get_text (data);
+ path = gtk_file_path_new_steal (text);
+ _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (priv->dialog), path,
+ NULL);
+ gtk_file_path_free (path);
+ break;
+
+ default:
+ break;
+ }
+
+ gtk_drag_finish (context, TRUE, FALSE, drag_time);
+}
+
+static void
+gtk_file_chooser_entry_show_all (GtkWidget *widget)
+{
+ gtk_widget_show (widget);
+}
+
+static void
+gtk_file_chooser_entry_hide_all (GtkWidget *widget)
+{
+ gtk_widget_hide (widget);
+}
+
+static void
+gtk_file_chooser_entry_show (GtkWidget *widget)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (widget);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->show)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->show) (widget);
+
+ if (priv->active)
+ open_dialog (GTK_FILE_CHOOSER_ENTRY (widget));
+}
+
+static void
+gtk_file_chooser_entry_hide (GtkWidget *widget)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (widget);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ gtk_widget_hide (priv->dialog);
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->hide)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->hide) (widget);
+}
+
+static void
+gtk_file_chooser_entry_map (GtkWidget *widget)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (widget);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ if (!priv->folder_has_been_set)
+ {
+ char *current_working_dir;
+
+ current_working_dir = g_get_current_dir ();
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), current_working_dir);
+ g_free (current_working_dir);
+
+ priv->folder_has_been_set = TRUE;
+ }
+
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->map)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->map) (widget);
+}
+
+static gboolean
+gtk_file_chooser_entry_mnemonic_activate (GtkWidget *widget,
+ gboolean group_cycling)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (widget);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (priv->dialog)))
+ {
+ case GTK_FILE_CHOOSER_ACTION_OPEN:
+ gtk_widget_grab_focus (priv->button);
+ break;
+ case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ return gtk_widget_mnemonic_activate (priv->combo_box, group_cycling);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return TRUE;
+}
+
+/* Changes the icons wherever it is needed */
+struct ChangeIconThemeData
+{
+ GtkFileChooserEntry *entry;
+ GtkTreeRowReference *row_ref;
+};
+
+static void
+change_icon_theme_get_info_cb (GtkFileSystemHandle *handle,
+ const GtkFileInfo *info,
+ const GError *error,
+ gpointer user_data)
+{
+ gboolean cancelled = handle->cancelled;
+ GdkPixbuf *pixbuf;
+ struct ChangeIconThemeData *data = user_data;
+
+ if (!g_slist_find (data->entry->priv->change_icon_theme_handles, handle))
+ goto out;
+
+ data->entry->priv->change_icon_theme_handles =
+ g_slist_remove (data->entry->priv->change_icon_theme_handles, handle);
+
+ if (cancelled || error)
+ goto out;
+
+ pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->entry),
+ data->entry->priv->icon_size, NULL);
+
+ if (pixbuf)
+ {
+ gint width = 0;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ width = MAX (width, gdk_pixbuf_get_width (pixbuf));
+
+ path = gtk_tree_row_reference_get_path (data->row_ref);
+ if (path)
+ {
+ gtk_tree_model_get_iter (data->entry->priv->model, &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_list_store_set (GTK_LIST_STORE (data->entry->priv->model), &iter,
+ ICON_COLUMN, pixbuf,
+ -1);
+
+ g_object_set (data->entry->priv->icon_cell,
+ "width", width,
+ NULL);
+ }
+ g_object_unref (pixbuf);
+ }
+
+out:
+ g_object_unref (data->entry);
+ gtk_tree_row_reference_free (data->row_ref);
+ g_free (data);
+
+ g_object_unref (handle);
+}
+
+static void
+change_icon_theme (GtkFileChooserEntry *entry)
+{
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GtkSettings *settings;
+ GtkIconTheme *theme;
+ GtkTreeIter iter;
+ GSList *l;
+ gint width = 0, height = 0;
+
+ for (l = entry->priv->change_icon_theme_handles; l; l = l->next)
+ {
+ GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data);
+ gtk_file_system_cancel_operation (handle);
+ }
+ g_slist_free (entry->priv->change_icon_theme_handles);
+ entry->priv->change_icon_theme_handles = NULL;
+
+ settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (entry)));
+
+ if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
+ &width, &height))
+ priv->icon_size = MAX (width, height);
+ else
+ priv->icon_size = FALLBACK_ICON_SIZE;
+
+ update_label_and_image (entry);
+
+ gtk_tree_model_get_iter_first (priv->model, &iter);
+
+ theme = get_icon_theme (GTK_WIDGET (entry));
+
+ do
+ {
+ GdkPixbuf *pixbuf;
+ gchar type;
+ gpointer data;
+
+ type = ROW_TYPE_INVALID;
+ gtk_tree_model_get (priv->model, &iter,
+ TYPE_COLUMN, &type,
+ DATA_COLUMN, &data,
+ -1);
+
+ switch (type)
+ {
+ case ROW_TYPE_SPECIAL:
+ case ROW_TYPE_SHORTCUT:
+ case ROW_TYPE_BOOKMARK:
+ case ROW_TYPE_CURRENT_FOLDER:
+ if (data)
+ {
+ if (gtk_file_system_path_is_local (priv->fs, (GtkFilePath *)data))
+ {
+ GtkTreePath *path;
+ GtkFileSystemHandle *handle;
+ struct ChangeIconThemeData *info;
+
+ info = g_new0 (struct ChangeIconThemeData, 1);
+ info->entry = g_object_ref (entry);
+ path = gtk_tree_model_get_path (priv->model, &iter);
+ info->row_ref = gtk_tree_row_reference_new (priv->model, path);
+ gtk_tree_path_free (path);
+
+ handle =
+ gtk_file_system_get_info (priv->fs, data, GTK_FILE_INFO_ICON,
+ change_icon_theme_get_info_cb,
+ info);
+ entry->priv->change_icon_theme_handles =
+ g_slist_append (entry->priv->change_icon_theme_handles, handle);
+ pixbuf = NULL;
+ }
+ else
+ /* Don't call get_info for remote paths to avoid latency and
+ * auth dialogs.
+ * If we switch to a better bookmarks file format (XBEL), we
+ * should use mime info to get a better icon.
+ */
+ pixbuf = gtk_icon_theme_load_icon (theme, "gnome-fs-share",
+ priv->icon_size, 0, NULL);
+ }
+ else
+ pixbuf = gtk_icon_theme_load_icon (theme, FALLBACK_ICON_NAME,
+ priv->icon_size, 0, NULL);
+ break;
+ case ROW_TYPE_VOLUME:
+ if (data)
+ pixbuf = gtk_file_system_volume_render_icon (priv->fs, data,
+ GTK_WIDGET (entry),
+ priv->icon_size,
+ NULL);
+ else
+ pixbuf = gtk_icon_theme_load_icon (theme, FALLBACK_ICON_NAME,
+ priv->icon_size, 0, NULL);
+ break;
+ default:
+ continue;
+ break;
+ }
+
+ if (pixbuf)
+ width = MAX (width, gdk_pixbuf_get_width (pixbuf));
+
+ gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
+ ICON_COLUMN, pixbuf,
+ -1);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+ }
+ while (gtk_tree_model_iter_next (priv->model, &iter));
+
+ g_object_set (entry->priv->icon_cell,
+ "width", width,
+ NULL);
+}
+
+static void
+gtk_file_chooser_entry_style_set (GtkWidget *widget,
+ GtkStyle *old_style)
+{
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->style_set)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->style_set) (widget,
+ old_style);
+
+ if (gtk_widget_has_screen (widget))
+ change_icon_theme (GTK_FILE_CHOOSER_ENTRY (widget));
+}
+
+static void
+gtk_file_chooser_entry_screen_changed (GtkWidget *widget,
+ GdkScreen *old_screen)
+{
+ if (GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->screen_changed)
+ (*GTK_WIDGET_CLASS (gtk_file_chooser_entry_parent_class)->screen_changed) (widget,
+ old_screen);
+
+ change_icon_theme (GTK_FILE_CHOOSER_ENTRY (widget));
+}
+
+
+/* ******************* *
+ * Utility Functions *
+ * ******************* */
+
+/* General */
+static GtkIconTheme *
+get_icon_theme (GtkWidget *widget)
+{
+ if (gtk_widget_has_screen (widget))
+ return gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
+
+ return gtk_icon_theme_get_default ();
+}
+
+
+struct SetDisplayNameData
+{
+ GtkFileChooserEntry *entry;
+ char *label;
+ GtkTreeRowReference *row_ref;
+};
+
+static void
+set_info_get_info_cb (GtkFileSystemHandle *handle,
+ const GtkFileInfo *info,
+ const GError *error,
+ gpointer callback_data)
+{
+ gboolean cancelled = handle->cancelled;
+ GdkPixbuf *pixbuf;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GtkFileSystemHandle *model_handle;
+ struct SetDisplayNameData *data = callback_data;
+
+ if (!data->entry->priv->model)
+ /* entry got destroyed */
+ goto out;
+
+ path = gtk_tree_row_reference_get_path (data->row_ref);
+ if (!path)
+ /* Handle doesn't exist anymore in the model */
+ goto out;
+
+ gtk_tree_model_get_iter (data->entry->priv->model, &iter, path);
+ gtk_tree_path_free (path);
+
+ /* Validate the handle */
+ gtk_tree_model_get (data->entry->priv->model, &iter,
+ HANDLE_COLUMN, &model_handle,
+ -1);
+ if (handle != model_handle)
+ goto out;
+
+ gtk_list_store_set (GTK_LIST_STORE (data->entry->priv->model), &iter,
+ HANDLE_COLUMN, NULL,
+ -1);
+
+ if (cancelled || error)
+ /* There was an error, leave the fallback name in there */
+ goto out;
+
+ pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->entry),
+ data->entry->priv->icon_size, NULL);
+
+ if (!data->label)
+ data->label = g_strdup (gtk_file_info_get_display_name (info));
+
+ gtk_list_store_set (GTK_LIST_STORE (data->entry->priv->model), &iter,
+ ICON_COLUMN, pixbuf,
+ DISPLAY_NAME_COLUMN, data->label,
+ IS_FOLDER_COLUMN, gtk_file_info_get_is_folder (info),
+ -1);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+out:
+ g_object_unref (data->entry);
+ g_free (data->label);
+ gtk_tree_row_reference_free (data->row_ref);
+ g_free (data);
+
+ g_object_unref (handle);
+}
+
+static void
+set_info_for_path_at_iter (GtkFileChooserEntry *entry,
+ const GtkFilePath *path,
+ GtkTreeIter *iter)
+{
+ struct SetDisplayNameData *data;
+ GtkTreePath *tree_path;
+ GtkFileSystemHandle *handle;
+
+ data = g_new0 (struct SetDisplayNameData, 1);
+ data->entry = g_object_ref (entry);
+ data->label = gtk_file_system_get_bookmark_label (entry->priv->fs, path);
+
+ tree_path = gtk_tree_model_get_path (entry->priv->model, iter);
+ data->row_ref = gtk_tree_row_reference_new (entry->priv->model, tree_path);
+ gtk_tree_path_free (tree_path);
+
+ handle = gtk_file_system_get_info (entry->priv->fs, path,
+ GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_ICON,
+ set_info_get_info_cb, data);
+
+ gtk_list_store_set (GTK_LIST_STORE (entry->priv->model), iter,
+ HANDLE_COLUMN, handle,
+ -1);
+}
+
+/* Shortcuts Model */
+static gint
+model_get_type_position (GtkFileChooserEntry *entry,
+ RowType row_type)
+{
+ gint retval = 0;
+
+ if (row_type == ROW_TYPE_SPECIAL)
+ return retval;
+
+ retval += entry->priv->n_special;
+
+ if (row_type == ROW_TYPE_VOLUME)
+ return retval;
+
+ retval += entry->priv->n_volumes;
+
+ if (row_type == ROW_TYPE_SHORTCUT)
+ return retval;
+
+ retval += entry->priv->n_shortcuts;
+
+ if (row_type == ROW_TYPE_BOOKMARK_SEPARATOR)
+ return retval;
+
+ retval += entry->priv->has_bookmark_separator;
+
+ if (row_type == ROW_TYPE_BOOKMARK)
+ return retval;
+
+ retval += entry->priv->n_bookmarks;
+
+ if (row_type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR)
+ return retval;
+
+ retval += entry->priv->has_current_folder_separator;
+
+ if (row_type == ROW_TYPE_CURRENT_FOLDER)
+ return retval;
+
+ retval += entry->priv->has_current_folder;
+
+ if (row_type == ROW_TYPE_OTHER_SEPARATOR)
+ return retval;
+
+ retval += entry->priv->has_other_separator;
+
+ if (row_type == ROW_TYPE_OTHER)
+ return retval;
+
+ g_assert_not_reached ();
+ return -1;
+}
+
+static void
+model_free_row_data (GtkFileChooserEntry *entry,
+ GtkTreeIter *iter)
+{
+ gchar *path;
+ gchar type;
+ gpointer data;
+ GtkFileSystemHandle *handle;
+
+ gtk_tree_model_get (entry->priv->model, iter,
+ PATH_COLUMN, &path,
+ TYPE_COLUMN, &type,
+ DATA_COLUMN, &data,
+ HANDLE_COLUMN, &handle,
+ -1);
+
+ if (handle)
+ gtk_file_system_cancel_operation (handle);
+
+ g_free (path);
+
+ switch (type)
+ {
+ case ROW_TYPE_SPECIAL:
+ case ROW_TYPE_SHORTCUT:
+ case ROW_TYPE_BOOKMARK:
+ case ROW_TYPE_CURRENT_FOLDER:
+ gtk_file_path_free (data);
+ break;
+ case ROW_TYPE_VOLUME:
+ gtk_file_system_volume_free (entry->priv->fs, data);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+model_add_special_get_info_cb (GtkFileSystemHandle *handle,
+ const GtkFileInfo *info,
+ const GError *error,
+ gpointer user_data)
+{
+ gboolean cancelled = handle->cancelled;
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GdkPixbuf *pixbuf;
+ GtkFileSystemHandle *model_handle;
+ struct ChangeIconThemeData *data = user_data;
+ gchar *name;
+
+ if (!data->entry->priv->model)
+ /* entry got destroyed */
+ goto out;
+
+ path = gtk_tree_row_reference_get_path (data->row_ref);
+ if (!path)
+ /* Handle doesn't exist anymore in the model */
+ goto out;
+
+ gtk_tree_model_get_iter (data->entry->priv->model, &iter, path);
+ gtk_tree_path_free (path);
+
+ gtk_tree_model_get (data->entry->priv->model, &iter,
+ HANDLE_COLUMN, &model_handle,
+ -1);
+ if (handle != model_handle)
+ goto out;
+
+ gtk_list_store_set (GTK_LIST_STORE (data->entry->priv->model), &iter,
+ HANDLE_COLUMN, NULL,
+ -1);
+
+ if (cancelled || error)
+ goto out;
+
+ pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->entry),
+ data->entry->priv->icon_size, NULL);
+
+ if (pixbuf)
+ {
+ gtk_list_store_set (GTK_LIST_STORE (data->entry->priv->model), &iter,
+ ICON_COLUMN, pixbuf,
+ -1);
+ g_object_unref (pixbuf);
+ }
+
+ gtk_tree_model_get (data->entry->priv->model, &iter,
+ DISPLAY_NAME_COLUMN, &name,
+ -1);
+ if (!name)
+ gtk_list_store_set (GTK_LIST_STORE (data->entry->priv->model), &iter,
+ DISPLAY_NAME_COLUMN, gtk_file_info_get_display_name (info),
+ -1);
+ g_free (name);
+
+out:
+ g_object_unref (data->entry);
+ gtk_tree_row_reference_free (data->row_ref);
+ g_free (data);
+
+ g_object_unref (handle);
+}
+
+static inline void
+model_add_special (GtkFileChooserEntry *entry)
+{
+ const gchar *homedir;
+ const gchar *desktopdir;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ GtkFilePath *path;
+ gint pos;
+
+ store = GTK_LIST_STORE (entry->priv->model);
+ pos = model_get_type_position (entry, ROW_TYPE_SPECIAL);
+
+ homedir = g_get_home_dir ();
+
+ if (homedir)
+ {
+ GtkTreePath *tree_path;
+ GtkFileSystemHandle *handle;
+ struct ChangeIconThemeData *info;
+
+ path = gtk_file_system_filename_to_path (entry->priv->fs, homedir);
+ gtk_list_store_insert (store, &iter, pos);
+ pos++;
+
+ info = g_new0 (struct ChangeIconThemeData, 1);
+ info->entry = g_object_ref (entry);
+ tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+ info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store),
+ tree_path);
+ gtk_tree_path_free (tree_path);
+
+ handle = gtk_file_system_get_info (entry->priv->fs, path,
+ GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON,
+ model_add_special_get_info_cb, info);
+
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, NULL,
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ TYPE_COLUMN, ROW_TYPE_SPECIAL,
+ DATA_COLUMN, path,
+ IS_FOLDER_COLUMN, TRUE,
+ HANDLE_COLUMN, handle,
+ -1);
+
+ entry->priv->n_special++;
+ }
+
+ desktopdir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
+
+ if (desktopdir)
+ {
+ GtkTreePath *tree_path;
+ GtkFileSystemHandle *handle;
+ struct ChangeIconThemeData *info;
+
+ path = gtk_file_system_filename_to_path (entry->priv->fs, desktopdir);
+ gtk_list_store_insert (store, &iter, pos);
+ pos++;
+
+ info = g_new0 (struct ChangeIconThemeData, 1);
+ info->entry = g_object_ref (entry);
+ tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
+ info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (store),
+ tree_path);
+ gtk_tree_path_free (tree_path);
+
+ handle = gtk_file_system_get_info (entry->priv->fs, path,
+ GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON,
+ model_add_special_get_info_cb, info);
+
+ gtk_list_store_set (store, &iter,
+ TYPE_COLUMN, ROW_TYPE_SPECIAL,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, _(DESKTOP_DISPLAY_NAME),
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ DATA_COLUMN, path,
+ IS_FOLDER_COLUMN, TRUE,
+ HANDLE_COLUMN, handle,
+ -1);
+
+ entry->priv->n_special++;
+ }
+}
+
+static void
+model_add_volumes (GtkFileChooserEntry *entry,
+ GSList *volumes)
+{
+ GtkListStore *store;
+ gint pos;
+ gboolean local_only;
+ GtkFileSystem *file_system;
+ GSList *l;
+
+ if (!volumes)
+ return;
+
+ store = GTK_LIST_STORE (entry->priv->model);
+ pos = model_get_type_position (entry, ROW_TYPE_VOLUME);
+ local_only = gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (entry->priv->dialog));
+ file_system = entry->priv->fs;
+
+ for (l = volumes; l; l = l->next)
+ {
+ GtkFileSystemVolume *volume;
+ GtkTreeIter iter;
+ GdkPixbuf *pixbuf;
+ gchar *display_name;
+ GtkFilePath *path;
+
+ volume = l->data;
+
+ if (local_only)
+ {
+ if (gtk_file_system_volume_get_is_mounted (file_system, volume))
+ {
+ GtkFilePath *base_path;
+
+ base_path = gtk_file_system_volume_get_base_path (file_system, volume);
+ if (base_path != NULL)
+ {
+ gboolean is_local = gtk_file_system_path_is_local (file_system, base_path);
+ gtk_file_path_free (base_path);
+
+ if (!is_local)
+ {
+ gtk_file_system_volume_free (file_system, volume);
+ continue;
+ }
+ }
+ }
+ }
+
+ pixbuf = gtk_file_system_volume_render_icon (file_system,
+ volume,
+ GTK_WIDGET (entry),
+ entry->priv->icon_size,
+ NULL);
+ display_name = gtk_file_system_volume_get_display_name (file_system, volume);
+
+ path = gtk_file_system_volume_get_base_path (file_system, volume);
+
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, pixbuf,
+ DISPLAY_NAME_COLUMN, display_name,
+ PATH_COLUMN, gtk_file_system_path_to_filename (file_system, path),
+ TYPE_COLUMN, ROW_TYPE_VOLUME,
+ DATA_COLUMN, volume,
+ IS_FOLDER_COLUMN, TRUE,
+ -1);
+
+ gtk_file_path_free (path);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+ g_free (display_name);
+
+ entry->priv->n_volumes++;
+ pos++;
+ }
+}
+
+extern gchar * _gtk_file_chooser_label_for_uri (const gchar *uri);
+
+static void
+model_add_bookmarks (GtkFileChooserEntry *entry,
+ GSList *bookmarks)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ gint pos;
+ gboolean local_only;
+ GSList *l;
+
+ if (!bookmarks)
+ return;
+
+ store = GTK_LIST_STORE (entry->priv->model);
+ pos = model_get_type_position (entry, ROW_TYPE_BOOKMARK);
+ local_only = gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (entry->priv->dialog));
+
+ for (l = bookmarks; l; l = l->next)
+ {
+ GtkFilePath *path;
+
+ path = l->data;
+
+ if (gtk_file_system_path_is_local (entry->priv->fs, path))
+ {
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME),
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ TYPE_COLUMN, ROW_TYPE_BOOKMARK,
+ DATA_COLUMN, gtk_file_path_copy (path),
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+ set_info_for_path_at_iter (entry, path, &iter);
+ }
+ else
+ {
+ gchar *label;
+ GtkIconTheme *icon_theme;
+ GdkPixbuf *pixbuf;
+
+ if (local_only)
+ continue;
+
+ /* Don't call get_info for remote paths to avoid latency and
+ * auth dialogs.
+ * If we switch to a better bookmarks file format (XBEL), we
+ * should use mime info to get a better icon.
+ */
+ label = gtk_file_system_get_bookmark_label (entry->priv->fs, path);
+ if (!label)
+ {
+ gchar *uri;
+
+ uri = gtk_file_system_path_to_uri (entry->priv->fs, path);
+ label = _gtk_file_chooser_label_for_uri (uri);
+ g_free (uri);
+ }
+
+ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (entry)));
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share",
+ entry->priv->icon_size, 0, NULL);
+
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, pixbuf,
+ DISPLAY_NAME_COLUMN, label,
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ TYPE_COLUMN, ROW_TYPE_BOOKMARK,
+ DATA_COLUMN, gtk_file_path_copy (path),
+ IS_FOLDER_COLUMN, TRUE,
+ -1);
+
+ g_free (label);
+ g_object_unref (pixbuf);
+ }
+
+ entry->priv->n_bookmarks++;
+ pos++;
+ }
+
+ if (entry->priv->n_bookmarks > 0 &&
+ !entry->priv->has_bookmark_separator)
+ {
+ pos = model_get_type_position (entry, ROW_TYPE_BOOKMARK_SEPARATOR);
+
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, NULL,
+ PATH_COLUMN, NULL,
+ TYPE_COLUMN, ROW_TYPE_BOOKMARK_SEPARATOR,
+ DATA_COLUMN, NULL,
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+ entry->priv->has_bookmark_separator = TRUE;
+ }
+}
+
+static void
+model_update_current_folder (GtkFileChooserEntry *entry,
+ const GtkFilePath *path)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ gint pos;
+
+ if (!path)
+ return;
+
+ store = GTK_LIST_STORE (entry->priv->model);
+
+ if (!entry->priv->has_current_folder_separator)
+ {
+ pos = model_get_type_position (entry, ROW_TYPE_CURRENT_FOLDER_SEPARATOR);
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, NULL,
+ PATH_COLUMN, NULL,
+ TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER_SEPARATOR,
+ DATA_COLUMN, NULL,
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+ entry->priv->has_current_folder_separator = TRUE;
+ }
+
+ pos = model_get_type_position (entry, ROW_TYPE_CURRENT_FOLDER);
+ if (!entry->priv->has_current_folder)
+ {
+ gtk_list_store_insert (store, &iter, pos);
+ entry->priv->has_current_folder = TRUE;
+ }
+ else
+ {
+ gtk_tree_model_iter_nth_child (entry->priv->model, &iter, NULL, pos);
+ model_free_row_data (entry, &iter);
+ }
+
+ if (gtk_file_system_path_is_local (entry->priv->fs, path))
+ {
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, _(FALLBACK_DISPLAY_NAME),
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER,
+ DATA_COLUMN, gtk_file_path_copy (path),
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+ set_info_for_path_at_iter (entry, path, &iter);
+ }
+ else
+ {
+ gchar *label;
+ GtkIconTheme *icon_theme;
+ GdkPixbuf *pixbuf;
+
+ /* Don't call get_info for remote paths to avoid latency and
+ * auth dialogs.
+ * If we switch to a better bookmarks file format (XBEL), we
+ * should use mime info to get a better icon.
+ */
+ label = gtk_file_system_get_bookmark_label (entry->priv->fs, path);
+ if (!label)
+ {
+ gchar *uri;
+
+ uri = gtk_file_system_path_to_uri (entry->priv->fs, path);
+ label = _gtk_file_chooser_label_for_uri (uri);
+ g_free (uri);
+ }
+
+ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (entry)));
+ if (gtk_file_system_path_is_local (entry->priv->fs, path))
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory",
+ entry->priv->icon_size, 0, NULL);
+ else
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share",
+ entry->priv->icon_size, 0, NULL);
+
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, pixbuf,
+ DISPLAY_NAME_COLUMN, label,
+ PATH_COLUMN, gtk_file_system_path_to_filename (entry->priv->fs, path),
+ TYPE_COLUMN, ROW_TYPE_CURRENT_FOLDER,
+ DATA_COLUMN, gtk_file_path_copy (path),
+ IS_FOLDER_COLUMN, TRUE,
+ -1);
+
+ g_free (label);
+ g_object_unref (pixbuf);
+ }
+}
+
+static inline void
+model_add_other (GtkFileChooserEntry *entry)
+{
+ GtkListStore *store;
+ GtkTreeIter iter;
+ gint pos;
+
+ store = GTK_LIST_STORE (entry->priv->model);
+ pos = model_get_type_position (entry, ROW_TYPE_OTHER_SEPARATOR);
+
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, NULL,
+ PATH_COLUMN, NULL,
+ TYPE_COLUMN, ROW_TYPE_OTHER_SEPARATOR,
+ DATA_COLUMN, NULL,
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+ entry->priv->has_other_separator = TRUE;
+ pos++;
+
+ gtk_list_store_insert (store, &iter, pos);
+ gtk_list_store_set (store, &iter,
+ ICON_COLUMN, NULL,
+ DISPLAY_NAME_COLUMN, _("Other..."),
+ PATH_COLUMN, NULL,
+ TYPE_COLUMN, ROW_TYPE_OTHER,
+ DATA_COLUMN, NULL,
+ IS_FOLDER_COLUMN, FALSE,
+ -1);
+}
+
+static void
+model_remove_rows (GtkFileChooserEntry *entry,
+ gint pos,
+ gint n_rows)
+{
+ GtkListStore *store;
+
+ if (!n_rows)
+ return;
+
+ store = GTK_LIST_STORE (entry->priv->model);
+
+ do
+ {
+ GtkTreeIter iter;
+
+ if (!gtk_tree_model_iter_nth_child (entry->priv->model, &iter, NULL, pos))
+ g_assert_not_reached ();
+
+ model_free_row_data (entry, &iter);
+ gtk_list_store_remove (store, &iter);
+ n_rows--;
+ }
+ while (n_rows);
+}
+
+/* Filter Model */
+static inline gboolean
+test_if_path_is_visible (GtkFileSystem *fs,
+ const GtkFilePath *path,
+ gboolean local_only,
+ gboolean is_folder)
+{
+ if (!path)
+ return FALSE;
+
+ if (local_only && !gtk_file_system_path_is_local (fs, path))
+ return FALSE;
+
+ if (!is_folder)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+filter_model_visible_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ gchar type;
+ gpointer data;
+ gboolean local_only, retval, is_folder;
+
+ type = ROW_TYPE_INVALID;
+ data = NULL;
+ local_only = gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog));
+
+ gtk_tree_model_get (model, iter,
+ TYPE_COLUMN, &type,
+ DATA_COLUMN, &data,
+ IS_FOLDER_COLUMN, &is_folder,
+ -1);
+
+ switch (type)
+ {
+ case ROW_TYPE_CURRENT_FOLDER:
+ retval = TRUE;
+ break;
+ case ROW_TYPE_SPECIAL:
+ case ROW_TYPE_SHORTCUT:
+ case ROW_TYPE_BOOKMARK:
+ retval = test_if_path_is_visible (priv->fs, data, local_only, is_folder);
+ break;
+ case ROW_TYPE_VOLUME:
+ {
+ retval = TRUE;
+ if (local_only)
+ {
+ if (gtk_file_system_volume_get_is_mounted (priv->fs, data))
+ {
+ GtkFilePath *base_path;
+
+ base_path = gtk_file_system_volume_get_base_path (priv->fs, data);
+ if (base_path)
+ {
+ gboolean is_local = gtk_file_system_path_is_local (priv->fs, base_path);
+
+ gtk_file_path_free (base_path);
+
+ if (!is_local)
+ retval = FALSE;
+ }
+ else
+ retval = FALSE;
+ }
+ }
+ }
+ break;
+ default:
+ retval = TRUE;
+ break;
+ }
+
+ return retval;
+}
+
+/* Combo Box */
+static void
+name_cell_data_func (GtkCellLayout *layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gchar type;
+
+ type = 0;
+ gtk_tree_model_get (model, iter,
+ TYPE_COLUMN, &type,
+ -1);
+
+ if (type == ROW_TYPE_CURRENT_FOLDER)
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ else
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL);
+}
+
+static gboolean
+combo_box_row_separator_func (GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gchar type = ROW_TYPE_INVALID;
+
+ gtk_tree_model_get (model, iter, TYPE_COLUMN, &type, -1);
+
+ return (type == ROW_TYPE_BOOKMARK_SEPARATOR ||
+ type == ROW_TYPE_CURRENT_FOLDER_SEPARATOR ||
+ type == ROW_TYPE_OTHER_SEPARATOR);
+}
+
+static void
+update_combo_box (GtkFileChooserEntry *entry)
+{
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GSList *paths;
+ GtkTreeIter iter;
+ gboolean row_found;
+
+ gtk_tree_model_get_iter_first (priv->filter_model, &iter);
+
+ paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
+
+ row_found = FALSE;
+
+ do
+ {
+ gchar type;
+ gpointer data;
+
+ type = ROW_TYPE_INVALID;
+ data = NULL;
+
+ gtk_tree_model_get (priv->filter_model, &iter,
+ TYPE_COLUMN, &type,
+ DATA_COLUMN, &data,
+ -1);
+
+ switch (type)
+ {
+ case ROW_TYPE_SPECIAL:
+ case ROW_TYPE_SHORTCUT:
+ case ROW_TYPE_BOOKMARK:
+ case ROW_TYPE_CURRENT_FOLDER:
+ row_found = (paths &&
+ paths->data &&
+ gtk_file_path_compare (data, paths->data) == 0);
+ break;
+ case ROW_TYPE_VOLUME:
+ {
+ GtkFilePath *base_path;
+
+ base_path = gtk_file_system_volume_get_base_path (priv->fs, data);
+ if (base_path)
+ {
+ row_found = (paths &&
+ paths->data &&
+ gtk_file_path_compare (base_path, paths->data) == 0);
+ gtk_file_path_free (base_path);
+ }
+ }
+ break;
+ default:
+ row_found = FALSE;
+ break;
+ }
+
+ if (row_found)
+ {
+ g_signal_handler_block (priv->combo_box, priv->combo_box_changed_id);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_box),
+ &iter);
+ g_signal_handler_unblock (priv->combo_box,
+ priv->combo_box_changed_id);
+ }
+ }
+ while (!row_found && gtk_tree_model_iter_next (priv->filter_model, &iter));
+
+ /* If it hasn't been found already, update & select the current-folder row. */
+ if (!row_found && paths && paths->data)
+ {
+ GtkTreeIter filter_iter;
+ gint pos;
+
+ model_update_current_folder (entry, paths->data);
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+
+ pos = model_get_type_position (entry, ROW_TYPE_CURRENT_FOLDER);
+ gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos);
+
+ gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (priv->filter_model),
+ &filter_iter, &iter);
+
+ g_signal_handler_block (priv->combo_box, priv->combo_box_changed_id);
+ gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combo_box), &filter_iter);
+ g_signal_handler_unblock (priv->combo_box, priv->combo_box_changed_id);
+ }
+
+ gtk_file_paths_free (paths);
+}
+
+/* Button */
+static void
+update_label_get_info_cb (GtkFileSystemHandle *handle,
+ const GtkFileInfo *info,
+ const GError *error,
+ gpointer data)
+{
+ gboolean cancelled = handle->cancelled;
+ GdkPixbuf *pixbuf;
+ GtkFileChooserEntry *entry = data;
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ if (handle != priv->update_entry_handle)
+ goto out;
+
+ priv->update_entry_handle = NULL;
+
+ if (cancelled || error)
+ goto out;
+
+ gtk_label_set_text (GTK_LABEL (priv->label), gtk_file_info_get_display_name (info));
+
+ pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (priv->image),
+ priv->icon_size, NULL);
+ if (!pixbuf)
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)),
+ FALLBACK_ICON_NAME,
+ priv->icon_size, 0, NULL);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
+ if (pixbuf)
+ g_object_unref (pixbuf);
+
+out:
+ g_object_unref (entry);
+ g_object_unref (handle);
+}
+
+static void
+update_label_and_image (GtkFileChooserEntry *entry)
+{
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GdkPixbuf *pixbuf;
+ gchar *label_text;
+ GSList *paths;
+
+ paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
+ label_text = NULL;
+ pixbuf = NULL;
+
+ if (paths && paths->data)
+ {
+ GtkFilePath *path;
+ GtkFileSystemVolume *volume = NULL;
+
+ path = paths->data;
+
+ volume = gtk_file_system_get_volume_for_path (priv->fs, path);
+ if (volume)
+ {
+ GtkFilePath *base_path;
+
+ base_path = gtk_file_system_volume_get_base_path (priv->fs, volume);
+ if (base_path && gtk_file_path_compare (base_path, path) == 0)
+ {
+ label_text = gtk_file_system_volume_get_display_name (priv->fs,
+ volume);
+ pixbuf = gtk_file_system_volume_render_icon (priv->fs, volume,
+ GTK_WIDGET (entry),
+ priv->icon_size,
+ NULL);
+ }
+
+ if (base_path)
+ gtk_file_path_free (base_path);
+
+ gtk_file_system_volume_free (priv->fs, volume);
+
+ if (label_text)
+ goto out;
+ }
+
+ if (priv->update_entry_handle)
+ {
+ gtk_file_system_cancel_operation (priv->update_entry_handle);
+ priv->update_entry_handle = NULL;
+ }
+
+ if (gtk_file_system_path_is_local (priv->fs, path))
+ {
+ priv->update_entry_handle =
+ gtk_file_system_get_info (priv->fs, path,
+ GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_ICON,
+ update_label_get_info_cb,
+ g_object_ref (entry));
+ }
+ else
+ {
+ GdkPixbuf *pixbuf;
+
+ label_text = gtk_file_system_get_bookmark_label (entry->priv->fs, path);
+
+ pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)),
+ "gnome-fs-regular",
+ priv->icon_size, 0, NULL);
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
+
+ if (pixbuf)
+ g_object_unref (pixbuf);
+ }
+ }
+out:
+ gtk_file_paths_free (paths);
+
+ if (label_text)
+ {
+ gtk_label_set_text (GTK_LABEL (priv->label), label_text);
+ g_free (label_text);
+ }
+ else
+ gtk_label_set_text (GTK_LABEL (priv->label), _(FALLBACK_DISPLAY_NAME));
+}
+
+
+/* ************************ *
+ * Child Object Callbacks *
+ * ************************ */
+
+/* File System */
+static void
+fs_volumes_changed_cb (GtkFileSystem *fs,
+ gpointer user_data)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GSList *volumes;
+
+ model_remove_rows (user_data,
+ model_get_type_position (user_data, ROW_TYPE_VOLUME),
+ priv->n_volumes);
+
+ priv->n_volumes = 0;
+
+ volumes = gtk_file_system_list_volumes (fs);
+ model_add_volumes (user_data, volumes);
+ g_slist_free (volumes);
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+
+ update_label_and_image (user_data);
+ update_combo_box (user_data);
+}
+
+static void
+fs_bookmarks_changed_cb (GtkFileSystem *fs,
+ gpointer user_data)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ GSList *bookmarks;
+
+ bookmarks = gtk_file_system_list_bookmarks (fs);
+ model_remove_rows (user_data,
+ model_get_type_position (user_data,
+ ROW_TYPE_BOOKMARK_SEPARATOR),
+ (priv->n_bookmarks + priv->has_bookmark_separator));
+ priv->has_bookmark_separator = FALSE;
+ priv->n_bookmarks = 0;
+ model_add_bookmarks (user_data, bookmarks);
+ gtk_file_paths_free (bookmarks);
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+
+ update_label_and_image (user_data);
+ update_combo_box (user_data);
+}
+
+/* Dialog */
+static void
+open_dialog (GtkFileChooserEntry *entry)
+{
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ /* Setup the dialog parent to be chooser entry's toplevel, and be modal
+ as needed. */
+ if (!GTK_WIDGET_VISIBLE (priv->dialog))
+ {
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (entry));
+
+ if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_IS_WINDOW (toplevel))
+ {
+ if (GTK_WINDOW (toplevel) != gtk_window_get_transient_for (GTK_WINDOW (priv->dialog)))
+ gtk_window_set_transient_for (GTK_WINDOW (priv->dialog),
+ GTK_WINDOW (toplevel));
+
+ gtk_window_set_modal (GTK_WINDOW (priv->dialog),
+ gtk_window_get_modal (GTK_WINDOW (toplevel)));
+ }
+ }
+
+ if (!priv->active)
+ {
+ GSList *paths;
+
+ g_signal_handler_block (priv->dialog,
+ priv->dialog_folder_changed_id);
+ g_signal_handler_block (priv->dialog,
+ priv->dialog_file_activated_id);
+ g_signal_handler_block (priv->dialog,
+ priv->dialog_selection_changed_id);
+ paths = _gtk_file_chooser_get_paths (GTK_FILE_CHOOSER (priv->dialog));
+ if (paths)
+ {
+ if (paths->data)
+ priv->old_path = gtk_file_path_copy (paths->data);
+
+ gtk_file_paths_free (paths);
+ }
+
+ priv->active = TRUE;
+ }
+
+ gtk_widget_set_sensitive (priv->combo_box, FALSE);
+ gtk_window_present (GTK_WINDOW (priv->dialog));
+}
+
+/* Combo Box */
+static void
+combo_box_changed_cb (GtkComboBox *combo_box,
+ gpointer user_data)
+{
+ GtkTreeIter iter;
+
+ if (gtk_combo_box_get_active_iter (combo_box, &iter))
+ {
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+ gchar type;
+ gpointer data;
+
+ type = ROW_TYPE_INVALID;
+ data = NULL;
+
+ gtk_tree_model_get (priv->filter_model, &iter,
+ TYPE_COLUMN, &type,
+ DATA_COLUMN, &data,
+ -1);
+
+ switch (type)
+ {
+ case ROW_TYPE_SPECIAL:
+ case ROW_TYPE_SHORTCUT:
+ case ROW_TYPE_BOOKMARK:
+ case ROW_TYPE_CURRENT_FOLDER:
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+ if (data)
+ _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
+ data, NULL);
+ break;
+ case ROW_TYPE_VOLUME:
+ {
+ GtkFilePath *base_path;
+
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (priv->dialog));
+ base_path = gtk_file_system_volume_get_base_path (priv->fs, data);
+ if (base_path)
+ {
+ _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (priv->dialog),
+ base_path, NULL);
+ gtk_file_path_free (base_path);
+ }
+ }
+ break;
+ case ROW_TYPE_OTHER:
+ open_dialog (user_data);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/* Button */
+static void
+button_clicked_cb (GtkButton *real_button,
+ gpointer user_data)
+{
+ open_dialog (user_data);
+}
+
+/* Dialog */
+static void
+dialog_current_folder_changed_cb (GtkFileChooser *dialog,
+ gpointer user_data)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ priv->folder_has_been_set = TRUE;
+
+ g_signal_emit_by_name (entry, "current-folder-changed");
+}
+
+static void
+dialog_file_activated_cb (GtkFileChooser *dialog,
+ gpointer user_data)
+{
+ g_signal_emit_by_name (user_data, "file-activated");
+}
+
+static void
+dialog_selection_changed_cb (GtkFileChooser *dialog,
+ gpointer user_data)
+{
+ update_label_and_image (user_data);
+ update_combo_box (user_data);
+ g_signal_emit_by_name (user_data, "selection-changed");
+}
+
+static void
+dialog_update_preview_cb (GtkFileChooser *dialog,
+ gpointer user_data)
+{
+ g_signal_emit_by_name (user_data, "update-preview");
+}
+
+static void
+dialog_notify_cb (GObject *dialog,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ gpointer iface;
+
+ iface = g_type_interface_peek (g_type_class_peek (G_OBJECT_TYPE (dialog)),
+ GTK_TYPE_FILE_CHOOSER);
+ if (g_object_interface_find_property (iface, pspec->name))
+ g_object_notify (user_data, pspec->name);
+
+ if (g_ascii_strcasecmp (pspec->name, "local-only") == 0)
+ {
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ if (priv->has_current_folder)
+ {
+ GtkTreeIter iter;
+ gint pos;
+ gpointer data;
+
+ pos = model_get_type_position (user_data,
+ ROW_TYPE_CURRENT_FOLDER);
+ gtk_tree_model_iter_nth_child (priv->model, &iter, NULL, pos);
+
+ data = NULL;
+ gtk_tree_model_get (priv->model, &iter, DATA_COLUMN, &data, -1);
+
+ /* If the path isn't local but we're in local-only mode now, remove
+ * the custom-folder row */
+ if (data &&
+ (!gtk_file_system_path_is_local (priv->fs, data) &&
+ gtk_file_chooser_get_local_only (GTK_FILE_CHOOSER (priv->dialog))))
+ {
+ pos--;
+ model_remove_rows (user_data, pos, 2);
+ }
+ }
+
+ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (priv->filter_model));
+ update_combo_box (user_data);
+ }
+}
+
+static gboolean
+dialog_delete_event_cb (GtkWidget *dialog,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ g_signal_emit_by_name (dialog, "response", GTK_RESPONSE_DELETE_EVENT);
+
+ return TRUE;
+}
+
+static void
+dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ gpointer user_data)
+{
+ GtkFileChooserEntry *entry = GTK_FILE_CHOOSER_ENTRY (user_data);
+ GtkFileChooserEntryPrivate *priv = entry->priv;
+
+ if (response == GTK_RESPONSE_ACCEPT ||
+ response == GTK_RESPONSE_OK)
+ {
+ g_signal_emit_by_name (user_data, "current-folder-changed");
+ g_signal_emit_by_name (user_data, "selection-changed");
+ }
+ else if (priv->old_path)
+ {
+ switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)))
+ {
+ case GTK_FILE_CHOOSER_ACTION_OPEN:
+ _gtk_file_chooser_select_path (GTK_FILE_CHOOSER (dialog), priv->old_path,
+ NULL);
+ break;
+ case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (dialog),
+ priv->old_path, NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+ else
+ gtk_file_chooser_unselect_all (GTK_FILE_CHOOSER (dialog));
+
+ if (priv->old_path)
+ {
+ gtk_file_path_free (priv->old_path);
+ priv->old_path = NULL;
+ }
+
+ update_label_and_image (user_data);
+ update_combo_box (user_data);
+
+ if (priv->active)
+ {
+ g_signal_handler_unblock (priv->dialog,
+ priv->dialog_folder_changed_id);
+ g_signal_handler_unblock (priv->dialog,
+ priv->dialog_file_activated_id);
+ g_signal_handler_unblock (priv->dialog,
+ priv->dialog_selection_changed_id);
+ priv->active = FALSE;
+ }
+
+ gtk_widget_set_sensitive (priv->combo_box, TRUE);
+ gtk_widget_hide (priv->dialog);
+
+ g_signal_emit_by_name (user_data, "file-set");
+}
+
+
+/* ************************************************************************** *
+ * Public API *
+ * ************************************************************************** */
+
+/**
+ * gtk_file_chooser_entry_new:
+ * @title: the title of the browse dialog.
+ * @action: the open mode for the widget.
+ *
+ * Creates a new file-selecting entry widget.
+ *
+ * Returns: a new entry widget.
+ *
+ * Since: 2.6
+ **/
+GtkWidget *
+gtk_file_chooser_entry_new (const gchar *title,
+ GtkFileChooserAction action)
+{
+ g_return_val_if_fail (action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, NULL);
+
+ return g_object_new (GTK_TYPE_FILE_CHOOSER_ENTRY,
+ "action", action,
+ "title", (title ? title : _(DEFAULT_TITLE)),
+ NULL);
+}
+
+/**
+ * gtk_file_chooser_entry_new_with_backend:
+ * @title: the title of the browse dialog.
+ * @action: the open mode for the widget.
+ * @backend: the name of the #GtkFileSystem backend to use.
+ *
+ * Creates a new file-selecting entry widget using @backend.
+ *
+ * Returns: a new entry widget.
+ *
+ * Since: 2.6
+ **/
+GtkWidget *
+gtk_file_chooser_entry_new_with_backend (const gchar *title,
+ GtkFileChooserAction action,
+ const gchar *backend)
+{
+ g_return_val_if_fail (action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, NULL);
+
+ return g_object_new (GTK_TYPE_FILE_CHOOSER_ENTRY,
+ "action", action,
+ "title", (title ? title : _(DEFAULT_TITLE)),
+ "file-system-backend", backend,
+ NULL);
+}
+
+/**
+ * gtk_file_chooser_entry_new_with_dialog:
+ * @dialog: the widget to use as dialog
+ *
+ * Creates a #GtkFileChooserEntry widget which uses @dialog as its
+ * file-picking window.
+ *
+ * Note that @dialog must be a #GtkDialog (or subclass) which
+ * implements the #GtkFileChooser interface and must not have
+ * %GTK_DIALOG_DESTROY_WITH_PARENT set.
+ *
+ * Also note that the dialog needs to have its confirmative entry
+ * added with response %GTK_RESPONSE_ACCEPT or %GTK_RESPONSE_OK in
+ * order for the entry to take over the file selected in the dialog.
+ *
+ * Returns: a new entry widget.
+ *
+ * Since: 2.6
+ **/
+GtkWidget *
+gtk_file_chooser_entry_new_with_dialog (GtkWidget *dialog)
+{
+ g_return_val_if_fail (GTK_IS_FILE_CHOOSER (dialog) && GTK_IS_DIALOG (dialog), NULL);
+
+ return g_object_new (GTK_TYPE_FILE_CHOOSER_ENTRY,
+ "dialog", dialog,
+ NULL);
+}
+
+/**
+ * gtk_file_chooser_entry_set_title:
+ * @entry: the entry widget to modify.
+ * @title: the new browse dialog title.
+ *
+ * Modifies the @title of the browse dialog used by @entry.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_file_chooser_entry_set_title (GtkFileChooserEntry *entry,
+ const gchar *title)
+{
+ g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry));
+
+ gtk_window_set_title (GTK_WINDOW (entry->priv->dialog), title);
+ g_object_notify (G_OBJECT (entry), "title");
+}
+
+/**
+ * gtk_file_chooser_entry_get_title:
+ * @entry: the entry widget to examine.
+ *
+ * Retrieves the title of the browse dialog used by @entry. The returned value
+ * should not be modified or freed.
+ *
+ * Returns: a pointer to the browse dialog's title.
+ *
+ * Since: 2.6
+ **/
+G_CONST_RETURN gchar *
+gtk_file_chooser_entry_get_title (GtkFileChooserEntry *entry)
+{
+ g_return_val_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry), NULL);
+
+ return gtk_window_get_title (GTK_WINDOW (entry->priv->dialog));
+}
+
+/**
+ * gtk_file_chooser_entry_get_width_chars:
+ * @entry: the entry widget to examine.
+ *
+ * Retrieves the width in characters of the @entry widget's entry and/or label.
+ *
+ * Returns: an integer width (in characters) that the entry will use to size itself.
+ *
+ * Since: 2.6
+ **/
+gint
+gtk_file_chooser_entry_get_width_chars (GtkFileChooserEntry *entry)
+{
+ g_return_val_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry), -1);
+
+ return gtk_label_get_width_chars (GTK_LABEL (entry->priv->label));
+}
+
+/**
+ * gtk_file_chooser_entry_set_width_chars:
+ * @entry: the entry widget to examine.
+ * @n_chars: the new width, in characters.
+ *
+ * Sets the width (in characters) that @entry will use to @n_chars.
+ *
+ * Since: 2.6
+ **/
+void
+gtk_file_chooser_entry_set_width_chars (GtkFileChooserEntry *entry,
+ gint n_chars)
+{
+ g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry));
+
+ gtk_label_set_width_chars (GTK_LABEL (entry->priv->label), n_chars);
+ g_object_notify (G_OBJECT (entry), "width-chars");
+}
+
+/**
+ * gtk_file_chooser_entry_set_focus_on_click:
+ * @entry: a #GtkFileChooserEntry
+ * @focus_on_click: whether the entry grabs focus when clicked with the mouse
+ *
+ * Sets whether the entry will grab focus when it is clicked with the mouse.
+ * Making mouse clicks not grab focus is useful in places like toolbars where
+ * you don't want the keyboard focus removed from the main area of the
+ * application.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_file_chooser_entry_set_focus_on_click (GtkFileChooserEntry *entry,
+ gboolean focus_on_click)
+{
+ GtkFileChooserEntryPrivate *priv;
+
+ g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry));
+
+ priv = entry->priv;
+
+ focus_on_click = focus_on_click != FALSE;
+
+ if (priv->focus_on_click != focus_on_click)
+ {
+ priv->focus_on_click = focus_on_click;
+ gtk_button_set_focus_on_click (GTK_BUTTON (priv->button), focus_on_click);
+ gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (priv->combo_box), focus_on_click);
+
+ g_object_notify (G_OBJECT (entry), "focus-on-click");
+ }
+}
+
+/**
+ * gtk_file_chooser_entry_get_focus_on_click:
+ * @entry: a #GtkFileChooserEntry
+ *
+ * Returns whether the entry grabs focus when it is clicked with the mouse.
+ * See gtk_file_chooser_entry_set_focus_on_click().
+ *
+ * Return value: %TRUE if the entry grabs focus when it is clicked with
+ * the mouse.
+ *
+ * Since: 2.10
+ **/
+gboolean
+gtk_file_chooser_entry_get_focus_on_click (GtkFileChooserEntry *entry)
+{
+ g_return_val_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (entry), FALSE);
+
+ return entry->priv->focus_on_click;
+}
+
+#define __GTK_FILE_CHOOSER_ENTRY_C__
+//#include <gtk/gtkaliasdef.c>
Added: thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.h
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.h (rev 0)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/gtkfilechooserentry.h 2007-10-18 22:30:16 UTC (rev 3399)
@@ -0,0 +1,92 @@
+/* GTK+: gtkfilechooserentry.h
+ *
+ * Copyright (c) 2004 James M. Cape <jcape at ignore-your.tv>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_FILE_CHOOSER_ENTRY_H__
+#define __GTK_FILE_CHOOSER_ENTRY_H__
+
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkfilechooser.h>
+
+G_BEGIN_DECLS
+
+
+#define GTK_TYPE_FILE_CHOOSER_ENTRY \
+ (gtk_file_chooser_entry_get_type ())
+#define GTK_FILE_CHOOSER_ENTRY(object) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_FILE_CHOOSER_ENTRY, GtkFileChooserEntry))
+#define GTK_FILE_CHOOSER_ENTRY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_ENTRY, GtkFileChooserEntryClass))
+#define GTK_IS_FILE_CHOOSER_ENTRY(object) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_FILE_CHOOSER_ENTRY))
+#define GTK_IS_FILE_CHOOSER_ENTRY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_CHOOSER_ENTRY))
+#define GTK_FILE_CHOOSER_ENTRY_GET_CLASS(object) \
+ (G_TYPE_INSTANCE_GET_CLASS ((object), GTK_TYPE_FILE_CHOOSER_ENTRY, GtkFileChooserEntryClass))
+
+
+typedef struct _GtkFileChooserEntry GtkFileChooserEntry;
+typedef struct _GtkFileChooserEntryPrivate GtkFileChooserEntryPrivate;
+typedef struct _GtkFileChooserEntryClass GtkFileChooserEntryClass;
+
+struct _GtkFileChooserEntry
+{
+ /*< private >*/
+ GtkHBox parent;
+
+ GtkFileChooserEntryPrivate *priv;
+};
+
+struct _GtkFileChooserEntryClass
+{
+ /*< private >*/
+ GtkHBoxClass parent_class;
+
+ void (* file_set) (GtkFileChooserEntry *fc);
+
+ void (*__gtk_reserved1);
+ void (*__gtk_reserved2);
+ void (*__gtk_reserved3);
+ void (*__gtk_reserved4);
+ void (*__gtk_reserved5);
+ void (*__gtk_reserved6);
+ void (*__gtk_reserved7);
+};
+
+
+GType gtk_file_chooser_entry_get_type (void) G_GNUC_CONST;
+GtkWidget * gtk_file_chooser_entry_new (const gchar *title,
+ GtkFileChooserAction action);
+GtkWidget * gtk_file_chooser_entry_new_with_backend (const gchar *title,
+ GtkFileChooserAction action,
+ const gchar *backend);
+GtkWidget * gtk_file_chooser_entry_new_with_dialog (GtkWidget *dialog);
+G_CONST_RETURN gchar *gtk_file_chooser_entry_get_title (GtkFileChooserEntry *entry);
+void gtk_file_chooser_entry_set_title (GtkFileChooserEntry *entry,
+ const gchar *title);
+gint gtk_file_chooser_entry_get_width_chars (GtkFileChooserEntry *entry);
+void gtk_file_chooser_entry_set_width_chars (GtkFileChooserEntry *entry,
+ gint n_chars);
+gboolean gtk_file_chooser_entry_get_focus_on_click (GtkFileChooserEntry *entry);
+void gtk_file_chooser_entry_set_focus_on_click (GtkFileChooserEntry *entry,
+ gboolean focus_on_click);
+
+G_END_DECLS
+
+#endif /* !__GTK_FILE_CHOOSER_ENTRY_H__ */
Modified: thunar-svn-plugin/trunk/tsp-svn-helper/main.c
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/main.c 2007-10-16 23:05:17 UTC (rev 3398)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/main.c 2007-10-18 22:30:16 UTC (rev 3399)
@@ -23,6 +23,7 @@
#endif
#include <glib.h>
+#include <glib/gprintf.h>
#include <gtk/gtk.h>
#include <thunar-vfs/thunar-vfs.h>
@@ -50,6 +51,7 @@
gboolean checkout = FALSE;
gboolean update = FALSE;
gchar **files = NULL;
+ GError *error = NULL;
GOptionEntry general_options_table[] =
{
@@ -87,7 +89,11 @@
g_thread_init (NULL);
gdk_threads_init ();
- g_option_context_parse(option_context, &argc, &argv, NULL);
+ if(!g_option_context_parse(option_context, &argc, &argv, &error))
+ {
+ g_fprintf(stderr, "%s: %s\n\tTry --help-all\n", g_get_prgname(), error->message);
+ g_error_free(error);
+ }
if(print_version)
{
Added: thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.c
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.c (rev 0)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.c 2007-10-18 22:30:16 UTC (rev 3399)
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 2006 Peter de Ridder <peter at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <thunar-vfs/thunar-vfs.h>
+#include <gtk/gtk.h>
+
+//#include "tsh-file-chooser-entry.h"
+#include "gtkfilechooserentry.h"
+
+#include "tsh-checkout-dialog.h"
+
+struct _TshCheckoutDialog
+{
+ GtkDialog dialog;
+
+ GtkWidget *repository;
+ GtkWidget *path;
+};
+
+struct _TshCheckoutDialogClass
+{
+ GtkDialogClass dialog_class;
+};
+
+G_DEFINE_TYPE (TshCheckoutDialog, tsh_checkout_dialog, GTK_TYPE_DIALOG)
+
+static void
+tsh_checkout_dialog_class_init (TshCheckoutDialogClass *klass)
+{
+}
+
+static void
+tsh_checkout_dialog_init (TshCheckoutDialog *dialog)
+{
+ GtkWidget *table;
+ GtkWidget *label;
+
+ table = gtk_table_new (2, 2, FALSE);
+
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, FALSE, TRUE, 0);
+ gtk_widget_show (table);
+
+ label = gtk_label_new_with_mnemonic (_("_Repository:"));
+ gtk_table_attach (GTK_TABLE (table), label,
+ 0, 1, 0, 1,
+ GTK_SHRINK | GTK_FILL,
+ GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ dialog->repository = gtk_file_chooser_entry_new(_("Select a folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);//tsh_file_chooser_entry_new ();
+ gtk_table_attach (GTK_TABLE (table), dialog->repository,
+ 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL,
+ GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->repository);
+ gtk_widget_show(label);
+ gtk_widget_show(dialog->repository);
+ gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (dialog->repository), FALSE);
+
+ label = gtk_label_new_with_mnemonic (_("_Checkout directory:"));
+ gtk_table_attach (GTK_TABLE (table), label,
+ 0, 1, 1, 2,
+ GTK_SHRINK | GTK_FILL,
+ GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ dialog->path = gtk_file_chooser_button_new (_("Select a folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ gtk_table_attach (GTK_TABLE (table), dialog->path,
+ 1, 2, 1, 2,
+ GTK_EXPAND | GTK_FILL,
+ GTK_SHRINK | GTK_FILL,
+ 0, 0);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->path);
+ gtk_widget_show(label);
+ gtk_widget_show(dialog->path);
+
+ gtk_window_set_title (GTK_WINDOW (dialog), _("Checkout"));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+}
+
+GtkWidget*
+tsh_checkout_dialog_new (const gchar *title, GtkWindow *parent, GtkDialogFlags flags, const gchar *checkout_dir)
+{
+ TshCheckoutDialog *dialog = g_object_new (TSH_TYPE_CHECKOUT_DIALOG, NULL);
+
+ if(title)
+ gtk_window_set_title (GTK_WINDOW(dialog), title);
+
+ if(parent)
+ gtk_window_set_transient_for (GTK_WINDOW(dialog), parent);
+
+ if(flags & GTK_DIALOG_MODAL)
+ gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+ if(flags & GTK_DIALOG_DESTROY_WITH_PARENT)
+ gtk_window_set_destroy_with_parent (GTK_WINDOW(dialog), TRUE);
+
+ if(flags & GTK_DIALOG_NO_SEPARATOR)
+ gtk_dialog_set_has_separator (GTK_DIALOG(dialog), FALSE);
+
+ if(checkout_dir)
+ {
+ gchar *absolute = NULL;
+ if(!g_path_is_absolute (checkout_dir))
+ {
+ //TODO: ".."
+ gchar *currdir = g_get_current_dir();
+ absolute = g_build_filename(currdir, (checkout_dir[0] == '.' && (!checkout_dir[1] || checkout_dir[1] == G_DIR_SEPARATOR || checkout_dir[1] == '/'))?&checkout_dir[1]:checkout_dir, NULL);
+ g_free (currdir);
+ }
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER(dialog->path), absolute?absolute:checkout_dir);
+ g_free (absolute);
+ }
+
+ return GTK_WIDGET(dialog);
+}
+
Added: thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.h
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.h (rev 0)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout-dialog.h 2007-10-18 22:30:16 UTC (rev 3399)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2006 Peter de Ridder <peter at xfce.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __TSH_CHECKOUT_DIALOG_H__
+#define __TSH_CHECKOUT_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _TshCheckoutDialogClass TshCheckoutDialogClass;
+typedef struct _TshCheckoutDialog TshCheckoutDialog;
+
+#define TSH_TYPE_CHECKOUT_DIALOG (tsh_checkout_dialog_get_type ())
+#define TSH_CHECKOUT_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TSH_TYPE_CHECKOUT_DIALOG, TshCheckoutDialog))
+#define TSH_CHECKOUT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TSH_TYPE_CHECKOUT_DIALOG, TshCheckoutDialogClass))
+#define TSH_IS_CHECKOUT_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TSH_TYPE_CHECKOUT_DIALOG))
+#define TSH_IS_CHECKOUT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TSH_TYPE_CHECKOUT_DIALOG))
+#define TSH_CHECKOUT_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TSH_TYPE_CHECKOUT_DIALOG, TshCheckoutDialogClass))
+
+GType tsh_checkout_dialog_get_type (void) G_GNUC_CONST G_GNUC_INTERNAL;
+
+GtkWidget* tsh_checkout_dialog_new (const gchar *title,
+ GtkWindow *parent,
+ GtkDialogFlags flags,
+ const gchar *checkout_dir) G_GNUC_MALLOC G_GNUC_INTERNAL;
+
+G_END_DECLS;
+
+#endif /* !__TSH_CHECKOUT_DIALOG_H__ */
Modified: thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout.c
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout.c 2007-10-16 23:05:17 UTC (rev 3398)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/tsh-checkout.c 2007-10-18 22:30:16 UTC (rev 3399)
@@ -36,6 +36,7 @@
#include "tsh-common.h"
#include "tsh-dialog-common.h"
#include "tsh-notify-dialog.h"
+#include "tsh-checkout-dialog.h"
#include "tsh-checkout.h"
@@ -84,6 +85,12 @@
GtkWidget *dialog;
struct thread_args *args;
+ dialog = tsh_checkout_dialog_new (NULL, NULL, 0, files?files[0]:NULL);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+
+ return NULL;
+
dialog = tsh_notify_dialog_new (_("Checkout"), NULL, 0);
tsh_dialog_start (GTK_DIALOG (dialog), TRUE);
Modified: thunar-svn-plugin/trunk/tsp-svn-helper/tsh-file-dialog.c
===================================================================
--- thunar-svn-plugin/trunk/tsp-svn-helper/tsh-file-dialog.c 2007-10-16 23:05:17 UTC (rev 3398)
+++ thunar-svn-plugin/trunk/tsp-svn-helper/tsh-file-dialog.c 2007-10-18 22:30:16 UTC (rev 3399)
@@ -30,7 +30,6 @@
{
GtkDialog dialog;
- GtkWidget *file_lbl;
GtkWidget *filename;
GtkWidget *may_save;
};
@@ -51,14 +50,15 @@
tsh_file_dialog_init (TshFileDialog *dialog)
{
GtkWidget *table;
+ GtkWidget *label;
table = gtk_table_new (2, 2, FALSE);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, FALSE, TRUE, 0);
gtk_widget_show (table);
- dialog->file_lbl = gtk_label_new_with_mnemonic (_("_Certificate:"));
- gtk_table_attach (GTK_TABLE (table), dialog->file_lbl,
+ label = gtk_label_new_with_mnemonic (_("_Certificate:"));
+ gtk_table_attach (GTK_TABLE (table), label,
0, 1, 0, 1,
GTK_SHRINK | GTK_FILL,
GTK_SHRINK | GTK_FILL,
@@ -71,8 +71,8 @@
GTK_SHRINK | GTK_FILL,
0, 0);
- gtk_label_set_mnemonic_widget (GTK_LABEL (dialog->file_lbl), dialog->filename);
- gtk_widget_show(dialog->file_lbl);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), dialog->filename);
+ gtk_widget_show(label);
gtk_widget_show(dialog->filename);
dialog->may_save = gtk_check_button_new_with_label(_("Remember"));
More information about the Goodies-commits
mailing list