summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@gnome.org>2013-04-15 19:29:37 -0500
committerFederico Mena Quintero <federico@gnome.org>2013-04-15 19:29:37 -0500
commit3b3eb4bdbc90ee6df387ba8d8fe061f5956ca442 (patch)
tree0733da2f4e168f1231f4d05c182e037682763ce9
parente3a22b3eba58b7dcb52496db893795f9f2d65983 (diff)
parenta6f9ef0d3a9149c6e5582b5907ebc3085cffdfce (diff)
downloadgtk+-3b3eb4bdbc90ee6df387ba8d8fe061f5956ca442.tar.gz
Merge branch 'merge-places-sidebar'
This is the new GtkPlacesSidebar widget, which is the sidebar used in GtkFileChooser to display a list of places/folders that the user may want to use. File managers are encouraged to use this widget for their own global list of folders.
-rw-r--r--docs/reference/gtk/gtk-docs.sgml1
-rw-r--r--docs/reference/gtk/gtk3-sections.txt26
-rw-r--r--gtk/Makefile.am6
-rw-r--r--gtk/glade/gtk-private-widgets.xml2
-rw-r--r--gtk/gtk-default.css7
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkbookmarksmanager.c596
-rw-r--r--gtk/gtkbookmarksmanager.h91
-rw-r--r--gtk/gtkfilechooser.c5
-rw-r--r--gtk/gtkfilechooserbutton.c35
-rw-r--r--gtk/gtkfilechooserdefault.c5270
-rw-r--r--gtk/gtkfilechooserdefault.ui158
-rw-r--r--gtk/gtkfilechooserdialog.c8
-rw-r--r--gtk/gtkfilechooserprivate.h55
-rw-r--r--gtk/gtkfilechooserwidget.c17
-rw-r--r--gtk/gtkfilesystem.c433
-rw-r--r--gtk/gtkfilesystem.h20
-rw-r--r--gtk/gtkgladecatalog.c2
-rw-r--r--gtk/gtkmarshalers.list8
-rw-r--r--gtk/gtkplacessidebar.c4335
-rw-r--r--gtk/gtkplacessidebar.h100
-rw-r--r--gtk/gtktrashmonitor.c267
-rw-r--r--gtk/gtktrashmonitor.h48
-rw-r--r--gtk/org.gtk.Settings.FileChooser.gschema.xml8
-rw-r--r--gtk/tests/filechooser.c1
-rw-r--r--po/POTFILES.in1
26 files changed, 6908 insertions, 4593 deletions
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index df6af83c7b..671c3b67d6 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -220,6 +220,7 @@
<xi:include href="xml/gtkfontbutton.xml" />
<xi:include href="xml/gtkfontchooserwidget.xml" />
<xi:include href="xml/gtkfontchooserdialog.xml" />
+ <xi:include href="xml/gtkplacessidebar.xml" />
</chapter>
<chapter id="LayoutContainers">
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index deb83f9eb5..39721dd959 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -2484,6 +2484,32 @@ gtk_paned_get_type
</SECTION>
<SECTION>
+<FILE>gtkplacessidebar</FILE>
+<TITLE>GtkPlacesSidebar</FILE>
+GtkPlacesSidebar
+GtkPlacesOpenFlags
+gtk_places_sidebar_new
+gtk_places_sidebar_set_open_flags
+gtk_places_sidebar_set_location
+gtk_places_sidebar_get_location
+gtk_places_sidebar_set_show_desktop
+gtk_places_sidebar_set_accept_uri_drops
+gtk_places_sidebar_add_shortcut
+gtk_places_sidebar_remove_shortcut
+gtk_places_sidebar_list_shortcuts
+gtk_places_sidebar_get_nth_bookmark
+<SUBSECTION Standard>
+GTK_PLACES_SIDEBAR
+GTK_IS_PLACES_SIDEBAR
+GTK_TYPE_PLACES_SIDEBAR
+GTK_PLACES_SIDEBAR_CLASS
+GTK_IS_PLACES_SIDEBAR_CLASS
+GTK_PLACES_SIDEBAR_GET_CLASS
+<SUBSECTION Private>
+gtk_places_sidebar_get_type
+</SECTION>
+
+<SECTION>
<FILE>gtkplug</FILE>
<TITLE>GtkPlug</TITLE>
GtkPlug
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 99f0e33941..9df87a0675 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -295,6 +295,7 @@ gtk_public_h_sources = \
gtkpagesetup.h \
gtkpaned.h \
gtkpapersize.h \
+ gtkplacessidebar.h \
gtkplug.h \
gtkprintcontext.h \
gtkprintoperation.h \
@@ -421,6 +422,7 @@ gtk_private_h_sources = \
gtkbindingsprivate.h \
gtkbitmaskprivate.h \
gtkbitmaskprivateimpl.h \
+ gtkbookmarksmanager.h \
gtkborderimageprivate.h \
gtkboxprivate.h \
gtkbubblewindowprivate.h \
@@ -547,6 +549,7 @@ gtk_private_h_sources = \
gtktextutil.h \
gtkthemingbackgroundprivate.h \
gtkthemingengineprivate.h \
+ gtktrashmonitor.h \
gtktoolpaletteprivate.h \
gtktreedatalist.h \
gtktreeprivate.h \
@@ -621,6 +624,7 @@ gtk_base_c_sources = \
gtkbbox.c \
gtkbin.c \
gtkbindings.c \
+ gtkbookmarksmanager.c \
gtkborder.c \
gtkborderimage.c \
gtkbox.c \
@@ -783,6 +787,7 @@ gtk_base_c_sources = \
gtkpango.c \
gtkpapersize.c \
gtkpathbar.c \
+ gtkplacessidebar.c \
gtkpressandhold.c \
gtkprintcontext.c \
gtkprintoperation.c \
@@ -866,6 +871,7 @@ gtk_base_c_sources = \
gtktoolpalette.c \
gtktoolshell.c \
gtktooltip.c \
+ gtktrashmonitor.c \
gtktreedatalist.c \
gtktreednd.c \
gtktreemenu.c \
diff --git a/gtk/glade/gtk-private-widgets.xml b/gtk/glade/gtk-private-widgets.xml
index 1a65e252e2..f1de19b9e6 100644
--- a/gtk/glade/gtk-private-widgets.xml
+++ b/gtk/glade/gtk-private-widgets.xml
@@ -22,6 +22,7 @@
<property id="size" disabled="True"/>
</properties>
</glade-widget-class>
+ <glade-widget-class name="GtkPlacesSidebar" generic-name="placessidebar" title="Places Sidebar"/>
</glade-widget-classes>
<glade-widget-group name="gtk-private" title="Private GTK+ Classes">
@@ -32,5 +33,6 @@
<glade-widget-class-ref name="GtkScaleButtonScale"/>
<glade-widget-class-ref name="ShortcutsPaneModelFilter"/>
<glade-widget-class-ref name="GtkPrinterOptionWidget"/>
+ <glade-widget-class-ref name="GtkPlacesSidebar"/>
</glade-widget-group>
</glade-catalog>
diff --git a/gtk/gtk-default.css b/gtk/gtk-default.css
index d0776802f5..b125cf68e2 100644
--- a/gtk/gtk-default.css
+++ b/gtk/gtk-default.css
@@ -41,6 +41,13 @@ GtkTreeView.view.expander:selected:hover {
color: @text_color;
}
+GtkTreeView.dnd {
+ border-color: @internal_element_color;
+ border-radius: 0;
+ border-width: 1px;
+ border-style: solid;
+}
+
*:insensitive {
border-color: shade (@bg_color, 0.7);
background-color: shade (@bg_color, 0.9);
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 3ebfaeaa84..61d4107c0c 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -145,6 +145,7 @@
#include <gtk/gtkpagesetup.h>
#include <gtk/gtkpapersize.h>
#include <gtk/gtkpaned.h>
+#include <gtk/gtkplacessidebar.h>
#include <gtk/gtkprintcontext.h>
#include <gtk/gtkprintoperation.h>
#include <gtk/gtkprintoperationpreview.h>
diff --git a/gtk/gtkbookmarksmanager.c b/gtk/gtkbookmarksmanager.c
new file mode 100644
index 0000000000..91ccd89c29
--- /dev/null
+++ b/gtk/gtkbookmarksmanager.c
@@ -0,0 +1,596 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* GTK - The GIMP Toolkit
+ * gtkbookmarksmanager.c: Utilities to manage and monitor ~/.gtk-bookmarks
+ * Copyright (C) 2003, Red Hat, Inc.
+ * Copyright (C) 2007-2008 Carlos Garnacho
+ * Copyright (C) 2011 Suse
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Federico Mena Quintero <federico@gnome.org>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n-lib.h>
+
+#include "gtkbookmarksmanager.h"
+#include "gtkfilechooser.h" /* for the GError types */
+
+static void
+_gtk_bookmark_free (GtkBookmark *bookmark)
+{
+ g_object_unref (bookmark->file);
+ g_free (bookmark->label);
+ g_slice_free (GtkBookmark, bookmark);
+}
+
+static GFile *
+get_legacy_bookmarks_file (void)
+{
+ GFile *file;
+ gchar *filename;
+
+ filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
+
+ return file;
+}
+
+static GFile *
+get_bookmarks_file (void)
+{
+ GFile *file;
+ gchar *filename;
+
+ filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
+ file = g_file_new_for_path (filename);
+ g_free (filename);
+
+ return file;
+}
+
+static GSList *
+read_bookmarks (GFile *file)
+{
+ gchar *contents;
+ gchar **lines, *space;
+ GSList *bookmarks = NULL;
+ gint i;
+
+ if (!g_file_load_contents (file, NULL, &contents,
+ NULL, NULL, NULL))
+ return NULL;
+
+ lines = g_strsplit (contents, "\n", -1);
+
+ for (i = 0; lines[i]; i++)
+ {
+ GtkBookmark *bookmark;
+
+ if (!*lines[i])
+ continue;
+
+ if (!g_utf8_validate (lines[i], -1, NULL))
+ continue;
+
+ bookmark = g_slice_new0 (GtkBookmark);
+
+ if ((space = strchr (lines[i], ' ')) != NULL)
+ {
+ space[0] = '\0';
+ bookmark->label = g_strdup (space + 1);
+ }
+
+ bookmark->file = g_file_new_for_uri (lines[i]);
+ bookmarks = g_slist_prepend (bookmarks, bookmark);
+ }
+
+ bookmarks = g_slist_reverse (bookmarks);
+ g_strfreev (lines);
+ g_free (contents);
+
+ return bookmarks;
+}
+
+static void
+save_bookmarks (GFile *bookmarks_file,
+ GSList *bookmarks)
+{
+ GError *error = NULL;
+ GString *contents;
+ GSList *l;
+
+ contents = g_string_new ("");
+
+ for (l = bookmarks; l; l = l->next)
+ {
+ GtkBookmark *bookmark = l->data;
+ gchar *uri;
+
+ uri = g_file_get_uri (bookmark->file);
+ if (!uri)
+ continue;
+
+ g_string_append (contents, uri);
+
+ if (bookmark->label)
+ g_string_append_printf (contents, " %s", bookmark->label);
+
+ g_string_append_c (contents, '\n');
+ g_free (uri);
+ }
+
+ if (!g_file_replace_contents (bookmarks_file,
+ contents->str,
+ strlen (contents->str),
+ NULL, FALSE, 0, NULL,
+ NULL, &error))
+ {
+ g_critical ("%s", error->message);
+ g_error_free (error);
+ }
+
+ g_string_free (contents, TRUE);
+}
+
+static void
+notify_changed (GtkBookmarksManager *manager)
+{
+ if (manager->changed_func)
+ manager->changed_func (manager->changed_func_data);
+}
+
+static void
+bookmarks_file_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer data)
+{
+ GtkBookmarksManager *manager = data;
+
+ switch (event)
+ {
+ case G_FILE_MONITOR_EVENT_CHANGED:
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ case G_FILE_MONITOR_EVENT_CREATED:
+ case G_FILE_MONITOR_EVENT_DELETED:
+ g_slist_foreach (manager->bookmarks, (GFunc) _gtk_bookmark_free, NULL);
+ g_slist_free (manager->bookmarks);
+
+ manager->bookmarks = read_bookmarks (file);
+
+ gdk_threads_enter ();
+ notify_changed (manager);
+ gdk_threads_leave ();
+ break;
+
+ default:
+ /* ignore at the moment */
+ break;
+ }
+}
+
+GtkBookmarksManager *
+_gtk_bookmarks_manager_new (GtkBookmarksChangedFunc changed_func, gpointer changed_func_data)
+{
+ GtkBookmarksManager *manager;
+ GFile *bookmarks_file;
+ GError *error;
+
+ manager = g_new0 (GtkBookmarksManager, 1);
+
+ manager->changed_func = changed_func;
+ manager->changed_func_data = changed_func_data;
+
+ bookmarks_file = get_bookmarks_file ();
+ manager->bookmarks = read_bookmarks (bookmarks_file);
+ if (!manager->bookmarks)
+ {
+ GFile *legacy_bookmarks_file;
+
+ /* Read the legacy one and write it to the new one */
+ legacy_bookmarks_file = get_legacy_bookmarks_file ();
+ manager->bookmarks = read_bookmarks (legacy_bookmarks_file);
+ save_bookmarks (bookmarks_file, manager->bookmarks);
+
+ g_object_unref (legacy_bookmarks_file);
+ }
+
+ error = NULL;
+ manager->bookmarks_monitor = g_file_monitor_file (bookmarks_file,
+ G_FILE_MONITOR_NONE,
+ NULL, &error);
+ if (error)
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+ else
+ manager->bookmarks_monitor_changed_id = g_signal_connect (manager->bookmarks_monitor, "changed",
+ G_CALLBACK (bookmarks_file_changed), manager);
+
+ g_object_unref (bookmarks_file);
+
+ return manager;
+}
+
+void
+_gtk_bookmarks_manager_free (GtkBookmarksManager *manager)
+{
+ g_return_if_fail (manager != NULL);
+
+ if (manager->bookmarks_monitor)
+ {
+ g_file_monitor_cancel (manager->bookmarks_monitor);
+ g_signal_handler_disconnect (manager->bookmarks_monitor, manager->bookmarks_monitor_changed_id);
+ manager->bookmarks_monitor_changed_id = 0;
+ g_object_unref (manager->bookmarks_monitor);
+ }
+
+ if (manager->bookmarks)
+ {
+ g_slist_foreach (manager->bookmarks, (GFunc) _gtk_bookmark_free, NULL);
+ g_slist_free (manager->bookmarks);
+ }
+
+ g_free (manager);
+}
+
+GSList *
+_gtk_bookmarks_manager_list_bookmarks (GtkBookmarksManager *manager)
+{
+ GSList *bookmarks, *files = NULL;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+
+ bookmarks = manager->bookmarks;
+
+ while (bookmarks)
+ {
+ GtkBookmark *bookmark;
+
+ bookmark = bookmarks->data;
+ bookmarks = bookmarks->next;
+
+ files = g_slist_prepend (files, g_object_ref (bookmark->file));
+ }
+
+ return g_slist_reverse (files);
+}
+
+static GSList *
+find_bookmark_link_for_file (GSList *bookmarks, GFile *file, int *position_ret)
+{
+ int pos;
+
+ pos = 0;
+ for (; bookmarks; bookmarks = bookmarks->next)
+ {
+ GtkBookmark *bookmark = bookmarks->data;
+
+ if (g_file_equal (file, bookmark->file))
+ {
+ if (position_ret)
+ *position_ret = pos;
+
+ return bookmarks;
+ }
+
+ pos++;
+ }
+
+ if (position_ret)
+ *position_ret = -1;
+
+ return NULL;
+}
+
+gboolean
+_gtk_bookmarks_manager_has_bookmark (GtkBookmarksManager *manager,
+ GFile *file)
+{
+ GSList *link;
+
+ link = find_bookmark_link_for_file (manager->bookmarks, file, NULL);
+ return (link != NULL);
+}
+
+gboolean
+_gtk_bookmarks_manager_insert_bookmark (GtkBookmarksManager *manager,
+ GFile *file,
+ gint position,
+ GError **error)
+{
+ GSList *link;
+ GtkBookmark *bookmark;
+ GFile *bookmarks_file;
+
+ g_return_val_if_fail (manager != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ link = find_bookmark_link_for_file (manager->bookmarks, file, NULL);
+
+ if (link)
+ {
+ bookmark = link->data;
+ gchar *uri = g_file_get_uri (bookmark->file);
+
+ g_set_error (error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
+ "%s already exists in the bookmarks list",
+ uri);
+
+ g_free (uri);
+
+ return FALSE;
+ }
+
+ bookmark = g_slice_new0 (GtkBookmark);
+ bookmark->file = g_object_ref (file);
+
+ manager->bookmarks = g_slist_insert (manager->bookmarks, bookmark, position);
+
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, manager->bookmarks);
+ g_object_unref (bookmarks_file);
+
+ notify_changed (manager);
+
+ return TRUE;
+}
+
+gboolean
+_gtk_bookmarks_manager_remove_bookmark (GtkBookmarksManager *manager,
+ GFile *file,
+ GError **error)
+{
+ GSList *link;
+ GFile *bookmarks_file;
+
+ g_return_val_if_fail (manager != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ if (!manager->bookmarks)
+ return FALSE;
+
+ link = find_bookmark_link_for_file (manager->bookmarks, file, NULL);
+ if (link)
+ {
+ GtkBookmark *bookmark = link->data;
+
+ manager->bookmarks = g_slist_remove_link (manager->bookmarks, link);
+ _gtk_bookmark_free (bookmark);
+ g_slist_free_1 (link);
+ }
+ else
+ {
+ gchar *uri = g_file_get_uri (file);
+
+ g_set_error (error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
+ "%s does not exist in the bookmarks list",
+ uri);
+
+ g_free (uri);
+
+ return FALSE;
+ }
+
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, manager->bookmarks);
+ g_object_unref (bookmarks_file);
+
+ notify_changed (manager);
+
+ return TRUE;
+}
+
+gboolean
+_gtk_bookmarks_manager_reorder_bookmark (GtkBookmarksManager *manager,
+ GFile *file,
+ gint new_position,
+ GError **error)
+{
+ GSList *link;
+ GFile *bookmarks_file;
+ int old_position;
+
+ g_return_val_if_fail (manager != NULL, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (new_position >= 0, FALSE);
+
+ if (!manager->bookmarks)
+ return FALSE;
+
+ link = find_bookmark_link_for_file (manager->bookmarks, file, &old_position);
+ if (new_position == old_position)
+ return TRUE;
+
+ if (link)
+ {
+ GtkBookmark *bookmark = link->data;
+
+ manager->bookmarks = g_slist_remove_link (manager->bookmarks, link);
+ g_slist_free_1 (link);
+
+ if (new_position > old_position)
+ new_position--;
+
+ manager->bookmarks = g_slist_insert (manager->bookmarks, bookmark, new_position);
+ }
+ else
+ {
+ gchar *uri = g_file_get_uri (file);
+
+ g_set_error (error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
+ "%s does not exist in the bookmarks list",
+ uri);
+
+ g_free (uri);
+
+ return FALSE;
+ }
+
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, manager->bookmarks);
+ g_object_unref (bookmarks_file);
+
+ notify_changed (manager);
+
+ return TRUE;
+}
+
+gchar *
+_gtk_bookmarks_manager_get_bookmark_label (GtkBookmarksManager *manager,
+ GFile *file)
+{
+ GSList *bookmarks;
+ gchar *label = NULL;
+
+ g_return_val_if_fail (manager != NULL, NULL);
+ g_return_val_if_fail (file != NULL, NULL);
+
+ bookmarks = manager->bookmarks;
+
+ while (bookmarks)
+ {
+ GtkBookmark *bookmark;
+
+ bookmark = bookmarks->data;
+ bookmarks = bookmarks->next;
+
+ if (g_file_equal (file, bookmark->file))
+ {
+ label = g_strdup (bookmark->label);
+ break;
+ }
+ }
+
+ return label;
+}
+
+gboolean
+_gtk_bookmarks_manager_set_bookmark_label (GtkBookmarksManager *manager,
+ GFile *file,
+ const gchar *label,
+ GError **error)
+{
+ GFile *bookmarks_file;
+ GSList *link;
+
+ g_return_val_if_fail (manager != NULL, FALSE);
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ link = find_bookmark_link_for_file (manager->bookmarks, file, NULL);
+ if (link)
+ {
+ GtkBookmark *bookmark = link->data;
+
+ g_free (bookmark->label);
+ bookmark->label = g_strdup (label);
+ }
+ else
+ {
+ gchar *uri = g_file_get_uri (file);
+
+ g_set_error (error,
+ GTK_FILE_CHOOSER_ERROR,
+ GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
+ "%s does not exist in the bookmarks list",
+ uri);
+
+ g_free (uri);
+
+ return FALSE;
+ }
+
+ bookmarks_file = get_bookmarks_file ();
+ save_bookmarks (bookmarks_file, manager->bookmarks);
+ g_object_unref (bookmarks_file);
+
+ notify_changed (manager);
+
+ return TRUE;
+}
+
+gboolean
+_gtk_bookmarks_manager_get_xdg_type (GtkBookmarksManager *manager,
+ GFile *file,
+ GUserDirectory *directory)
+{
+ GSList *link;
+ gboolean match;
+ GFile *location;
+ const gchar *path;
+ GUserDirectory dir;
+ GtkBookmark *bookmark;
+
+ link = find_bookmark_link_for_file (manager->bookmarks, file, NULL);
+ if (!link)
+ return FALSE;
+
+ match = FALSE;
+ bookmark = link->data;
+
+ for (dir = 0; dir < G_USER_N_DIRECTORIES; dir++)
+ {
+ path = g_get_user_special_dir (dir);
+ if (!path)
+ continue;
+
+ location = g_file_new_for_path (path);
+ match = g_file_equal (location, bookmark->file);
+ g_object_unref (location);
+
+ if (match)
+ break;
+ }
+
+ if (match && directory != NULL)
+ *directory = dir;
+
+ return match;
+}
+
+gboolean
+_gtk_bookmarks_manager_get_is_builtin (GtkBookmarksManager *manager,
+ GFile *file)
+{
+ GUserDirectory xdg_type;
+
+ /* if this is not an XDG dir, it's never builtin */
+ if (!_gtk_bookmarks_manager_get_xdg_type (manager, file, &xdg_type))
+ return FALSE;
+
+ /* exclude XDG locations we don't display by default */
+ return _gtk_bookmarks_manager_get_is_xdg_dir_builtin (xdg_type);
+}
+
+gboolean
+_gtk_bookmarks_manager_get_is_xdg_dir_builtin (GUserDirectory xdg_type)
+{
+ return (xdg_type != G_USER_DIRECTORY_DESKTOP) &&
+ (xdg_type != G_USER_DIRECTORY_TEMPLATES) &&
+ (xdg_type != G_USER_DIRECTORY_PUBLIC_SHARE);
+}
diff --git a/gtk/gtkbookmarksmanager.h b/gtk/gtkbookmarksmanager.h
new file mode 100644
index 0000000000..f2efd6577b
--- /dev/null
+++ b/gtk/gtkbookmarksmanager.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* GTK - The GIMP Toolkit
+ * gtkbookmarksmanager.h: Utilities to manage and monitor ~/.gtk-bookmarks
+ * Copyright (C) 2003, Red Hat, Inc.
+ * Copyright (C) 2007-2008 Carlos Garnacho
+ * Copyright (C) 2011 Suse
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Federico Mena Quintero <federico@gnome.org>
+ */
+
+#ifndef __GTK_BOOKMARKS_MANAGER_H__
+#define __GTK_BOOKMARKS_MANAGER_H__
+
+#include <gio/gio.h>
+
+typedef void (* GtkBookmarksChangedFunc) (gpointer data);
+
+typedef struct
+{
+ /* This list contains GtkBookmark structs */
+ GSList *bookmarks;
+
+ GFileMonitor *bookmarks_monitor;
+ gulong bookmarks_monitor_changed_id;
+
+ gpointer changed_func_data;
+ GtkBookmarksChangedFunc changed_func;
+} GtkBookmarksManager;
+
+typedef struct
+{
+ GFile *file;
+ gchar *label;
+} GtkBookmark;
+
+GtkBookmarksManager *_gtk_bookmarks_manager_new (GtkBookmarksChangedFunc changed_func,
+ gpointer changed_func_data);
+
+
+void _gtk_bookmarks_manager_free (GtkBookmarksManager *manager);
+
+GSList *_gtk_bookmarks_manager_list_bookmarks (GtkBookmarksManager *manager);
+
+gboolean _gtk_bookmarks_manager_insert_bookmark (GtkBookmarksManager *manager,
+ GFile *file,
+ gint position,
+ GError **error);
+
+gboolean _gtk_bookmarks_manager_remove_bookmark (GtkBookmarksManager *manager,
+ GFile *file,
+ GError **error);
+
+gboolean _gtk_bookmarks_manager_reorder_bookmark (GtkBookmarksManager *manager,
+ GFile *file,
+ gint new_position,
+ GError **error);
+
+gboolean _gtk_bookmarks_manager_has_bookmark (GtkBookmarksManager *manager,
+ GFile *file);
+
+gchar * _gtk_bookmarks_manager_get_bookmark_label (GtkBookmarksManager *manager,
+ GFile *file);
+
+gboolean _gtk_bookmarks_manager_set_bookmark_label (GtkBookmarksManager *manager,
+ GFile *file,
+ const gchar *label,
+ GError **error);
+
+gboolean _gtk_bookmarks_manager_get_xdg_type (GtkBookmarksManager *manager,
+ GFile *file,
+ GUserDirectory *directory);
+gboolean _gtk_bookmarks_manager_get_is_builtin (GtkBookmarksManager *manager,
+ GFile *file);
+
+gboolean _gtk_bookmarks_manager_get_is_xdg_dir_builtin (GUserDirectory xdg_type);
+
+#endif /* __GTK_BOOKMARKS_MANAGER_H__ */
diff --git a/gtk/gtkfilechooser.c b/gtk/gtkfilechooser.c
index 141e8bf76e..2600a136a9 100644
--- a/gtk/gtkfilechooser.c
+++ b/gtk/gtkfilechooser.c
@@ -55,9 +55,8 @@
* <varlistentry>
* <term>Shortcuts</term>
* <listitem>
- * can be provided by the application or by the underlying filesystem
- * abstraction (e.g. both the gnome-vfs and the Windows filesystems
- * provide "Desktop" shortcuts). Shortcuts cannot be modified by the
+ * can be provided by the application. For example, a Paint program may
+ * want to add a shortcut for a Clipart folder. Shortcuts cannot be modified by the
* user.
* </listitem>
* </varlistentry>
diff --git a/gtk/gtkfilechooserbutton.c b/gtk/gtkfilechooserbutton.c
index 86403d650c..8c744ce8fd 100644
--- a/gtk/gtkfilechooserbutton.c
+++ b/gtk/gtkfilechooserbutton.c
@@ -186,12 +186,13 @@ struct _GtkFileChooserButtonPrivate
GFile *current_folder_while_inactive;
gulong fs_volumes_changed_id;
- gulong fs_bookmarks_changed_id;
GCancellable *dnd_select_folder_cancellable;
GCancellable *update_button_cancellable;
GSList *change_icon_theme_cancellables;
+ GtkBookmarksManager *bookmarks_manager;
+
gint icon_size;
guint8 n_special;
@@ -323,8 +324,7 @@ static void update_label_and_image (GtkFileChooserButton *button)
/* 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 bookmarks_changed_cb (gpointer user_data);
static void combo_box_changed_cb (GtkComboBox *combo_box,
gpointer user_data);
@@ -502,6 +502,8 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
gtk_widget_init_template (GTK_WIDGET (button));
+ /* Bookmarks manager */
+ priv->bookmarks_manager = _gtk_bookmarks_manager_new (bookmarks_changed_cb, button);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->combo_box),
priv->name_cell, name_cell_data_func,
NULL, NULL);
@@ -849,7 +851,7 @@ gtk_file_chooser_button_constructor (GType type,
model_add_volumes (button, list);
g_slist_free (list);
- list = _gtk_file_system_list_bookmarks (priv->fs);
+ list = _gtk_bookmarks_manager_list_bookmarks (priv->bookmarks_manager);
model_add_bookmarks (button, list);
g_slist_foreach (list, (GFunc) g_object_unref, NULL);
g_slist_free (list);
@@ -878,9 +880,6 @@ gtk_file_chooser_button_constructor (GType type,
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);
update_label_and_image (button);
update_combo_box (button);
@@ -964,7 +963,7 @@ gtk_file_chooser_button_set_property (GObject *object,
case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
g_object_set_property (G_OBJECT (priv->dialog), pspec->name, value);
fs_volumes_changed_cb (priv->fs, button);
- fs_bookmarks_changed_cb (priv->fs, button);
+ bookmarks_changed_cb (button);
break;
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
@@ -1089,11 +1088,16 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
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 (priv->bookmarks_manager)
+ {
+ _gtk_bookmarks_manager_free (priv->bookmarks_manager);
+ priv->bookmarks_manager = NULL;
+ }
+
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->destroy (widget);
}
@@ -1604,7 +1608,7 @@ set_info_for_file_at_iter (GtkFileChooserButton *button,
data = g_new0 (struct SetDisplayNameData, 1);
data->button = g_object_ref (button);
- data->label = _gtk_file_system_get_bookmark_label (button->priv->fs, file);
+ data->label = _gtk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
tree_path = gtk_tree_model_get_path (button->priv->model, iter);
data->row_ref = gtk_tree_row_reference_new (button->priv->model, tree_path);
@@ -1988,7 +1992,7 @@ model_add_bookmarks (GtkFileChooserButton *button,
* 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 (button->priv->fs, file);
+ label = _gtk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
if (!label)
label = _gtk_file_chooser_label_for_file (file);
@@ -2091,7 +2095,7 @@ model_update_current_folder (GtkFileChooserButton *button,
* 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 (button->priv->fs, file);
+ label = _gtk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
if (!label)
label = _gtk_file_chooser_label_for_file (file);
@@ -2548,7 +2552,7 @@ update_label_and_image (GtkFileChooserButton *button)
{
GdkPixbuf *pixbuf;
- label_text = _gtk_file_system_get_bookmark_label (button->priv->fs, file);
+ label_text = _gtk_bookmarks_manager_get_bookmark_label (button->priv->bookmarks_manager, file);
pixbuf = gtk_icon_theme_load_icon (get_icon_theme (GTK_WIDGET (priv->image)),
"text-x-generic",
priv->icon_size, 0, NULL);
@@ -2616,14 +2620,13 @@ fs_volumes_changed_cb (GtkFileSystem *fs,
}
static void
-fs_bookmarks_changed_cb (GtkFileSystem *fs,
- gpointer user_data)
+bookmarks_changed_cb (gpointer user_data)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (user_data);
GtkFileChooserButtonPrivate *priv = button->priv;
GSList *bookmarks;
- bookmarks = _gtk_file_system_list_bookmarks (fs);
+ bookmarks = _gtk_bookmarks_manager_list_bookmarks (priv->bookmarks_manager);
model_remove_rows (user_data,
model_get_type_position (user_data,
ROW_TYPE_BOOKMARK_SEPARATOR),
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 75dcfde859..c6bea3946f 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -17,6 +17,11 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+/* TODO:
+ *
+ * * Fix FIXME-places-sidebar
+ */
+
#include "config.h"
#include "gtkfilechooserdefault.h"
@@ -51,6 +56,7 @@
#include "gtkmountoperation.h"
#include "gtkpaned.h"
#include "gtkpathbar.h"
+#include "gtkplacessidebar.h"
#include "gtkprivate.h"
#include "gtkradiobutton.h"
#include "gtkrecentfilter.h"
@@ -140,9 +146,35 @@ _gtk_file_chooser_profile_log (const char *func, int indent, const char *msg1, c
#endif
+typedef enum {
+ LOAD_EMPTY, /* There is no model */
+ LOAD_PRELOAD, /* Model is loading and a timer is running; model isn't inserted into the tree yet */
+ LOAD_LOADING, /* Timeout expired, model is inserted into the tree, but not fully loaded yet */
+ LOAD_FINISHED /* Model is fully loaded and inserted into the tree */
+} LoadState;
-struct _GtkFileChooserDefaultPrivate
-{
+typedef enum {
+ RELOAD_EMPTY, /* No folder has been set */
+ RELOAD_HAS_FOLDER /* We have a folder, although it may not be completely loaded yet; no need to reload */
+} ReloadState;
+
+typedef enum {
+ LOCATION_MODE_PATH_BAR,
+ LOCATION_MODE_FILENAME_ENTRY
+} LocationMode;
+
+typedef enum {
+ OPERATION_MODE_BROWSE,
+ OPERATION_MODE_SEARCH,
+ OPERATION_MODE_RECENT
+} OperationMode;
+
+typedef enum {
+ STARTUP_MODE_RECENT,
+ STARTUP_MODE_CWD
+} StartupMode;
+
+typedef struct {
GtkFileChooserAction action;
GtkFileSystem *file_system;
@@ -157,14 +189,6 @@ struct _GtkFileChooserDefaultPrivate
GtkWidget *browse_widgets_box;
GtkWidget *browse_widgets_hpaned;
GtkWidget *browse_header_box;
- GtkWidget *browse_shortcuts_swin;
- GtkWidget *browse_shortcuts_toolbar;
- GtkWidget *browse_shortcuts_tree_view;
- GtkWidget *browse_shortcuts_add_button;
- GtkWidget *browse_shortcuts_remove_button;
- GtkWidget *browse_shortcuts_popup_menu;
- GtkWidget *browse_shortcuts_popup_menu_remove_item;
- GtkWidget *browse_shortcuts_popup_menu_rename_item;
GtkWidget *browse_files_tree_view;
GtkWidget *browse_files_popup_menu;
GtkWidget *browse_files_popup_menu_add_shortcut_item;
@@ -185,6 +209,9 @@ struct _GtkFileChooserDefaultPrivate
GtkFileSystemModel *browse_files_model;
char *browse_files_last_selected_name;
+ GtkWidget *places_sidebar;
+ StartupMode startup_mode;
+
/* OPERATION_MODE_SEARCH */
GtkWidget *search_hbox;
GtkWidget *search_entry;
@@ -211,13 +238,6 @@ struct _GtkFileChooserDefaultPrivate
GtkWidget *location_entry;
LocationMode location_mode;
- GtkListStore *shortcuts_model;
-
- /* Filter for the shortcuts pane. We filter out the "current folder" row and
- * the separator that we use for the "Save in folder" combo.
- */
- GtkTreeModel *shortcuts_pane_filter_model;
-
/* Handles */
GSList *loading_shortcuts;
GSList *reload_icon_cancellables;
@@ -239,6 +259,8 @@ struct _GtkFileChooserDefaultPrivate
GtkFileFilter *current_filter;
GSList *filters;
+ GtkBookmarksManager *bookmarks_manager;
+
int num_volumes;
int num_shortcuts;
int num_bookmarks;
@@ -252,8 +274,8 @@ struct _GtkFileChooserDefaultPrivate
char *preview_display_name;
GtkTreeViewColumn *list_name_column;
- GtkCellRenderer *list_pixbuf_renderer;
GtkCellRenderer *list_name_renderer;
+ GtkCellRenderer *list_pixbuf_renderer;
GtkTreeViewColumn *list_mtime_column;
GtkTreeViewColumn *list_size_column;
@@ -271,11 +293,6 @@ struct _GtkFileChooserDefaultPrivate
gint sort_column;
GtkSortType sort_order;
-#if 0
- GdkDragContext *shortcuts_drag_context;
- GSource *shortcuts_drag_outside_idle;
-#endif
-
/* Flags */
guint local_only : 1;
@@ -293,13 +310,7 @@ struct _GtkFileChooserDefaultPrivate
guint has_recent: 1;
guint show_size_column : 1;
guint create_folders : 1;
-
-#if 0
- guint shortcuts_drag_outside : 1;
-#endif
-};
-
-typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
+} GtkFileChooserDefaultPrivate;
#define GTK_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
#define GTK_IS_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT))
@@ -309,6 +320,15 @@ typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
#define DEFAULT_NEW_FOLDER_NAME _("Type name of new folder")
+typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
+
+struct _GtkFileChooserDefault
+{
+ GtkBox parent_instance;
+
+ GtkFileChooserDefaultPrivate *priv;
+};
+
struct _GtkFileChooserDefaultClass
{
GtkBoxClass parent_class;
@@ -333,26 +353,6 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
-/* Column numbers for the shortcuts tree. Keep these in sync with shortcuts_model_create() */
-enum {
- SHORTCUTS_COL_PIXBUF,
- SHORTCUTS_COL_NAME,
- SHORTCUTS_COL_DATA,
- SHORTCUTS_COL_TYPE,
- SHORTCUTS_COL_REMOVABLE,
- SHORTCUTS_COL_PIXBUF_VISIBLE,
- SHORTCUTS_COL_CANCELLABLE,
- SHORTCUTS_COL_NUM_COLUMNS
-};
-
-typedef enum {
- SHORTCUT_TYPE_FILE,
- SHORTCUT_TYPE_VOLUME,
- SHORTCUT_TYPE_SEPARATOR,
- SHORTCUT_TYPE_SEARCH,
- SHORTCUT_TYPE_RECENT
-} ShortcutType;
-
#define MODEL_ATTRIBUTES "standard::name,standard::type,standard::display-name," \
"standard::is-hidden,standard::is-backup,standard::size," \
"standard::content-type,time::modified"
@@ -392,21 +392,6 @@ enum {
GTK_TREE_MODEL_ROW,
};
-/* Interesting places in the shortcuts bar */
-typedef enum {
- SHORTCUTS_SEARCH,
- SHORTCUTS_RECENT,
- SHORTCUTS_RECENT_SEPARATOR,
- SHORTCUTS_HOME,
- SHORTCUTS_DESKTOP,
- SHORTCUTS_VOLUMES,
- SHORTCUTS_SHORTCUTS,
- SHORTCUTS_BOOKMARKS_SEPARATOR,
- SHORTCUTS_BOOKMARKS,
- SHORTCUTS_CURRENT_FOLDER_SEPARATOR,
- SHORTCUTS_CURRENT_FOLDER
-} ShortcutsIndex;
-
/* Icon size for if we can't get it from the theme */
#define FALLBACK_ICON_SIZE 16
@@ -497,6 +482,8 @@ static void search_shortcut_handler (GtkFileChooserDefault *impl);
static void recent_shortcut_handler (GtkFileChooserDefault *impl);
static void update_appearance (GtkFileChooserDefault *impl);
+static void operation_mode_set (GtkFileChooserDefault *impl, OperationMode mode);
+
static void set_current_filter (GtkFileChooserDefault *impl,
GtkFileFilter *filter);
static void check_preview_change (GtkFileChooserDefault *impl);
@@ -504,26 +491,6 @@ static void check_preview_change (GtkFileChooserDefault *impl);
static void filter_combo_changed (GtkComboBox *combo_box,
GtkFileChooserDefault *impl);
-static gboolean shortcuts_key_press_event_cb (GtkWidget *widget,
- GdkEventKey *event,
- GtkFileChooserDefault *impl);
-
-static gboolean shortcuts_select_func (GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currently_selected,
- gpointer data);
-static gboolean shortcuts_get_selected (GtkFileChooserDefault *impl,
- GtkTreeIter *iter);
-static void shortcuts_activate_iter (GtkFileChooserDefault *impl,
- GtkTreeIter *iter);
-static int shortcuts_get_index (GtkFileChooserDefault *impl,
- ShortcutsIndex where);
-static int shortcut_find_position (GtkFileChooserDefault *impl,
- GFile *file);
-
-static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl);
-
static gboolean list_select_func (GtkTreeSelection *selection,
GtkTreeModel *model,
GtkTreePath *path,
@@ -543,11 +510,6 @@ static void path_bar_clicked (GtkPathBar *path_bar,
gboolean child_is_hidden,
GtkFileChooserDefault *impl);
-static void add_bookmark_button_clicked_cb (GtkButton *button,
- GtkFileChooserDefault *impl);
-static void remove_bookmark_button_clicked_cb (GtkButton *button,
- GtkFileChooserDefault *impl);
-
static void update_cell_renderer_attributes (GtkFileChooserDefault *impl);
static void load_remove_timer (GtkFileChooserDefault *impl, LoadState new_load_state);
@@ -580,34 +542,6 @@ static GSList * recent_get_selected_files (GtkFileChooserDefault *impl);
static void set_file_system_backend (GtkFileChooserDefault *impl);
static void unset_file_system_backend (GtkFileChooserDefault *impl);
-
-
-
-/* Drag and drop interface declarations */
-
-typedef struct {
- GtkTreeModelFilter parent;
-
- GtkFileChooserDefault *impl;
-} ShortcutsPaneModelFilter;
-
-typedef struct {
- GtkTreeModelFilterClass parent_class;
-} ShortcutsPaneModelFilterClass;
-
-#define SHORTCUTS_PANE_MODEL_FILTER_TYPE (_shortcuts_pane_model_filter_get_type ())
-#define SHORTCUTS_PANE_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_PANE_MODEL_FILTER_TYPE, ShortcutsPaneModelFilter))
-
-static void shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
-
-GType _shortcuts_pane_model_filter_get_type (void);
-
-G_DEFINE_TYPE_WITH_CODE (ShortcutsPaneModelFilter,
- _shortcuts_pane_model_filter,
- GTK_TYPE_TREE_MODEL_FILTER,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
- shortcuts_pane_model_filter_drag_source_iface_init))
-
G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_BOX,
@@ -616,128 +550,88 @@ G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_T
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER_EMBED,
gtk_file_chooser_embed_default_iface_init));
-
-static void
-add_normal_and_shifted_binding (GtkBindingSet *binding_set,
- guint keyval,
- GdkModifierType modifiers,
- const gchar *signal_name)
-{
- gtk_binding_entry_add_signal (binding_set,
- keyval, modifiers,
- signal_name, 0);
-
- gtk_binding_entry_add_signal (binding_set,
- keyval, modifiers | GDK_SHIFT_MASK,
- signal_name, 0);
-}
-
-/* Frees the data columns for the specified iter in the shortcuts model*/
static void
-shortcuts_free_row_data (GtkFileChooserDefault *impl,
- GtkTreeIter *iter)
+gtk_file_chooser_default_iface_init (GtkFileChooserIface *iface)
{
- gpointer col_data;
- ShortcutType shortcut_type;
- GCancellable *cancellable;
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- SHORTCUTS_COL_CANCELLABLE, &cancellable,
- -1);
-
- if (cancellable)
- {
- g_cancellable_cancel (cancellable);
- g_object_unref (cancellable);
- }
-
- if (!(shortcut_type == SHORTCUT_TYPE_FILE ||
- shortcut_type == SHORTCUT_TYPE_VOLUME) ||
- !col_data)
- return;
-
- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
- {
- GtkFileSystemVolume *volume;
-
- volume = col_data;
- _gtk_file_system_volume_unref (volume);
- }
- if (shortcut_type == SHORTCUT_TYPE_FILE)
- {
- GFile *file;
-
- file = col_data;
- g_object_unref (file);
- }
+ iface->select_file = gtk_file_chooser_default_select_file;
+ iface->unselect_file = gtk_file_chooser_default_unselect_file;
+ iface->select_all = gtk_file_chooser_default_select_all;
+ iface->unselect_all = gtk_file_chooser_default_unselect_all;
+ iface->get_files = gtk_file_chooser_default_get_files;
+ iface->get_preview_file = gtk_file_chooser_default_get_preview_file;
+ iface->get_file_system = gtk_file_chooser_default_get_file_system;
+ iface->set_current_folder = gtk_file_chooser_default_set_current_folder;
+ iface->get_current_folder = gtk_file_chooser_default_get_current_folder;
+ iface->set_current_name = gtk_file_chooser_default_set_current_name;
+ iface->add_filter = gtk_file_chooser_default_add_filter;
+ iface->remove_filter = gtk_file_chooser_default_remove_filter;
+ iface->list_filters = gtk_file_chooser_default_list_filters;
+ iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder;
+ iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder;
+ iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders;
}
-/* Frees all the data columns in the shortcuts model */
static void
-shortcuts_free (GtkFileChooserDefault *impl)
+gtk_file_chooser_embed_default_iface_init (GtkFileChooserEmbedIface *iface)
{
- GtkTreeIter iter;
-
- if (!impl->priv->shortcuts_model)
- return;
-
- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter))
- do
- {
- shortcuts_free_row_data (impl, &iter);
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter));
-
- impl->priv->shortcuts_model = NULL;
+ iface->get_default_size = gtk_file_chooser_default_get_default_size;
+ iface->should_respond = gtk_file_chooser_default_should_respond;
+ iface->initial_focus = gtk_file_chooser_default_initial_focus;
}
static void
pending_select_files_free (GtkFileChooserDefault *impl)
{
- g_slist_free_full (impl->priv->pending_select_files, g_object_unref);
- impl->priv->pending_select_files = NULL;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_slist_free_full (priv->pending_select_files, g_object_unref);
+ priv->pending_select_files = NULL;
}
static void
pending_select_files_add (GtkFileChooserDefault *impl,
GFile *file)
{
- impl->priv->pending_select_files =
- g_slist_prepend (impl->priv->pending_select_files, g_object_ref (file));
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ priv->pending_select_files =
+ g_slist_prepend (priv->pending_select_files, g_object_ref (file));
}
static void
gtk_file_chooser_default_finalize (GObject *object)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GSList *l;
unset_file_system_backend (impl);
- g_free (impl->priv->browse_files_last_selected_name);
+ g_free (priv->browse_files_last_selected_name);
- for (l = impl->priv->filters; l; l = l->next)
+ for (l = priv->filters; l; l = l->next)
{
GtkFileFilter *filter;
filter = GTK_FILE_FILTER (l->data);
g_object_unref (filter);
}
- g_slist_free (impl->priv->filters);
+ g_slist_free (priv->filters);
+
+ if (priv->current_filter)
+ g_object_unref (priv->current_filter);
- if (impl->priv->current_filter)
- g_object_unref (impl->priv->current_filter);
+ if (priv->current_volume_file)
+ g_object_unref (priv->current_volume_file);
- if (impl->priv->current_volume_file)
- g_object_unref (impl->priv->current_volume_file);
+ if (priv->current_folder)
+ g_object_unref (priv->current_folder);
- if (impl->priv->current_folder)
- g_object_unref (impl->priv->current_folder);
+ if (priv->preview_file)
+ g_object_unref (priv->preview_file);
- if (impl->priv->preview_file)
- g_object_unref (impl->priv->preview_file);
+ if (priv->browse_path_bar_size_group)
+ g_object_unref (priv->browse_path_bar_size_group);
/* Free all the Models we have */
stop_loading_and_clear_list_model (impl, FALSE);
@@ -745,11 +639,13 @@ gtk_file_chooser_default_finalize (GObject *object)
recent_clear_model (impl, FALSE);
/* stopping the load above should have cleared this */
- g_assert (impl->priv->load_timeout_id == 0);
+ g_assert (priv->load_timeout_id == 0);
+
+ g_free (priv->preview_display_name);
- g_free (impl->priv->preview_display_name);
+ g_free (priv->edited_new_text);
- g_free (impl->priv->edited_new_text);
+ impl->priv = NULL;
G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->finalize (object);
}
@@ -823,41 +719,6 @@ error_dialog (GtkFileChooserDefault *impl,
}
}
-/* Displays an error message about not being able to get information for a file.
- * Frees the GError as well.
- */
-static void
-error_getting_info_dialog (GtkFileChooserDefault *impl,
- GFile *file,
- GError *error)
-{
- error_dialog (impl,
- _("Could not retrieve information about the file"),
- file, error);
-}
-
-/* Shows an error dialog about not being able to add a bookmark */
-static void
-error_adding_bookmark_dialog (GtkFileChooserDefault *impl,
- GFile *file,
- GError *error)
-{
- error_dialog (impl,
- _("Could not add a bookmark"),
- file, error);
-}
-
-/* Shows an error dialog about not being able to remove a bookmark */
-static void
-error_removing_bookmark_dialog (GtkFileChooserDefault *impl,
- GFile *file,
- GError *error)
-{
- error_dialog (impl,
- _("Could not remove bookmark"),
- file, error);
-}
-
/* Shows an error dialog about not being able to create a folder */
static void
error_creating_folder_dialog (GtkFileChooserDefault *impl,
@@ -971,30 +832,32 @@ emit_default_size_changed (GtkFileChooserDefault *impl)
static void
update_preview_widget_visibility (GtkFileChooserDefault *impl)
{
- if (impl->priv->use_preview_label)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->use_preview_label)
{
- if (!impl->priv->preview_label)
+ if (!priv->preview_label)
{
- impl->priv->preview_label = gtk_label_new (impl->priv->preview_display_name);
- gtk_box_pack_start (GTK_BOX (impl->priv->preview_box), impl->priv->preview_label, FALSE, FALSE, 0);
- gtk_box_reorder_child (GTK_BOX (impl->priv->preview_box), impl->priv->preview_label, 0);
- gtk_label_set_ellipsize (GTK_LABEL (impl->priv->preview_label), PANGO_ELLIPSIZE_MIDDLE);
- gtk_widget_show (impl->priv->preview_label);
+ priv->preview_label = gtk_label_new (priv->preview_display_name);
+ gtk_box_pack_start (GTK_BOX (priv->preview_box), priv->preview_label, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (priv->preview_box), priv->preview_label, 0);
+ gtk_label_set_ellipsize (GTK_LABEL (priv->preview_label), PANGO_ELLIPSIZE_MIDDLE);
+ gtk_widget_show (priv->preview_label);
}
}
else
{
- if (impl->priv->preview_label)
+ if (priv->preview_label)
{
- gtk_widget_destroy (impl->priv->preview_label);
- impl->priv->preview_label = NULL;
+ gtk_widget_destroy (priv->preview_label);
+ priv->preview_label = NULL;
}
}
- if (impl->priv->preview_widget_active && impl->priv->preview_widget)
- gtk_widget_show (impl->priv->preview_box);
+ if (priv->preview_widget_active && priv->preview_widget)
+ gtk_widget_show (priv->preview_box);
else
- gtk_widget_hide (impl->priv->preview_box);
+ gtk_widget_hide (priv->preview_box);
if (!gtk_widget_get_mapped (GTK_WIDGET (impl)))
emit_default_size_changed (impl);
@@ -1004,413 +867,28 @@ static void
set_preview_widget (GtkFileChooserDefault *impl,
GtkWidget *preview_widget)
{
- if (preview_widget == impl->priv->preview_widget)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (preview_widget == priv->preview_widget)
return;
- if (impl->priv->preview_widget)
- gtk_container_remove (GTK_CONTAINER (impl->priv->preview_box),
- impl->priv->preview_widget);
+ if (priv->preview_widget)
+ gtk_container_remove (GTK_CONTAINER (priv->preview_box),
+ priv->preview_widget);
- impl->priv->preview_widget = preview_widget;
- if (impl->priv->preview_widget)
+ priv->preview_widget = preview_widget;
+ if (priv->preview_widget)
{
- gtk_widget_show (impl->priv->preview_widget);
- gtk_box_pack_start (GTK_BOX (impl->priv->preview_box), impl->priv->preview_widget, TRUE, TRUE, 0);
- gtk_box_reorder_child (GTK_BOX (impl->priv->preview_box),
- impl->priv->preview_widget,
- (impl->priv->use_preview_label && impl->priv->preview_label) ? 1 : 0);
+ gtk_widget_show (priv->preview_widget);
+ gtk_box_pack_start (GTK_BOX (priv->preview_box), priv->preview_widget, TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (priv->preview_box),
+ priv->preview_widget,
+ (priv->use_preview_label && priv->preview_label) ? 1 : 0);
}
update_preview_widget_visibility (impl);
}
-/* Renders a "Search" icon at an appropriate size for a tree view */
-static GdkPixbuf *
-render_search_icon (GtkFileChooserDefault *impl)
-{
- return gtk_widget_render_icon_pixbuf (GTK_WIDGET (impl), GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
-}
-
-static GdkPixbuf *
-render_recent_icon (GtkFileChooserDefault *impl)
-{
- GtkIconTheme *theme;
- GdkPixbuf *retval;
-
- if (gtk_widget_has_screen (GTK_WIDGET (impl)))
- theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
- else
- theme = gtk_icon_theme_get_default ();
-
- retval = gtk_icon_theme_load_icon (theme, "document-open-recent",
- impl->priv->icon_size, 0,
- NULL);
-
- /* fallback */
- if (!retval)
- retval = gtk_widget_render_icon_pixbuf (GTK_WIDGET (impl), GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
-
- return retval;
-}
-
-
-/* Re-reads all the icons for the shortcuts, used when the theme changes */
-struct ReloadIconsData
-{
- GtkFileChooserDefault *impl;
- GtkTreeRowReference *row_ref;
-};
-
-static void
-shortcuts_reload_icons_get_info_cb (GCancellable *cancellable,
- GFileInfo *info,
- const GError *error,
- gpointer user_data)
-{
- GdkPixbuf *pixbuf;
- GtkTreeIter iter;
- GtkTreePath *path;
- gboolean cancelled = g_cancellable_is_cancelled (cancellable);
- struct ReloadIconsData *data = user_data;
-
- if (!g_slist_find (data->impl->priv->reload_icon_cancellables, cancellable))
- goto out;
-
- data->impl->priv->reload_icon_cancellables = g_slist_remove (data->impl->priv->reload_icon_cancellables, cancellable);
-
- if (cancelled || error)
- goto out;
-
- pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (data->impl), data->impl->priv->icon_size);
-
- path = gtk_tree_row_reference_get_path (data->row_ref);
- if (path)
- {
- gtk_tree_model_get_iter (GTK_TREE_MODEL (data->impl->priv->shortcuts_model), &iter, path);
- gtk_list_store_set (data->impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, pixbuf,
- -1);
- gtk_tree_path_free (path);
- }
-
- if (pixbuf)
- g_object_unref (pixbuf);
-
-out:
- gtk_tree_row_reference_free (data->row_ref);
- g_object_unref (data->impl);
- g_free (data);
-
- g_object_unref (cancellable);
-}
-
-static void
-shortcuts_reload_icons (GtkFileChooserDefault *impl)
-{
- GSList *l;
- GtkTreeIter iter;
-
- profile_start ("start", NULL);
-
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter))
- goto out;
-
- for (l = impl->priv->reload_icon_cancellables; l; l = l->next)
- {
- GCancellable *cancellable = G_CANCELLABLE (l->data);
- g_cancellable_cancel (cancellable);
- }
- g_slist_free (impl->priv->reload_icon_cancellables);
- impl->priv->reload_icon_cancellables = NULL;
-
- do
- {
- gpointer data;
- ShortcutType shortcut_type;
- gboolean pixbuf_visible;
- GdkPixbuf *pixbuf;
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_DATA, &data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- SHORTCUTS_COL_PIXBUF_VISIBLE, &pixbuf_visible,
- -1);
-
- pixbuf = NULL;
- if (pixbuf_visible)
- {
- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
- {
- GtkFileSystemVolume *volume;
-
- volume = data;
- pixbuf = _gtk_file_system_volume_render_icon (volume, GTK_WIDGET (impl),
- impl->priv->icon_size, NULL);
- }
- else if (shortcut_type == SHORTCUT_TYPE_FILE)
- {
- if (g_file_is_native (G_FILE (data)))
- {
- GFile *file;
- struct ReloadIconsData *info;
- GtkTreePath *tree_path;
- GCancellable *cancellable;
-
- file = data;
-
- info = g_new0 (struct ReloadIconsData, 1);
- info->impl = g_object_ref (impl);
- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter);
- info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->priv->shortcuts_model), tree_path);
- gtk_tree_path_free (tree_path);
-
- cancellable = _gtk_file_system_get_info (impl->priv->file_system, file,
- "standard::icon",
- shortcuts_reload_icons_get_info_cb,
- info);
- impl->priv->reload_icon_cancellables = g_slist_append (impl->priv->reload_icon_cancellables, cancellable);
- }
- else
- {
- GtkIconTheme *icon_theme;
-
- /* 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.
- */
- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
- pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote",
- impl->priv->icon_size, 0, NULL);
- }
- }
- else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
- {
- pixbuf = render_search_icon (impl);
- }
- else if (shortcut_type == SHORTCUT_TYPE_RECENT)
- {
- pixbuf = render_recent_icon (impl);
- }
-
- gtk_list_store_set (impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, pixbuf,
- -1);
-
- if (pixbuf)
- g_object_unref (pixbuf);
-
- }
- }
- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->priv->shortcuts_model),&iter));
-
- out:
-
- profile_end ("end", NULL);
-}
-
-static void
-shortcuts_find_folder (GtkFileChooserDefault *impl,
- GFile *folder)
-{
- GtkTreeSelection *selection;
- int pos;
- GtkTreePath *path;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view));
-
- g_assert (folder != NULL);
- pos = shortcut_find_position (impl, folder);
- if (pos == -1)
- {
- gtk_tree_selection_unselect_all (selection);
- return;
- }
-
- path = gtk_tree_path_new_from_indices (pos, -1);
- gtk_tree_selection_select_path (selection, path);
- gtk_tree_path_free (path);
-}
-
-/* If a shortcut corresponds to the current folder, selects it */
-static void
-shortcuts_find_current_folder (GtkFileChooserDefault *impl)
-{
- shortcuts_find_folder (impl, impl->priv->current_folder);
-}
-
-/* Removes the specified number of rows from the shortcuts list */
-static void
-shortcuts_remove_rows (GtkFileChooserDefault *impl,
- int start_row,
- int n_rows)
-{
- GtkTreePath *path;
-
- path = gtk_tree_path_new_from_indices (start_row, -1);
-
- for (; n_rows; n_rows--)
- {
- GtkTreeIter iter;
-
- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter, path))
- g_assert_not_reached ();
-
- shortcuts_free_row_data (impl, &iter);
- gtk_list_store_remove (impl->priv->shortcuts_model, &iter);
- }
-
- gtk_tree_path_free (path);
-}
-
-static void
-shortcuts_update_count (GtkFileChooserDefault *impl,
- ShortcutsIndex type,
- gint value)
-{
- switch (type)
- {
- case SHORTCUTS_HOME:
- if (value < 0)
- impl->priv->has_home = FALSE;
- else
- impl->priv->has_home = TRUE;
- break;
-
- case SHORTCUTS_DESKTOP:
- if (value < 0)
- impl->priv->has_desktop = FALSE;
- else
- impl->priv->has_desktop = TRUE;
- break;
-
- case SHORTCUTS_VOLUMES:
- impl->priv->num_volumes += value;
- break;
-
- case SHORTCUTS_SHORTCUTS:
- impl->priv->num_shortcuts += value;
- break;
-
- case SHORTCUTS_BOOKMARKS:
- impl->priv->num_bookmarks += value;
- break;
-
- case SHORTCUTS_CURRENT_FOLDER:
- if (value < 0)
- impl->priv->shortcuts_current_folder_active = FALSE;
- else
- impl->priv->shortcuts_current_folder_active = TRUE;
- break;
-
- default:
- /* nothing */
- break;
- }
-}
-
-struct ShortcutsInsertRequest
-{
- GtkFileChooserDefault *impl;
- GFile *file;
- int pos;
- char *label_copy;
- GtkTreeRowReference *row_ref;
- ShortcutsIndex type;
- gboolean name_only;
- gboolean removable;
-};
-
-static void
-get_file_info_finished (GCancellable *cancellable,
- GFileInfo *info,
- const GError *error,
- gpointer data)
-{
- gboolean cancelled = g_cancellable_is_cancelled (cancellable);
- GdkPixbuf *pixbuf;
- GtkTreePath *path;
- GtkTreeIter iter;
- GCancellable *model_cancellable = NULL;
- struct ShortcutsInsertRequest *request = data;
-
- path = gtk_tree_row_reference_get_path (request->row_ref);
- if (!path)
- /* Handle doesn't exist anymore in the model */
- goto out;
-
- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->priv->shortcuts_model),
- &iter, path);
- gtk_tree_path_free (path);
-
- /* validate cancellable, else goto out */
- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_CANCELLABLE, &model_cancellable,
- -1);
- if (cancellable != model_cancellable)
- goto out;
-
- /* set the cancellable to NULL in the model (we unref later on) */
- gtk_list_store_set (request->impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_CANCELLABLE, NULL,
- -1);
-
- if (cancelled)
- goto out;
-
- if (!info)
- {
- gtk_list_store_remove (request->impl->priv->shortcuts_model, &iter);
- shortcuts_update_count (request->impl, request->type, -1);
-
- if (request->type == SHORTCUTS_HOME)
- {
- GFile *home;
-
- home = g_file_new_for_path (g_get_home_dir ());
- error_getting_info_dialog (request->impl, home, g_error_copy (error));
- g_object_unref (home);
- }
- else if (request->type == SHORTCUTS_CURRENT_FOLDER)
- {
- /* Remove the current folder separator */
- gint separator_pos = shortcuts_get_index (request->impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
- shortcuts_remove_rows (request->impl, separator_pos, 1);
- }
-
- goto out;
- }
-
- if (!request->label_copy)
- request->label_copy = g_strdup (g_file_info_get_display_name (info));
- pixbuf = _gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
- request->impl->priv->icon_size);
-
- gtk_list_store_set (request->impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, pixbuf,
- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
- SHORTCUTS_COL_NAME, request->label_copy,
- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_FILE,
- SHORTCUTS_COL_REMOVABLE, request->removable,
- -1);
-
- if (request->impl->priv->shortcuts_pane_filter_model)
- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->priv->shortcuts_pane_filter_model));
-
- if (pixbuf)
- g_object_unref (pixbuf);
-
-out:
- g_object_unref (request->impl);
- g_object_unref (request->file);
- gtk_tree_row_reference_free (request->row_ref);
- g_free (request->label_copy);
- g_free (request);
-
- if (model_cancellable)
- g_object_unref (model_cancellable);
-}
-
/* FIXME: GtkFileSystem needs a function to split a remote path
* into hostname and path components, or maybe just have a
* gtk_file_system_path_get_display_name().
@@ -1467,639 +945,32 @@ _gtk_file_chooser_label_for_file (GFile *file)
return label;
}
-/* Inserts a path in the shortcuts tree, making a copy of it; alternatively,
- * inserts a volume. A position of -1 indicates the end of the tree.
- */
-static void
-shortcuts_insert_file (GtkFileChooserDefault *impl,
- int pos,
- ShortcutType shortcut_type,
- GtkFileSystemVolume *volume,
- GFile *file,
- const char *label,
- gboolean removable,
- ShortcutsIndex type)
-{
- char *label_copy;
- GdkPixbuf *pixbuf = NULL;
- gpointer data = NULL;
- GtkTreeIter iter;
- GtkIconTheme *icon_theme;
-
- profile_start ("start shortcut", NULL);
-
- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
- {
- data = volume;
- label_copy = _gtk_file_system_volume_get_display_name (volume);
- pixbuf = _gtk_file_system_volume_render_icon (volume, GTK_WIDGET (impl),
- impl->priv->icon_size, NULL);
- }
- else if (shortcut_type == SHORTCUT_TYPE_FILE)
- {
- if (g_file_is_native (file))
- {
- struct ShortcutsInsertRequest *request;
- GCancellable *cancellable;
- GtkTreePath *p;
-
- request = g_new0 (struct ShortcutsInsertRequest, 1);
- request->impl = g_object_ref (impl);
- request->file = g_object_ref (file);
- request->name_only = TRUE;
- request->removable = removable;
- request->pos = pos;
- request->type = type;
- if (label)
- request->label_copy = g_strdup (label);
-
- if (pos == -1)
- gtk_list_store_append (impl->priv->shortcuts_model, &iter);
- else
- gtk_list_store_insert (impl->priv->shortcuts_model, &iter, pos);
-
- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter);
- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->priv->shortcuts_model), p);
- gtk_tree_path_free (p);
-
- cancellable = _gtk_file_system_get_info (request->impl->priv->file_system, request->file,
- "standard::is-hidden,standard::is-backup,standard::display-name,standard::icon",
- get_file_info_finished, request);
-
- gtk_list_store_set (impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_DATA, g_object_ref (file),
- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_FILE,
- SHORTCUTS_COL_CANCELLABLE, cancellable,
- -1);
-
- shortcuts_update_count (impl, type, 1);
-
- return;
- }
- else
- {
- /* Don't call get_info for remote paths to avoid latency and
- * auth dialogs.
- */
- data = g_object_ref (file);
- if (label)
- label_copy = g_strdup (label);
- else
- label_copy = _gtk_file_chooser_label_for_file (file);
-
- /* If we switch to a better bookmarks file format (XBEL), we
- * should use mime info to get a better icon.
- */
- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
- pixbuf = gtk_icon_theme_load_icon (icon_theme, "folder-remote",
- impl->priv->icon_size, 0, NULL);
- }
- }
- else
- {
- g_assert_not_reached ();
-
- return;
- }
-
- if (pos == -1)
- gtk_list_store_append (impl->priv->shortcuts_model, &iter);
- else
- gtk_list_store_insert (impl->priv->shortcuts_model, &iter, pos);
-
- shortcuts_update_count (impl, type, 1);
-
- gtk_list_store_set (impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, pixbuf,
- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
- SHORTCUTS_COL_NAME, label_copy,
- SHORTCUTS_COL_DATA, data,
- SHORTCUTS_COL_TYPE, shortcut_type,
- SHORTCUTS_COL_REMOVABLE, removable,
- SHORTCUTS_COL_CANCELLABLE, NULL,
- -1);
-
- if (impl->priv->shortcuts_pane_filter_model)
- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model));
-
- g_free (label_copy);
-
- if (pixbuf)
- g_object_unref (pixbuf);
-
- profile_end ("end", NULL);
-}
-
-static void
-shortcuts_append_search (GtkFileChooserDefault *impl)
-{
- GdkPixbuf *pixbuf;
- GtkTreeIter iter;
-
- pixbuf = render_search_icon (impl);
-
- gtk_list_store_append (impl->priv->shortcuts_model, &iter);
- gtk_list_store_set (impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, pixbuf,
- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
- SHORTCUTS_COL_NAME, _("Search"),
- SHORTCUTS_COL_DATA, NULL,
- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_SEARCH,
- SHORTCUTS_COL_REMOVABLE, FALSE,
- -1);
-
- if (pixbuf)
- g_object_unref (pixbuf);
-
- impl->priv->has_search = TRUE;
-}
-
-static gboolean
-shortcuts_get_recent_enabled (GtkWidget *widget)
-{
- GtkSettings *settings;
- gboolean enabled;
-
- if (gtk_widget_has_screen (widget))
- settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget));
- else
- settings = gtk_settings_get_default ();
-
- g_object_get (settings, "gtk-recent-files-enabled", &enabled, NULL);
- return enabled;
-}
-
-static void
-shortcuts_append_recent (GtkFileChooserDefault *impl)
-{
- GdkPixbuf *pixbuf;
- GtkTreeIter iter;
- gboolean enabled;
-
- enabled = shortcuts_get_recent_enabled (GTK_WIDGET (impl));
- if (!enabled)
- return;
-
- pixbuf = render_recent_icon (impl);
-
- gtk_list_store_append (impl->priv->shortcuts_model, &iter);
- gtk_list_store_set (impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, pixbuf,
- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
- SHORTCUTS_COL_NAME, _("Recently Used"),
- SHORTCUTS_COL_DATA, NULL,
- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_RECENT,
- SHORTCUTS_COL_REMOVABLE, FALSE,
- -1);
-
- if (pixbuf)
- g_object_unref (pixbuf);
-
- impl->priv->has_recent = TRUE;
-}
-
-/* Appends an item for the user's home directory to the shortcuts model */
-static void
-shortcuts_append_home (GtkFileChooserDefault *impl)
-{
- const char *home_path;
- GFile *home;
-
- profile_start ("start", NULL);
-
- home_path = g_get_home_dir ();
- if (home_path == NULL)
- {
- profile_end ("end - no home directory!?", NULL);
- return;
- }
-
- home = g_file_new_for_path (home_path);
- shortcuts_insert_file (impl, -1, SHORTCUT_TYPE_FILE, NULL, home, NULL, FALSE, SHORTCUTS_HOME);
- impl->priv->has_home = TRUE;
-
- g_object_unref (home);
-
- profile_end ("end", NULL);
-}
-
-/* Appends the ~/Desktop directory to the shortcuts model */
-static void
-shortcuts_append_desktop (GtkFileChooserDefault *impl)
-{
- const char *name;
- GFile *file;
-
- profile_start ("start", NULL);
-
- name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
- /* "To disable a directory, point it to the homedir."
- * See http://freedesktop.org/wiki/Software/xdg-user-dirs
- **/
- if (!g_strcmp0 (name, g_get_home_dir ()))
- {
- profile_end ("end", NULL);
- return;
- }
-
- file = g_file_new_for_path (name);
- shortcuts_insert_file (impl, -1, SHORTCUT_TYPE_FILE, NULL, file, _("Desktop"), FALSE, SHORTCUTS_DESKTOP);
- impl->priv->has_desktop = TRUE;
-
- /* We do not actually pop up an error dialog if there is no desktop directory
- * because some people may really not want to have one.
- */
-
- g_object_unref (file);
-
- profile_end ("end", NULL);
-}
-
-/* Appends a list of GFile to the shortcuts model; returns how many were inserted */
-static int
-shortcuts_append_bookmarks (GtkFileChooserDefault *impl,
- GSList *bookmarks)
-{
- int start_row;
- int num_inserted;
- gchar *label;
-
- profile_start ("start", NULL);
-
- start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR) + 1;
- num_inserted = 0;
-
- for (; bookmarks; bookmarks = bookmarks->next)
- {
- GFile *file;
-
- file = bookmarks->data;
-
- if (impl->priv->local_only && !_gtk_file_has_native_path (file))
- continue;
-
- if (shortcut_find_position (impl, file) != -1)
- continue;
-
- label = _gtk_file_system_get_bookmark_label (impl->priv->file_system, file);
-
- shortcuts_insert_file (impl, start_row + num_inserted, SHORTCUT_TYPE_FILE, NULL, file, label, TRUE, SHORTCUTS_BOOKMARKS);
- g_free (label);
-
- num_inserted++;
- }
-
- profile_end ("end", NULL);
-
- return num_inserted;
-}
-
-/* Returns the index for the corresponding item in the shortcuts bar */
-static int
-shortcuts_get_index (GtkFileChooserDefault *impl,
- ShortcutsIndex where)
-{
- int n;
-
- n = 0;
-
- if (where == SHORTCUTS_SEARCH)
- goto out;
-
- n += impl->priv->has_search ? 1 : 0;
-
- if (where == SHORTCUTS_RECENT)
- goto out;
-
- n += impl->priv->has_recent ? 1 : 0;
-
- if (where == SHORTCUTS_RECENT_SEPARATOR)
- goto out;
-
- n += 1; /* we always have the separator after the recently-used item */
-
- if (where == SHORTCUTS_HOME)
- goto out;
-
- n += impl->priv->has_home ? 1 : 0;
-
- if (where == SHORTCUTS_DESKTOP)
- goto out;
-
- n += impl->priv->has_desktop ? 1 : 0;
-
- if (where == SHORTCUTS_VOLUMES)
- goto out;
-
- n += impl->priv->num_volumes;
-
- if (where == SHORTCUTS_SHORTCUTS)
- goto out;
-
- n += impl->priv->num_shortcuts;
-
- if (where == SHORTCUTS_BOOKMARKS_SEPARATOR)
- goto out;
-
- /* If there are no bookmarks there won't be a separator */
- n += (impl->priv->num_bookmarks > 0) ? 1 : 0;
-
- if (where == SHORTCUTS_BOOKMARKS)
- goto out;
-
- n += impl->priv->num_bookmarks;
-
- if (where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR)
- goto out;
-
- n += 1;
-
- if (where == SHORTCUTS_CURRENT_FOLDER)
- goto out;
-
- g_assert_not_reached ();
-
- out:
-
- return n;
-}
-
-/* Adds all the file system volumes to the shortcuts model */
-static void
-shortcuts_add_volumes (GtkFileChooserDefault *impl)
-{
- int start_row;
- GSList *list, *l;
- int n;
- gboolean old_changing_folders;
-
- profile_start ("start", NULL);
-
- old_changing_folders = impl->priv->changing_folder;
- impl->priv->changing_folder = TRUE;
-
- start_row = shortcuts_get_index (impl, SHORTCUTS_VOLUMES);
- shortcuts_remove_rows (impl, start_row, impl->priv->num_volumes);
- impl->priv->num_volumes = 0;
-
- list = _gtk_file_system_list_volumes (impl->priv->file_system);
-
- n = 0;
-
- for (l = list; l; l = l->next)
- {
- GtkFileSystemVolume *volume;
-
- volume = l->data;
-
- if (impl->priv->local_only)
- {
- if (_gtk_file_system_volume_is_mounted (volume))
- {
- GFile *base_file;
- gboolean base_has_native_path = FALSE;
-
- base_file = _gtk_file_system_volume_get_root (volume);
- if (base_file != NULL)
- {
- base_has_native_path = _gtk_file_has_native_path (base_file);
- g_object_unref (base_file);
- }
-
- if (!base_has_native_path)
- continue;
- }
- }
-
- shortcuts_insert_file (impl,
- start_row + n,
- SHORTCUT_TYPE_VOLUME,
- _gtk_file_system_volume_ref (volume),
- NULL,
- NULL,
- FALSE,
- SHORTCUTS_VOLUMES);
- n++;
- }
-
- impl->priv->num_volumes = n;
- g_slist_free (list);
-
- if (impl->priv->shortcuts_pane_filter_model)
- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model));
-
- impl->priv->changing_folder = old_changing_folders;
-
- profile_end ("end", NULL);
-}
-
-/* Inserts a separator node in the shortcuts list */
-static void
-shortcuts_insert_separator (GtkFileChooserDefault *impl,
- ShortcutsIndex where)
-{
- GtkTreeIter iter;
-
- g_assert (where == SHORTCUTS_RECENT_SEPARATOR ||
- where == SHORTCUTS_BOOKMARKS_SEPARATOR ||
- where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
-
- gtk_list_store_insert (impl->priv->shortcuts_model, &iter,
- shortcuts_get_index (impl, where));
- gtk_list_store_set (impl->priv->shortcuts_model, &iter,
- SHORTCUTS_COL_PIXBUF, NULL,
- SHORTCUTS_COL_PIXBUF_VISIBLE, FALSE,
- SHORTCUTS_COL_NAME, NULL,
- SHORTCUTS_COL_DATA, NULL,
- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_SEPARATOR,
- -1);
-}
-
-/* Updates the list of bookmarks */
-static void
-shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
-{
- GSList *bookmarks;
- gboolean old_changing_folders;
- GtkTreeIter iter;
- GFile *list_selected = NULL;
- ShortcutType shortcut_type;
- gpointer col_data;
-
- profile_start ("start", NULL);
-
- old_changing_folders = impl->priv->changing_folder;
- impl->priv->changing_folder = TRUE;
-
- if (shortcuts_get_selected (impl, &iter))
- {
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model),
- &iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
-
- if (col_data && shortcut_type == SHORTCUT_TYPE_FILE)
- list_selected = g_object_ref (col_data);
- }
-
- if (impl->priv->num_bookmarks > 0)
- shortcuts_remove_rows (impl,
- shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR),
- impl->priv->num_bookmarks + 1);
-
- impl->priv->num_bookmarks = 0;
- shortcuts_insert_separator (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
-
- bookmarks = _gtk_file_system_list_bookmarks (impl->priv->file_system);
- shortcuts_append_bookmarks (impl, bookmarks);
- g_slist_foreach (bookmarks, (GFunc) g_object_unref, NULL);
- g_slist_free (bookmarks);
-
- if (impl->priv->num_bookmarks == 0)
- shortcuts_remove_rows (impl, shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR), 1);
-
- if (impl->priv->shortcuts_pane_filter_model)
- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model));
-
- if (list_selected)
- {
- shortcuts_find_folder (impl, list_selected);
- g_object_unref (list_selected);
- }
-
- impl->priv->changing_folder = old_changing_folders;
-
- profile_end ("end", NULL);
-}
-
-/* Appends a separator and a row to the shortcuts list for the current folder */
-static void
-shortcuts_add_current_folder (GtkFileChooserDefault *impl)
-{
- int pos;
-
- g_assert (!impl->priv->shortcuts_current_folder_active);
-
- g_assert (impl->priv->current_folder != NULL);
-
- pos = shortcut_find_position (impl, impl->priv->current_folder);
- if (pos == -1)
- {
- GtkFileSystemVolume *volume;
- GFile *base_file;
-
- /* Separator */
- shortcuts_insert_separator (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
-
- /* Item */
- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
-
- volume = _gtk_file_system_get_volume_for_file (impl->priv->file_system, impl->priv->current_folder);
- if (volume)
- base_file = _gtk_file_system_volume_get_root (volume);
- else
- base_file = NULL;
-
- if (base_file && g_file_equal (base_file, impl->priv->current_folder))
- shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
- else
- shortcuts_insert_file (impl, pos, SHORTCUT_TYPE_FILE, NULL, impl->priv->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
-
- if (base_file)
- g_object_unref (base_file);
- }
-}
-
-/* Updates the current folder row in the shortcuts model */
-static void
-shortcuts_update_current_folder (GtkFileChooserDefault *impl)
-{
- int pos;
-
- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
-
- if (impl->priv->shortcuts_current_folder_active)
- {
- shortcuts_remove_rows (impl, pos, 2);
- impl->priv->shortcuts_current_folder_active = FALSE;
- }
-
- shortcuts_add_current_folder (impl);
-}
-
-/* Filter function used for the shortcuts filter model */
-static gboolean
-shortcuts_pane_filter_cb (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- GtkFileChooserDefault *impl;
- GtkTreePath *path;
- int pos;
-
- impl = GTK_FILE_CHOOSER_DEFAULT (data);
-
- path = gtk_tree_model_get_path (model, iter);
- if (!path)
- return FALSE;
-
- pos = *gtk_tree_path_get_indices (path);
- gtk_tree_path_free (path);
-
- return (pos < shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR));
-}
-
-/* Creates the list model for shortcuts */
-static void
-shortcuts_model_populate (GtkFileChooserDefault *impl)
-{
- shortcuts_append_search (impl);
-
- if (impl->priv->recent_manager)
- {
- shortcuts_append_recent (impl);
- shortcuts_insert_separator (impl, SHORTCUTS_RECENT_SEPARATOR);
- }
-
- if (impl->priv->file_system)
- {
- shortcuts_append_home (impl);
- shortcuts_append_desktop (impl);
- shortcuts_add_volumes (impl);
- }
-
- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model),
- shortcuts_pane_filter_cb,
- impl,
- NULL);
-}
-
/* Callback used when the "New Folder" button is clicked */
static void
new_folder_button_clicked (GtkButton *button,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeIter iter;
GtkTreePath *path;
- if (!impl->priv->browse_files_model)
+ if (!priv->browse_files_model)
return; /* FIXME: this sucks. Disable the New Folder button or something. */
/* Prevent button from being clicked twice */
- gtk_widget_set_sensitive (impl->priv->browse_new_folder_button, FALSE);
+ gtk_widget_set_sensitive (priv->browse_new_folder_button, FALSE);
- _gtk_file_system_model_add_editable (impl->priv->browse_files_model, &iter);
+ _gtk_file_system_model_add_editable (priv->browse_files_model, &iter);
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->priv->browse_files_model), &iter);
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
- path, impl->priv->list_name_column,
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->browse_files_model), &iter);
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ path, priv->list_name_column,
FALSE, 0.0, 0.0);
- g_object_set (impl->priv->list_name_renderer, "editable", TRUE, NULL);
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
+ g_object_set (priv->list_name_renderer, "editable", TRUE, NULL);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view),
path,
- impl->priv->list_name_column,
+ priv->list_name_column,
TRUE);
gtk_tree_path_free (path);
@@ -2124,25 +995,27 @@ add_idle_while_impl_is_alive (GtkFileChooserDefault *impl, GCallback callback)
static gboolean
edited_idle_cb (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
gdk_threads_enter ();
- g_source_destroy (impl->priv->edited_idle);
- impl->priv->edited_idle = NULL;
+ g_source_destroy (priv->edited_idle);
+ priv->edited_idle = NULL;
- _gtk_file_system_model_remove_editable (impl->priv->browse_files_model);
- g_object_set (impl->priv->list_name_renderer, "editable", FALSE, NULL);
+ _gtk_file_system_model_remove_editable (priv->browse_files_model);
+ g_object_set (priv->list_name_renderer, "editable", FALSE, NULL);
- gtk_widget_set_sensitive (impl->priv->browse_new_folder_button, TRUE);
+ gtk_widget_set_sensitive (priv->browse_new_folder_button, TRUE);
- if (impl->priv->edited_new_text /* not cancelled? */
- && (strlen (impl->priv->edited_new_text) != 0)
- && (strcmp (impl->priv->edited_new_text, DEFAULT_NEW_FOLDER_NAME) != 0)) /* Don't create folder if name is empty or has not been edited */
+ if (priv->edited_new_text /* not cancelled? */
+ && (strlen (priv->edited_new_text) != 0)
+ && (strcmp (priv->edited_new_text, DEFAULT_NEW_FOLDER_NAME) != 0)) /* Don't create folder if name is empty or has not been edited */
{
GError *error = NULL;
GFile *file;
- file = g_file_get_child_for_display_name (impl->priv->current_folder,
- impl->priv->edited_new_text,
+ file = g_file_get_child_for_display_name (priv->current_folder,
+ priv->edited_new_text,
&error);
if (file)
{
@@ -2158,8 +1031,8 @@ edited_idle_cb (GtkFileChooserDefault *impl)
else
error_creating_folder_dialog (impl, file, error);
- g_free (impl->priv->edited_new_text);
- impl->priv->edited_new_text = NULL;
+ g_free (priv->edited_new_text);
+ priv->edited_new_text = NULL;
}
gdk_threads_leave ();
@@ -2171,15 +1044,17 @@ static void
queue_edited_idle (GtkFileChooserDefault *impl,
const gchar *new_text)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
/* We create the folder in an idle handler so that we don't modify the tree
* just now.
*/
- if (!impl->priv->edited_idle)
- impl->priv->edited_idle = add_idle_while_impl_is_alive (impl, G_CALLBACK (edited_idle_cb));
+ if (!priv->edited_idle)
+ priv->edited_idle = add_idle_while_impl_is_alive (impl, G_CALLBACK (edited_idle_cb));
- g_free (impl->priv->edited_new_text);
- impl->priv->edited_new_text = g_strdup (new_text);
+ g_free (priv->edited_new_text);
+ priv->edited_new_text = g_strdup (new_text);
}
/* Callback used from the text cell renderer when the new folder is named */
@@ -2208,204 +1083,6 @@ renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text,
queue_edited_idle (impl, NULL);
}
-/* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */
-static int
-shortcut_find_position (GtkFileChooserDefault *impl,
- GFile *file)
-{
- GtkTreeIter iter;
- int i;
- int current_folder_separator_idx;
-
- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter))
- return -1;
-
- current_folder_separator_idx = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
-
-#if 0
- /* FIXME: is this still needed? */
- if (current_folder_separator_idx >= impl->priv->shortcuts_model->length)
- return -1;
-#endif
-
- for (i = 0; i < current_folder_separator_idx; i++)
- {
- gpointer col_data;
- ShortcutType shortcut_type;
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
-
- if (col_data)
- {
- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
- {
- GtkFileSystemVolume *volume;
- GFile *base_file;
- gboolean exists;
-
- volume = col_data;
- base_file = _gtk_file_system_volume_get_root (volume);
-
- exists = base_file && g_file_equal (file, base_file);
-
- if (base_file)
- g_object_unref (base_file);
-
- if (exists)
- return i;
- }
- else if (shortcut_type == SHORTCUT_TYPE_FILE)
- {
- GFile *model_file;
-
- model_file = col_data;
-
- if (model_file && g_file_equal (model_file, file))
- return i;
- }
- }
-
- if (i < current_folder_separator_idx - 1)
- {
- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter))
- g_assert_not_reached ();
- }
- }
-
- return -1;
-}
-
-/* Tries to add a bookmark from a path name */
-static gboolean
-shortcuts_add_bookmark_from_file (GtkFileChooserDefault *impl,
- GFile *file,
- int pos)
-{
- GError *error;
-
- g_return_val_if_fail (G_IS_FILE (file), FALSE);
-
- if (shortcut_find_position (impl, file) != -1)
- return FALSE;
-
- error = NULL;
- if (!_gtk_file_system_insert_bookmark (impl->priv->file_system, file, pos, &error))
- {
- error_adding_bookmark_dialog (impl, file, error);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-add_bookmark_foreach_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- GtkFileChooserDefault *impl;
- GFile *file;
-
- impl = (GtkFileChooserDefault *) data;
-
- gtk_tree_model_get (model, iter,
- MODEL_COL_FILE, &file,
- -1);
-
- shortcuts_add_bookmark_from_file (impl, file, -1);
-
- g_object_unref (file);
-}
-
-/* Adds a bookmark from the currently selected item in the file list */
-static void
-bookmarks_add_selected_folder (GtkFileChooserDefault *impl)
-{
- GtkTreeSelection *selection;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
-
- if (gtk_tree_selection_count_selected_rows (selection) == 0)
- shortcuts_add_bookmark_from_file (impl, impl->priv->current_folder, -1);
- else
- gtk_tree_selection_selected_foreach (selection,
- add_bookmark_foreach_cb,
- impl);
-}
-
-/* Callback used when the "Add bookmark" button is clicked */
-static void
-add_bookmark_button_clicked_cb (GtkButton *button,
- GtkFileChooserDefault *impl)
-{
- bookmarks_add_selected_folder (impl);
-}
-
-/* Returns TRUE plus an iter in the shortcuts_model if a row is selected;
- * returns FALSE if no shortcut is selected.
- */
-static gboolean
-shortcuts_get_selected (GtkFileChooserDefault *impl,
- GtkTreeIter *iter)
-{
- GtkTreeSelection *selection;
- GtkTreeIter parent_iter;
-
- if (!impl->priv->browse_shortcuts_tree_view)
- return FALSE;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view));
-
- if (!gtk_tree_selection_get_selected (selection, NULL, &parent_iter))
- return FALSE;
-
- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model),
- iter,
- &parent_iter);
- return TRUE;
-}
-
-/* Removes the selected bookmarks */
-static void
-remove_selected_bookmarks (GtkFileChooserDefault *impl)
-{
- GtkTreeIter iter;
- gpointer col_data;
- GFile *file;
- gboolean removable;
- GError *error;
-
- if (!shortcuts_get_selected (impl, &iter))
- return;
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_REMOVABLE, &removable,
- -1);
-
- if (!removable)
- return;
-
- g_assert (col_data != NULL);
-
- file = col_data;
-
- error = NULL;
- if (!_gtk_file_system_remove_bookmark (impl->priv->file_system, file, &error))
- error_removing_bookmark_dialog (impl, file, error);
-}
-
-/* Callback used when the "Remove bookmark" button is clicked */
-static void
-remove_bookmark_button_clicked_cb (GtkButton *button,
- GtkFileChooserDefault *impl)
-{
- remove_selected_bookmarks (impl);
-}
struct selection_check_closure {
GtkFileChooserDefault *impl;
@@ -2449,6 +1126,7 @@ selection_check (GtkFileChooserDefault *impl,
gboolean *all_files,
gboolean *all_folders)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
struct selection_check_closure closure;
GtkTreeSelection *selection;
@@ -2457,7 +1135,7 @@ selection_check (GtkFileChooserDefault *impl,
closure.all_files = TRUE;
closure.all_folders = TRUE;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_selected_foreach (selection,
selection_check_foreach_cb,
&closure);
@@ -2474,859 +1152,55 @@ selection_check (GtkFileChooserDefault *impl,
*all_folders = closure.all_folders;
}
-struct get_selected_file_closure {
- GtkFileChooserDefault *impl;
- GFile *file;
-};
-
-static void
-get_selected_file_foreach_cb (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- struct get_selected_file_closure *closure = data;
-
- if (closure->file)
- {
- /* Just in case this function gets run more than once with a multiple selection; we only care about one file */
- g_object_unref (closure->file);
- closure->file = NULL;
- }
-
- gtk_tree_model_get (model, iter,
- MODEL_COL_FILE, &closure->file, /* this will give us a reffed file */
- -1);
-}
-
-/* Returns a selected path from the file list */
-static GFile *
-get_selected_file (GtkFileChooserDefault *impl)
-{
- struct get_selected_file_closure closure;
- GtkTreeSelection *selection;
-
- closure.impl = impl;
- closure.file = NULL;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
- gtk_tree_selection_selected_foreach (selection,
- get_selected_file_foreach_cb,
- &closure);
-
- return closure.file;
-}
-
-typedef struct {
- GtkFileChooserDefault *impl;
- gchar *tip;
-} UpdateTooltipData;
-
-static void
-update_tooltip (GtkTreeModel *model,
- GtkTreePath *path,
- GtkTreeIter *iter,
- gpointer data)
-{
- UpdateTooltipData *udata = data;
-
- if (udata->tip == NULL)
- {
- gchar *display_name;
-
- gtk_tree_model_get (model, iter,
- MODEL_COL_NAME, &display_name,
- -1);
-
- udata->tip = g_strdup_printf (_("Add the folder '%s' to the bookmarks"),
- display_name);
- g_free (display_name);
- }
-}
-
-
-/* Sensitize the "add bookmark" button if all the selected items are folders, or
- * if there are no selected items *and* the current folder is not in the
- * bookmarks list. De-sensitize the button otherwise.
- */
-static void
-bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl)
-{
- gint num_selected;
- gboolean all_folders;
- gboolean active;
- gchar *tip;
-
- selection_check (impl, &num_selected, NULL, &all_folders);
-
- if (num_selected == 0)
- active = (impl->priv->current_folder != NULL) && (shortcut_find_position (impl, impl->priv->current_folder) == -1);
- else if (num_selected == 1)
- {
- GFile *file;
-
- file = get_selected_file (impl);
- active = file && all_folders && (shortcut_find_position (impl, file) == -1);
- if (file)
- g_object_unref (file);
- }
- else
- active = all_folders;
-
- gtk_widget_set_sensitive (impl->priv->browse_shortcuts_add_button, active);
-
- if (impl->priv->browse_files_popup_menu_add_shortcut_item)
- gtk_widget_set_sensitive (impl->priv->browse_files_popup_menu_add_shortcut_item,
- (num_selected == 0) ? FALSE : active);
-
- if (active)
- {
- if (num_selected == 0)
- tip = g_strdup_printf (_("Add the current folder to the bookmarks"));
- else if (num_selected > 1)
- tip = g_strdup_printf (_("Add the selected folders to the bookmarks"));
- else
- {
- GtkTreeSelection *selection;
- UpdateTooltipData data;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
- data.impl = impl;
- data.tip = NULL;
- gtk_tree_selection_selected_foreach (selection, update_tooltip, &data);
- tip = data.tip;
- }
-
- gtk_widget_set_tooltip_text (impl->priv->browse_shortcuts_add_button, tip);
- g_free (tip);
- }
-}
-
-/* Sets the sensitivity of the "remove bookmark" button depending on whether a
- * bookmark row is selected in the shortcuts tree.
- */
-static void
-bookmarks_check_remove_sensitivity (GtkFileChooserDefault *impl)
-{
- GtkTreeIter iter;
- gboolean removable = FALSE;
- gchar *name = NULL;
- gchar *tip;
-
- if (shortcuts_get_selected (impl, &iter))
- {
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_REMOVABLE, &removable,
- SHORTCUTS_COL_NAME, &name,
- -1);
- gtk_widget_set_sensitive (impl->priv->browse_shortcuts_remove_button, removable);
-
- if (removable)
- tip = g_strdup_printf (_("Remove the bookmark '%s'"), name);
- else
- tip = g_strdup_printf (_("Bookmark '%s' cannot be removed"), name);
-
- gtk_widget_set_tooltip_text (impl->priv->browse_shortcuts_remove_button, tip);
- g_free (tip);
- }
- else
- gtk_widget_set_tooltip_text (impl->priv->browse_shortcuts_remove_button,
- _("Remove the selected bookmark"));
- g_free (name);
-}
-
-static void
-shortcuts_check_popup_sensitivity (GtkFileChooserDefault *impl)
-{
- GtkTreeIter iter;
- gboolean removable = FALSE;
-
- if (impl->priv->browse_shortcuts_popup_menu == NULL)
- return;
-
- if (shortcuts_get_selected (impl, &iter))
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_REMOVABLE, &removable,
- -1);
-
- gtk_widget_set_sensitive (impl->priv->browse_shortcuts_popup_menu_remove_item, removable);
- gtk_widget_set_sensitive (impl->priv->browse_shortcuts_popup_menu_rename_item, removable);
-}
-
-/* GtkWidget::drag-begin handler for the shortcuts list. */
-static void
-shortcuts_drag_begin_cb (GtkWidget *widget,
- GdkDragContext *context,
- GtkFileChooserDefault *impl)
-{
-#if 0
- impl->priv->shortcuts_drag_context = g_object_ref (context);
-#endif
-}
-
-#if 0
-/* Removes the idle handler for outside drags */
-static void
-shortcuts_cancel_drag_outside_idle (GtkFileChooserDefault *impl)
-{
- if (!impl->priv->shortcuts_drag_outside_idle)
- return;
-
- g_source_destroy (impl->priv->shortcuts_drag_outside_idle);
- impl->priv->shortcuts_drag_outside_idle = NULL;
-}
-#endif
-
-/* GtkWidget::drag-end handler for the shortcuts list. */
-static void
-shortcuts_drag_end_cb (GtkWidget *widget,
- GdkDragContext *context,
- GtkFileChooserDefault *impl)
-{
-#if 0
- g_object_unref (impl->priv->shortcuts_drag_context);
-
- shortcuts_cancel_drag_outside_idle (impl);
-
- if (!impl->priv->shortcuts_drag_outside)
- return;
-
- gtk_button_clicked (GTK_BUTTON (impl->priv->browse_shortcuts_remove_button));
-
- impl->priv->shortcuts_drag_outside = FALSE;
-#endif
-}
-
-/* GtkWidget::drag-data-delete handler for the shortcuts list. */
-static void
-shortcuts_drag_data_delete_cb (GtkWidget *widget,
- GdkDragContext *context,
- GtkFileChooserDefault *impl)
-{
- g_signal_stop_emission_by_name (widget, "drag-data-delete");
-}
-
-/* GtkWidget::drag-leave handler for the shortcuts list. We unhighlight the
- * drop position.
- */
-static void
-shortcuts_drag_leave_cb (GtkWidget *widget,
- GdkDragContext *context,
- guint time_,
- GtkFileChooserDefault *impl)
-{
-#if 0
- if (gtk_drag_get_source_widget (context) == widget && !impl->priv->shortcuts_drag_outside_idle)
- {
- impl->priv->shortcuts_drag_outside_idle = add_idle_while_impl_is_alive (impl, G_CALLBACK (shortcuts_drag_outside_idle_cb));
- }
-#endif
-
- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view),
- NULL,
- GTK_TREE_VIEW_DROP_BEFORE);
-
- g_signal_stop_emission_by_name (widget, "drag-leave");
-}
-
-/* Computes the appropriate row and position for dropping */
-static void
-shortcuts_compute_drop_position (GtkFileChooserDefault *impl,
- int x,
- int y,
- GtkTreePath **path,
- GtkTreeViewDropPosition *pos)
-{
- GtkTreeView *tree_view;
- GtkTreeViewColumn *column;
- int cell_y;
- GdkRectangle cell;
- int row;
- int bookmarks_index;
- int header_height = 0;
-
- tree_view = GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view);
-
- if (gtk_tree_view_get_headers_visible (tree_view))
- header_height = _gtk_tree_view_get_header_height (tree_view);
-
- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
-
- if (!gtk_tree_view_get_path_at_pos (tree_view,
- x,
- y - header_height,
- path,
- &column,
- NULL,
- &cell_y))
- {
- row = bookmarks_index + impl->priv->num_bookmarks - 1;
- *path = gtk_tree_path_new_from_indices (row, -1);
- *pos = GTK_TREE_VIEW_DROP_AFTER;
- return;
- }
-
- row = *gtk_tree_path_get_indices (*path);
- gtk_tree_view_get_background_area (tree_view, *path, column, &cell);
- gtk_tree_path_free (*path);
-
- if (row < bookmarks_index)
- {
- row = bookmarks_index;
- *pos = GTK_TREE_VIEW_DROP_BEFORE;
- }
- else if (row > bookmarks_index + impl->priv->num_bookmarks - 1)
- {
- row = bookmarks_index + impl->priv->num_bookmarks - 1;
- *pos = GTK_TREE_VIEW_DROP_AFTER;
- }
- else
- {
- if (cell_y < cell.height / 2)
- *pos = GTK_TREE_VIEW_DROP_BEFORE;
- else
- *pos = GTK_TREE_VIEW_DROP_AFTER;
- }
-
- *path = gtk_tree_path_new_from_indices (row, -1);
-}
-
-/* GtkWidget::drag-motion handler for the shortcuts list. We basically
- * implement the destination side of DnD by hand, due to limitations in
- * GtkTreeView's DnD API.
- */
-static gboolean
-shortcuts_drag_motion_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time_,
- GtkFileChooserDefault *impl)
-{
- GtkTreePath *path;
- GtkTreeViewDropPosition pos;
- GdkDragAction action;
-
-#if 0
- if (gtk_drag_get_source_widget (context) == widget)
- {
- shortcuts_cancel_drag_outside_idle (impl);
-
- if (impl->priv->shortcuts_drag_outside)
- {
- shortcuts_drag_set_delete_cursor (impl, FALSE);
- impl->priv->shortcuts_drag_outside = FALSE;
- }
- }
-#endif
-
- if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_COPY ||
- (gdk_drag_context_get_actions (context) & GDK_ACTION_COPY) != 0)
- action = GDK_ACTION_COPY;
- else if (gdk_drag_context_get_suggested_action (context) == GDK_ACTION_MOVE ||
- (gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
- action = GDK_ACTION_MOVE;
- else
- {
- action = 0;
- goto out;
- }
-
- shortcuts_compute_drop_position (impl, x, y, &path, &pos);
- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view), path, pos);
- gtk_tree_path_free (path);
-
- out:
-
- g_signal_stop_emission_by_name (widget, "drag-motion");
-
- if (action != 0)
- {
- gdk_drag_status (context, action, time_);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/* GtkWidget::drag-drop handler for the shortcuts list. */
static gboolean
-shortcuts_drag_drop_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time_,
- GtkFileChooserDefault *impl)
+file_is_recent_uri (GFile *file)
{
-#if 0
- shortcuts_cancel_drag_outside_idle (impl);
-#endif
-
- g_signal_stop_emission_by_name (widget, "drag-drop");
- return TRUE;
-}
-
-/* Parses a "text/uri-list" string and inserts its URIs as bookmarks */
-static void
-shortcuts_drop_uris (GtkFileChooserDefault *impl,
- GtkSelectionData *selection_data,
- int position)
-{
- gchar **uris;
- gint i;
+ GFile *recent;
+ gboolean same;
- uris = gtk_selection_data_get_uris (selection_data);
- if (!uris)
- return;
+ recent = g_file_new_for_uri ("recent:///");
+ same = g_file_equal (file, recent);
+ g_object_unref (recent);
- for (i = 0; uris[i]; i++)
- {
- char *uri;
- GFile *file;
-
- uri = uris[i];
- file = g_file_new_for_uri (uri);
-
- if (shortcuts_add_bookmark_from_file (impl, file, position))
- position++;
-
- g_object_unref (file);
- }
-
- g_strfreev (uris);
+ return same;
}
-/* Reorders the selected bookmark to the specified position */
static void
-shortcuts_reorder (GtkFileChooserDefault *impl,
- int new_position)
+places_sidebar_open_location_cb (GtkPlacesSidebar *sidebar, GFile *location, GtkPlacesOpenFlags open_flags, GtkFileChooserDefault *impl)
{
- GtkTreeIter iter;
- gpointer col_data;
- ShortcutType shortcut_type;
- GtkTreePath *path;
- int old_position;
- int bookmarks_index;
- GFile *file;
- GError *error;
- gchar *name = NULL;
-
- /* Get the selected path */
-
- if (!shortcuts_get_selected (impl, &iter))
- g_assert_not_reached ();
-
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter);
- old_position = *gtk_tree_path_get_indices (path);
- gtk_tree_path_free (path);
-
- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
- old_position -= bookmarks_index;
- g_assert (old_position >= 0 && old_position < impl->priv->num_bookmarks);
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_NAME, &name,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
- g_assert (col_data != NULL);
- g_assert (shortcut_type == SHORTCUT_TYPE_FILE);
-
- file = col_data;
- g_object_ref (file); /* removal below will free file, so we need a new ref */
-
- /* Remove the path from the old position and insert it in the new one */
-
- if (new_position > old_position)
- new_position--;
-
- if (old_position == new_position)
- goto out;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ gboolean clear_entry;
- error = NULL;
- if (_gtk_file_system_remove_bookmark (impl->priv->file_system, file, &error))
- {
- shortcuts_add_bookmark_from_file (impl, file, new_position);
- _gtk_file_system_set_bookmark_label (impl->priv->file_system, file, name);
- }
+ /* In the Save modes, we want to preserve what the uesr typed in the filename
+ * entry, so that he may choose another folder without erasing his typed name.
+ */
+ if (priv->location_entry
+ && !(priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
+ clear_entry = TRUE;
else
- error_adding_bookmark_dialog (impl, file, error);
-
- out:
-
- g_object_unref (file);
- g_free (name);
-}
-
-/* Callback used when we get the drag data for the bookmarks list. We add the
- * received URIs as bookmarks if they are folders.
- */
-static void
-shortcuts_drag_data_received_cb (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- GtkSelectionData *selection_data,
- guint info,
- guint time_,
- gpointer data)
-{
- GtkFileChooserDefault *impl;
- GtkTreePath *tree_path;
- GtkTreeViewDropPosition tree_pos;
- GdkAtom target;
- int position;
- int bookmarks_index;
-
- impl = GTK_FILE_CHOOSER_DEFAULT (data);
-
- /* Compute position */
-
- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
-
- shortcuts_compute_drop_position (impl, x, y, &tree_path, &tree_pos);
- position = *gtk_tree_path_get_indices (tree_path);
- gtk_tree_path_free (tree_path);
-
- if (tree_pos == GTK_TREE_VIEW_DROP_AFTER)
- position++;
-
- g_assert (position >= bookmarks_index);
- position -= bookmarks_index;
-
- target = gtk_selection_data_get_target (selection_data);
-
- if (gtk_targets_include_uri (&target, 1))
- shortcuts_drop_uris (impl, selection_data, position);
- else if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
- shortcuts_reorder (impl, position);
-
- g_signal_stop_emission_by_name (widget, "drag-data-received");
-}
-
-/* Callback used to display a tooltip in the shortcuts tree */
-static gboolean
-shortcuts_query_tooltip_cb (GtkWidget *widget,
- gint x,
- gint y,
- gboolean keyboard_mode,
- GtkTooltip *tooltip,
- GtkFileChooserDefault *impl)
-{
- GtkTreeModel *model;
- GtkTreeIter iter;
-
- if (gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget),
- &x, &y,
- keyboard_mode,
- &model,
- NULL,
- &iter))
- {
- gpointer col_data;
- ShortcutType shortcut_type;
-
- gtk_tree_model_get (model, &iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
-
- if (shortcut_type == SHORTCUT_TYPE_SEPARATOR)
- return FALSE;
- else if (shortcut_type == SHORTCUT_TYPE_VOLUME)
- return FALSE;
- else if (shortcut_type == SHORTCUT_TYPE_FILE)
- {
- GFile *file;
- char *parse_name;
+ clear_entry = FALSE;
- file = G_FILE (col_data);
- parse_name = g_file_get_parse_name (file);
-
- gtk_tooltip_set_text (tooltip, parse_name);
-
- g_free (parse_name);
-
- return TRUE;
- }
- else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
- {
- return FALSE;
- }
- else if (shortcut_type == SHORTCUT_TYPE_RECENT)
- {
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
-
-/* Callback used when the selection in the shortcuts tree changes */
-static void
-shortcuts_selection_changed_cb (GtkTreeSelection *selection,
- GtkFileChooserDefault *impl)
-{
- GtkTreeIter iter;
- GtkTreeIter child_iter;
-
- bookmarks_check_remove_sensitivity (impl);
- shortcuts_check_popup_sensitivity (impl);
-
- if (impl->priv->changing_folder)
- return;
-
- if (gtk_tree_selection_get_selected(selection, NULL, &iter))
- {
- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model),
- &child_iter,
- &iter);
- shortcuts_activate_iter (impl, &child_iter);
- }
-}
-
-static gboolean
-shortcuts_row_separator_func (GtkTreeModel *model,
- GtkTreeIter *iter,
- gpointer data)
-{
- ShortcutType shortcut_type;
-
- gtk_tree_model_get (model, iter, SHORTCUTS_COL_TYPE, &shortcut_type, -1);
-
- return shortcut_type == SHORTCUT_TYPE_SEPARATOR;
-}
-
-static gboolean
-shortcuts_key_press_event_after_cb (GtkWidget *tree_view,
- GdkEventKey *event,
- GtkFileChooserDefault *impl)
-{
- GtkWidget *entry;
-
- /* Connect "after" to key-press-event on the shortcuts pane. We want this action to be possible:
- *
- * 1. user brings up a SAVE dialog
- * 2. user clicks on a shortcut in the shortcuts pane
- * 3. user starts typing a filename
+ /* FIXME-places-sidebar:
*
- * Normally, the user's typing would be ignored, as the shortcuts treeview doesn't
- * support interactive search. However, we'd rather focus the location entry
- * so that the user can type *there*.
- *
- * To preserve keyboard navigation in the shortcuts pane, we don't focus the
- * filename entry if one clicks on a shortcut; rather, we focus the entry only
- * if the user starts typing while the focus is in the shortcuts pane.
+ * GtkPlacesSidebar doesn't have a Search item anymore. We should put that function in a toolbar-like button, like
+ * in Nautilus, and do operation_mode_set (impl, OPERATION_MODE_SEARCH);
*/
- /* don't screw up focus switching with Tab */
- if (event->keyval == GDK_KEY_Tab
- || event->keyval == GDK_KEY_KP_Tab
- || event->keyval == GDK_KEY_ISO_Left_Tab
- || event->length < 1)
- return FALSE;
-
- if (impl->priv->location_entry)
- entry = impl->priv->location_entry;
- else if (impl->priv->search_entry)
- entry = impl->priv->search_entry;
+ if (file_is_recent_uri (location))
+ operation_mode_set (impl, OPERATION_MODE_RECENT);
else
- entry = NULL;
-
- if (entry)
- {
- gtk_widget_grab_focus (entry);
- return gtk_widget_event (entry, (GdkEvent *) event);
- }
- else
- return FALSE;
-}
-
-/* Callback used when the file list's popup menu is detached */
-static void
-shortcuts_popup_menu_detach_cb (GtkWidget *attach_widget,
- GtkMenu *menu)
-{
- GtkFileChooserDefault *impl;
-
- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
-
- impl->priv->browse_shortcuts_popup_menu = NULL;
- impl->priv->browse_shortcuts_popup_menu_remove_item = NULL;
- impl->priv->browse_shortcuts_popup_menu_rename_item = NULL;
-}
-
-static void
-remove_shortcut_cb (GtkMenuItem *item,
- GtkFileChooserDefault *impl)
-{
- remove_selected_bookmarks (impl);
-}
-
-/* Rename the selected bookmark */
-static void
-rename_selected_bookmark (GtkFileChooserDefault *impl)
-{
- GtkTreeIter iter;
- GtkTreePath *path;
- GtkTreeViewColumn *column;
- GtkCellRenderer *cell;
- GList *renderers;
-
- if (shortcuts_get_selected (impl, &iter))
- {
- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter);
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view), 0);
- renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
- cell = g_list_nth_data (renderers, 1);
- g_list_free (renderers);
- g_object_set (cell, "editable", TRUE, NULL);
- gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view),
- path, column, cell, TRUE);
- gtk_tree_path_free (path);
- }
-}
-
-static void
-rename_shortcut_cb (GtkMenuItem *item,
- GtkFileChooserDefault *impl)
-{
- rename_selected_bookmark (impl);
-}
-
-/* Constructs the popup menu for the file list if needed */
-static void
-shortcuts_build_popup_menu (GtkFileChooserDefault *impl)
-{
- GtkWidget *item;
-
- if (impl->priv->browse_shortcuts_popup_menu)
- return;
-
- impl->priv->browse_shortcuts_popup_menu = gtk_menu_new ();
- gtk_menu_attach_to_widget (GTK_MENU (impl->priv->browse_shortcuts_popup_menu),
- impl->priv->browse_shortcuts_tree_view,
- shortcuts_popup_menu_detach_cb);
-
- item = gtk_image_menu_item_new_with_label (_("Remove"));
- impl->priv->browse_shortcuts_popup_menu_remove_item = item;
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
- gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
- g_signal_connect (item, "activate",
- G_CALLBACK (remove_shortcut_cb), impl);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (impl->priv->browse_shortcuts_popup_menu), item);
-
- item = gtk_menu_item_new_with_label (_("Rename…"));
- impl->priv->browse_shortcuts_popup_menu_rename_item = item;
- g_signal_connect (item, "activate",
- G_CALLBACK (rename_shortcut_cb), impl);
- gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (impl->priv->browse_shortcuts_popup_menu), item);
-}
-
-static void
-shortcuts_update_popup_menu (GtkFileChooserDefault *impl)
-{
- shortcuts_build_popup_menu (impl);
- shortcuts_check_popup_sensitivity (impl);
-}
-
-static void
-popup_position_func (GtkMenu *menu,
- gint *x,
- gint *y,
- gboolean *push_in,
- gpointer user_data);
-
-static void
-shortcuts_popup_menu (GtkFileChooserDefault *impl,
- GdkEventButton *event)
-{
- shortcuts_update_popup_menu (impl);
- if (event)
- gtk_menu_popup (GTK_MENU (impl->priv->browse_shortcuts_popup_menu),
- NULL, NULL, NULL, NULL,
- event->button, event->time);
- else
- {
- gtk_menu_popup (GTK_MENU (impl->priv->browse_shortcuts_popup_menu),
- NULL, NULL,
- popup_position_func, impl->priv->browse_shortcuts_tree_view,
- 0, GDK_CURRENT_TIME);
- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->priv->browse_shortcuts_popup_menu),
- FALSE);
- }
-}
-
-/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
-static gboolean
-shortcuts_popup_menu_cb (GtkWidget *widget,
- GtkFileChooserDefault *impl)
-{
- shortcuts_popup_menu (impl, NULL);
- return TRUE;
-}
-
-/* Callback used when a button is pressed on the shortcuts list.
- * We trap button 3 to bring up a popup menu.
- */
-static gboolean
-shortcuts_button_press_event_cb (GtkWidget *widget,
- GdkEventButton *event,
- GtkFileChooserDefault *impl)
-{
- static gboolean in_press = FALSE;
- gboolean handled;
-
- if (in_press)
- return FALSE;
-
- if (!gdk_event_triggers_context_menu ((GdkEvent *) event))
- return FALSE;
-
- in_press = TRUE;
- handled = gtk_widget_event (impl->priv->browse_shortcuts_tree_view, (GdkEvent *) event);
- in_press = FALSE;
-
- if (!handled)
- return FALSE;
-
- shortcuts_popup_menu (impl, event);
- return TRUE;
+ change_folder_and_display_error (impl, location, clear_entry);
}
+/* Callback used when the places sidebar needs us to display an error message */
static void
-shortcuts_edited (GtkCellRenderer *cell,
- gchar *path_string,
- gchar *new_text,
- GtkFileChooserDefault *impl)
+places_sidebar_show_error_message_cb (GtkPlacesSidebar *sidebar,
+ const char *primary,
+ const char *secondary,
+ GtkFileChooserDefault *impl)
{
- GtkTreePath *path;
- GtkTreeIter iter;
- GFile *shortcut;
-
- g_object_set (cell, "editable", FALSE, NULL);
-
- path = gtk_tree_path_new_from_string (path_string);
- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter, path))
- g_assert_not_reached ();
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_DATA, &shortcut,
- -1);
- gtk_tree_path_free (path);
-
- _gtk_file_system_set_bookmark_label (impl->priv->file_system, shortcut, new_text);
-}
-
-static void
-shortcuts_editing_canceled (GtkCellRenderer *cell,
- GtkFileChooserDefault *impl)
-{
- g_object_set (cell, "editable", FALSE, NULL);
+ error_message (impl, primary, secondary);
}
static gboolean
@@ -3352,11 +1226,10 @@ browse_files_key_press_event_cb (GtkWidget *widget,
GdkEventKey *event,
gpointer data)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = (GtkFileChooserDefault *) data;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GdkModifierType no_text_input_mask;
- impl = (GtkFileChooserDefault *) data;
-
no_text_input_mask =
gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_NO_TEXT_INPUT);
@@ -3373,7 +1246,7 @@ browse_files_key_press_event_cb (GtkWidget *widget,
if (key_is_left_or_right (event))
{
- gtk_widget_grab_focus (impl->priv->browse_shortcuts_tree_view);
+ gtk_widget_grab_focus (priv->places_sidebar);
return TRUE;
}
@@ -3383,8 +1256,8 @@ browse_files_key_press_event_cb (GtkWidget *widget,
|| event->keyval == GDK_KEY_space
|| event->keyval == GDK_KEY_KP_Space)
&& !(event->state & gtk_accelerator_get_default_mod_mask ())
- && !(impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
+ && !(priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
{
GtkWindow *window;
@@ -3414,15 +1287,39 @@ static void
popup_menu_detach_cb (GtkWidget *attach_widget,
GtkMenu *menu)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
+ GtkFileChooserDefaultPrivate *priv;
- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
- impl->priv->browse_files_popup_menu = NULL;
- impl->priv->browse_files_popup_menu_add_shortcut_item = NULL;
- impl->priv->browse_files_popup_menu_hidden_files_item = NULL;
- impl->priv->browse_files_popup_menu_copy_file_location_item = NULL;
+ priv = impl->priv;
+
+ priv->browse_files_popup_menu = NULL;
+ priv->browse_files_popup_menu_add_shortcut_item = NULL;
+ priv->browse_files_popup_menu_hidden_files_item = NULL;
+ priv->browse_files_popup_menu_copy_file_location_item = NULL;
+}
+
+/* Callback used from gtk_tree_selection_selected_foreach(); adds a bookmark for
+ * each selected item in the file list.
+ */
+static void
+add_bookmark_foreach_cb (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ GtkFileChooserDefault *impl = (GtkFileChooserDefault *) data;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GFile *file;
+
+ gtk_tree_model_get (model, iter,
+ MODEL_COL_FILE, &file,
+ -1);
+
+ _gtk_bookmarks_manager_insert_bookmark (priv->bookmarks_manager, file, 0, NULL); /* NULL-GError */
+
+ g_object_unref (file);
}
/* Callback used when the "Add to Bookmarks" menu item is activated */
@@ -3430,7 +1327,14 @@ static void
add_to_shortcuts_cb (GtkMenuItem *item,
GtkFileChooserDefault *impl)
{
- bookmarks_add_selected_folder (impl);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+
+ gtk_tree_selection_selected_foreach (selection,
+ add_bookmark_foreach_cb,
+ impl);
}
/* callback used to set data to clipboard */
@@ -3560,10 +1464,12 @@ static void
show_size_column_toggled_cb (GtkCheckMenuItem *item,
GtkFileChooserDefault *impl)
{
- impl->priv->show_size_column = gtk_check_menu_item_get_active (item);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- gtk_tree_view_column_set_visible (impl->priv->list_size_column,
- impl->priv->show_size_column);
+ priv->show_size_column = gtk_check_menu_item_get_active (item);
+
+ gtk_tree_view_column_set_visible (priv->list_size_column,
+ priv->show_size_column);
}
/* Shows an error dialog about not being able to select a dragged file */
@@ -3617,17 +1523,18 @@ file_list_drag_data_received_get_info_cb (GCancellable *cancellable,
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
struct FileListDragData *data = user_data;
GtkFileChooser *chooser = GTK_FILE_CHOOSER (data->impl);
+ GtkFileChooserDefaultPrivate *priv = data->impl->priv;
- if (cancellable != data->impl->priv->file_list_drag_data_received_cancellable)
+ if (cancellable != priv->file_list_drag_data_received_cancellable)
goto out;
- data->impl->priv->file_list_drag_data_received_cancellable = NULL;
+ priv->file_list_drag_data_received_cancellable = NULL;
if (cancelled || error)
goto out;
- if ((data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE) &&
+ if ((priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE) &&
data->uris[1] == 0 && !error && _gtk_file_info_consider_as_directory (info))
change_folder_and_display_error (data->impl, data->file, FALSE);
else
@@ -3642,7 +1549,7 @@ file_list_drag_data_received_get_info_cb (GCancellable *cancellable,
browse_files_center_selected_row (data->impl);
}
- if (data->impl->priv->select_multiple)
+ if (priv->select_multiple)
file_list_drag_data_select_uris (data->impl, data->uris);
out:
@@ -3664,13 +1571,12 @@ file_list_drag_data_received_cb (GtkWidget *widget,
guint time_,
gpointer data)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gchar **uris;
char *uri;
GFile *file;
- impl = GTK_FILE_CHOOSER_DEFAULT (data);
-
/* Allow only drags from other widgets; see bug #533891. */
if (gtk_drag_get_source_widget (context) == widget)
{
@@ -3692,11 +1598,11 @@ file_list_drag_data_received_cb (GtkWidget *widget,
data->uris = uris;
data->file = file;
- if (impl->priv->file_list_drag_data_received_cancellable)
- g_cancellable_cancel (impl->priv->file_list_drag_data_received_cancellable);
+ if (priv->file_list_drag_data_received_cancellable)
+ g_cancellable_cancel (priv->file_list_drag_data_received_cancellable);
- impl->priv->file_list_drag_data_received_cancellable =
- _gtk_file_system_get_info (impl->priv->file_system, file,
+ priv->file_list_drag_data_received_cancellable =
+ _gtk_file_system_get_info (priv->file_system, file,
"standard::type",
file_list_drag_data_received_get_info_cb,
data);
@@ -3738,17 +1644,18 @@ file_list_drag_motion_cb (GtkWidget *widget,
static void
check_copy_file_location_sensitivity (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
gboolean active;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
if (gtk_tree_selection_count_selected_rows (selection) == 0)
active = FALSE;
else
active = TRUE;
- if (impl->priv->browse_files_popup_menu_copy_file_location_item)
- gtk_widget_set_sensitive (impl->priv->browse_files_popup_menu_copy_file_location_item, active);
+ if (priv->browse_files_popup_menu_copy_file_location_item)
+ gtk_widget_set_sensitive (priv->browse_files_popup_menu_copy_file_location_item, active);
}
static GtkWidget *
@@ -3757,6 +1664,7 @@ file_list_add_image_menu_item (GtkFileChooserDefault *impl,
const char *mnemonic_label,
GCallback callback)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *item;
item = gtk_image_menu_item_new_with_mnemonic (mnemonic_label);
@@ -3764,7 +1672,7 @@ file_list_add_image_menu_item (GtkFileChooserDefault *impl,
gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU));
g_signal_connect (item, "activate", callback, impl);
gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (impl->priv->browse_files_popup_menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->browse_files_popup_menu), item);
return item;
}
@@ -3774,12 +1682,13 @@ file_list_add_check_menu_item (GtkFileChooserDefault *impl,
const char *mnemonic_label,
GCallback callback)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *item;
item = gtk_check_menu_item_new_with_mnemonic (mnemonic_label);
g_signal_connect (item, "toggled", callback, impl);
gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (impl->priv->browse_files_popup_menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->browse_files_popup_menu), item);
return item;
}
@@ -3788,36 +1697,36 @@ file_list_add_check_menu_item (GtkFileChooserDefault *impl,
static void
file_list_build_popup_menu (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *item;
- if (impl->priv->browse_files_popup_menu)
+ if (priv->browse_files_popup_menu)
return;
- impl->priv->browse_files_popup_menu = gtk_menu_new ();
- gtk_menu_attach_to_widget (GTK_MENU (impl->priv->browse_files_popup_menu),
- impl->priv->browse_files_tree_view,
+ priv->browse_files_popup_menu = gtk_menu_new ();
+ gtk_menu_attach_to_widget (GTK_MENU (priv->browse_files_popup_menu),
+ priv->browse_files_tree_view,
popup_menu_detach_cb);
- impl->priv->browse_files_popup_menu_visit_file_item = file_list_add_image_menu_item (impl, GTK_STOCK_DIRECTORY, _("_Visit this file"),
+ priv->browse_files_popup_menu_visit_file_item = file_list_add_image_menu_item (impl, GTK_STOCK_DIRECTORY, _("_Visit this file"),
G_CALLBACK (visit_file_cb));
- impl->priv->browse_files_popup_menu_copy_file_location_item = file_list_add_image_menu_item (impl, GTK_STOCK_COPY, _("_Copy file’s location"),
+ priv->browse_files_popup_menu_copy_file_location_item = file_list_add_image_menu_item (impl, GTK_STOCK_COPY, _("_Copy file’s location"),
G_CALLBACK (copy_file_location_cb));
- impl->priv->browse_files_popup_menu_add_shortcut_item = file_list_add_image_menu_item (impl, GTK_STOCK_ADD, _("_Add to Bookmarks"),
+ priv->browse_files_popup_menu_add_shortcut_item = file_list_add_image_menu_item (impl, GTK_STOCK_ADD, _("_Add to Bookmarks"),
G_CALLBACK (add_to_shortcuts_cb));
item = gtk_separator_menu_item_new ();
gtk_widget_show (item);
- gtk_menu_shell_append (GTK_MENU_SHELL (impl->priv->browse_files_popup_menu), item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (priv->browse_files_popup_menu), item);
- impl->priv->browse_files_popup_menu_hidden_files_item = file_list_add_check_menu_item (impl, _("Show _Hidden Files"),
+ priv->browse_files_popup_menu_hidden_files_item = file_list_add_check_menu_item (impl, _("Show _Hidden Files"),
G_CALLBACK (show_hidden_toggled_cb));
- impl->priv->browse_files_popup_menu_size_column_item = file_list_add_check_menu_item (impl, _("Show _Size Column"),
+ priv->browse_files_popup_menu_size_column_item = file_list_add_check_menu_item (impl, _("Show _Size Column"),
G_CALLBACK (show_size_column_toggled_cb));
- bookmarks_check_add_sensitivity (impl);
check_copy_file_location_sensitivity (impl);
}
@@ -3825,6 +1734,8 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl)
static void
file_list_update_popup_menu (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
file_list_build_popup_menu (impl);
/* The sensitivity of the Add to Bookmarks item is set in
@@ -3832,22 +1743,22 @@ file_list_update_popup_menu (GtkFileChooserDefault *impl)
*/
/* 'Visit this file' */
- gtk_widget_set_visible (impl->priv->browse_files_popup_menu_visit_file_item, (impl->priv->operation_mode != OPERATION_MODE_BROWSE));
+ gtk_widget_set_visible (priv->browse_files_popup_menu_visit_file_item, (priv->operation_mode != OPERATION_MODE_BROWSE));
/* 'Show Hidden Files' */
- g_signal_handlers_block_by_func (impl->priv->browse_files_popup_menu_hidden_files_item,
+ g_signal_handlers_block_by_func (priv->browse_files_popup_menu_hidden_files_item,
G_CALLBACK (show_hidden_toggled_cb), impl);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->priv->browse_files_popup_menu_hidden_files_item),
- impl->priv->show_hidden);
- g_signal_handlers_unblock_by_func (impl->priv->browse_files_popup_menu_hidden_files_item,
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (priv->browse_files_popup_menu_hidden_files_item),
+ priv->show_hidden);
+ g_signal_handlers_unblock_by_func (priv->browse_files_popup_menu_hidden_files_item,
G_CALLBACK (show_hidden_toggled_cb), impl);
/* 'Show Size Column' */
- g_signal_handlers_block_by_func (impl->priv->browse_files_popup_menu_size_column_item,
+ g_signal_handlers_block_by_func (priv->browse_files_popup_menu_size_column_item,
G_CALLBACK (show_size_column_toggled_cb), impl);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->priv->browse_files_popup_menu_size_column_item),
- impl->priv->show_size_column);
- g_signal_handlers_unblock_by_func (impl->priv->browse_files_popup_menu_size_column_item,
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (priv->browse_files_popup_menu_size_column_item),
+ priv->show_size_column);
+ g_signal_handlers_unblock_by_func (priv->browse_files_popup_menu_size_column_item,
G_CALLBACK (show_size_column_toggled_cb), impl);
}
@@ -3890,18 +1801,20 @@ static void
file_list_popup_menu (GtkFileChooserDefault *impl,
GdkEventButton *event)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
file_list_update_popup_menu (impl);
if (event)
- gtk_menu_popup (GTK_MENU (impl->priv->browse_files_popup_menu),
+ gtk_menu_popup (GTK_MENU (priv->browse_files_popup_menu),
NULL, NULL, NULL, NULL,
event->button, event->time);
else
{
- gtk_menu_popup (GTK_MENU (impl->priv->browse_files_popup_menu),
+ gtk_menu_popup (GTK_MENU (priv->browse_files_popup_menu),
NULL, NULL,
- popup_position_func, impl->priv->browse_files_tree_view,
+ popup_position_func, priv->browse_files_tree_view,
0, GDK_CURRENT_TIME);
- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->priv->browse_files_popup_menu),
+ gtk_menu_shell_select_first (GTK_MENU_SHELL (priv->browse_files_popup_menu),
FALSE);
}
@@ -3924,6 +1837,8 @@ list_button_press_event_cb (GtkWidget *widget,
GdkEventButton *event,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
static gboolean in_press = FALSE;
if (in_press)
@@ -3933,7 +1848,7 @@ list_button_press_event_cb (GtkWidget *widget,
return FALSE;
in_press = TRUE;
- gtk_widget_event (impl->priv->browse_files_tree_view, (GdkEvent *) event);
+ gtk_widget_event (priv->browse_files_tree_view, (GdkEvent *) event);
in_press = FALSE;
file_list_popup_menu (impl, event);
@@ -3952,9 +1867,11 @@ typedef struct {
static void
file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
{
- gtk_tree_view_column_set_sort_column_id (impl->priv->list_name_column, MODEL_COL_NAME);
- gtk_tree_view_column_set_sort_column_id (impl->priv->list_mtime_column, MODEL_COL_MTIME);
- gtk_tree_view_column_set_sort_column_id (impl->priv->list_size_column, MODEL_COL_SIZE);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ gtk_tree_view_column_set_sort_column_id (priv->list_name_column, MODEL_COL_NAME);
+ gtk_tree_view_column_set_sort_column_id (priv->list_mtime_column, MODEL_COL_MTIME);
+ gtk_tree_view_column_set_sort_column_id (priv->list_size_column, MODEL_COL_SIZE);
}
static gboolean
@@ -3966,17 +1883,18 @@ file_list_query_tooltip_cb (GtkWidget *widget,
gpointer user_data)
{
GtkFileChooserDefault *impl = user_data;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeModel *model;
GtkTreePath *path;
GtkTreeIter iter;
GFile *file;
gchar *filename;
- if (impl->priv->operation_mode == OPERATION_MODE_BROWSE)
+ if (priv->operation_mode == OPERATION_MODE_BROWSE)
return FALSE;
- if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
+ if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (priv->browse_files_tree_view),
&x, &y,
keyboard_tip,
&model, &path, &iter))
@@ -3994,7 +1912,7 @@ file_list_query_tooltip_cb (GtkWidget *widget,
filename = g_file_get_path (file);
gtk_tooltip_set_text (tooltip, filename);
- gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
+ gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (priv->browse_files_tree_view),
tooltip,
path);
@@ -4008,87 +1926,94 @@ file_list_query_tooltip_cb (GtkWidget *widget,
static void
set_icon_cell_renderer_fixed_size (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gint xpad, ypad;
- gtk_cell_renderer_get_padding (impl->priv->list_pixbuf_renderer, &xpad, &ypad);
- gtk_cell_renderer_set_fixed_size (impl->priv->list_pixbuf_renderer,
- xpad * 2 + impl->priv->icon_size,
- ypad * 2 + impl->priv->icon_size);
+ gtk_cell_renderer_get_padding (priv->list_pixbuf_renderer, &xpad, &ypad);
+ gtk_cell_renderer_set_fixed_size (priv->list_pixbuf_renderer,
+ xpad * 2 + priv->icon_size,
+ ypad * 2 + priv->icon_size);
}
+
static void
location_entry_create (GtkFileChooserDefault *impl)
{
- if (!impl->priv->location_entry)
- impl->priv->location_entry = _gtk_file_chooser_entry_new (TRUE);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (!priv->location_entry)
+ priv->location_entry = _gtk_file_chooser_entry_new (TRUE);
- _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), impl->priv->local_only);
- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), impl->priv->action);
- gtk_entry_set_width_chars (GTK_ENTRY (impl->priv->location_entry), 45);
- gtk_entry_set_activates_default (GTK_ENTRY (impl->priv->location_entry), TRUE);
+ _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->local_only);
+ _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
+ gtk_entry_set_width_chars (GTK_ENTRY (priv->location_entry), 45);
+ gtk_entry_set_activates_default (GTK_ENTRY (priv->location_entry), TRUE);
}
/* Creates the widgets specific to Save mode */
static void
save_widgets_create (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *vbox;
GtkWidget *widget;
- if (impl->priv->save_widgets != NULL)
+ if (priv->save_widgets != NULL)
return;
location_switch_to_path_bar (impl);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
- impl->priv->save_widgets_table = gtk_grid_new ();
- gtk_box_pack_start (GTK_BOX (vbox), impl->priv->save_widgets_table, FALSE, FALSE, 0);
- gtk_widget_show (impl->priv->save_widgets_table);
- gtk_grid_set_row_spacing (GTK_GRID (impl->priv->save_widgets_table), 12);
- gtk_grid_set_column_spacing (GTK_GRID (impl->priv->save_widgets_table), 12);
+ priv->save_widgets_table = gtk_grid_new ();
+ gtk_box_pack_start (GTK_BOX (vbox), priv->save_widgets_table, FALSE, FALSE, 0);
+ gtk_widget_show (priv->save_widgets_table);
+ gtk_grid_set_row_spacing (GTK_GRID (priv->save_widgets_table), 12);
+ gtk_grid_set_column_spacing (GTK_GRID (priv->save_widgets_table), 12);
/* Label */
widget = gtk_label_new_with_mnemonic (_("_Name:"));
gtk_widget_set_halign (widget, GTK_ALIGN_START);
gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
- gtk_grid_attach (GTK_GRID (impl->priv->save_widgets_table), widget, 0, 0, 1, 1);
+ gtk_grid_attach (GTK_GRID (priv->save_widgets_table), widget, 0, 0, 1, 1);
gtk_widget_show (widget);
/* Location entry */
location_entry_create (impl);
- gtk_widget_set_hexpand (impl->priv->location_entry, TRUE);
- gtk_grid_attach (GTK_GRID (impl->priv->save_widgets_table), impl->priv->location_entry, 1, 0, 1, 1);
- gtk_widget_show (impl->priv->location_entry);
- gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->priv->location_entry);
+ gtk_widget_set_hexpand (priv->location_entry, TRUE);
+ gtk_grid_attach (GTK_GRID (priv->save_widgets_table), priv->location_entry, 1, 0, 1, 1);
+ gtk_widget_show (priv->location_entry);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (widget), priv->location_entry);
/* Folder combo */
- impl->priv->save_folder_label = gtk_label_new (NULL);
- gtk_widget_set_halign (impl->priv->save_folder_label, GTK_ALIGN_START);
- gtk_widget_set_valign (impl->priv->save_folder_label, GTK_ALIGN_CENTER);
- gtk_grid_attach (GTK_GRID (impl->priv->save_widgets_table), impl->priv->save_folder_label, 0, 1, 1, 1);
- gtk_widget_show (impl->priv->save_folder_label);
+ priv->save_folder_label = gtk_label_new (NULL);
+ gtk_widget_set_halign (priv->save_folder_label, GTK_ALIGN_START);
+ gtk_widget_set_valign (priv->save_folder_label, GTK_ALIGN_CENTER);
+ gtk_grid_attach (GTK_GRID (priv->save_widgets_table), priv->save_folder_label, 0, 1, 1, 1);
+ gtk_widget_show (priv->save_folder_label);
- impl->priv->save_widgets = vbox;
- gtk_box_pack_start (GTK_BOX (impl), impl->priv->save_widgets, FALSE, FALSE, 0);
- gtk_box_reorder_child (GTK_BOX (impl), impl->priv->save_widgets, 0);
- gtk_widget_show (impl->priv->save_widgets);
+ priv->save_widgets = vbox;
+ gtk_box_pack_start (GTK_BOX (impl), priv->save_widgets, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (impl), priv->save_widgets, 0);
+ gtk_widget_show (priv->save_widgets);
}
/* Destroys the widgets specific to Save mode */
static void
save_widgets_destroy (GtkFileChooserDefault *impl)
{
- if (impl->priv->save_widgets == NULL)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->save_widgets == NULL)
return;
- gtk_widget_destroy (impl->priv->save_widgets);
- impl->priv->save_widgets = NULL;
- impl->priv->save_widgets_table = NULL;
- impl->priv->location_entry = NULL;
- impl->priv->save_folder_label = NULL;
+ gtk_widget_destroy (priv->save_widgets);
+ priv->save_widgets = NULL;
+ priv->save_widgets_table = NULL;
+ priv->location_entry = NULL;
+ priv->save_folder_label = NULL;
}
/* Turns on the path bar widget. Can be called even if we are already in that
@@ -4097,13 +2022,15 @@ save_widgets_destroy (GtkFileChooserDefault *impl)
static void
location_switch_to_path_bar (GtkFileChooserDefault *impl)
{
- if (impl->priv->location_entry)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->location_entry)
{
- gtk_widget_destroy (impl->priv->location_entry);
- impl->priv->location_entry = NULL;
+ gtk_widget_destroy (priv->location_entry);
+ priv->location_entry = NULL;
}
- gtk_widget_hide (impl->priv->location_entry_box);
+ gtk_widget_hide (priv->location_entry_box);
}
/* Turns on the location entry. Can be called even if we are already in that
@@ -4112,35 +2039,37 @@ location_switch_to_path_bar (GtkFileChooserDefault *impl)
static void
location_switch_to_filename_entry (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
/* when in search or recent files mode, we are not showing the
* location_entry_box container, so there's no point in switching
* to it.
*/
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH ||
- impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH ||
+ priv->operation_mode == OPERATION_MODE_RECENT)
return;
/* Box */
- gtk_widget_show (impl->priv->location_entry_box);
+ gtk_widget_show (priv->location_entry_box);
/* Entry */
- if (!impl->priv->location_entry)
+ if (!priv->location_entry)
{
location_entry_create (impl);
- gtk_box_pack_start (GTK_BOX (impl->priv->location_entry_box), impl->priv->location_entry, TRUE, TRUE, 0);
- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->priv->location_label), impl->priv->location_entry);
+ gtk_box_pack_start (GTK_BOX (priv->location_entry_box), priv->location_entry, TRUE, TRUE, 0);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->location_label), priv->location_entry);
}
/* Configure the entry */
- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), impl->priv->current_folder);
+ _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->current_folder);
/* Done */
- gtk_widget_show (impl->priv->location_entry);
- gtk_widget_grab_focus (impl->priv->location_entry);
+ gtk_widget_show (priv->location_entry);
+ gtk_widget_grab_focus (priv->location_entry);
}
/* Sets a new location mode. set_buttons determines whether the toggle button
@@ -4151,8 +2080,10 @@ location_mode_set (GtkFileChooserDefault *impl,
LocationMode new_mode,
gboolean set_button)
{
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
GtkWindow *toplevel;
GtkWidget *current_focus;
@@ -4173,14 +2104,14 @@ location_mode_set (GtkFileChooserDefault *impl,
if (toplevel)
{
current_focus = gtk_window_get_focus (toplevel);
- if (!current_focus || current_focus == impl->priv->location_entry)
+ if (!current_focus || current_focus == priv->location_entry)
switch_to_file_list = TRUE;
}
location_switch_to_path_bar (impl);
if (switch_to_file_list)
- gtk_widget_grab_focus (impl->priv->browse_files_tree_view);
+ gtk_widget_grab_focus (priv->browse_files_tree_view);
break;
@@ -4196,46 +2127,48 @@ location_mode_set (GtkFileChooserDefault *impl,
if (set_button)
{
- g_signal_handlers_block_by_func (impl->priv->location_button,
+ g_signal_handlers_block_by_func (priv->location_button,
G_CALLBACK (location_button_toggled_cb), impl);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->priv->location_button), button_active);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->location_button), button_active);
- g_signal_handlers_unblock_by_func (impl->priv->location_button,
+ g_signal_handlers_unblock_by_func (priv->location_button,
G_CALLBACK (location_button_toggled_cb), impl);
}
}
- impl->priv->location_mode = new_mode;
+ priv->location_mode = new_mode;
}
static void
location_toggle_popup_handler (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
/* when in search or recent files mode, we are not showing the
* location_entry_box container, so there's no point in switching
* to it.
*/
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH ||
- impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH ||
+ priv->operation_mode == OPERATION_MODE_RECENT)
return;
/* If the file entry is not visible, show it.
* If it is visible, turn it off only if it is focused. Otherwise, switch to the entry.
*/
- if (impl->priv->location_mode == LOCATION_MODE_PATH_BAR)
+ if (priv->location_mode == LOCATION_MODE_PATH_BAR)
{
location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY, TRUE);
}
- else if (impl->priv->location_mode == LOCATION_MODE_FILENAME_ENTRY)
+ else if (priv->location_mode == LOCATION_MODE_FILENAME_ENTRY)
{
- if (gtk_widget_has_focus (impl->priv->location_entry))
+ if (gtk_widget_has_focus (priv->location_entry))
{
location_mode_set (impl, LOCATION_MODE_PATH_BAR, TRUE);
}
else
{
- gtk_widget_grab_focus (impl->priv->location_entry);
+ gtk_widget_grab_focus (priv->location_entry);
}
}
}
@@ -4245,6 +2178,7 @@ static void
location_button_toggled_cb (GtkToggleButton *toggle,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gboolean is_active;
LocationMode new_mode;
@@ -4252,12 +2186,12 @@ location_button_toggled_cb (GtkToggleButton *toggle,
if (is_active)
{
- g_assert (impl->priv->location_mode == LOCATION_MODE_PATH_BAR);
+ g_assert (priv->location_mode == LOCATION_MODE_PATH_BAR);
new_mode = LOCATION_MODE_FILENAME_ENTRY;
}
else
{
- g_assert (impl->priv->location_mode == LOCATION_MODE_FILENAME_ENTRY);
+ g_assert (priv->location_mode == LOCATION_MODE_FILENAME_ENTRY);
new_mode = LOCATION_MODE_PATH_BAR;
}
@@ -4277,6 +2211,7 @@ typedef enum {
static void
info_bar_set (GtkFileChooserDefault *impl, PathBarMode mode)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
char *str;
gboolean free_str;
GtkMessageType message_type;
@@ -4306,11 +2241,11 @@ info_bar_set (GtkFileChooserDefault *impl, PathBarMode mode)
return;
}
- gtk_info_bar_set_message_type (GTK_INFO_BAR (impl->priv->browse_select_a_folder_info_bar), message_type);
- gtk_image_set_from_stock (GTK_IMAGE (impl->priv->browse_select_a_folder_icon),
+ gtk_info_bar_set_message_type (GTK_INFO_BAR (priv->browse_select_a_folder_info_bar), message_type);
+ gtk_image_set_from_stock (GTK_IMAGE (priv->browse_select_a_folder_icon),
(message_type == GTK_MESSAGE_WARNING) ? GTK_STOCK_DIALOG_WARNING : GTK_STOCK_DIRECTORY,
GTK_ICON_SIZE_MENU);
- gtk_label_set_markup (GTK_LABEL (impl->priv->browse_select_a_folder_label), str);
+ gtk_label_set_markup (GTK_LABEL (priv->browse_select_a_folder_label), str);
if (free_str)
g_free (str);
@@ -4324,6 +2259,7 @@ info_bar_set (GtkFileChooserDefault *impl, PathBarMode mode)
static void
path_bar_set_mode (GtkFileChooserDefault *impl, PathBarMode mode)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gboolean path_bar_visible = FALSE;
gboolean special_mode_widgets_visible = FALSE;
gboolean info_bar_visible = FALSE;
@@ -4345,20 +2281,20 @@ path_bar_set_mode (GtkFileChooserDefault *impl, PathBarMode mode)
break;
case PATH_BAR_RECENTLY_USED:
- gtk_image_set_from_icon_name (GTK_IMAGE (impl->priv->browse_special_mode_icon), "document-open-recent", GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_icon_name (GTK_IMAGE (priv->browse_special_mode_icon), "document-open-recent", GTK_ICON_SIZE_BUTTON);
tmp = g_strdup_printf ("<b>%s</b>", _("Recently Used"));
- gtk_label_set_markup (GTK_LABEL (impl->priv->browse_special_mode_label), tmp);
+ gtk_label_set_markup (GTK_LABEL (priv->browse_special_mode_label), tmp);
g_free (tmp);
special_mode_widgets_visible = TRUE;
break;
case PATH_BAR_SEARCH:
- gtk_image_set_from_stock (GTK_IMAGE (impl->priv->browse_special_mode_icon), GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_stock (GTK_IMAGE (priv->browse_special_mode_icon), GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
tmp = g_strdup_printf ("<b>%s</b>", _("Search:"));
- gtk_label_set_markup (GTK_LABEL (impl->priv->browse_special_mode_label), tmp);
+ gtk_label_set_markup (GTK_LABEL (priv->browse_special_mode_label), tmp);
g_free (tmp);
special_mode_widgets_visible = TRUE;
@@ -4368,28 +2304,30 @@ path_bar_set_mode (GtkFileChooserDefault *impl, PathBarMode mode)
g_assert_not_reached ();
}
- gtk_widget_set_visible (impl->priv->browse_path_bar, path_bar_visible);
- gtk_widget_set_visible (impl->priv->browse_special_mode_icon, special_mode_widgets_visible);
- gtk_widget_set_visible (impl->priv->browse_special_mode_label, special_mode_widgets_visible);
- gtk_widget_set_visible (impl->priv->browse_select_a_folder_info_bar, info_bar_visible);
+ gtk_widget_set_visible (priv->browse_path_bar, path_bar_visible);
+ gtk_widget_set_visible (priv->browse_special_mode_icon, special_mode_widgets_visible);
+ gtk_widget_set_visible (priv->browse_special_mode_label, special_mode_widgets_visible);
+ gtk_widget_set_visible (priv->browse_select_a_folder_info_bar, info_bar_visible);
if (path_bar_visible)
{
- if (impl->priv->create_folders
- && impl->priv->action != GTK_FILE_CHOOSER_ACTION_OPEN
- && impl->priv->operation_mode != OPERATION_MODE_RECENT)
+ if (priv->create_folders
+ && priv->action != GTK_FILE_CHOOSER_ACTION_OPEN
+ && priv->operation_mode != OPERATION_MODE_RECENT)
create_folder_visible = TRUE;
}
- gtk_widget_set_visible (impl->priv->browse_new_folder_button, create_folder_visible);
+ gtk_widget_set_visible (priv->browse_new_folder_button, create_folder_visible);
}
+
static GObject*
gtk_file_chooser_default_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
GtkFileChooserDefault *impl;
+ GtkFileChooserDefaultPrivate *priv;
GObject *object;
profile_start ("start", NULL);
@@ -4398,9 +2336,9 @@ gtk_file_chooser_default_constructor (GType type,
n_construct_properties,
construct_params);
impl = GTK_FILE_CHOOSER_DEFAULT (object);
+ priv = impl->priv;
-
- g_assert (impl->priv->file_system);
+ g_assert (priv->file_system);
update_appearance (impl);
@@ -4414,6 +2352,8 @@ static void
set_extra_widget (GtkFileChooserDefault *impl,
GtkWidget *extra_widget)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
if (extra_widget)
{
g_object_ref (extra_widget);
@@ -4421,93 +2361,84 @@ set_extra_widget (GtkFileChooserDefault *impl,
gtk_widget_show (extra_widget);
}
- if (impl->priv->extra_widget)
+ if (priv->extra_widget)
{
- gtk_container_remove (GTK_CONTAINER (impl->priv->extra_align), impl->priv->extra_widget);
- g_object_unref (impl->priv->extra_widget);
+ gtk_container_remove (GTK_CONTAINER (priv->extra_align), priv->extra_widget);
+ g_object_unref (priv->extra_widget);
}
- impl->priv->extra_widget = extra_widget;
- if (impl->priv->extra_widget)
+ priv->extra_widget = extra_widget;
+ if (priv->extra_widget)
{
- gtk_container_add (GTK_CONTAINER (impl->priv->extra_align), impl->priv->extra_widget);
- gtk_widget_show (impl->priv->extra_align);
+ gtk_container_add (GTK_CONTAINER (priv->extra_align), priv->extra_widget);
+ gtk_widget_show (priv->extra_align);
}
else
- gtk_widget_hide (impl->priv->extra_align);
+ gtk_widget_hide (priv->extra_align);
+}
+
+static void
+switch_to_home_dir (GtkFileChooserDefault *impl)
+{
+ const gchar *home = g_get_home_dir ();
+ GFile *home_file;
+
+ if (home == NULL)
+ return;
+
+ home_file = g_file_new_for_path (home);
+
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (impl), home_file, NULL); /* NULL-GError */
+
+ g_object_unref (home_file);
}
static void
set_local_only (GtkFileChooserDefault *impl,
gboolean local_only)
{
- if (local_only != impl->priv->local_only)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (local_only != priv->local_only)
{
- impl->priv->local_only = local_only;
+ priv->local_only = local_only;
- if (impl->priv->location_entry)
- _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), local_only);
+ if (priv->location_entry)
+ _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), local_only);
- if (impl->priv->shortcuts_model && impl->priv->file_system)
- {
- shortcuts_add_volumes (impl);
- shortcuts_add_bookmarks (impl);
- }
-
- if (local_only && impl->priv->current_folder &&
- !_gtk_file_has_native_path (impl->priv->current_folder))
+ if (local_only && priv->current_folder &&
+ !_gtk_file_has_native_path (priv->current_folder))
{
/* If we are pointing to a non-local folder, make an effort to change
* back to a local folder, but it's really up to the app to not cause
* such a situation, so we ignore errors.
*/
- const gchar *home = g_get_home_dir ();
- GFile *home_file;
-
- if (home == NULL)
- return;
-
- home_file = g_file_new_for_path (home);
-
- gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (impl), home_file, NULL);
-
- g_object_unref (home_file);
+ switch_to_home_dir (impl);
}
}
}
-static void
-volumes_bookmarks_changed_cb (GtkFileSystem *file_system,
- GtkFileChooserDefault *impl)
-{
- shortcuts_add_volumes (impl);
- shortcuts_add_bookmarks (impl);
-
- bookmarks_check_add_sensitivity (impl);
- bookmarks_check_remove_sensitivity (impl);
- shortcuts_check_popup_sensitivity (impl);
-}
-
/* Sets the file chooser to multiple selection mode */
static void
set_select_multiple (GtkFileChooserDefault *impl,
gboolean select_multiple,
gboolean property_notify)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
GtkSelectionMode mode;
- if (select_multiple == impl->priv->select_multiple)
+ if (select_multiple == priv->select_multiple)
return;
mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_set_mode (selection, mode);
- gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), select_multiple);
+ gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (priv->browse_files_tree_view), select_multiple);
- impl->priv->select_multiple = select_multiple;
+ priv->select_multiple = select_multiple;
g_object_notify (G_OBJECT (impl), "select-multiple");
check_preview_change (impl);
@@ -4516,14 +2447,11 @@ set_select_multiple (GtkFileChooserDefault *impl,
static void
set_file_system_backend (GtkFileChooserDefault *impl)
{
- profile_start ("start for backend", "default");
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- impl->priv->file_system = _gtk_file_system_new ();
+ profile_start ("start for backend", "default");
- g_signal_connect (impl->priv->file_system, "volumes-changed",
- G_CALLBACK (volumes_bookmarks_changed_cb), impl);
- g_signal_connect (impl->priv->file_system, "bookmarks-changed",
- G_CALLBACK (volumes_bookmarks_changed_cb), impl);
+ priv->file_system = _gtk_file_system_new ();
profile_end ("end", NULL);
}
@@ -4531,12 +2459,11 @@ set_file_system_backend (GtkFileChooserDefault *impl)
static void
unset_file_system_backend (GtkFileChooserDefault *impl)
{
- g_signal_handlers_disconnect_by_func (impl->priv->file_system,
- G_CALLBACK (volumes_bookmarks_changed_cb), impl);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- g_object_unref (impl->priv->file_system);
+ g_object_unref (priv->file_system);
- impl->priv->file_system = NULL;
+ priv->file_system = NULL;
}
/* Saves the widgets around the pathbar so they can be reparented later
@@ -4546,13 +2473,14 @@ unset_file_system_backend (GtkFileChooserDefault *impl)
static void
save_path_bar (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *parent;
- g_object_ref (impl->priv->browse_path_bar_hbox);
+ g_object_ref (priv->browse_path_bar_hbox);
- parent = gtk_widget_get_parent (impl->priv->browse_path_bar_hbox);
+ parent = gtk_widget_get_parent (priv->browse_path_bar_hbox);
if (parent)
- gtk_container_remove (GTK_CONTAINER (parent), impl->priv->browse_path_bar_hbox);
+ gtk_container_remove (GTK_CONTAINER (parent), priv->browse_path_bar_hbox);
}
/* Reparents the path bar and the "Create folder" button to the right place:
@@ -4563,61 +2491,65 @@ save_path_bar (GtkFileChooserDefault *impl)
static void
restore_path_bar (GtkFileChooserDefault *impl)
{
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
- gtk_box_pack_start (GTK_BOX (impl->priv->browse_header_box), impl->priv->browse_path_bar_hbox, FALSE, FALSE, 0);
- gtk_box_reorder_child (GTK_BOX (impl->priv->browse_header_box), impl->priv->browse_path_bar_hbox, 0);
+ gtk_box_pack_start (GTK_BOX (priv->browse_header_box), priv->browse_path_bar_hbox, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (priv->browse_header_box), priv->browse_path_bar_hbox, 0);
}
- else if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
- gtk_widget_set_hexpand (impl->priv->browse_path_bar_hbox, TRUE);
- gtk_grid_attach (GTK_GRID (impl->priv->save_widgets_table), impl->priv->browse_path_bar_hbox, 1, 1, 1, 1);
- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->priv->save_folder_label), impl->priv->browse_path_bar);
+ gtk_widget_set_hexpand (priv->browse_path_bar_hbox, TRUE);
+ gtk_grid_attach (GTK_GRID (priv->save_widgets_table), priv->browse_path_bar_hbox, 1, 1, 1, 1);
+ gtk_label_set_mnemonic_widget (GTK_LABEL (priv->save_folder_label), priv->browse_path_bar);
}
else
g_assert_not_reached ();
- g_object_unref (impl->priv->browse_path_bar_hbox);
+ g_object_unref (priv->browse_path_bar_hbox);
}
/* Takes the folder stored in a row in the recent_model, and puts it in the pathbar */
static void
put_recent_folder_in_pathbar (GtkFileChooserDefault *impl, GtkTreeIter *iter)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GFile *file;
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->recent_model), iter,
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->recent_model), iter,
MODEL_COL_FILE, &file,
-1);
- _gtk_path_bar_set_file (GTK_PATH_BAR (impl->priv->browse_path_bar), file, FALSE);
+ _gtk_path_bar_set_file (GTK_PATH_BAR (priv->browse_path_bar), file, FALSE);
g_object_unref (file);
}
/* Sets the pathbar in the appropriate mode according to the current operation mode and action. This is the central function for
- * dealing with the pathbar's widgets; as long as impl->priv->action and impl->priv->operation_mode are set correctly, then calling this
+ * dealing with the pathbar's widgets; as long as impl->action and impl->operation_mode are set correctly, then calling this
* function will update all the pathbar's widgets.
*/
static void
path_bar_update (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
PathBarMode mode;
- switch (impl->priv->operation_mode)
+ switch (priv->operation_mode)
{
case OPERATION_MODE_BROWSE:
mode = PATH_BAR_FOLDER_PATH;
break;
case OPERATION_MODE_RECENT:
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
GtkTreeSelection *selection;
gboolean have_selected;
GtkTreeIter iter;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
/* Save mode means single-selection mode, so the following is valid */
have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
@@ -4650,12 +2582,14 @@ path_bar_update (GtkFileChooserDefault *impl)
static void
operation_mode_discard_search_widgets (GtkFileChooserDefault *impl)
{
- if (impl->priv->search_hbox)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->search_hbox)
{
- gtk_widget_destroy (impl->priv->search_hbox);
+ gtk_widget_destroy (priv->search_hbox);
- impl->priv->search_hbox = NULL;
- impl->priv->search_entry = NULL;
+ priv->search_hbox = NULL;
+ priv->search_entry = NULL;
}
}
@@ -4689,25 +2623,29 @@ operation_mode_stop (GtkFileChooserDefault *impl, OperationMode mode)
static void
operation_mode_set_browse (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
path_bar_update (impl);
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
- gtk_widget_show (impl->priv->location_button);
- location_mode_set (impl, impl->priv->location_mode, TRUE);
+ gtk_widget_show (priv->location_button);
+ location_mode_set (impl, priv->location_mode, TRUE);
- if (impl->priv->location_mode == LOCATION_MODE_FILENAME_ENTRY)
- gtk_widget_show (impl->priv->location_entry_box);
+ if (priv->location_mode == LOCATION_MODE_FILENAME_ENTRY)
+ gtk_widget_show (priv->location_entry_box);
}
}
static void
operation_mode_set_search (GtkFileChooserDefault *impl)
{
- g_assert (impl->priv->search_hbox == NULL);
- g_assert (impl->priv->search_entry == NULL);
- g_assert (impl->priv->search_model == NULL);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_assert (priv->search_hbox == NULL);
+ g_assert (priv->search_entry == NULL);
+ g_assert (priv->search_model == NULL);
search_setup_widgets (impl);
}
@@ -4715,70 +2653,52 @@ operation_mode_set_search (GtkFileChooserDefault *impl)
static void
operation_mode_set_recent (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
path_bar_update (impl);
/* Hide the location widgets temporarily */
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
- gtk_widget_hide (impl->priv->location_button);
- gtk_widget_hide (impl->priv->location_entry_box);
+ gtk_widget_hide (priv->location_button);
+ gtk_widget_hide (priv->location_entry_box);
}
recent_start_loading (impl);
}
-/* Sometimes we need to frob the selection in the shortcuts list manually */
-static void
-shortcuts_select_item_without_activating (GtkFileChooserDefault *impl, int pos)
-{
- GtkTreeSelection *selection;
- GtkTreePath *path;
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view));
-
- g_signal_handlers_block_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
-
- path = gtk_tree_path_new_from_indices (pos, -1);
- gtk_tree_selection_select_path (selection, path);
- gtk_tree_path_free (path);
-
- g_signal_handlers_unblock_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
-}
-
static void
operation_mode_set (GtkFileChooserDefault *impl, OperationMode mode)
{
- ShortcutsIndex shortcut_to_select;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GFile *file;
- operation_mode_stop (impl, impl->priv->operation_mode);
+ operation_mode_stop (impl, priv->operation_mode);
- impl->priv->operation_mode = mode;
+ priv->operation_mode = mode;
- switch (impl->priv->operation_mode)
+ switch (priv->operation_mode)
{
case OPERATION_MODE_BROWSE:
operation_mode_set_browse (impl);
- shortcut_to_select = SHORTCUTS_CURRENT_FOLDER;
break;
case OPERATION_MODE_SEARCH:
operation_mode_set_search (impl);
- shortcut_to_select = SHORTCUTS_SEARCH;
break;
case OPERATION_MODE_RECENT:
operation_mode_set_recent (impl);
- shortcut_to_select = SHORTCUTS_RECENT;
+ file = g_file_new_for_uri ("recent:///");
+ gtk_places_sidebar_set_location (GTK_PLACES_SIDEBAR (priv->places_sidebar), file);
+ g_object_unref (file);
break;
default:
g_assert_not_reached ();
return;
}
-
- if (shortcut_to_select != SHORTCUTS_CURRENT_FOLDER)
- shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, shortcut_to_select));
}
/* This function is basically a do_all function.
@@ -4789,40 +2709,42 @@ operation_mode_set (GtkFileChooserDefault *impl, OperationMode mode)
static void
update_appearance (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
save_path_bar (impl);
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
const char *text;
- gtk_widget_hide (impl->priv->location_button);
+ gtk_widget_hide (priv->location_button);
save_widgets_create (impl);
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
text = _("Save in _folder:");
else
text = _("Create in _folder:");
- gtk_label_set_text_with_mnemonic (GTK_LABEL (impl->priv->save_folder_label), text);
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (priv->save_folder_label), text);
- if (impl->priv->select_multiple)
+ if (priv->select_multiple)
{
g_warning ("Save mode cannot be set in conjunction with multiple selection mode. "
"Re-setting to single selection mode.");
set_select_multiple (impl, FALSE, TRUE);
}
}
- else if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
- gtk_widget_show (impl->priv->location_button);
+ gtk_widget_show (priv->location_button);
save_widgets_destroy (impl);
- location_mode_set (impl, impl->priv->location_mode, TRUE);
+ location_mode_set (impl, priv->location_mode, TRUE);
}
- if (impl->priv->location_entry)
- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), impl->priv->action);
+ if (priv->location_entry)
+ _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
restore_path_bar (impl);
path_bar_update (impl);
@@ -4830,7 +2752,7 @@ update_appearance (GtkFileChooserDefault *impl)
/* This *is* needed; we need to redraw the file list because the "sensitivity"
* of files may change depending whether we are in a file or folder-only mode.
*/
- gtk_widget_queue_draw (impl->priv->browse_files_tree_view);
+ gtk_widget_queue_draw (priv->browse_files_tree_view);
emit_default_size_changed (impl);
}
@@ -4843,6 +2765,7 @@ gtk_file_chooser_default_set_property (GObject *object,
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
switch (prop_id)
{
@@ -4850,20 +2773,20 @@ gtk_file_chooser_default_set_property (GObject *object,
{
GtkFileChooserAction action = g_value_get_enum (value);
- if (action != impl->priv->action)
+ if (action != priv->action)
{
gtk_file_chooser_default_unselect_all (GTK_FILE_CHOOSER (impl));
if ((action == GTK_FILE_CHOOSER_ACTION_SAVE ||
action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- && impl->priv->select_multiple)
+ && priv->select_multiple)
{
g_warning ("Tried to change the file chooser action to SAVE or CREATE_FOLDER, but "
"this is not allowed in multiple selection mode. Resetting the file chooser "
"to single selection mode.");
set_select_multiple (impl, FALSE, TRUE);
}
- impl->priv->action = action;
+ priv->action = action;
update_cell_renderer_attributes (impl);
update_appearance (impl);
settings_load (impl);
@@ -4884,12 +2807,12 @@ gtk_file_chooser_default_set_property (GObject *object,
break;
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
- impl->priv->preview_widget_active = g_value_get_boolean (value);
+ priv->preview_widget_active = g_value_get_boolean (value);
update_preview_widget_visibility (impl);
break;
case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
- impl->priv->use_preview_label = g_value_get_boolean (value);
+ priv->use_preview_label = g_value_get_boolean (value);
update_preview_widget_visibility (impl);
break;
@@ -4900,8 +2823,8 @@ gtk_file_chooser_default_set_property (GObject *object,
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
{
gboolean select_multiple = g_value_get_boolean (value);
- if ((impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if ((priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
&& select_multiple)
{
g_warning ("Tried to set the file chooser to multiple selection mode, but this is "
@@ -4917,12 +2840,12 @@ gtk_file_chooser_default_set_property (GObject *object,
case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
{
gboolean show_hidden = g_value_get_boolean (value);
- if (show_hidden != impl->priv->show_hidden)
+ if (show_hidden != priv->show_hidden)
{
- impl->priv->show_hidden = show_hidden;
+ priv->show_hidden = show_hidden;
- if (impl->priv->browse_files_model)
- _gtk_file_system_model_set_show_hidden (impl->priv->browse_files_model, show_hidden);
+ if (priv->browse_files_model)
+ _gtk_file_system_model_set_show_hidden (priv->browse_files_model, show_hidden);
}
}
break;
@@ -4930,14 +2853,14 @@ gtk_file_chooser_default_set_property (GObject *object,
case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
{
gboolean do_overwrite_confirmation = g_value_get_boolean (value);
- impl->priv->do_overwrite_confirmation = do_overwrite_confirmation;
+ priv->do_overwrite_confirmation = do_overwrite_confirmation;
}
break;
case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS:
{
gboolean create_folders = g_value_get_boolean (value);
- impl->priv->create_folders = create_folders;
+ priv->create_folders = create_folders;
update_appearance (impl);
}
break;
@@ -4955,51 +2878,52 @@ gtk_file_chooser_default_get_property (GObject *object,
GParamSpec *pspec)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
switch (prop_id)
{
case GTK_FILE_CHOOSER_PROP_ACTION:
- g_value_set_enum (value, impl->priv->action);
+ g_value_set_enum (value, priv->action);
break;
case GTK_FILE_CHOOSER_PROP_FILTER:
- g_value_set_object (value, impl->priv->current_filter);
+ g_value_set_object (value, priv->current_filter);
break;
case GTK_FILE_CHOOSER_PROP_LOCAL_ONLY:
- g_value_set_boolean (value, impl->priv->local_only);
+ g_value_set_boolean (value, priv->local_only);
break;
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
- g_value_set_object (value, impl->priv->preview_widget);
+ g_value_set_object (value, priv->preview_widget);
break;
case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
- g_value_set_boolean (value, impl->priv->preview_widget_active);
+ g_value_set_boolean (value, priv->preview_widget_active);
break;
case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
- g_value_set_boolean (value, impl->priv->use_preview_label);
+ g_value_set_boolean (value, priv->use_preview_label);
break;
case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
- g_value_set_object (value, impl->priv->extra_widget);
+ g_value_set_object (value, priv->extra_widget);
break;
case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
- g_value_set_boolean (value, impl->priv->select_multiple);
+ g_value_set_boolean (value, priv->select_multiple);
break;
case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
- g_value_set_boolean (value, impl->priv->show_hidden);
+ g_value_set_boolean (value, priv->show_hidden);
break;
case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
- g_value_set_boolean (value, impl->priv->do_overwrite_confirmation);
+ g_value_set_boolean (value, priv->do_overwrite_confirmation);
break;
case GTK_FILE_CHOOSER_PROP_CREATE_FOLDERS:
- g_value_set_boolean (value, impl->priv->create_folders);
+ g_value_set_boolean (value, priv->create_folders);
break;
default:
@@ -5012,66 +2936,67 @@ gtk_file_chooser_default_get_property (GObject *object,
static void
cancel_all_operations (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GSList *l;
pending_select_files_free (impl);
- if (impl->priv->reload_icon_cancellables)
+ if (priv->reload_icon_cancellables)
{
- for (l = impl->priv->reload_icon_cancellables; l; l = l->next)
+ for (l = priv->reload_icon_cancellables; l; l = l->next)
{
GCancellable *cancellable = G_CANCELLABLE (l->data);
g_cancellable_cancel (cancellable);
}
- g_slist_free (impl->priv->reload_icon_cancellables);
- impl->priv->reload_icon_cancellables = NULL;
+ g_slist_free (priv->reload_icon_cancellables);
+ priv->reload_icon_cancellables = NULL;
}
- if (impl->priv->loading_shortcuts)
+ if (priv->loading_shortcuts)
{
- for (l = impl->priv->loading_shortcuts; l; l = l->next)
+ for (l = priv->loading_shortcuts; l; l = l->next)
{
GCancellable *cancellable = G_CANCELLABLE (l->data);
g_cancellable_cancel (cancellable);
}
- g_slist_free (impl->priv->loading_shortcuts);
- impl->priv->loading_shortcuts = NULL;
+ g_slist_free (priv->loading_shortcuts);
+ priv->loading_shortcuts = NULL;
}
- if (impl->priv->file_list_drag_data_received_cancellable)
+ if (priv->file_list_drag_data_received_cancellable)
{
- g_cancellable_cancel (impl->priv->file_list_drag_data_received_cancellable);
- impl->priv->file_list_drag_data_received_cancellable = NULL;
+ g_cancellable_cancel (priv->file_list_drag_data_received_cancellable);
+ priv->file_list_drag_data_received_cancellable = NULL;
}
- if (impl->priv->update_current_folder_cancellable)
+ if (priv->update_current_folder_cancellable)
{
- g_cancellable_cancel (impl->priv->update_current_folder_cancellable);
- impl->priv->update_current_folder_cancellable = NULL;
+ g_cancellable_cancel (priv->update_current_folder_cancellable);
+ priv->update_current_folder_cancellable = NULL;
}
- if (impl->priv->should_respond_get_info_cancellable)
+ if (priv->should_respond_get_info_cancellable)
{
- g_cancellable_cancel (impl->priv->should_respond_get_info_cancellable);
- impl->priv->should_respond_get_info_cancellable = NULL;
+ g_cancellable_cancel (priv->should_respond_get_info_cancellable);
+ priv->should_respond_get_info_cancellable = NULL;
}
- if (impl->priv->file_exists_get_info_cancellable)
+ if (priv->file_exists_get_info_cancellable)
{
- g_cancellable_cancel (impl->priv->file_exists_get_info_cancellable);
- impl->priv->file_exists_get_info_cancellable = NULL;
+ g_cancellable_cancel (priv->file_exists_get_info_cancellable);
+ priv->file_exists_get_info_cancellable = NULL;
}
- if (impl->priv->update_from_entry_cancellable)
+ if (priv->update_from_entry_cancellable)
{
- g_cancellable_cancel (impl->priv->update_from_entry_cancellable);
- impl->priv->update_from_entry_cancellable = NULL;
+ g_cancellable_cancel (priv->update_from_entry_cancellable);
+ priv->update_from_entry_cancellable = NULL;
}
- if (impl->priv->shortcuts_activate_iter_cancellable)
+ if (priv->shortcuts_activate_iter_cancellable)
{
- g_cancellable_cancel (impl->priv->shortcuts_activate_iter_cancellable);
- impl->priv->shortcuts_activate_iter_cancellable = NULL;
+ g_cancellable_cancel (priv->shortcuts_activate_iter_cancellable);
+ priv->shortcuts_activate_iter_cancellable = NULL;
}
search_stop_searching (impl, TRUE);
@@ -5083,14 +3008,16 @@ static void
remove_settings_signal (GtkFileChooserDefault *impl,
GdkScreen *screen)
{
- if (impl->priv->settings_signal_id)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->settings_signal_id)
{
GtkSettings *settings;
settings = gtk_settings_get_for_screen (screen);
g_signal_handler_disconnect (settings,
- impl->priv->settings_signal_id);
- impl->priv->settings_signal_id = 0;
+ priv->settings_signal_id);
+ priv->settings_signal_id = 0;
}
}
@@ -5098,19 +3025,24 @@ static void
gtk_file_chooser_default_dispose (GObject *object)
{
GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
cancel_all_operations (impl);
- shortcuts_free (impl);
-
- if (impl->priv->extra_widget)
+ if (priv->extra_widget)
{
- g_object_unref (impl->priv->extra_widget);
- impl->priv->extra_widget = NULL;
+ g_object_unref (priv->extra_widget);
+ priv->extra_widget = NULL;
}
remove_settings_signal (impl, gtk_widget_get_screen (GTK_WIDGET (impl)));
+ if (priv->bookmarks_manager)
+ {
+ _gtk_bookmarks_manager_free (priv->bookmarks_manager);
+ priv->bookmarks_manager = NULL;
+ }
+
G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->dispose (object);
}
@@ -5122,11 +3054,12 @@ static void
gtk_file_chooser_default_show_all (GtkWidget *widget)
{
GtkFileChooserDefault *impl = (GtkFileChooserDefault *) widget;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gtk_widget_show (widget);
- if (impl->priv->extra_widget)
- gtk_widget_show_all (impl->priv->extra_widget);
+ if (priv->extra_widget)
+ gtk_widget_show_all (priv->extra_widget);
}
/* Handler for GtkWindow::set-focus; this is where we save the last-focused
@@ -5137,7 +3070,9 @@ toplevel_set_focus_cb (GtkWindow *window,
GtkWidget *focus,
GtkFileChooserDefault *impl)
{
- impl->priv->toplevel_last_focus_widget = gtk_window_get_focus (window);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ priv->toplevel_last_focus_widget = gtk_window_get_focus (window);
}
/* We monitor the focus widget on our toplevel to be able to know which widget
@@ -5147,27 +3082,27 @@ static void
gtk_file_chooser_default_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (widget);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *toplevel;
- impl = GTK_FILE_CHOOSER_DEFAULT (widget);
toplevel = gtk_widget_get_toplevel (widget);
if (previous_toplevel &&
- impl->priv->toplevel_set_focus_id != 0)
+ priv->toplevel_set_focus_id != 0)
{
g_signal_handler_disconnect (previous_toplevel,
- impl->priv->toplevel_set_focus_id);
- impl->priv->toplevel_set_focus_id = 0;
- impl->priv->toplevel_last_focus_widget = NULL;
+ priv->toplevel_set_focus_id);
+ priv->toplevel_set_focus_id = 0;
+ priv->toplevel_last_focus_widget = NULL;
}
if (gtk_widget_is_toplevel (toplevel))
{
- g_assert (impl->priv->toplevel_set_focus_id == 0);
- impl->priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus",
+ g_assert (priv->toplevel_set_focus_id == 0);
+ priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus",
G_CALLBACK (toplevel_set_focus_cb), impl);
- impl->priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
+ priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
}
}
@@ -5175,6 +3110,7 @@ gtk_file_chooser_default_hierarchy_changed (GtkWidget *widget,
static void
change_icon_theme (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkSettings *settings;
gint width, height;
@@ -5183,20 +3119,16 @@ change_icon_theme (GtkFileChooserDefault *impl)
settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, &width, &height))
- impl->priv->icon_size = MAX (width, height);
+ priv->icon_size = MAX (width, height);
else
- impl->priv->icon_size = FALLBACK_ICON_SIZE;
-
- shortcuts_reload_icons (impl);
+ priv->icon_size = FALLBACK_ICON_SIZE;
- /* the first cell in the first column is the icon column,
- * and we have a fixed size there
- */
+ /* the first cell in the first column is the icon column, and we have a fixed size there */
set_icon_cell_renderer_fixed_size (impl);
- if (impl->priv->browse_files_model)
- _gtk_file_system_model_clear_cache (impl->priv->browse_files_model, MODEL_COL_PIXBUF);
- gtk_widget_queue_resize (impl->priv->browse_files_tree_view);
+ if (priv->browse_files_model)
+ _gtk_file_system_model_clear_cache (priv->browse_files_model, MODEL_COL_PIXBUF);
+ gtk_widget_queue_resize (priv->browse_files_tree_view);
profile_end ("end", NULL);
}
@@ -5226,11 +3158,12 @@ settings_notify_cb (GObject *object,
static void
check_icon_theme (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkSettings *settings;
profile_start ("start", NULL);
- if (impl->priv->settings_signal_id)
+ if (priv->settings_signal_id)
{
profile_end ("end", NULL);
return;
@@ -5239,7 +3172,7 @@ check_icon_theme (GtkFileChooserDefault *impl)
if (gtk_widget_has_screen (GTK_WIDGET (impl)))
{
settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
- impl->priv->settings_signal_id = g_signal_connect (settings, "notify",
+ priv->settings_signal_id = g_signal_connect (settings, "notify",
G_CALLBACK (settings_notify_cb), impl);
change_icon_theme (impl);
@@ -5293,27 +3226,30 @@ gtk_file_chooser_default_screen_changed (GtkWidget *widget,
static void
set_sort_column (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSortable *sortable;
- sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view)));
+ sortable = GTK_TREE_SORTABLE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)));
/* can happen when we're still populating the model */
if (sortable == NULL)
return;
gtk_tree_sortable_set_sort_column_id (sortable,
- impl->priv->sort_column,
- impl->priv->sort_order);
+ priv->sort_column,
+ priv->sort_order);
}
static void
settings_load (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
LocationMode location_mode;
gboolean show_hidden;
gboolean show_size_column;
gint sort_column;
GtkSortType sort_order;
+ StartupMode startup_mode;
gint sidebar_width;
GSettings *settings;
@@ -5325,41 +3261,45 @@ settings_load (GtkFileChooserDefault *impl)
sort_column = g_settings_get_enum (settings, SETTINGS_KEY_SORT_COLUMN);
sort_order = g_settings_get_enum (settings, SETTINGS_KEY_SORT_ORDER);
sidebar_width = g_settings_get_int (settings, SETTINGS_KEY_SIDEBAR_WIDTH);
+ startup_mode = g_settings_get_enum (settings, SETTINGS_KEY_STARTUP_MODE);
location_mode_set (impl, location_mode, TRUE);
gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden);
- impl->priv->show_size_column = show_size_column;
- gtk_tree_view_column_set_visible (impl->priv->list_size_column, show_size_column);
+ priv->show_size_column = show_size_column;
+ gtk_tree_view_column_set_visible (priv->list_size_column, show_size_column);
+
+ priv->sort_column = sort_column;
+ priv->sort_order = sort_order;
+ priv->startup_mode = startup_mode;
- impl->priv->sort_column = sort_column;
- impl->priv->sort_order = sort_order;
/* We don't call set_sort_column() here as the models may not have been
* created yet. The individual functions that create and set the models will
* call set_sort_column() themselves.
*/
- gtk_paned_set_position (GTK_PANED (impl->priv->browse_widgets_hpaned), sidebar_width);
+ gtk_paned_set_position (GTK_PANED (priv->browse_widgets_hpaned), sidebar_width);
}
static void
settings_save (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GSettings *settings;
settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
/* All the other state */
- g_settings_set_enum (settings, SETTINGS_KEY_LOCATION_MODE, impl->priv->location_mode);
+ g_settings_set_enum (settings, SETTINGS_KEY_LOCATION_MODE, priv->location_mode);
g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN,
gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
- g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, impl->priv->show_size_column);
- g_settings_set_enum (settings, SETTINGS_KEY_SORT_COLUMN, impl->priv->sort_column);
- g_settings_set_enum (settings, SETTINGS_KEY_SORT_ORDER, impl->priv->sort_order);
+ g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, priv->show_size_column);
+ g_settings_set_enum (settings, SETTINGS_KEY_SORT_COLUMN, priv->sort_column);
+ g_settings_set_enum (settings, SETTINGS_KEY_SORT_ORDER, priv->sort_order);
g_settings_set_int (settings, SETTINGS_KEY_SIDEBAR_WIDTH,
- gtk_paned_get_position (GTK_PANED (impl->priv->browse_widgets_hpaned)));
+ gtk_paned_get_position (GTK_PANED (priv->browse_widgets_hpaned)));
/* Now apply the settings */
g_settings_apply (settings);
@@ -5378,24 +3318,120 @@ gtk_file_chooser_default_realize (GtkWidget *widget)
emit_default_size_changed (impl);
}
+/* Changes the current folder to $CWD */
+static void
+switch_to_cwd (GtkFileChooserDefault *impl)
+{
+ char *current_working_dir;
+
+ current_working_dir = g_get_current_dir ();
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl), current_working_dir);
+ g_free (current_working_dir);
+}
+
+/* Sets the file chooser to showing Recent Files or $CWD, depending on the
+ * user's settings.
+ */
+static void
+set_startup_mode (GtkFileChooserDefault *impl)
+{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ switch (priv->startup_mode)
+ {
+ case STARTUP_MODE_RECENT:
+ operation_mode_set (impl, OPERATION_MODE_RECENT);
+ break;
+
+ case STARTUP_MODE_CWD:
+ switch_to_cwd (impl);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gboolean
+shortcut_exists (GtkFileChooserDefault *impl, GFile *needle)
+{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GSList *haystack;
+ GSList *l;
+ gboolean exists;
+
+ exists = FALSE;
+
+ haystack = gtk_places_sidebar_list_shortcuts (GTK_PLACES_SIDEBAR (priv->places_sidebar));
+ for (l = haystack; l; l = l->next)
+ {
+ GFile *hay;
+
+ hay = G_FILE (l->data);
+ if (g_file_equal (hay, needle))
+ {
+ exists = TRUE;
+ break;
+ }
+ }
+ g_slist_free_full (haystack, g_object_unref);
+
+ return exists;
+}
+
+static void
+add_cwd_to_sidebar_if_needed (GtkFileChooserDefault *impl)
+{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ char *cwd;
+ GFile *cwd_file;
+ GFile *home_file;
+
+ cwd = g_get_current_dir ();
+ cwd_file = g_file_new_for_path (cwd);
+ g_free (cwd);
+
+ if (shortcut_exists (impl, cwd_file))
+ goto out;
+
+ home_file = g_file_new_for_path (g_get_home_dir ());
+
+ /* We only add an item for $CWD if it is different from $HOME. This way,
+ * applications which get launched from a shell in a terminal (by someone who
+ * knows what they are doing) will get an item for $CWD in the places sidebar,
+ * and "normal" applications launched from the desktop shell (whose $CWD is
+ * $HOME) won't get any extra clutter in the sidebar.
+ */
+ if (!g_file_equal (home_file, cwd_file))
+ gtk_places_sidebar_add_shortcut (GTK_PLACES_SIDEBAR (priv->places_sidebar), cwd_file);
+
+ g_object_unref (home_file);
+
+ out:
+ g_object_unref (cwd_file);
+}
+
/* GtkWidget::map method */
static void
gtk_file_chooser_default_map (GtkWidget *widget)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (widget);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
profile_start ("start", NULL);
- impl = GTK_FILE_CHOOSER_DEFAULT (widget);
-
GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->map (widget);
- if (impl->priv->operation_mode == OPERATION_MODE_BROWSE)
+ settings_load (impl);
+
+ add_cwd_to_sidebar_if_needed (impl);
+
+ if (priv->operation_mode == OPERATION_MODE_BROWSE)
{
- switch (impl->priv->reload_state)
+ switch (priv->reload_state)
{
case RELOAD_EMPTY:
- recent_shortcut_handler (impl);
+ set_startup_mode (impl);
break;
case RELOAD_HAS_FOLDER:
@@ -5409,10 +3445,6 @@ gtk_file_chooser_default_map (GtkWidget *widget)
}
}
- volumes_bookmarks_changed_cb (impl->priv->file_system, impl);
-
- settings_load (impl);
-
profile_end ("end", NULL);
}
@@ -5420,20 +3452,20 @@ gtk_file_chooser_default_map (GtkWidget *widget)
static void
gtk_file_chooser_default_unmap (GtkWidget *widget)
{
- GtkFileChooserDefault *impl;
-
- impl = GTK_FILE_CHOOSER_DEFAULT (widget);
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (widget);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
settings_save (impl);
cancel_all_operations (impl);
- impl->priv->reload_state = RELOAD_EMPTY;
+ priv->reload_state = RELOAD_EMPTY;
GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->unmap (widget);
}
#define COMPARE_DIRECTORIES \
GtkFileChooserDefault *impl = user_data; \
+ GtkFileChooserDefaultPrivate *priv = impl->priv; \
GtkFileSystemModel *fs_model = GTK_FILE_SYSTEM_MODEL (model); \
gboolean dir_a, dir_b; \
\
@@ -5441,7 +3473,7 @@ gtk_file_chooser_default_unmap (GtkWidget *widget)
dir_b = g_value_get_boolean (_gtk_file_system_model_get_value (fs_model, b, MODEL_COL_IS_FOLDER)); \
\
if (dir_a != dir_b) \
- return impl->priv->list_sort_ascending ? (dir_a ? -1 : 1) : (dir_a ? 1 : -1) /* Directories *always* go first */
+ return priv->list_sort_ascending ? (dir_a ? -1 : 1) : (dir_a ? 1 : -1) /* Directories *always* go first */
/* Sort callback for the filename column */
static gint
@@ -5517,14 +3549,15 @@ static void
list_sort_column_changed_cb (GtkTreeSortable *sortable,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gint sort_column_id;
GtkSortType sort_type;
if (gtk_tree_sortable_get_sort_column_id (sortable, &sort_column_id, &sort_type))
{
- impl->priv->list_sort_ascending = (sort_type == GTK_SORT_ASCENDING);
- impl->priv->sort_column = sort_column_id;
- impl->priv->sort_order = sort_type;
+ priv->list_sort_ascending = (sort_type == GTK_SORT_ASCENDING);
+ priv->sort_column = sort_column_id;
+ priv->sort_order = sort_type;
}
}
@@ -5560,20 +3593,22 @@ set_busy_cursor (GtkFileChooserDefault *impl,
static void
load_set_model (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
profile_start ("start", NULL);
- g_assert (impl->priv->browse_files_model != NULL);
+ g_assert (priv->browse_files_model != NULL);
profile_msg (" gtk_tree_view_set_model start", NULL);
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
- GTK_TREE_MODEL (impl->priv->browse_files_model));
- gtk_tree_view_columns_autosize (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
- gtk_tree_view_set_search_column (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ GTK_TREE_MODEL (priv->browse_files_model));
+ gtk_tree_view_columns_autosize (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ gtk_tree_view_set_search_column (GTK_TREE_VIEW (priv->browse_files_tree_view),
MODEL_COL_NAME);
file_list_set_sort_column_ids (impl);
set_sort_column (impl);
profile_msg (" gtk_tree_view_set_model end", NULL);
- impl->priv->list_sort_ascending = TRUE;
+ priv->list_sort_ascending = TRUE;
profile_end ("end", NULL);
}
@@ -5582,17 +3617,17 @@ load_set_model (GtkFileChooserDefault *impl)
static gboolean
load_timeout_cb (gpointer data)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
profile_start ("start", NULL);
- impl = GTK_FILE_CHOOSER_DEFAULT (data);
- g_assert (impl->priv->load_state == LOAD_PRELOAD);
- g_assert (impl->priv->load_timeout_id != 0);
- g_assert (impl->priv->browse_files_model != NULL);
+ g_assert (priv->load_state == LOAD_PRELOAD);
+ g_assert (priv->load_timeout_id != 0);
+ g_assert (priv->browse_files_model != NULL);
- impl->priv->load_timeout_id = 0;
- impl->priv->load_state = LOAD_LOADING;
+ priv->load_timeout_id = 0;
+ priv->load_state = LOAD_LOADING;
load_set_model (impl);
@@ -5605,44 +3640,49 @@ load_timeout_cb (gpointer data)
static void
load_setup_timer (GtkFileChooserDefault *impl)
{
- g_assert (impl->priv->load_timeout_id == 0);
- g_assert (impl->priv->load_state != LOAD_PRELOAD);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_assert (priv->load_timeout_id == 0);
+ g_assert (priv->load_state != LOAD_PRELOAD);
- impl->priv->load_timeout_id = gdk_threads_add_timeout (MAX_LOADING_TIME, load_timeout_cb, impl);
- impl->priv->load_state = LOAD_PRELOAD;
+ priv->load_timeout_id = gdk_threads_add_timeout (MAX_LOADING_TIME, load_timeout_cb, impl);
+ priv->load_state = LOAD_PRELOAD;
}
-/* Removes the load timeout; changes the impl->priv->load_state to the specified value. */
+/* Removes the load timeout; changes the impl->load_state to the specified value. */
static void
load_remove_timer (GtkFileChooserDefault *impl, LoadState new_load_state)
{
- if (impl->priv->load_timeout_id != 0)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->load_timeout_id != 0)
{
- g_assert (impl->priv->load_state == LOAD_PRELOAD);
+ g_assert (priv->load_state == LOAD_PRELOAD);
- g_source_remove (impl->priv->load_timeout_id);
- impl->priv->load_timeout_id = 0;
+ g_source_remove (priv->load_timeout_id);
+ priv->load_timeout_id = 0;
}
else
- g_assert (impl->priv->load_state == LOAD_EMPTY ||
- impl->priv->load_state == LOAD_LOADING ||
- impl->priv->load_state == LOAD_FINISHED);
+ g_assert (priv->load_state == LOAD_EMPTY ||
+ priv->load_state == LOAD_LOADING ||
+ priv->load_state == LOAD_FINISHED);
g_assert (new_load_state == LOAD_EMPTY ||
new_load_state == LOAD_LOADING ||
new_load_state == LOAD_FINISHED);
- impl->priv->load_state = new_load_state;
+ priv->load_state = new_load_state;
}
/* Selects the first row in the file list */
static void
browse_files_select_first_row (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreePath *path;
GtkTreeIter dummy_iter;
GtkTreeModel *tree_model;
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view));
if (!tree_model)
return;
@@ -5651,7 +3691,7 @@ browse_files_select_first_row (GtkFileChooserDefault *impl)
/* If the list is empty, do nothing. */
if (gtk_tree_model_get_iter (tree_model, &dummy_iter, path))
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), path, NULL, FALSE);
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view), path, NULL, FALSE);
gtk_tree_path_free (path);
}
@@ -5684,13 +3724,14 @@ center_selected_row_foreach_cb (GtkTreeModel *model,
static void
browse_files_center_selected_row (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
struct center_selected_row_closure closure;
GtkTreeSelection *selection;
closure.impl = impl;
closure.already_centered = FALSE;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_selected_foreach (selection, center_selected_row_foreach_cb, &closure);
}
@@ -5698,22 +3739,23 @@ static gboolean
show_and_select_files (GtkFileChooserDefault *impl,
GSList *files)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
GtkFileSystemModel *fsmodel;
gboolean enabled_hidden, removed_filters;
gboolean selected_a_file;
GSList *walk;
- g_assert (impl->priv->load_state == LOAD_FINISHED);
- g_assert (impl->priv->browse_files_model != NULL);
+ g_assert (priv->load_state == LOAD_FINISHED);
+ g_assert (priv->browse_files_model != NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
- fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view)));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
+ fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view)));
- g_assert (fsmodel == impl->priv->browse_files_model);
+ g_assert (fsmodel == priv->browse_files_model);
- enabled_hidden = impl->priv->show_hidden;
- removed_filters = (impl->priv->current_filter == NULL);
+ enabled_hidden = priv->show_hidden;
+ removed_filters = (priv->current_filter == NULL);
selected_a_file = FALSE;
@@ -5767,7 +3809,7 @@ show_and_select_files (GtkFileChooserDefault *impl,
gtk_tree_selection_select_iter (selection, &iter);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (fsmodel), &iter);
- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view),
path, NULL, FALSE);
gtk_tree_path_free (path);
@@ -5784,12 +3826,14 @@ show_and_select_files (GtkFileChooserDefault *impl,
static void
pending_select_files_process (GtkFileChooserDefault *impl)
{
- g_assert (impl->priv->load_state == LOAD_FINISHED);
- g_assert (impl->priv->browse_files_model != NULL);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_assert (priv->load_state == LOAD_FINISHED);
+ g_assert (priv->browse_files_model != NULL);
- if (impl->priv->pending_select_files)
+ if (priv->pending_select_files)
{
- show_and_select_files (impl, impl->priv->pending_select_files);
+ show_and_select_files (impl, priv->pending_select_files);
pending_select_files_free (impl);
browse_files_center_selected_row (impl);
}
@@ -5802,21 +3846,22 @@ pending_select_files_process (GtkFileChooserDefault *impl)
* that case, the chooser's selection should be what the caller expects,
* as the user can't see that something else got selected. See bug #165264.
*/
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN &&
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN &&
gtk_widget_get_mapped (GTK_WIDGET (impl)))
browse_files_select_first_row (impl);
}
- g_assert (impl->priv->pending_select_files == NULL);
+ g_assert (priv->pending_select_files == NULL);
}
static void
show_error_on_reading_current_folder (GtkFileChooserDefault *impl, GError *error)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GFileInfo *info;
char *msg;
- info = g_file_query_info (impl->priv->current_folder,
+ info = g_file_query_info (priv->current_folder,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
G_FILE_QUERY_INFO_NONE,
NULL,
@@ -5839,17 +3884,19 @@ browse_files_model_finished_loading_cb (GtkFileSystemModel *model,
GError *error,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
profile_start ("start", NULL);
if (error)
show_error_on_reading_current_folder (impl, error);
- if (impl->priv->load_state == LOAD_PRELOAD)
+ if (priv->load_state == LOAD_PRELOAD)
{
load_remove_timer (impl, LOAD_FINISHED);
load_set_model (impl);
}
- else if (impl->priv->load_state == LOAD_LOADING)
+ else if (priv->load_state == LOAD_LOADING)
{
/* Nothing */
}
@@ -5862,9 +3909,9 @@ browse_files_model_finished_loading_cb (GtkFileSystemModel *model,
return;
}
- g_assert (impl->priv->load_timeout_id == 0);
+ g_assert (priv->load_timeout_id == 0);
- impl->priv->load_state = LOAD_FINISHED;
+ priv->load_state = LOAD_FINISHED;
pending_select_files_process (impl);
set_busy_cursor (impl, FALSE);
@@ -5879,16 +3926,18 @@ static void
stop_loading_and_clear_list_model (GtkFileChooserDefault *impl,
gboolean remove_from_treeview)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
load_remove_timer (impl, LOAD_EMPTY);
- if (impl->priv->browse_files_model)
+ if (priv->browse_files_model)
{
- g_object_unref (impl->priv->browse_files_model);
- impl->priv->browse_files_model = NULL;
+ g_object_unref (priv->browse_files_model);
+ priv->browse_files_model = NULL;
}
if (remove_from_treeview)
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
}
static char *
@@ -6049,6 +4098,7 @@ file_system_model_set (GtkFileSystemModel *model,
gpointer data)
{
GtkFileChooserDefault *impl = data;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
switch (column)
{
@@ -6075,8 +4125,8 @@ file_system_model_set (GtkFileSystemModel *model,
{
gboolean sensitive = TRUE;
- if (!(impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
+ if (!(priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
{
sensitive = TRUE; /* for file modes... */
}
@@ -6103,7 +4153,7 @@ file_system_model_set (GtkFileSystemModel *model,
{
if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ICON))
{
- g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), impl->priv->icon_size));
+ g_value_take_object (value, _gtk_file_info_render_icon (info, GTK_WIDGET (impl), priv->icon_size));
}
else
{
@@ -6111,11 +4161,11 @@ file_system_model_set (GtkFileSystemModel *model,
GtkTreePath *path, *start, *end;
GtkTreeIter iter;
- if (impl->priv->browse_files_tree_view == NULL ||
+ if (priv->browse_files_tree_view == NULL ||
g_file_info_has_attribute (info, "filechooser::queried"))
return FALSE;
- tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ tree_model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view));
if (tree_model != GTK_TREE_MODEL (model))
return FALSE;
@@ -6123,7 +4173,7 @@ file_system_model_set (GtkFileSystemModel *model,
&iter,
file))
g_assert_not_reached ();
- if (!gtk_tree_view_get_visible_range (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), &start, &end))
+ if (!gtk_tree_view_get_visible_range (GTK_TREE_VIEW (priv->browse_files_tree_view), &start, &end))
return FALSE;
path = gtk_tree_model_get_path (tree_model, &iter);
if (gtk_tree_path_compare (start, path) != 1 &&
@@ -6189,7 +4239,9 @@ static gboolean
set_list_model (GtkFileChooserDefault *impl,
GError **error)
{
- g_assert (impl->priv->current_folder != NULL);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_assert (priv->current_folder != NULL);
profile_start ("start", NULL);
@@ -6197,31 +4249,31 @@ set_list_model (GtkFileChooserDefault *impl,
set_busy_cursor (impl, TRUE);
- impl->priv->browse_files_model =
- _gtk_file_system_model_new_for_directory (impl->priv->current_folder,
+ priv->browse_files_model =
+ _gtk_file_system_model_new_for_directory (priv->current_folder,
MODEL_ATTRIBUTES,
file_system_model_set,
impl,
MODEL_COLUMN_TYPES);
- _gtk_file_system_model_set_show_hidden (impl->priv->browse_files_model, impl->priv->show_hidden);
+ _gtk_file_system_model_set_show_hidden (priv->browse_files_model, priv->show_hidden);
profile_msg (" set sort function", NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->browse_files_model), MODEL_COL_NAME, name_sort_func, impl, NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->browse_files_model), MODEL_COL_SIZE, size_sort_func, impl, NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->browse_files_model), MODEL_COL_MTIME, mtime_sort_func, impl, NULL);
- gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (impl->priv->browse_files_model), NULL, NULL, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->browse_files_model), MODEL_COL_NAME, name_sort_func, impl, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->browse_files_model), MODEL_COL_SIZE, size_sort_func, impl, NULL);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->browse_files_model), MODEL_COL_MTIME, mtime_sort_func, impl, NULL);
+ gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (priv->browse_files_model), NULL, NULL, NULL);
set_sort_column (impl);
- impl->priv->list_sort_ascending = TRUE;
- g_signal_connect (impl->priv->browse_files_model, "sort-column-changed",
+ priv->list_sort_ascending = TRUE;
+ g_signal_connect (priv->browse_files_model, "sort-column-changed",
G_CALLBACK (list_sort_column_changed_cb), impl);
load_setup_timer (impl); /* This changes the state to LOAD_PRELOAD */
- g_signal_connect (impl->priv->browse_files_model, "finished-loading",
+ g_signal_connect (priv->browse_files_model, "finished-loading",
G_CALLBACK (browse_files_model_finished_loading_cb), impl);
- _gtk_file_system_model_set_filter (impl->priv->browse_files_model, impl->priv->current_filter);
+ _gtk_file_system_model_set_filter (priv->browse_files_model, priv->current_filter);
profile_end ("end", NULL);
@@ -6269,42 +4321,43 @@ update_chooser_entry_selected_foreach (GtkTreeModel *model,
static void
update_chooser_entry (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
struct update_chooser_entry_selected_foreach_closure closure;
/* no need to update the file chooser's entry if there's no entry */
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH ||
- !impl->priv->location_entry)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH ||
+ !priv->location_entry)
return;
- if (!(impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
- || ((impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
- && impl->priv->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
+ if (!(priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+ || ((priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ && priv->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
return;
- g_assert (impl->priv->location_entry != NULL);
+ g_assert (priv->location_entry != NULL);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
closure.num_selected = 0;
gtk_tree_selection_selected_foreach (selection, update_chooser_entry_selected_foreach, &closure);
if (closure.num_selected == 0)
{
- if (impl->priv->operation_mode == OPERATION_MODE_RECENT)
- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), NULL);
+ if (priv->operation_mode == OPERATION_MODE_RECENT)
+ _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), NULL);
else
goto maybe_clear_entry;
}
else if (closure.num_selected == 1)
{
- if (impl->priv->operation_mode == OPERATION_MODE_BROWSE)
+ if (priv->operation_mode == OPERATION_MODE_BROWSE)
{
GFileInfo *info;
gboolean change_entry;
- info = _gtk_file_system_model_get_info (impl->priv->browse_files_model, &closure.first_selected_iter);
+ info = _gtk_file_system_model_get_info (priv->browse_files_model, &closure.first_selected_iter);
/* If the cursor moved to the row of the newly created folder,
* retrieving info will return NULL.
@@ -6312,13 +4365,13 @@ update_chooser_entry (GtkFileChooserDefault *impl)
if (!info)
return;
- g_free (impl->priv->browse_files_last_selected_name);
- impl->priv->browse_files_last_selected_name =
+ g_free (priv->browse_files_last_selected_name);
+ priv->browse_files_last_selected_name =
g_strdup (g_file_info_get_display_name (info));
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
/* Don't change the name when clicking on a folder... */
change_entry = (! _gtk_file_info_consider_as_directory (info));
@@ -6328,52 +4381,52 @@ update_chooser_entry (GtkFileChooserDefault *impl)
if (change_entry)
{
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), impl->priv->browse_files_last_selected_name);
+ gtk_entry_set_text (GTK_ENTRY (priv->location_entry), priv->browse_files_last_selected_name);
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
- _gtk_file_chooser_entry_select_filename (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry));
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ _gtk_file_chooser_entry_select_filename (GTK_FILE_CHOOSER_ENTRY (priv->location_entry));
}
return;
}
- else if (impl->priv->operation_mode == OPERATION_MODE_RECENT
- && impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ else if (priv->operation_mode == OPERATION_MODE_RECENT
+ && priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
GFile *folder;
/* Set the base folder on the name entry, so it will do completion relative to the correct recent-folder */
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->recent_model), &closure.first_selected_iter,
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->recent_model), &closure.first_selected_iter,
MODEL_COL_FILE, &folder,
-1);
- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry), folder);
+ _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), folder);
g_object_unref (folder);
return;
}
}
else
{
- g_assert (!(impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
+ g_assert (!(priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
/* Multiple selection, so just clear the entry. */
- g_free (impl->priv->browse_files_last_selected_name);
- impl->priv->browse_files_last_selected_name = NULL;
+ g_free (priv->browse_files_last_selected_name);
+ priv->browse_files_last_selected_name = NULL;
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (priv->location_entry), "");
return;
}
maybe_clear_entry:
- if ((impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN || impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
- && impl->priv->browse_files_last_selected_name)
+ if ((priv->action == GTK_FILE_CHOOSER_ACTION_OPEN || priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ && priv->browse_files_last_selected_name)
{
const char *entry_text;
int len;
gboolean clear_entry;
- entry_text = gtk_entry_get_text (GTK_ENTRY (impl->priv->location_entry));
+ entry_text = gtk_entry_get_text (GTK_ENTRY (priv->location_entry));
len = strlen (entry_text);
if (len != 0)
{
@@ -6385,17 +4438,17 @@ update_chooser_entry (GtkFileChooserDefault *impl)
gchar *tmp;
tmp = g_strndup (entry_text, len - 1);
- clear_entry = (compare_utf8_filenames (impl->priv->browse_files_last_selected_name, tmp) == 0);
+ clear_entry = (compare_utf8_filenames (priv->browse_files_last_selected_name, tmp) == 0);
g_free (tmp);
}
else
- clear_entry = (compare_utf8_filenames (impl->priv->browse_files_last_selected_name, entry_text) == 0);
+ clear_entry = (compare_utf8_filenames (priv->browse_files_last_selected_name, entry_text) == 0);
}
else
clear_entry = FALSE;
if (clear_entry)
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (priv->location_entry), "");
}
}
@@ -6424,14 +4477,15 @@ update_current_folder_mount_enclosing_volume_cb (GCancellable *cancellabl
const GError *error,
gpointer user_data)
{
- gboolean cancelled = g_cancellable_is_cancelled (cancellable);
struct UpdateCurrentFolderData *data = user_data;
GtkFileChooserDefault *impl = data->impl;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ gboolean cancelled = g_cancellable_is_cancelled (cancellable);
- if (cancellable != impl->priv->update_current_folder_cancellable)
+ if (cancellable != priv->update_current_folder_cancellable)
goto out;
- impl->priv->update_current_folder_cancellable = NULL;
+ priv->update_current_folder_cancellable = NULL;
set_busy_cursor (impl, FALSE);
if (cancelled)
@@ -6440,7 +4494,7 @@ update_current_folder_mount_enclosing_volume_cb (GCancellable *cancellabl
if (error)
{
error_changing_folder_dialog (data->impl, data->file, g_error_copy (error));
- impl->priv->reload_state = RELOAD_EMPTY;
+ priv->reload_state = RELOAD_EMPTY;
goto out;
}
@@ -6462,12 +4516,13 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
struct UpdateCurrentFolderData *data = user_data;
GtkFileChooserDefault *impl = data->impl;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (cancellable != impl->priv->update_current_folder_cancellable)
+ if (cancellable != priv->update_current_folder_cancellable)
goto out;
- impl->priv->update_current_folder_cancellable = NULL;
- impl->priv->reload_state = RELOAD_EMPTY;
+ priv->update_current_folder_cancellable = NULL;
+ priv->reload_state = RELOAD_EMPTY;
set_busy_cursor (impl, FALSE);
@@ -6490,8 +4545,8 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
set_busy_cursor (impl, TRUE);
- impl->priv->update_current_folder_cancellable =
- _gtk_file_system_mount_enclosing_volume (impl->priv->file_system, data->file,
+ priv->update_current_folder_cancellable =
+ _gtk_file_system_mount_enclosing_volume (priv->file_system, data->file,
mount_operation,
update_current_folder_mount_enclosing_volume_cb,
data);
@@ -6516,10 +4571,10 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
g_object_unref (cancellable);
/* restart the update current folder operation */
- impl->priv->reload_state = RELOAD_HAS_FOLDER;
+ priv->reload_state = RELOAD_HAS_FOLDER;
- impl->priv->update_current_folder_cancellable =
- _gtk_file_system_get_info (impl->priv->file_system, data->file,
+ priv->update_current_folder_cancellable =
+ _gtk_file_system_get_info (priv->file_system, data->file,
"standard::type",
update_current_folder_get_info_cb,
data);
@@ -6560,38 +4615,27 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
if (! _gtk_file_info_consider_as_directory (info))
goto out;
- _gtk_path_bar_set_file (GTK_PATH_BAR (impl->priv->browse_path_bar), data->file, data->keep_trail);
+ _gtk_path_bar_set_file (GTK_PATH_BAR (priv->browse_path_bar), data->file, data->keep_trail);
- if (impl->priv->current_folder != data->file)
+ if (priv->current_folder != data->file)
{
- if (impl->priv->current_folder)
- g_object_unref (impl->priv->current_folder);
+ if (priv->current_folder)
+ g_object_unref (priv->current_folder);
- impl->priv->current_folder = g_object_ref (data->file);
+ priv->current_folder = g_object_ref (data->file);
}
- impl->priv->reload_state = RELOAD_HAS_FOLDER;
-
- /* Update the widgets that may trigger a folder change themselves. */
-
- if (!impl->priv->changing_folder)
- {
- impl->priv->changing_folder = TRUE;
-
- shortcuts_update_current_folder (impl);
-
- impl->priv->changing_folder = FALSE;
- }
+ priv->reload_state = RELOAD_HAS_FOLDER;
/* Set the folder on the save entry */
- if (impl->priv->location_entry)
+ if (priv->location_entry)
{
- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry),
- impl->priv->current_folder);
+ _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (priv->location_entry),
+ priv->current_folder);
if (data->clear_entry)
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), "");
+ gtk_entry_set_text (GTK_ENTRY (priv->location_entry), "");
}
/* Create a new list model. This is slightly evil; we store the result value
@@ -6602,12 +4646,11 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
/* Refresh controls */
- shortcuts_find_current_folder (impl);
+ gtk_places_sidebar_set_location (GTK_PLACES_SIDEBAR (priv->places_sidebar), priv->current_folder);
g_signal_emit_by_name (impl, "current-folder-changed", 0);
check_preview_change (impl);
- bookmarks_check_add_sensitivity (impl);
g_signal_emit_by_name (impl, "selection-changed", 0);
@@ -6626,6 +4669,7 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser,
GError **error)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
struct UpdateCurrentFolderData *data;
profile_start ("start", NULL);
@@ -6634,7 +4678,7 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser,
operation_mode_set (impl, OPERATION_MODE_BROWSE);
- if (impl->priv->local_only && !_gtk_file_has_native_path (file))
+ if (priv->local_only && !_gtk_file_has_native_path (file))
{
g_set_error_literal (error,
GTK_FILE_CHOOSER_ERROR,
@@ -6646,8 +4690,8 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser,
return FALSE;
}
- if (impl->priv->update_current_folder_cancellable)
- g_cancellable_cancel (impl->priv->update_current_folder_cancellable);
+ if (priv->update_current_folder_cancellable)
+ g_cancellable_cancel (priv->update_current_folder_cancellable);
/* Test validity of path here. */
data = g_new0 (struct UpdateCurrentFolderData, 1);
@@ -6656,10 +4700,10 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser *chooser,
data->keep_trail = keep_trail;
data->clear_entry = clear_entry;
- impl->priv->reload_state = RELOAD_HAS_FOLDER;
+ priv->reload_state = RELOAD_HAS_FOLDER;
- impl->priv->update_current_folder_cancellable =
- _gtk_file_system_get_info (impl->priv->file_system, file,
+ priv->update_current_folder_cancellable =
+ _gtk_file_system_get_info (priv->file_system, file,
"standard::type",
update_current_folder_get_info_cb,
data);
@@ -6675,13 +4719,14 @@ static GFile *
gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH ||
- impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH ||
+ priv->operation_mode == OPERATION_MODE_RECENT)
return NULL;
- if (impl->priv->current_folder)
- return g_object_ref (impl->priv->current_folder);
+ if (priv->current_folder)
+ return g_object_ref (priv->current_folder);
return NULL;
}
@@ -6691,12 +4736,13 @@ gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser,
const gchar *name)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- g_return_if_fail (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
+ g_return_if_fail (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
pending_select_files_free (impl);
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), name);
+ gtk_entry_set_text (GTK_ENTRY (priv->location_entry), name);
}
static gboolean
@@ -6705,6 +4751,7 @@ gtk_file_chooser_default_select_file (GtkFileChooser *chooser,
GError **error)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GFile *parent_file;
gboolean same_path;
@@ -6713,20 +4760,20 @@ gtk_file_chooser_default_select_file (GtkFileChooser *chooser,
if (!parent_file)
return gtk_file_chooser_set_current_folder_file (chooser, file, error);
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH ||
- impl->priv->operation_mode == OPERATION_MODE_RECENT ||
- impl->priv->load_state == LOAD_EMPTY)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH ||
+ priv->operation_mode == OPERATION_MODE_RECENT ||
+ priv->load_state == LOAD_EMPTY)
{
same_path = FALSE;
}
else
{
- g_assert (impl->priv->current_folder != NULL);
+ g_assert (priv->current_folder != NULL);
- same_path = g_file_equal (parent_file, impl->priv->current_folder);
+ same_path = g_file_equal (parent_file, priv->current_folder);
}
- if (same_path && impl->priv->load_state == LOAD_FINISHED)
+ if (same_path && priv->load_state == LOAD_FINISHED)
{
gboolean result;
GSList files;
@@ -6759,13 +4806,14 @@ gtk_file_chooser_default_unselect_file (GtkFileChooser *chooser,
GFile *file)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- GtkTreeView *tree_view = GTK_TREE_VIEW (impl->priv->browse_files_tree_view);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GtkTreeView *tree_view = GTK_TREE_VIEW (priv->browse_files_tree_view);
GtkTreeIter iter;
- if (!impl->priv->browse_files_model)
+ if (!priv->browse_files_model)
return;
- if (!_gtk_file_system_model_get_iter_for_file (impl->priv->browse_files_model,
+ if (!_gtk_file_system_model_get_iter_for_file (priv->browse_files_model,
&iter,
file))
return;
@@ -6781,11 +4829,12 @@ maybe_select (GtkTreeModel *model,
gpointer data)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
gboolean is_sensitive;
gboolean is_folder;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_model_get (model, iter,
MODEL_COL_IS_FOLDER, &is_folder,
@@ -6793,8 +4842,8 @@ maybe_select (GtkTreeModel *model,
-1);
if (is_sensitive &&
- ((is_folder && impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
- (!is_folder && impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)))
+ ((is_folder && priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
+ (!is_folder && priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)))
gtk_tree_selection_select_iter (selection, iter);
else
gtk_tree_selection_unselect_iter (selection, iter);
@@ -6806,19 +4855,20 @@ static void
gtk_file_chooser_default_select_all (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH ||
- impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH ||
+ priv->operation_mode == OPERATION_MODE_RECENT)
{
GtkTreeSelection *selection;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_select_all (selection);
return;
}
- if (impl->priv->select_multiple)
- gtk_tree_model_foreach (GTK_TREE_MODEL (impl->priv->browse_files_model),
+ if (priv->select_multiple)
+ gtk_tree_model_foreach (GTK_TREE_MODEL (priv->browse_files_model),
maybe_select, impl);
}
@@ -6826,7 +4876,8 @@ static void
gtk_file_chooser_default_unselect_all (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_unselect_all (selection);
pending_select_files_free (impl);
@@ -6849,19 +4900,20 @@ check_save_entry (GtkFileChooserDefault *impl,
gboolean *is_file_part_empty_ret,
gboolean *is_folder)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkFileChooserEntry *chooser_entry;
GFile *current_folder;
const char *file_part;
GFile *file;
GError *error;
- g_assert (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
- || ((impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
- && impl->priv->location_mode == LOCATION_MODE_FILENAME_ENTRY));
+ g_assert (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+ || ((priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ && priv->location_mode == LOCATION_MODE_FILENAME_ENTRY));
- chooser_entry = GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry);
+ chooser_entry = GTK_FILE_CHOOSER_ENTRY (priv->location_entry);
if (strlen (gtk_entry_get_text (GTK_ENTRY (chooser_entry))) == 0)
{
@@ -6951,6 +5003,7 @@ static GSList *
gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
struct get_files_closure info;
GtkWindow *toplevel;
GtkWidget *current_focus;
@@ -6960,12 +5013,12 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
info.result = NULL;
info.file_from_entry = NULL;
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH)
return search_get_selected_files (impl);
- if (impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ if (priv->operation_mode == OPERATION_MODE_RECENT)
{
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
file_list_seen = TRUE;
goto file_entry;
@@ -6981,14 +5034,14 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
current_focus = NULL;
file_list_seen = FALSE;
- if (current_focus == impl->priv->browse_files_tree_view)
+ if (current_focus == priv->browse_files_tree_view)
{
GtkTreeSelection *selection;
file_list:
file_list_seen = TRUE;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_selected_foreach (selection, get_files_foreach, &info);
/* If there is no selection in the file list, we probably have this situation:
@@ -6999,10 +5052,10 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
* So we want the selection to be "bar/foo.txt". Jump to the case for the
* filename entry to see if that is the case.
*/
- if (info.result == NULL && impl->priv->location_entry)
+ if (info.result == NULL && priv->location_entry)
goto file_entry;
}
- else if (impl->priv->location_entry && current_focus == impl->priv->location_entry)
+ else if (priv->location_entry && current_focus == priv->location_entry)
{
gboolean is_well_formed, is_empty, is_file_part_empty, is_folder;
@@ -7016,7 +5069,7 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
if (!is_well_formed)
return NULL;
- if (is_file_part_empty && impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (is_file_part_empty && priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
g_object_unref (info.file_from_entry);
return NULL;
@@ -7029,15 +5082,15 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
else
return NULL;
}
- else if (impl->priv->toplevel_last_focus_widget == impl->priv->browse_files_tree_view)
+ else if (priv->toplevel_last_focus_widget == priv->browse_files_tree_view)
goto file_list;
- else if (impl->priv->location_entry && impl->priv->toplevel_last_focus_widget == impl->priv->location_entry)
+ else if (priv->location_entry && priv->toplevel_last_focus_widget == priv->location_entry)
goto file_entry;
else
{
/* The focus is on a dialog's action area button or something else */
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
goto file_entry;
else
goto file_list;
@@ -7047,7 +5100,7 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
/* If there's no folder selected, and we're in SELECT_FOLDER mode, then we
* fall back to the current directory */
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
info.result == NULL)
{
GFile *current_folder;
@@ -7065,9 +5118,10 @@ GFile *
gtk_file_chooser_default_get_preview_file (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (impl->priv->preview_file)
- return g_object_ref (impl->priv->preview_file);
+ if (priv->preview_file)
+ return g_object_ref (priv->preview_file);
else
return NULL;
}
@@ -7076,8 +5130,9 @@ static GtkFileSystem *
gtk_file_chooser_default_get_file_system (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- return impl->priv->file_system;
+ return priv->file_system;
}
/* Shows or hides the filter widgets */
@@ -7085,10 +5140,12 @@ static void
show_filters (GtkFileChooserDefault *impl,
gboolean show)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
if (show)
- gtk_widget_show (impl->priv->filter_combo_hbox);
+ gtk_widget_show (priv->filter_combo_hbox);
else
- gtk_widget_hide (impl->priv->filter_combo_hbox);
+ gtk_widget_hide (priv->filter_combo_hbox);
}
static void
@@ -7096,24 +5153,25 @@ gtk_file_chooser_default_add_filter (GtkFileChooser *chooser,
GtkFileFilter *filter)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
const gchar *name;
- if (g_slist_find (impl->priv->filters, filter))
+ if (g_slist_find (priv->filters, filter))
{
g_warning ("gtk_file_chooser_add_filter() called on filter already in list\n");
return;
}
g_object_ref_sink (filter);
- impl->priv->filters = g_slist_append (impl->priv->filters, filter);
+ priv->filters = g_slist_append (priv->filters, filter);
name = gtk_file_filter_get_name (filter);
if (!name)
name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
- gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (impl->priv->filter_combo), name);
+ gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (priv->filter_combo), name);
- if (!g_slist_find (impl->priv->filters, impl->priv->current_filter))
+ if (!g_slist_find (priv->filters, priv->current_filter))
set_current_filter (impl, filter);
show_filters (impl, TRUE);
@@ -7124,11 +5182,12 @@ gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
GtkFileFilter *filter)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeModel *model;
GtkTreeIter iter;
gint filter_index;
- filter_index = g_slist_index (impl->priv->filters, filter);
+ filter_index = g_slist_index (priv->filters, filter);
if (filter_index < 0)
{
@@ -7136,18 +5195,18 @@ gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
return;
}
- impl->priv->filters = g_slist_remove (impl->priv->filters, filter);
+ priv->filters = g_slist_remove (priv->filters, filter);
- if (filter == impl->priv->current_filter)
+ if (filter == priv->current_filter)
{
- if (impl->priv->filters)
- set_current_filter (impl, impl->priv->filters->data);
+ if (priv->filters)
+ set_current_filter (impl, priv->filters->data);
else
set_current_filter (impl, NULL);
}
/* Remove row from the combo box */
- model = gtk_combo_box_get_model (GTK_COMBO_BOX (impl->priv->filter_combo));
+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->filter_combo));
if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, filter_index))
g_assert_not_reached ();
@@ -7155,7 +5214,7 @@ gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
g_object_unref (filter);
- if (!impl->priv->filters)
+ if (!priv->filters)
show_filters (impl, FALSE);
}
@@ -7163,55 +5222,9 @@ static GSList *
gtk_file_chooser_default_list_filters (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- return g_slist_copy (impl->priv->filters);
-}
-
-/* Returns the position in the shortcuts tree where the nth specified shortcut would appear */
-static int
-shortcuts_get_pos_for_shortcut_folder (GtkFileChooserDefault *impl,
- int pos)
-{
- return pos + shortcuts_get_index (impl, SHORTCUTS_SHORTCUTS);
-}
-
-struct AddShortcutData
-{
- GtkFileChooserDefault *impl;
- GFile *file;
-};
-
-static void
-add_shortcut_get_info_cb (GCancellable *cancellable,
- GFileInfo *info,
- const GError *error,
- gpointer user_data)
-{
- int pos;
- gboolean cancelled = g_cancellable_is_cancelled (cancellable);
- struct AddShortcutData *data = user_data;
-
- if (!g_slist_find (data->impl->priv->loading_shortcuts, cancellable))
- goto out;
-
- data->impl->priv->loading_shortcuts = g_slist_remove (data->impl->priv->loading_shortcuts, cancellable);
-
- if (cancelled || error || (! _gtk_file_info_consider_as_directory (info)))
- goto out;
-
- pos = shortcuts_get_pos_for_shortcut_folder (data->impl, data->impl->priv->num_shortcuts);
-
- shortcuts_insert_file (data->impl, pos, SHORTCUT_TYPE_FILE, NULL, data->file, NULL, FALSE, SHORTCUTS_SHORTCUTS);
-
- /* need to call shortcuts_add_bookmarks to flush out any duplicates bug #577806 */
- shortcuts_add_bookmarks (data->impl);
-
-out:
- g_object_unref (data->impl);
- g_object_unref (data->file);
- g_free (data);
-
- g_object_unref (cancellable);
+ return g_slist_copy (priv->filters);
}
static gboolean
@@ -7219,66 +5232,10 @@ gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
GFile *file,
GError **error)
{
- GCancellable *cancellable;
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- struct AddShortcutData *data;
- GSList *l;
- int pos;
-
- /* Avoid adding duplicates */
- pos = shortcut_find_position (impl, file);
- if (pos >= 0 && pos < shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR))
- {
- gchar *uri;
-
- uri = g_file_get_uri (file);
- /* translators, "Shortcut" means "Bookmark" here */
- g_set_error (error,
- GTK_FILE_CHOOSER_ERROR,
- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
- _("Shortcut %s already exists"),
- uri);
- g_free (uri);
-
- return FALSE;
- }
-
- for (l = impl->priv->loading_shortcuts; l; l = l->next)
- {
- GCancellable *c = l->data;
- GFile *f;
-
- f = g_object_get_data (G_OBJECT (c), "add-shortcut-path-key");
- if (f && g_file_equal (file, f))
- {
- gchar *uri;
-
- uri = g_file_get_uri (file);
- g_set_error (error,
- GTK_FILE_CHOOSER_ERROR,
- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
- _("Shortcut %s already exists"),
- uri);
- g_free (uri);
-
- return FALSE;
- }
- }
-
- data = g_new0 (struct AddShortcutData, 1);
- data->impl = g_object_ref (impl);
- data->file = g_object_ref (file);
-
- cancellable = _gtk_file_system_get_info (impl->priv->file_system, file,
- "standard::type",
- add_shortcut_get_info_cb, data);
-
- if (!cancellable)
- return FALSE;
-
- impl->priv->loading_shortcuts = g_slist_append (impl->priv->loading_shortcuts, cancellable);
- g_object_set_data (G_OBJECT (cancellable), "add-shortcut-path-key", data->file);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ gtk_places_sidebar_add_shortcut (GTK_PLACES_SIDEBAR (priv->places_sidebar), file);
return TRUE;
}
@@ -7288,114 +5245,19 @@ gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
GError **error)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- int pos;
- GtkTreeIter iter;
- GSList *l;
- char *uri;
- int i;
-
- for (l = impl->priv->loading_shortcuts; l; l = l->next)
- {
- GCancellable *c = l->data;
- GFile *f;
-
- f = g_object_get_data (G_OBJECT (c), "add-shortcut-path-key");
- if (f && g_file_equal (file, f))
- {
- impl->priv->loading_shortcuts = g_slist_remove (impl->priv->loading_shortcuts, c);
- g_cancellable_cancel (c);
- return TRUE;
- }
- }
-
- if (impl->priv->num_shortcuts == 0)
- goto out;
-
- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter, NULL, pos))
- g_assert_not_reached ();
-
- for (i = 0; i < impl->priv->num_shortcuts; i++)
- {
- gpointer col_data;
- ShortcutType shortcut_type;
- GFile *shortcut;
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
- g_assert (col_data != NULL);
- g_assert (shortcut_type == SHORTCUT_TYPE_FILE);
-
- shortcut = col_data;
- if (g_file_equal (shortcut, file))
- {
- shortcuts_remove_rows (impl, pos + i, 1);
- impl->priv->num_shortcuts--;
- return TRUE;
- }
-
- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter))
- g_assert_not_reached ();
- }
-
- out:
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- uri = g_file_get_uri (file);
- /* translators, "Shortcut" means "Bookmark" here */
- g_set_error (error,
- GTK_FILE_CHOOSER_ERROR,
- GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
- _("Shortcut %s does not exist"),
- uri);
- g_free (uri);
-
- return FALSE;
+ gtk_places_sidebar_remove_shortcut (GTK_PLACES_SIDEBAR (priv->places_sidebar), file);
+ return TRUE;
}
static GSList *
gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
{
GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
- int pos;
- GtkTreeIter iter;
- int i;
- GSList *list;
-
- if (impl->priv->num_shortcuts == 0)
- return NULL;
-
- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter, NULL, pos))
- g_assert_not_reached ();
-
- list = NULL;
-
- for (i = 0; i < impl->priv->num_shortcuts; i++)
- {
- gpointer col_data;
- ShortcutType shortcut_type;
- GFile *shortcut;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
- g_assert (col_data != NULL);
- g_assert (shortcut_type == SHORTCUT_TYPE_FILE);
-
- shortcut = col_data;
- list = g_slist_prepend (list, g_object_ref (shortcut));
-
- if (i != impl->priv->num_shortcuts - 1)
- {
- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter))
- g_assert_not_reached ();
- }
- }
-
- return g_slist_reverse (list);
+ return gtk_places_sidebar_list_shortcuts (GTK_PLACES_SIDEBAR (priv->places_sidebar));
}
/* Guesses a size based upon font sizes */
@@ -7435,13 +5297,12 @@ gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
gint *default_width,
gint *default_height)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkRequisition req;
int x, y, width, height;
GSettings *settings;
- impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
-
settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
g_settings_get (settings, SETTINGS_KEY_WINDOW_POSITION, "(ii)", &x, &y);
@@ -7456,19 +5317,19 @@ gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height);
- if (impl->priv->preview_widget_active &&
- impl->priv->preview_widget &&
- gtk_widget_get_visible (impl->priv->preview_widget))
+ if (priv->preview_widget_active &&
+ priv->preview_widget &&
+ gtk_widget_get_visible (priv->preview_widget))
{
- gtk_widget_get_preferred_size (impl->priv->preview_box,
+ gtk_widget_get_preferred_size (priv->preview_box,
&req, NULL);
*default_width += PREVIEW_HBOX_SPACING + req.width;
}
- if (impl->priv->extra_widget &&
- gtk_widget_get_visible (impl->priv->extra_widget))
+ if (priv->extra_widget &&
+ gtk_widget_get_visible (priv->extra_widget))
{
- gtk_widget_get_preferred_size (impl->priv->extra_align,
+ gtk_widget_get_preferred_size (priv->extra_align,
&req, NULL);
*default_height += gtk_box_get_spacing (GTK_BOX (chooser_embed)) + req.height;
}
@@ -7499,6 +5360,7 @@ switch_folder_foreach_cb (GtkTreeModel *model,
static void
switch_to_selected_folder (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
struct switch_folder_closure closure;
@@ -7510,7 +5372,7 @@ switch_to_selected_folder (GtkFileChooserDefault *impl)
closure.file = NULL;
closure.num_selected = 0;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_selected_foreach (selection, switch_folder_foreach_cb, &closure);
g_assert (closure.file && closure.num_selected == 1);
@@ -7525,12 +5387,13 @@ static GFileInfo *
get_selected_file_info_from_file_list (GtkFileChooserDefault *impl,
gboolean *had_selection)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
GtkTreeIter iter;
GFileInfo *info;
- g_assert (!impl->priv->select_multiple);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ g_assert (!priv->select_multiple);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
{
*had_selection = FALSE;
@@ -7539,7 +5402,7 @@ get_selected_file_info_from_file_list (GtkFileChooserDefault *impl,
*had_selection = TRUE;
- info = _gtk_file_system_model_get_info (impl->priv->browse_files_model, &iter);
+ info = _gtk_file_system_model_get_info (priv->browse_files_model, &iter);
return info;
}
@@ -7646,11 +5509,12 @@ confirmation_confirm_get_info_cb (GCancellable *cancellable,
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
gboolean should_respond = FALSE;
struct GetDisplayNameData *data = user_data;
+ GtkFileChooserDefaultPrivate *priv = data->impl->priv;
- if (cancellable != data->impl->priv->should_respond_get_info_cancellable)
+ if (cancellable != priv->should_respond_get_info_cancellable)
goto out;
- data->impl->priv->should_respond_get_info_cancellable = NULL;
+ priv->should_respond_get_info_cancellable = NULL;
if (cancelled)
goto out;
@@ -7681,9 +5545,10 @@ should_respond_after_confirm_overwrite (GtkFileChooserDefault *impl,
const gchar *file_part,
GFile *parent_file)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkFileChooserConfirmation conf;
- if (!impl->priv->do_overwrite_confirmation)
+ if (!priv->do_overwrite_confirmation)
return TRUE;
conf = GTK_FILE_CHOOSER_CONFIRMATION_CONFIRM;
@@ -7702,11 +5567,11 @@ should_respond_after_confirm_overwrite (GtkFileChooserDefault *impl,
data->impl = g_object_ref (impl);
data->file_part = g_strdup (file_part);
- if (impl->priv->should_respond_get_info_cancellable)
- g_cancellable_cancel (impl->priv->should_respond_get_info_cancellable);
+ if (priv->should_respond_get_info_cancellable)
+ g_cancellable_cancel (priv->should_respond_get_info_cancellable);
- impl->priv->should_respond_get_info_cancellable =
- _gtk_file_system_get_info (impl->priv->file_system, parent_file,
+ priv->should_respond_get_info_cancellable =
+ _gtk_file_system_get_info (priv->file_system, parent_file,
"standard::display-name",
confirmation_confirm_get_info_cb,
data);
@@ -7743,13 +5608,15 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
gboolean parent_is_folder;
gboolean cancelled = g_cancellable_is_cancelled (cancellable);
struct FileExistsData *data = user_data;
+ GtkFileChooserDefault *impl = data->impl;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (cancellable != data->impl->priv->should_respond_get_info_cancellable)
+ if (cancellable != priv->should_respond_get_info_cancellable)
goto out;
- data->impl->priv->should_respond_get_info_cancellable = NULL;
+ priv->should_respond_get_info_cancellable = NULL;
- set_busy_cursor (data->impl, FALSE);
+ set_busy_cursor (impl, FALSE);
if (cancelled)
goto out;
@@ -7761,11 +5628,11 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
if (parent_is_folder)
{
- if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)
{
- request_response_and_add_to_recent_list (data->impl); /* even if the file doesn't exist, apps can make good use of that (e.g. Emacs) */
+ request_response_and_add_to_recent_list (impl); /* even if the file doesn't exist, apps can make good use of that (e.g. Emacs) */
}
- else if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
if (data->file_exists_and_is_not_folder)
{
@@ -7776,18 +5643,18 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
* depending on what clients do in the confirm-overwrite
* signal and this corrupts the pointer
*/
- file_part = g_strdup (_gtk_file_chooser_entry_get_file_part (GTK_FILE_CHOOSER_ENTRY (data->impl->priv->location_entry)));
- retval = should_respond_after_confirm_overwrite (data->impl, file_part, data->parent_file);
+ file_part = g_strdup (_gtk_file_chooser_entry_get_file_part (GTK_FILE_CHOOSER_ENTRY (priv->location_entry)));
+ retval = should_respond_after_confirm_overwrite (impl, file_part, data->parent_file);
g_free (file_part);
if (retval)
- request_response_and_add_to_recent_list (data->impl);
+ request_response_and_add_to_recent_list (impl);
}
else
- request_response_and_add_to_recent_list (data->impl);
+ request_response_and_add_to_recent_list (impl);
}
- else if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
- || data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
GError *mkdir_error = NULL;
@@ -7795,14 +5662,14 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
* "/blah/nonexistent" you *will* want a folder created.
*/
- set_busy_cursor (data->impl, TRUE);
+ set_busy_cursor (impl, TRUE);
g_file_make_directory (data->file, NULL, &mkdir_error);
- set_busy_cursor (data->impl, FALSE);
+ set_busy_cursor (impl, FALSE);
if (!mkdir_error)
- request_response_and_add_to_recent_list (data->impl);
+ request_response_and_add_to_recent_list (impl);
else
- error_creating_folder_dialog (data->impl, data->file, mkdir_error);
+ error_creating_folder_dialog (impl, data->file, mkdir_error);
}
else
g_assert_not_reached ();
@@ -7812,7 +5679,7 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
if (info)
{
/* The parent exists, but it's not a folder! Someone probably typed existing_file.txt/subfile.txt */
- error_with_file_under_nonfolder (data->impl, data->parent_file);
+ error_with_file_under_nonfolder (impl, data->parent_file);
}
else
{
@@ -7821,7 +5688,7 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
/* The parent folder is not readable for some reason */
error_copy = g_error_copy (error);
- error_changing_folder_dialog (data->impl, data->parent_file, error_copy);
+ error_changing_folder_dialog (impl, data->parent_file, error_copy);
}
}
@@ -7846,13 +5713,15 @@ file_exists_get_info_cb (GCancellable *cancellable,
gboolean is_folder;
gboolean needs_parent_check = FALSE;
struct FileExistsData *data = user_data;
+ GtkFileChooserDefault *impl = data->impl;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (cancellable != data->impl->priv->file_exists_get_info_cancellable)
+ if (cancellable != priv->file_exists_get_info_cancellable)
goto out;
- data->impl->priv->file_exists_get_info_cancellable = NULL;
+ priv->file_exists_get_info_cancellable = NULL;
- set_busy_cursor (data->impl, FALSE);
+ set_busy_cursor (impl, FALSE);
if (cancelled)
goto out;
@@ -7860,26 +5729,26 @@ file_exists_get_info_cb (GCancellable *cancellable,
file_exists = (info != NULL);
is_folder = (file_exists && _gtk_file_info_consider_as_directory (info));
- if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)
{
if (is_folder)
- change_folder_and_display_error (data->impl, data->file, TRUE);
+ change_folder_and_display_error (impl, data->file, TRUE);
else
{
if (file_exists)
- request_response_and_add_to_recent_list (data->impl); /* user typed an existing filename; we are done */
+ request_response_and_add_to_recent_list (impl); /* user typed an existing filename; we are done */
else
needs_parent_check = TRUE; /* file doesn't exist; see if its parent exists */
}
}
- else if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
if (file_exists && !is_folder)
{
/* Oops, the user typed the name of an existing path which is not
* a folder
*/
- error_creating_folder_over_existing_file_dialog (data->impl, data->file,
+ error_creating_folder_over_existing_file_dialog (impl, data->file,
g_error_copy (error));
}
else
@@ -7887,7 +5756,7 @@ file_exists_get_info_cb (GCancellable *cancellable,
needs_parent_check = TRUE;
}
}
- else if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
if (!file_exists)
{
@@ -7898,16 +5767,16 @@ file_exists_get_info_cb (GCancellable *cancellable,
if (is_folder)
{
/* User typed a folder; we are done */
- request_response_and_add_to_recent_list (data->impl);
+ request_response_and_add_to_recent_list (impl);
}
else
- error_selecting_folder_over_existing_file_dialog (data->impl, data->file);
+ error_selecting_folder_over_existing_file_dialog (impl, data->file);
}
}
- else if (data->impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
if (is_folder)
- change_folder_and_display_error (data->impl, data->file, TRUE);
+ change_folder_and_display_error (impl, data->file, TRUE);
else
needs_parent_check = TRUE;
}
@@ -7922,22 +5791,22 @@ file_exists_get_info_cb (GCancellable *cancellable,
data->file_exists_and_is_not_folder = file_exists && !is_folder;
data_ownership_taken = TRUE;
- if (data->impl->priv->should_respond_get_info_cancellable)
- g_cancellable_cancel (data->impl->priv->should_respond_get_info_cancellable);
+ if (priv->should_respond_get_info_cancellable)
+ g_cancellable_cancel (priv->should_respond_get_info_cancellable);
- data->impl->priv->should_respond_get_info_cancellable =
- _gtk_file_system_get_info (data->impl->priv->file_system,
+ priv->should_respond_get_info_cancellable =
+ _gtk_file_system_get_info (priv->file_system,
data->parent_file,
"standard::type",
name_entry_get_parent_info_cb,
data);
- set_busy_cursor (data->impl, TRUE);
+ set_busy_cursor (impl, TRUE);
}
out:
if (!data_ownership_taken)
{
- g_object_unref (data->impl);
+ g_object_unref (impl);
g_object_unref (data->file);
g_object_unref (data->parent_file);
g_free (data);
@@ -7979,6 +5848,7 @@ location_popup_on_paste_handler (GtkFileChooserDefault *impl)
static void
add_selection_to_recent_list (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GSList *files;
GSList *l;
@@ -7992,7 +5862,7 @@ add_selection_to_recent_list (GtkFileChooserDefault *impl)
uri = g_file_get_uri (file);
if (uri)
{
- gtk_recent_manager_add_item (impl->priv->recent_manager, uri);
+ gtk_recent_manager_add_item (priv->recent_manager, uri);
g_free (uri);
}
}
@@ -8004,13 +5874,12 @@ add_selection_to_recent_list (GtkFileChooserDefault *impl)
static gboolean
gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *toplevel;
GtkWidget *current_focus;
gboolean retval;
- impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
-
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (impl));
g_assert (GTK_IS_WINDOW (toplevel));
@@ -8018,9 +5887,9 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
- if (current_focus == impl->priv->browse_files_tree_view)
+ if (current_focus == priv->browse_files_tree_view)
{
- /* The following array encodes what we do based on the impl->priv->action and the
+ /* The following array encodes what we do based on the priv->action and the
* number of files selected.
*/
typedef enum {
@@ -8047,17 +5916,17 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
file_list:
- g_assert (impl->priv->action >= GTK_FILE_CHOOSER_ACTION_OPEN && impl->priv->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
+ g_assert (priv->action >= GTK_FILE_CHOOSER_ACTION_OPEN && priv->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
- if (impl->priv->operation_mode == OPERATION_MODE_SEARCH)
+ if (priv->operation_mode == OPERATION_MODE_SEARCH)
{
retval = search_should_respond (impl);
goto out;
}
- if (impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ if (priv->operation_mode == OPERATION_MODE_RECENT)
{
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
goto save_entry;
else
{
@@ -8073,7 +5942,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
else
k = num_selected;
- action = what_to_do [impl->priv->action] [k];
+ action = what_to_do [priv->action] [k];
switch (action)
{
@@ -8092,11 +5961,11 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
switch_to_selected_folder (impl);
return FALSE;
}
- else if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
retval = should_respond_after_confirm_overwrite (impl,
get_display_name_from_file_list (impl),
- impl->priv->current_folder);
+ priv->current_folder);
goto out;
}
else
@@ -8120,7 +5989,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
g_assert_not_reached ();
}
}
- else if ((impl->priv->location_entry != NULL) && (current_focus == impl->priv->location_entry))
+ else if ((priv->location_entry != NULL) && (current_focus == priv->location_entry))
{
GFile *file;
gboolean is_well_formed, is_empty, is_file_part_empty;
@@ -8130,20 +5999,20 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
save_entry:
- g_assert (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
- || ((impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
- && impl->priv->location_mode == LOCATION_MODE_FILENAME_ENTRY));
+ g_assert (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+ || ((priv->action == GTK_FILE_CHOOSER_ACTION_OPEN
+ || priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ && priv->location_mode == LOCATION_MODE_FILENAME_ENTRY));
- entry = GTK_FILE_CHOOSER_ENTRY (impl->priv->location_entry);
+ entry = GTK_FILE_CHOOSER_ENTRY (priv->location_entry);
check_save_entry (impl, &file, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
if (!is_well_formed)
{
if (!is_empty
- && impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- && impl->priv->operation_mode == OPERATION_MODE_RECENT)
+ && priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ && priv->operation_mode == OPERATION_MODE_RECENT)
{
path_bar_set_mode (impl, PATH_BAR_ERROR_NO_FOLDER);
#if 0
@@ -8152,7 +6021,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
* a selection causes the error message from path_bar_set_mode() to go away,
* but we want the user to see that message!
*/
- gtk_widget_grab_focus (impl->priv->browse_files_tree_view);
+ gtk_widget_grab_focus (priv->browse_files_tree_view);
#endif
}
/* FIXME: else show an "invalid filename" error as the pathbar mode? */
@@ -8162,11 +6031,11 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
if (is_empty)
{
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
path_bar_set_mode (impl, PATH_BAR_ERROR_NO_FILENAME);
- gtk_widget_grab_focus (impl->priv->location_entry);
+ gtk_widget_grab_focus (priv->location_entry);
return FALSE;
}
@@ -8178,13 +6047,13 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
error = NULL;
if (is_folder)
{
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
change_folder_and_display_error (impl, file, TRUE);
}
- else if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
/* The folder already exists, so we do not need to create it.
* Just respond to terminate the dialog.
@@ -8211,11 +6080,11 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
data->file = g_object_ref (file);
data->parent_file = _gtk_file_chooser_entry_get_current_folder (entry);
- if (impl->priv->file_exists_get_info_cancellable)
- g_cancellable_cancel (impl->priv->file_exists_get_info_cancellable);
+ if (priv->file_exists_get_info_cancellable)
+ g_cancellable_cancel (priv->file_exists_get_info_cancellable);
- impl->priv->file_exists_get_info_cancellable =
- _gtk_file_system_get_info (impl->priv->file_system, file,
+ priv->file_exists_get_info_cancellable =
+ _gtk_file_system_get_info (priv->file_system, file,
"standard::type",
file_exists_get_info_cb,
data);
@@ -8228,19 +6097,19 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
g_object_unref (file);
}
- else if (impl->priv->toplevel_last_focus_widget == impl->priv->browse_files_tree_view)
+ else if (priv->toplevel_last_focus_widget == priv->browse_files_tree_view)
{
/* The focus is on a dialog's action area button, *and* the widget that
* was focused immediately before it is the file list.
*/
goto file_list;
}
- else if (impl->priv->operation_mode == OPERATION_MODE_SEARCH && impl->priv->toplevel_last_focus_widget == impl->priv->search_entry)
+ else if (priv->operation_mode == OPERATION_MODE_SEARCH && priv->toplevel_last_focus_widget == priv->search_entry)
{
- search_entry_activate_cb (GTK_ENTRY (impl->priv->search_entry), impl);
+ search_entry_activate_cb (GTK_ENTRY (priv->search_entry), impl);
return FALSE;
}
- else if (impl->priv->location_entry && impl->priv->toplevel_last_focus_widget == impl->priv->location_entry)
+ else if (priv->location_entry && priv->toplevel_last_focus_widget == priv->location_entry)
{
/* The focus is on a dialog's action area button, *and* the widget that
* was focused immediately before it is the location entry.
@@ -8249,8 +6118,8 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
}
else
/* The focus is on a dialog's action area button or something else */
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
goto save_entry;
else
goto file_list;
@@ -8267,23 +6136,22 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
static void
gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkWidget *widget;
- impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
-
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
- if (impl->priv->location_mode == LOCATION_MODE_PATH_BAR
- || impl->priv->operation_mode == OPERATION_MODE_RECENT)
- widget = impl->priv->browse_files_tree_view;
+ if (priv->location_mode == LOCATION_MODE_PATH_BAR
+ || priv->operation_mode == OPERATION_MODE_RECENT)
+ widget = priv->browse_files_tree_view;
else
- widget = impl->priv->location_entry;
+ widget = priv->location_entry;
}
- else if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- widget = impl->priv->location_entry;
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ widget = priv->location_entry;
else
{
g_assert_not_reached ();
@@ -8314,12 +6182,13 @@ search_selected_foreach_get_file_cb (GtkTreeModel *model,
static GSList *
search_get_selected_files (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GSList *result;
GtkTreeSelection *selection;
result = NULL;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_file_cb, &result);
result = g_slist_reverse (result);
@@ -8332,11 +6201,12 @@ search_get_selected_files (GtkFileChooserDefault *impl)
static gboolean
search_should_respond (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
- g_assert (impl->priv->operation_mode == OPERATION_MODE_SEARCH);
+ g_assert (priv->operation_mode == OPERATION_MODE_SEARCH);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
return (gtk_tree_selection_count_selected_rows (selection) != 0);
}
@@ -8345,6 +6215,7 @@ static void
search_add_hit (GtkFileChooserDefault *impl,
gchar *uri)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GFile *file;
file = g_file_new_for_uri (uri);
@@ -8357,7 +6228,7 @@ search_add_hit (GtkFileChooserDefault *impl,
return;
}
- _gtk_file_system_model_add_and_query_file (impl->priv->search_model,
+ _gtk_file_system_model_add_and_query_file (priv->search_model,
file,
MODEL_ATTRIBUTES);
@@ -8392,8 +6263,8 @@ search_engine_finished_cb (GtkSearchEngine *engine,
/* EB: setting the model here will avoid loads of row events,
* but it'll make the search look like blocked.
*/
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
- GTK_TREE_MODEL (impl->priv->search_model));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
+ GTK_TREE_MODEL (impl->search_model));
file_list_set_sort_column_ids (impl);
#endif
@@ -8434,14 +6305,16 @@ static void
search_clear_model (GtkFileChooserDefault *impl,
gboolean remove_from_treeview)
{
- if (!impl->priv->search_model)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (!priv->search_model)
return;
- g_object_unref (impl->priv->search_model);
- impl->priv->search_model = NULL;
+ g_object_unref (priv->search_model);
+ priv->search_model = NULL;
if (remove_from_treeview)
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
}
/* Stops any ongoing searches; does not touch the search_model */
@@ -8449,18 +6322,20 @@ static void
search_stop_searching (GtkFileChooserDefault *impl,
gboolean remove_query)
{
- if (remove_query && impl->priv->search_query)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (remove_query && priv->search_query)
{
- g_object_unref (impl->priv->search_query);
- impl->priv->search_query = NULL;
+ g_object_unref (priv->search_query);
+ priv->search_query = NULL;
}
- if (impl->priv->search_engine)
+ if (priv->search_engine)
{
- _gtk_search_engine_stop (impl->priv->search_engine);
+ _gtk_search_engine_stop (priv->search_engine);
- g_object_unref (impl->priv->search_engine);
- impl->priv->search_engine = NULL;
+ g_object_unref (priv->search_engine);
+ priv->search_engine = NULL;
}
}
@@ -8468,21 +6343,23 @@ search_stop_searching (GtkFileChooserDefault *impl,
static void
search_setup_model (GtkFileChooserDefault *impl)
{
- g_assert (impl->priv->search_model == NULL);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_assert (priv->search_model == NULL);
- impl->priv->search_model = _gtk_file_system_model_new (file_system_model_set,
+ priv->search_model = _gtk_file_system_model_new (file_system_model_set,
impl,
MODEL_COLUMN_TYPES);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->search_model),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->search_model),
MODEL_COL_NAME,
name_sort_func,
impl, NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->search_model),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->search_model),
MODEL_COL_MTIME,
mtime_sort_func,
impl, NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->search_model),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->search_model),
MODEL_COL_SIZE,
size_sort_func,
impl, NULL);
@@ -8492,8 +6369,8 @@ search_setup_model (GtkFileChooserDefault *impl)
* more "alive" than setting the model at the end of the search
* run
*/
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
- GTK_TREE_MODEL (impl->priv->search_model));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ GTK_TREE_MODEL (priv->search_model));
file_list_set_sort_column_ids (impl);
}
@@ -8502,37 +6379,39 @@ static void
search_start_query (GtkFileChooserDefault *impl,
const gchar *query_text)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
search_stop_searching (impl, FALSE);
search_clear_model (impl, TRUE);
search_setup_model (impl);
set_busy_cursor (impl, TRUE);
- if (impl->priv->search_engine == NULL)
- impl->priv->search_engine = _gtk_search_engine_new ();
+ if (priv->search_engine == NULL)
+ priv->search_engine = _gtk_search_engine_new ();
- if (!impl->priv->search_engine)
+ if (!priv->search_engine)
{
set_busy_cursor (impl, FALSE);
search_error_could_not_create_client (impl); /* lame; we don't get an error code or anything */
return;
}
- if (!impl->priv->search_query)
+ if (!priv->search_query)
{
- impl->priv->search_query = _gtk_query_new ();
- _gtk_query_set_text (impl->priv->search_query, query_text);
+ priv->search_query = _gtk_query_new ();
+ _gtk_query_set_text (priv->search_query, query_text);
}
- _gtk_search_engine_set_query (impl->priv->search_engine, impl->priv->search_query);
+ _gtk_search_engine_set_query (priv->search_engine, priv->search_query);
- g_signal_connect (impl->priv->search_engine, "hits-added",
+ g_signal_connect (priv->search_engine, "hits-added",
G_CALLBACK (search_engine_hits_added_cb), impl);
- g_signal_connect (impl->priv->search_engine, "finished",
+ g_signal_connect (priv->search_engine, "finished",
G_CALLBACK (search_engine_finished_cb), impl);
- g_signal_connect (impl->priv->search_engine, "error",
+ g_signal_connect (priv->search_engine, "error",
G_CALLBACK (search_engine_error_cb), impl);
- _gtk_search_engine_start (impl->priv->search_engine);
+ _gtk_search_engine_start (priv->search_engine);
}
/* Callback used when the user presses Enter while typing on the search
@@ -8542,20 +6421,19 @@ static void
search_entry_activate_cb (GtkEntry *entry,
gpointer data)
{
- GtkFileChooserDefault *impl;
+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
const char *text;
- impl = GTK_FILE_CHOOSER_DEFAULT (data);
-
- text = gtk_entry_get_text (GTK_ENTRY (impl->priv->search_entry));
+ text = gtk_entry_get_text (GTK_ENTRY (priv->search_entry));
if (strlen (text) == 0)
return;
/* reset any existing query object */
- if (impl->priv->search_query)
+ if (priv->search_query)
{
- g_object_unref (impl->priv->search_query);
- impl->priv->search_query = NULL;
+ g_object_unref (priv->search_query);
+ priv->search_query = NULL;
}
search_start_query (impl, text);
@@ -8564,13 +6442,15 @@ search_entry_activate_cb (GtkEntry *entry,
static gboolean
focus_entry_idle_cb (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
gdk_threads_enter ();
- g_source_destroy (impl->priv->focus_entry_idle);
- impl->priv->focus_entry_idle = NULL;
+ g_source_destroy (priv->focus_entry_idle);
+ priv->focus_entry_idle = NULL;
- if (impl->priv->search_entry)
- gtk_widget_grab_focus (impl->priv->search_entry);
+ if (priv->search_entry)
+ gtk_widget_grab_focus (priv->search_entry);
gdk_threads_leave ();
@@ -8580,6 +6460,8 @@ focus_entry_idle_cb (GtkFileChooserDefault *impl)
static void
focus_search_entry_in_idle (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
/* bgo#634558 - When the user clicks on the Search entry in the shortcuts
* pane, we get a selection-changed signal and we set up the search widgets.
* However, gtk_tree_view_button_press() focuses the treeview *after* making
@@ -8588,55 +6470,57 @@ focus_search_entry_in_idle (GtkFileChooserDefault *impl)
* handler.
*/
- if (!impl->priv->focus_entry_idle)
- impl->priv->focus_entry_idle = add_idle_while_impl_is_alive (impl, G_CALLBACK (focus_entry_idle_cb));
+ if (!priv->focus_entry_idle)
+ priv->focus_entry_idle = add_idle_while_impl_is_alive (impl, G_CALLBACK (focus_entry_idle_cb));
}
/* Hides the path bar and creates the search entry */
static void
search_setup_widgets (GtkFileChooserDefault *impl)
{
- impl->priv->search_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ priv->search_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
path_bar_update (impl);
- impl->priv->search_entry = gtk_entry_new ();
- g_signal_connect (impl->priv->search_entry, "activate",
+ priv->search_entry = gtk_entry_new ();
+ g_signal_connect (priv->search_entry, "activate",
G_CALLBACK (search_entry_activate_cb),
impl);
- gtk_box_pack_start (GTK_BOX (impl->priv->search_hbox), impl->priv->search_entry, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->search_hbox), priv->search_entry, TRUE, TRUE, 0);
/* if there already is a query, restart it */
- if (impl->priv->search_query)
+ if (priv->search_query)
{
- gchar *query = _gtk_query_get_text (impl->priv->search_query);
+ gchar *query = _gtk_query_get_text (priv->search_query);
if (query)
{
- gtk_entry_set_text (GTK_ENTRY (impl->priv->search_entry), query);
+ gtk_entry_set_text (GTK_ENTRY (priv->search_entry), query);
search_start_query (impl, query);
g_free (query);
}
else
{
- g_object_unref (impl->priv->search_query);
- impl->priv->search_query = NULL;
+ g_object_unref (priv->search_query);
+ priv->search_query = NULL;
}
}
/* Box for search widgets */
- gtk_box_pack_start (GTK_BOX (impl->priv->browse_path_bar_hbox), impl->priv->search_hbox, TRUE, TRUE, 0);
- gtk_widget_show_all (impl->priv->search_hbox);
- gtk_size_group_add_widget (GTK_SIZE_GROUP (impl->priv->browse_path_bar_size_group), impl->priv->search_hbox);
+ gtk_box_pack_start (GTK_BOX (priv->browse_path_bar_hbox), priv->search_hbox, TRUE, TRUE, 0);
+ gtk_widget_show_all (priv->search_hbox);
+ gtk_size_group_add_widget (GTK_SIZE_GROUP (priv->browse_path_bar_size_group), priv->search_hbox);
/* Hide the location widgets temporarily */
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
- gtk_widget_hide (impl->priv->location_button);
- gtk_widget_hide (impl->priv->location_entry_box);
+ gtk_widget_hide (priv->location_button);
+ gtk_widget_hide (priv->location_entry_box);
}
focus_search_entry_in_idle (impl);
@@ -8653,14 +6537,16 @@ static void
recent_clear_model (GtkFileChooserDefault *impl,
gboolean remove_from_treeview)
{
- if (!impl->priv->recent_model)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (!priv->recent_model)
return;
if (remove_from_treeview)
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), NULL);
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view), NULL);
- g_object_unref (impl->priv->recent_model);
- impl->priv->recent_model = NULL;
+ g_object_unref (priv->recent_model);
+ priv->recent_model = NULL;
}
/* Stops any ongoing loading of the recent files list; does
@@ -8669,33 +6555,37 @@ recent_clear_model (GtkFileChooserDefault *impl,
static void
recent_stop_loading (GtkFileChooserDefault *impl)
{
- if (impl->priv->load_recent_id)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->load_recent_id)
{
- g_source_remove (impl->priv->load_recent_id);
- impl->priv->load_recent_id = 0;
+ g_source_remove (priv->load_recent_id);
+ priv->load_recent_id = 0;
}
}
static void
recent_setup_model (GtkFileChooserDefault *impl)
{
- g_assert (impl->priv->recent_model == NULL);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ g_assert (priv->recent_model == NULL);
- impl->priv->recent_model = _gtk_file_system_model_new (file_system_model_set,
+ priv->recent_model = _gtk_file_system_model_new (file_system_model_set,
impl,
MODEL_COLUMN_TYPES);
- _gtk_file_system_model_set_filter (impl->priv->recent_model,
- impl->priv->current_filter);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->recent_model),
+ _gtk_file_system_model_set_filter (priv->recent_model,
+ priv->current_filter);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->recent_model),
MODEL_COL_NAME,
name_sort_func,
impl, NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->recent_model),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->recent_model),
MODEL_COL_SIZE,
size_sort_func,
impl, NULL);
- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->priv->recent_model),
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (priv->recent_model),
MODEL_COL_MTIME,
mtime_sort_func,
impl, NULL);
@@ -8713,15 +6603,16 @@ recent_idle_cleanup (gpointer data)
{
RecentLoadData *load_data = data;
GtkFileChooserDefault *impl = load_data->impl;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view),
- GTK_TREE_MODEL (impl->priv->recent_model));
+ gtk_tree_view_set_model (GTK_TREE_VIEW (priv->browse_files_tree_view),
+ GTK_TREE_MODEL (priv->recent_model));
file_list_set_sort_column_ids (impl);
- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->priv->recent_model), MODEL_COL_MTIME, GTK_SORT_DESCENDING);
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->recent_model), MODEL_COL_MTIME, GTK_SORT_DESCENDING);
set_busy_cursor (impl, FALSE);
- impl->priv->load_recent_id = 0;
+ priv->load_recent_id = 0;
g_free (load_data);
}
@@ -8746,6 +6637,7 @@ get_recent_files_limit (GtkWidget *widget)
static void
populate_model_with_recent_items (GtkFileChooserDefault *impl, GList *items)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gint limit;
GList *l;
int n;
@@ -8760,7 +6652,7 @@ populate_model_with_recent_items (GtkFileChooserDefault *impl, GList *items)
GFile *file;
file = g_file_new_for_uri (gtk_recent_info_get_uri (info));
- _gtk_file_system_model_add_and_query_file (impl->priv->recent_model,
+ _gtk_file_system_model_add_and_query_file (priv->recent_model,
file,
MODEL_ATTRIBUTES);
g_object_unref (file);
@@ -8774,6 +6666,7 @@ populate_model_with_recent_items (GtkFileChooserDefault *impl, GList *items)
static void
populate_model_with_folders (GtkFileChooserDefault *impl, GList *items)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GList *folders;
GList *l;
@@ -8783,7 +6676,7 @@ populate_model_with_folders (GtkFileChooserDefault *impl, GList *items)
{
GFile *folder = l->data;
- _gtk_file_system_model_add_and_query_file (impl->priv->recent_model,
+ _gtk_file_system_model_add_and_query_file (priv->recent_model,
folder,
MODEL_ATTRIBUTES);
}
@@ -8797,15 +6690,16 @@ recent_idle_load (gpointer data)
{
RecentLoadData *load_data = data;
GtkFileChooserDefault *impl = load_data->impl;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (!impl->priv->recent_manager)
+ if (!priv->recent_manager)
return FALSE;
- load_data->items = gtk_recent_manager_get_items (impl->priv->recent_manager);
+ load_data->items = gtk_recent_manager_get_items (priv->recent_manager);
if (!load_data->items)
return FALSE;
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN)
populate_model_with_recent_items (impl, load_data->items);
else
populate_model_with_folders (impl, load_data->items);
@@ -8820,6 +6714,7 @@ recent_idle_load (gpointer data)
static void
recent_start_loading (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
RecentLoadData *load_data;
recent_stop_loading (impl);
@@ -8827,14 +6722,14 @@ recent_start_loading (GtkFileChooserDefault *impl)
recent_setup_model (impl);
set_busy_cursor (impl, TRUE);
- g_assert (impl->priv->load_recent_id == 0);
+ g_assert (priv->load_recent_id == 0);
load_data = g_new (RecentLoadData, 1);
load_data->impl = impl;
load_data->items = NULL;
/* begin lazy loading the recent files into the model */
- impl->priv->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
+ priv->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
recent_idle_load,
load_data,
recent_idle_cleanup);
@@ -8859,12 +6754,13 @@ recent_selected_foreach_get_file_cb (GtkTreeModel *model,
static GSList *
recent_get_selected_files (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GSList *result;
GtkTreeSelection *selection;
result = NULL;
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_file_cb, &result);
result = g_slist_reverse (result);
@@ -8877,11 +6773,12 @@ recent_get_selected_files (GtkFileChooserDefault *impl)
static gboolean
recent_should_respond (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeSelection *selection;
- g_assert (impl->priv->operation_mode == OPERATION_MODE_RECENT);
+ g_assert (priv->operation_mode == OPERATION_MODE_RECENT);
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
return (gtk_tree_selection_count_selected_rows (selection) != 0);
}
@@ -8889,44 +6786,46 @@ static void
set_current_filter (GtkFileChooserDefault *impl,
GtkFileFilter *filter)
{
- if (impl->priv->current_filter != filter)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->current_filter != filter)
{
int filter_index;
/* NULL filters are allowed to reset to non-filtered status
*/
- filter_index = g_slist_index (impl->priv->filters, filter);
- if (impl->priv->filters && filter && filter_index < 0)
+ filter_index = g_slist_index (priv->filters, filter);
+ if (priv->filters && filter && filter_index < 0)
return;
- if (impl->priv->current_filter)
- g_object_unref (impl->priv->current_filter);
- impl->priv->current_filter = filter;
- if (impl->priv->current_filter)
+ if (priv->current_filter)
+ g_object_unref (priv->current_filter);
+ priv->current_filter = filter;
+ if (priv->current_filter)
{
- g_object_ref_sink (impl->priv->current_filter);
+ g_object_ref_sink (priv->current_filter);
}
- if (impl->priv->filters)
- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->priv->filter_combo),
+ if (priv->filters)
+ gtk_combo_box_set_active (GTK_COMBO_BOX (priv->filter_combo),
filter_index);
- if (impl->priv->browse_files_model)
+ if (priv->browse_files_model)
{
- _gtk_file_system_model_set_filter (impl->priv->browse_files_model, impl->priv->current_filter);
- _gtk_file_system_model_clear_cache (impl->priv->browse_files_model, MODEL_COL_IS_SENSITIVE);
+ _gtk_file_system_model_set_filter (priv->browse_files_model, priv->current_filter);
+ _gtk_file_system_model_clear_cache (priv->browse_files_model, MODEL_COL_IS_SENSITIVE);
}
- if (impl->priv->search_model)
+ if (priv->search_model)
{
- _gtk_file_system_model_set_filter (impl->priv->search_model, filter);
- _gtk_file_system_model_clear_cache (impl->priv->search_model, MODEL_COL_IS_SENSITIVE);
+ _gtk_file_system_model_set_filter (priv->search_model, filter);
+ _gtk_file_system_model_clear_cache (priv->search_model, MODEL_COL_IS_SENSITIVE);
}
- if (impl->priv->recent_model)
+ if (priv->recent_model)
{
- _gtk_file_system_model_set_filter (impl->priv->recent_model, filter);
- _gtk_file_system_model_clear_cache (impl->priv->recent_model, MODEL_COL_IS_SENSITIVE);
+ _gtk_file_system_model_set_filter (priv->recent_model, filter);
+ _gtk_file_system_model_clear_cache (priv->recent_model, MODEL_COL_IS_SENSITIVE);
}
g_object_notify (G_OBJECT (impl), "filter");
@@ -8937,8 +6836,9 @@ static void
filter_combo_changed (GtkComboBox *combo_box,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
gint new_index = gtk_combo_box_get_active (combo_box);
- GtkFileFilter *new_filter = g_slist_nth_data (impl->priv->filters, new_index);
+ GtkFileFilter *new_filter = g_slist_nth_data (priv->filters, new_index);
set_current_filter (impl, new_filter);
}
@@ -8946,13 +6846,14 @@ filter_combo_changed (GtkComboBox *combo_box,
static void
check_preview_change (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreePath *cursor_path;
GFile *new_file;
char *new_display_name;
GtkTreeModel *model;
- gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), &cursor_path, NULL);
- model = gtk_tree_view_get_model (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
+ gtk_tree_view_get_cursor (GTK_TREE_VIEW (priv->browse_files_tree_view), &cursor_path, NULL);
+ model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->browse_files_tree_view));
if (cursor_path)
{
GtkTreeIter iter;
@@ -8971,30 +6872,30 @@ check_preview_change (GtkFileChooserDefault *impl)
new_display_name = NULL;
}
- if (new_file != impl->priv->preview_file &&
- !(new_file && impl->priv->preview_file &&
- g_file_equal (new_file, impl->priv->preview_file)))
+ if (new_file != priv->preview_file &&
+ !(new_file && priv->preview_file &&
+ g_file_equal (new_file, priv->preview_file)))
{
- if (impl->priv->preview_file)
+ if (priv->preview_file)
{
- g_object_unref (impl->priv->preview_file);
- g_free (impl->priv->preview_display_name);
+ g_object_unref (priv->preview_file);
+ g_free (priv->preview_display_name);
}
if (new_file)
{
- impl->priv->preview_file = new_file;
- impl->priv->preview_display_name = new_display_name;
+ priv->preview_file = new_file;
+ priv->preview_display_name = new_display_name;
}
else
{
- impl->priv->preview_file = NULL;
- impl->priv->preview_display_name = NULL;
+ priv->preview_file = NULL;
+ priv->preview_display_name = NULL;
g_free (new_display_name);
}
- if (impl->priv->use_preview_label && impl->priv->preview_label)
- gtk_label_set_text (GTK_LABEL (impl->priv->preview_label), impl->priv->preview_display_name);
+ if (priv->use_preview_label && priv->preview_label)
+ gtk_label_set_text (GTK_LABEL (priv->preview_label), priv->preview_display_name);
g_signal_emit_by_name (impl, "update-preview");
}
@@ -9007,304 +6908,6 @@ check_preview_change (GtkFileChooserDefault *impl)
}
}
-static void
-shortcuts_activate_volume_mount_cb (GCancellable *cancellable,
- GtkFileSystemVolume *volume,
- const GError *error,
- gpointer data)
-{
- GFile *file;
- gboolean cancelled = g_cancellable_is_cancelled (cancellable);
- GtkFileChooserDefault *impl = data;
-
- if (cancellable != impl->priv->shortcuts_activate_iter_cancellable)
- goto out;
-
- impl->priv->shortcuts_activate_iter_cancellable = NULL;
-
- set_busy_cursor (impl, FALSE);
-
- if (cancelled)
- goto out;
-
- if (error)
- {
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED_HANDLED))
- {
- char *msg, *name;
-
- name = _gtk_file_system_volume_get_display_name (volume);
- msg = g_strdup_printf (_("Could not mount %s"), name);
-
- error_message (impl, msg, error->message);
-
- g_free (msg);
- g_free (name);
- }
-
- goto out;
- }
-
- file = _gtk_file_system_volume_get_root (volume);
- if (file != NULL)
- {
- change_folder_and_display_error (impl, file, FALSE);
- g_object_unref (file);
- }
-
-out:
- g_object_unref (impl);
- g_object_unref (cancellable);
-}
-
-
-/* Activates a volume by mounting it if necessary and then switching to its
- * base path.
- */
-static void
-shortcuts_activate_volume (GtkFileChooserDefault *impl,
- GtkFileSystemVolume *volume)
-{
- GFile *file;
-
- operation_mode_set (impl, OPERATION_MODE_BROWSE);
-
- /* We ref the file chooser since volume_mount() may run a main loop, and the
- * user could close the file chooser window in the meantime.
- */
- g_object_ref (impl);
-
- if (!_gtk_file_system_volume_is_mounted (volume))
- {
- GMountOperation *mount_op;
-
- set_busy_cursor (impl, TRUE);
-
- mount_op = gtk_mount_operation_new (get_toplevel (GTK_WIDGET (impl)));
- impl->priv->shortcuts_activate_iter_cancellable =
- _gtk_file_system_mount_volume (impl->priv->file_system, volume, mount_op,
- shortcuts_activate_volume_mount_cb,
- g_object_ref (impl));
- g_object_unref (mount_op);
- }
- else
- {
- file = _gtk_file_system_volume_get_root (volume);
- if (file != NULL)
- {
- change_folder_and_display_error (impl, file, FALSE);
- g_object_unref (file);
- }
- }
-
- g_object_unref (impl);
-}
-
-/* Opens the folder or volume at the specified iter in the shortcuts model */
-struct ShortcutsActivateData
-{
- GtkFileChooserDefault *impl;
- GFile *file;
-};
-
-static void
-shortcuts_activate_get_info_cb (GCancellable *cancellable,
- GFileInfo *info,
- const GError *error,
- gpointer user_data)
-{
- gboolean cancelled = g_cancellable_is_cancelled (cancellable);
- struct ShortcutsActivateData *data = user_data;
-
- if (cancellable != data->impl->priv->shortcuts_activate_iter_cancellable)
- goto out;
-
- data->impl->priv->shortcuts_activate_iter_cancellable = NULL;
-
- if (cancelled)
- goto out;
-
- if (!error && _gtk_file_info_consider_as_directory (info))
- change_folder_and_display_error (data->impl, data->file, FALSE);
- else
- gtk_file_chooser_default_select_file (GTK_FILE_CHOOSER (data->impl),
- data->file,
- NULL);
-
-out:
- g_object_unref (data->impl);
- g_object_unref (data->file);
- g_free (data);
-
- g_object_unref (cancellable);
-}
-
-static void
-shortcuts_activate_mount_enclosing_volume (GCancellable *cancellable,
- GtkFileSystemVolume *volume,
- const GError *error,
- gpointer user_data)
-{
- struct ShortcutsActivateData *data = user_data;
-
- if (error)
- {
- error_changing_folder_dialog (data->impl, data->file, g_error_copy (error));
-
- g_object_unref (data->impl);
- g_object_unref (data->file);
- g_free (data);
-
- return;
- }
-
- data->impl->priv->shortcuts_activate_iter_cancellable =
- _gtk_file_system_get_info (data->impl->priv->file_system, data->file,
- "standard::type",
- shortcuts_activate_get_info_cb, data);
-
- if (volume)
- _gtk_file_system_volume_unref (volume);
-}
-
-static void
-shortcuts_activate_iter (GtkFileChooserDefault *impl,
- GtkTreeIter *iter)
-{
- gpointer col_data;
- ShortcutType shortcut_type;
-
- /* In the Save modes, we want to preserve what the uesr typed in the filename
- * entry, so that he may choose another folder without erasing his typed name.
- */
- if (impl->priv->location_entry
- && !(impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), "");
-
- gtk_tree_model_get (GTK_TREE_MODEL (impl->priv->shortcuts_model), iter,
- SHORTCUTS_COL_DATA, &col_data,
- SHORTCUTS_COL_TYPE, &shortcut_type,
- -1);
-
- if (impl->priv->shortcuts_activate_iter_cancellable)
- {
- g_cancellable_cancel (impl->priv->shortcuts_activate_iter_cancellable);
- impl->priv->shortcuts_activate_iter_cancellable = NULL;
- }
-
- if (shortcut_type == SHORTCUT_TYPE_SEPARATOR)
- return;
- else if (shortcut_type == SHORTCUT_TYPE_VOLUME)
- {
- GtkFileSystemVolume *volume;
-
- volume = col_data;
-
- operation_mode_set (impl, OPERATION_MODE_BROWSE);
-
- shortcuts_activate_volume (impl, volume);
- }
- else if (shortcut_type == SHORTCUT_TYPE_FILE)
- {
- struct ShortcutsActivateData *data;
- GtkFileSystemVolume *volume;
-
- operation_mode_set (impl, OPERATION_MODE_BROWSE);
-
- volume = _gtk_file_system_get_volume_for_file (impl->priv->file_system, col_data);
-
- data = g_new0 (struct ShortcutsActivateData, 1);
- data->impl = g_object_ref (impl);
- data->file = g_object_ref (col_data);
-
- if (!volume || !_gtk_file_system_volume_is_mounted (volume))
- {
- GMountOperation *mount_operation;
- GtkWidget *toplevel;
-
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (impl));
-
- mount_operation = gtk_mount_operation_new (GTK_WINDOW (toplevel));
-
- impl->priv->shortcuts_activate_iter_cancellable =
- _gtk_file_system_mount_enclosing_volume (impl->priv->file_system, col_data,
- mount_operation,
- shortcuts_activate_mount_enclosing_volume,
- data);
- }
- else
- {
- impl->priv->shortcuts_activate_iter_cancellable =
- _gtk_file_system_get_info (impl->priv->file_system, data->file,
- "standard::type",
- shortcuts_activate_get_info_cb, data);
- }
- }
- else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
- {
- operation_mode_set (impl, OPERATION_MODE_SEARCH);
- }
- else if (shortcut_type == SHORTCUT_TYPE_RECENT)
- {
- operation_mode_set (impl, OPERATION_MODE_RECENT);
- }
-}
-
-/* Handler for GtkWidget::key-press-event on the shortcuts list */
-static gboolean
-shortcuts_key_press_event_cb (GtkWidget *widget,
- GdkEventKey *event,
- GtkFileChooserDefault *impl)
-{
- guint modifiers;
-
- modifiers = gtk_accelerator_get_default_mod_mask ();
-
- if (key_is_left_or_right (event))
- {
- gtk_widget_grab_focus (impl->priv->browse_files_tree_view);
- return TRUE;
- }
-
- if ((event->keyval == GDK_KEY_BackSpace
- || event->keyval == GDK_KEY_Delete
- || event->keyval == GDK_KEY_KP_Delete)
- && (event->state & modifiers) == 0)
- {
- remove_selected_bookmarks (impl);
- return TRUE;
- }
-
- if ((event->keyval == GDK_KEY_F2)
- && (event->state & modifiers) == 0)
- {
- rename_selected_bookmark (impl);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-shortcuts_select_func (GtkTreeSelection *selection,
- GtkTreeModel *model,
- GtkTreePath *path,
- gboolean path_currently_selected,
- gpointer data)
-{
- GtkFileChooserDefault *impl = data;
- GtkTreeIter filter_iter;
- ShortcutType shortcut_type;
-
- if (!gtk_tree_model_get_iter (impl->priv->shortcuts_pane_filter_model, &filter_iter, path))
- g_assert_not_reached ();
-
- gtk_tree_model_get (impl->priv->shortcuts_pane_filter_model, &filter_iter, SHORTCUTS_COL_TYPE, &shortcut_type, -1);
-
- return shortcut_type != SHORTCUT_TYPE_SEPARATOR;
-}
-
static gboolean
list_select_func (GtkTreeSelection *selection,
GtkTreeModel *model,
@@ -9313,9 +6916,10 @@ list_select_func (GtkTreeSelection *selection,
gpointer data)
{
GtkFileChooserDefault *impl = data;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
GtkTreeIter iter;
gboolean is_sensitive;
@@ -9338,9 +6942,11 @@ static void
list_selection_changed (GtkTreeSelection *selection,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
/* See if we are in the new folder editable row for Save mode */
- if (impl->priv->operation_mode == OPERATION_MODE_BROWSE &&
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->operation_mode == OPERATION_MODE_BROWSE &&
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
GFileInfo *info;
gboolean had_selection;
@@ -9355,13 +6961,12 @@ list_selection_changed (GtkTreeSelection *selection,
out:
- if (impl->priv->location_entry)
+ if (priv->location_entry)
update_chooser_entry (impl);
path_bar_update (impl);
check_preview_change (impl);
- bookmarks_check_add_sensitivity (impl);
check_copy_file_location_sensitivity (impl);
g_signal_emit_by_name (impl, "selection-changed", 0);
@@ -9374,6 +6979,7 @@ list_row_activated (GtkTreeView *tree_view,
GtkTreeViewColumn *column,
GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GFile *file;
GtkTreeIter iter;
GtkTreeModel *model;
@@ -9397,8 +7003,8 @@ list_row_activated (GtkTreeView *tree_view,
goto out;
}
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SAVE)
g_signal_emit_by_name (impl, "file-activated");
out:
@@ -9431,6 +7037,7 @@ path_bar_clicked (GtkPathBar *path_bar,
static void
update_cell_renderer_attributes (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GList *walk, *list;
@@ -9438,7 +7045,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
/* Keep the following column numbers in sync with create_file_list() */
/* name */
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), 0);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 0);
list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
for (walk = list; walk; walk = walk->next)
{
@@ -9462,7 +7069,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
g_list_free (list);
/* size */
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), 1);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 1);
list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
renderer = list->data;
gtk_tree_view_column_set_attributes (column, renderer,
@@ -9473,7 +7080,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
g_list_free (list);
/* mtime */
- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->priv->browse_files_tree_view), 2);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (priv->browse_files_tree_view), 2);
list = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
renderer = list->data;
gtk_tree_view_column_set_attributes (column, renderer,
@@ -9493,34 +7100,38 @@ static void
location_set_user_text (GtkFileChooserDefault *impl,
const gchar *path)
{
- gtk_entry_set_text (GTK_ENTRY (impl->priv->location_entry), path);
- gtk_editable_set_position (GTK_EDITABLE (impl->priv->location_entry), -1);
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ gtk_entry_set_text (GTK_ENTRY (priv->location_entry), path);
+ gtk_editable_set_position (GTK_EDITABLE (priv->location_entry), -1);
}
static void
location_popup_handler (GtkFileChooserDefault *impl,
const gchar *path)
{
- if (impl->priv->operation_mode != OPERATION_MODE_BROWSE)
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ if (priv->operation_mode != OPERATION_MODE_BROWSE)
{
GtkWidget *widget_to_focus;
operation_mode_set (impl, OPERATION_MODE_BROWSE);
- if (impl->priv->current_folder)
- change_folder_and_display_error (impl, impl->priv->current_folder, FALSE);
+ if (priv->current_folder)
+ change_folder_and_display_error (impl, priv->current_folder, FALSE);
- if (impl->priv->location_mode == LOCATION_MODE_PATH_BAR)
- widget_to_focus = impl->priv->browse_files_tree_view;
+ if (priv->location_mode == LOCATION_MODE_PATH_BAR)
+ widget_to_focus = priv->browse_files_tree_view;
else
- widget_to_focus = impl->priv->location_entry;
+ widget_to_focus = priv->location_entry;
gtk_widget_grab_focus (widget_to_focus);
return;
}
- if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
{
if (!path)
return;
@@ -9528,10 +7139,10 @@ location_popup_handler (GtkFileChooserDefault *impl,
location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY, TRUE);
location_set_user_text (impl, path);
}
- else if (impl->priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
- impl->priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
+ else if (priv->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
{
- gtk_widget_grab_focus (impl->priv->location_entry);
+ gtk_widget_grab_focus (priv->location_entry);
if (path != NULL)
location_set_user_text (impl, path);
}
@@ -9543,162 +7154,107 @@ location_popup_handler (GtkFileChooserDefault *impl,
static void
up_folder_handler (GtkFileChooserDefault *impl)
{
- _gtk_path_bar_up (GTK_PATH_BAR (impl->priv->browse_path_bar));
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
+ _gtk_path_bar_up (GTK_PATH_BAR (priv->browse_path_bar));
}
/* Handler for the "down-folder" keybinding signal */
static void
down_folder_handler (GtkFileChooserDefault *impl)
{
- _gtk_path_bar_down (GTK_PATH_BAR (impl->priv->browse_path_bar));
-}
-
-/* Switches to the shortcut in the specified index */
-static void
-switch_to_shortcut (GtkFileChooserDefault *impl,
- int pos)
-{
- GtkTreeIter iter;
-
- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->priv->shortcuts_model), &iter, NULL, pos))
- g_assert_not_reached ();
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- shortcuts_activate_iter (impl, &iter);
+ _gtk_path_bar_down (GTK_PATH_BAR (priv->browse_path_bar));
}
/* Handler for the "home-folder" keybinding signal */
static void
home_folder_handler (GtkFileChooserDefault *impl)
{
- if (impl->priv->has_home)
- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_HOME));
+ switch_to_home_dir (impl);
}
/* Handler for the "desktop-folder" keybinding signal */
static void
desktop_folder_handler (GtkFileChooserDefault *impl)
{
- if (impl->priv->has_desktop)
- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_DESKTOP));
+ const char *name;
+
+ name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
+ /* "To disable a directory, point it to the homedir."
+ * See http://freedesktop.org/wiki/Software/xdg-user-dirs
+ **/
+ if (!g_strcmp0 (name, g_get_home_dir ())) {
+ return;
+ }
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl), name);
}
/* Handler for the "search-shortcut" keybinding signal */
static void
search_shortcut_handler (GtkFileChooserDefault *impl)
{
- if (impl->priv->has_search)
- {
- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_SEARCH));
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
- /* we want the entry widget to grab the focus the first
- * time, not the browse_files_tree_view widget.
- */
- if (impl->priv->search_entry)
- gtk_widget_grab_focus (impl->priv->search_entry);
- }
+ operation_mode_set (impl, OPERATION_MODE_SEARCH);
+
+ /* we want the entry widget to grab the focus the first
+ * time, not the browse_files_tree_view widget.
+ */
+ if (priv->search_entry)
+ gtk_widget_grab_focus (priv->search_entry);
}
/* Handler for the "recent-shortcut" keybinding signal */
static void
recent_shortcut_handler (GtkFileChooserDefault *impl)
{
- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_RECENT));
+ operation_mode_set (impl, OPERATION_MODE_RECENT);
}
static void
quick_bookmark_handler (GtkFileChooserDefault *impl,
gint bookmark_index)
{
- int bookmark_pos;
- GtkTreePath *path;
-
- if (bookmark_index < 0 || bookmark_index >= impl->priv->num_bookmarks)
- return;
-
- bookmark_pos = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS) + bookmark_index;
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+ GFile *file;
- path = gtk_tree_path_new_from_indices (bookmark_pos, -1);
- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view),
- path, NULL,
- FALSE, 0.0, 0.0);
- gtk_tree_path_free (path);
+ file = gtk_places_sidebar_get_nth_bookmark (GTK_PLACES_SIDEBAR (priv->places_sidebar), bookmark_index);
- switch_to_shortcut (impl, bookmark_pos);
+ if (file)
+ {
+ change_folder_and_display_error (impl, file, FALSE);
+ g_object_unref (file);
+ }
}
static void
show_hidden_handler (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv = impl->priv;
+
g_object_set (impl,
- "show-hidden", !impl->priv->show_hidden,
+ "show-hidden", !priv->show_hidden,
NULL);
}
-/********************************************************************
- * ShortcutsPaneModelFilter *
- ********************************************************************/
static void
-_shortcuts_pane_model_filter_class_init (ShortcutsPaneModelFilterClass *class)
-{
-}
-
-static void
-_shortcuts_pane_model_filter_init (ShortcutsPaneModelFilter *model)
-{
- model->impl = NULL;
-}
-
-/* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
-static gboolean
-shortcuts_pane_model_filter_row_draggable (GtkTreeDragSource *drag_source,
- GtkTreePath *path)
-{
- ShortcutsPaneModelFilter *model;
- int pos;
- int bookmarks_pos;
-
- model = SHORTCUTS_PANE_MODEL_FILTER (drag_source);
-
- pos = *gtk_tree_path_get_indices (path);
- bookmarks_pos = shortcuts_get_index (model->impl, SHORTCUTS_BOOKMARKS);
-
- return (pos >= bookmarks_pos && pos < bookmarks_pos + model->impl->priv->num_bookmarks);
-}
-
-/* GtkTreeDragSource::drag_data_get implementation for the shortcuts
- * filter model
- */
-static gboolean
-shortcuts_pane_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
- GtkTreePath *path,
- GtkSelectionData *selection_data)
-{
- /* FIXME */
-
- return FALSE;
-}
-
-/* Fill the GtkTreeDragSourceIface vtable */
-static void
-shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface)
+add_normal_and_shifted_binding (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const gchar *signal_name)
{
- iface->row_draggable = shortcuts_pane_model_filter_row_draggable;
- iface->drag_data_get = shortcuts_pane_model_filter_drag_data_get;
-}
+ gtk_binding_entry_add_signal (binding_set,
+ keyval, modifiers,
+ signal_name, 0);
-#if 0
-/* Fill the GtkTreeDragDestIface vtable */
-static void
-shortcuts_pane_model_filter_drag_dest_iface_init (GtkTreeDragDestIface *iface)
-{
- iface->drag_data_received = shortcuts_pane_model_filter_drag_data_received;
- iface->row_drop_possible = shortcuts_pane_model_filter_row_drop_possible;
+ gtk_binding_entry_add_signal (binding_set,
+ keyval, modifiers | GDK_SHIFT_MASK,
+ signal_name, 0);
}
-#endif
-/********************************************************************
- * Class/Instance Initializer *
- ********************************************************************/
static void
_gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
{
@@ -9901,21 +7457,18 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
g_type_class_add_private (gobject_class, sizeof (GtkFileChooserDefaultPrivate));
- /* Bind class to template
- */
+ /* Bind class to template */
+
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gtk/libgtk/gtkfilechooserdefault.ui");
/* A *lot* of widgets that we need to handle .... */
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_shortcuts_toolbar);
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_shortcuts_swin);
+
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_widgets_box);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_widgets_hpaned);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_header_box);
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_shortcuts_tree_view);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_widgets_box);
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_shortcuts_add_button);
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_shortcuts_remove_button);
+ gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, places_sidebar);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_files_tree_view);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_new_folder_button);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, browse_path_bar_hbox);
@@ -9933,8 +7486,6 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, location_button);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, location_entry_box);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, location_label);
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, shortcuts_model);
- gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, shortcuts_pane_filter_model);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, list_name_column);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, list_pixbuf_renderer);
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, list_name_renderer);
@@ -9942,23 +7493,6 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
gtk_widget_class_bind_child (widget_class, GtkFileChooserDefaultPrivate, list_size_column);
/* And a *lot* of callbacks to bind ... */
- gtk_widget_class_bind_callback (widget_class, shortcuts_key_press_event_after_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_key_press_event_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_drop_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_data_received_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_data_delete_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_end_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_popup_menu_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_query_tooltip_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_button_press_event_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_motion_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_leave_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_drag_begin_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_selection_changed_cb);
- gtk_widget_class_bind_callback (widget_class, shortcuts_editing_canceled);
- gtk_widget_class_bind_callback (widget_class, shortcuts_edited);
- gtk_widget_class_bind_callback (widget_class, add_bookmark_button_clicked_cb);
- gtk_widget_class_bind_callback (widget_class, remove_bookmark_button_clicked_cb);
gtk_widget_class_bind_callback (widget_class, browse_files_key_press_event_cb);
gtk_widget_class_bind_callback (widget_class, file_list_drag_drop_cb);
gtk_widget_class_bind_callback (widget_class, file_list_drag_data_received_cb);
@@ -9974,75 +7508,22 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
gtk_widget_class_bind_callback (widget_class, location_button_toggled_cb);
gtk_widget_class_bind_callback (widget_class, new_folder_button_clicked);
gtk_widget_class_bind_callback (widget_class, path_bar_clicked);
-}
-
-static void
-gtk_file_chooser_default_iface_init (GtkFileChooserIface *iface)
-{
- iface->select_file = gtk_file_chooser_default_select_file;
- iface->unselect_file = gtk_file_chooser_default_unselect_file;
- iface->select_all = gtk_file_chooser_default_select_all;
- iface->unselect_all = gtk_file_chooser_default_unselect_all;
- iface->get_files = gtk_file_chooser_default_get_files;
- iface->get_preview_file = gtk_file_chooser_default_get_preview_file;
- iface->get_file_system = gtk_file_chooser_default_get_file_system;
- iface->set_current_folder = gtk_file_chooser_default_set_current_folder;
- iface->get_current_folder = gtk_file_chooser_default_get_current_folder;
- iface->set_current_name = gtk_file_chooser_default_set_current_name;
- iface->add_filter = gtk_file_chooser_default_add_filter;
- iface->remove_filter = gtk_file_chooser_default_remove_filter;
- iface->list_filters = gtk_file_chooser_default_list_filters;
- iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder;
- iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder;
- iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders;
-}
-
-static void
-gtk_file_chooser_embed_default_iface_init (GtkFileChooserEmbedIface *iface)
-{
- iface->get_default_size = gtk_file_chooser_default_get_default_size;
- iface->should_respond = gtk_file_chooser_default_should_respond;
- iface->initial_focus = gtk_file_chooser_default_initial_focus;
+ gtk_widget_class_bind_callback (widget_class, places_sidebar_open_location_cb);
+ gtk_widget_class_bind_callback (widget_class, places_sidebar_show_error_message_cb);
}
static void
post_process_ui (GtkFileChooserDefault *impl)
{
GtkTreeSelection *selection;
- GtkStyleContext *context;
GtkCellRenderer *cell;
GList *cells;
- /* Target types for dragging a row to/from the shortcuts list */
- const GtkTargetEntry tree_model_row_targets[] = {
- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
- };
-
- /* Shortcuts model needs a pointer back to the 'impl' */
- SHORTCUTS_PANE_MODEL_FILTER (impl->priv->shortcuts_pane_filter_model)->impl = impl;
-
/* Some qdata, qdata can't be set with GtkBuilder */
-#ifdef PROFILE_FILE_CHOOSER
- g_object_set_data (G_OBJECT (impl->priv->browse_shortcuts_tree_view), "fmq-name", "shortcuts");
g_object_set_data (G_OBJECT (impl->priv->browse_files_tree_view), "fmq-name", "file_list");
-#endif
g_object_set_data (G_OBJECT (impl->priv->browse_files_tree_view), I_("GtkFileChooserDefault"), impl);
- /* Setup Places and File List Treeviews
- */
- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view),
- GDK_BUTTON1_MASK,
- tree_model_row_targets,
- G_N_ELEMENTS (tree_model_row_targets),
- GDK_ACTION_MOVE);
-
- gtk_drag_dest_set (impl->priv->browse_shortcuts_tree_view,
- GTK_DEST_DEFAULT_ALL,
- tree_model_row_targets,
- G_N_ELEMENTS (tree_model_row_targets),
- GDK_ACTION_COPY | GDK_ACTION_MOVE);
- gtk_drag_dest_add_uri_targets (impl->priv->browse_shortcuts_tree_view);
-
+ /* Setup file list treeview */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_files_tree_view));
gtk_tree_selection_set_select_function (selection,
list_select_func,
@@ -10053,29 +7534,12 @@ post_process_ui (GtkFileChooserDefault *impl)
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_source_add_uri_targets (impl->priv->browse_files_tree_view);
-
- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view));
- gtk_tree_selection_set_select_function (selection,
- shortcuts_select_func,
- impl, NULL);
-
- gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (impl->priv->browse_shortcuts_tree_view),
- shortcuts_row_separator_func,
- NULL, NULL);
-
gtk_drag_dest_set (impl->priv->browse_files_tree_view,
GTK_DEST_DEFAULT_ALL,
NULL, 0,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gtk_drag_dest_add_uri_targets (impl->priv->browse_files_tree_view);
- /* GtkStyleContext 'junctions' cannot be set with GtkBuilder */
- context = gtk_widget_get_style_context (impl->priv->browse_shortcuts_swin);
- gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
-
- context = gtk_widget_get_style_context (impl->priv->browse_shortcuts_toolbar);
- gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
-
/* File browser treemodel columns are shared between GtkFileChooser implementations,
* so we don't set cell renderer attributes in GtkBuilder, but rather keep that
* in code.
@@ -10109,43 +7573,43 @@ post_process_ui (GtkFileChooserDefault *impl)
static void
_gtk_file_chooser_default_init (GtkFileChooserDefault *impl)
{
+ GtkFileChooserDefaultPrivate *priv;
+
profile_start ("start", NULL);
#ifdef PROFILE_FILE_CHOOSER
access ("MARK: *** CREATE FILE CHOOSER", F_OK);
#endif
-
impl->priv = G_TYPE_INSTANCE_GET_PRIVATE (impl,
GTK_TYPE_FILE_CHOOSER_DEFAULT,
GtkFileChooserDefaultPrivate);
-
- impl->priv->local_only = TRUE;
- impl->priv->preview_widget_active = TRUE;
- impl->priv->use_preview_label = TRUE;
- impl->priv->select_multiple = FALSE;
- impl->priv->show_hidden = FALSE;
- impl->priv->show_size_column = TRUE;
- impl->priv->icon_size = FALLBACK_ICON_SIZE;
- impl->priv->load_state = LOAD_EMPTY;
- impl->priv->reload_state = RELOAD_EMPTY;
- impl->priv->pending_select_files = NULL;
- impl->priv->location_mode = LOCATION_MODE_PATH_BAR;
- impl->priv->operation_mode = OPERATION_MODE_BROWSE;
- impl->priv->sort_column = MODEL_COL_NAME;
- impl->priv->sort_order = GTK_SORT_ASCENDING;
- impl->priv->recent_manager = gtk_recent_manager_get_default ();
- impl->priv->create_folders = TRUE;
+ priv = impl->priv;
+
+ priv->local_only = TRUE;
+ priv->preview_widget_active = TRUE;
+ priv->use_preview_label = TRUE;
+ priv->select_multiple = FALSE;
+ priv->show_hidden = FALSE;
+ priv->show_size_column = TRUE;
+ priv->icon_size = FALLBACK_ICON_SIZE;
+ priv->load_state = LOAD_EMPTY;
+ priv->reload_state = RELOAD_EMPTY;
+ priv->pending_select_files = NULL;
+ priv->location_mode = LOCATION_MODE_PATH_BAR;
+ priv->operation_mode = OPERATION_MODE_BROWSE;
+ priv->sort_column = MODEL_COL_NAME;
+ priv->sort_order = GTK_SORT_ASCENDING;
+ priv->recent_manager = gtk_recent_manager_get_default ();
+ priv->create_folders = TRUE;
/* Ensure GTK+ private types used by the template
* definition before calling gtk_widget_init_template()
*/
- g_type_ensure (SHORTCUTS_PANE_MODEL_FILTER_TYPE);
g_type_ensure (GTK_TYPE_PATH_BAR);
gtk_widget_init_template (GTK_WIDGET (impl));
set_file_system_backend (impl);
- /* Populate the Places sidebar */
- shortcuts_model_populate (impl);
+ priv->bookmarks_manager = _gtk_bookmarks_manager_new (NULL, NULL);
/* Setup various attributes and callbacks in the UI
* which cannot be done with GtkBuilder.
diff --git a/gtk/gtkfilechooserdefault.ui b/gtk/gtkfilechooserdefault.ui
index 44124ca44d..5cf2ef3896 100644
--- a/gtk/gtkfilechooserdefault.ui
+++ b/gtk/gtkfilechooserdefault.ui
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="gtk30">
- <!-- interface-requires gtkprivate 3.10 -->
<!-- interface-requires gtk+ 3.10 -->
+ <!-- interface-requires gtkprivate 3.10 -->
<object class="GtkImage" id="location_button_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -31,7 +31,8 @@
<object class="GtkLabel" id="location_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Location:</property>
+ <property name="label" translatable="yes">_Location:</property>
+ <property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
@@ -204,126 +205,13 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
- <object class="GtkBox" id="browse_shortcuts_box">
+ <object class="GtkPlacesSidebar" id="places_sidebar">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkScrolledWindow" id="browse_shortcuts_swin">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkTreeView" id="browse_shortcuts_tree_view">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_tooltip">True</property>
- <property name="model">shortcuts_pane_filter_model</property>
- <property name="enable_search">False</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="browse_shortcuts_tree_view-atkobject">
- <property name="AtkObject::accessible-name" translatable="yes">Places</property>
- </object>
- </child>
- <style>
- <class name="sidebar"/>
- </style>
- <signal name="button-press-event" handler="shortcuts_button_press_event_cb" swapped="no"/>
- <signal name="drag-begin" handler="shortcuts_drag_begin_cb" swapped="no"/>
- <signal name="drag-data-delete" handler="shortcuts_drag_data_delete_cb" swapped="no"/>
- <signal name="drag-data-received" handler="shortcuts_drag_data_received_cb" swapped="no"/>
- <signal name="drag-drop" handler="shortcuts_drag_drop_cb" swapped="no"/>
- <signal name="drag-end" handler="shortcuts_drag_end_cb" swapped="no"/>
- <signal name="drag-leave" handler="shortcuts_drag_leave_cb" swapped="no"/>
- <signal name="drag-motion" handler="shortcuts_drag_motion_cb" swapped="no"/>
- <signal name="key-press-event" handler="shortcuts_key_press_event_after_cb" after="yes" swapped="no"/>
- <signal name="key-press-event" handler="shortcuts_key_press_event_cb" swapped="no"/>
- <signal name="popup-menu" handler="shortcuts_popup_menu_cb" swapped="no"/>
- <signal name="query-tooltip" handler="shortcuts_query_tooltip_cb" swapped="no"/>
- <child internal-child="selection">
- <object class="GtkTreeSelection" id="treeview-selection1">
- <signal name="changed" handler="shortcuts_selection_changed_cb" swapped="no"/>
- </object>
- </child>
- <child>
- <object class="GtkTreeViewColumn" id="treeviewcolumn1">
- <property name="title" translatable="yes">Places</property>
- <child>
- <object class="GtkCellRendererPixbuf" id="cellrendererpixbuf1"/>
- <attributes>
- <attribute name="visible">5</attribute>
- <attribute name="pixbuf">0</attribute>
- </attributes>
- </child>
- <child>
- <object class="GtkCellRendererText" id="cellrenderertext1">
- <property name="ellipsize">end</property>
- <property name="width_chars">12</property>
- <signal name="edited" handler="shortcuts_edited" swapped="no"/>
- <signal name="editing-canceled" handler="shortcuts_editing_canceled" swapped="no"/>
- </object>
- <attributes>
- <attribute name="text">1</attribute>
- </attributes>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="browse_shortcuts_toolbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="toolbar_style">icons</property>
- <style>
- <class name="inline-toolbar"/>
- </style>
- <property name="icon_size">1</property>
- <child>
- <object class="GtkToolButton" id="browse_shortcuts_add_button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Add the selected folder to the Bookmarks</property>
- <property name="use_underline">True</property>
- <property name="icon_name">list-add-symbolic</property>
- <signal name="clicked" handler="add_bookmark_button_clicked_cb" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="browse_shortcuts_remove_button">
- <property name="visible">True</property>
- <property name="sensitive">False</property>
- <property name="can_focus">False</property>
- <property name="tooltip_text" translatable="yes">Remove the selected bookmark</property>
- <property name="use_underline">True</property>
- <property name="icon_name">list-remove-symbolic</property>
- <signal name="clicked" handler="remove_bookmark_button_clicked_cb" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">never</property>
+ <property name="shadow_type">in</property>
+ <signal name="open-location" handler="places_sidebar_open_location_cb" swapped="no"/>
+ <signal name="show-error-message" handler="places_sidebar_show_error_message_cb" swapped="no"/>
</object>
<packing>
<property name="resize">False</property>
@@ -524,32 +412,4 @@
<widget name="browse_new_folder_button"/>
</widgets>
</object>
- <object class="GtkSizeGroup" id="paned_group">
- <property name="mode">vertical</property>
- <widgets>
- <widget name="browse_shortcuts_swin"/>
- <widget name="browse_files_swin"/>
- </widgets>
- </object>
- <object class="GtkListStore" id="shortcuts_model">
- <columns>
- <!-- column-name pixbuf -->
- <column type="GdkPixbuf"/>
- <!-- column-name name -->
- <column type="gchararray"/>
- <!-- column-name path-or-volume -->
- <column type="gpointer"/>
- <!-- column-name shortcut-type -->
- <column type="gint"/>
- <!-- column-name removable -->
- <column type="gboolean"/>
- <!-- column-name pixbuf-visible -->
- <column type="gboolean"/>
- <!-- column-name cancellable -->
- <column type="gpointer"/>
- </columns>
- </object>
- <object class="ShortcutsPaneModelFilter" id="shortcuts_pane_filter_model">
- <property name="child_model">shortcuts_model</property>
- </object>
</interface>
diff --git a/gtk/gtkfilechooserdialog.c b/gtk/gtkfilechooserdialog.c
index 6d32a98ba4..64d50390ba 100644
--- a/gtk/gtkfilechooserdialog.c
+++ b/gtk/gtkfilechooserdialog.c
@@ -193,6 +193,14 @@
*/
+struct _GtkFileChooserDialogPrivate
+{
+ GtkWidget *widget;
+
+ /* for use with GtkFileChooserEmbed */
+ gboolean response_requested;
+};
+
#define GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE(o) (GTK_FILE_CHOOSER_DIALOG (o)->priv)
static void gtk_file_chooser_dialog_set_property (GObject *object,
diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h
index 34ff0f0f66..61a3aac6db 100644
--- a/gtk/gtkfilechooserprivate.h
+++ b/gtk/gtkfilechooserprivate.h
@@ -19,6 +19,7 @@
#ifndef __GTK_FILE_CHOOSER_PRIVATE_H__
#define __GTK_FILE_CHOOSER_PRIVATE_H__
+#include "gtkbookmarksmanager.h"
#include "gtkfilechooser.h"
#include "gtkfilesystem.h"
#include "gtkfilesystemmodel.h"
@@ -42,11 +43,11 @@ G_BEGIN_DECLS
#define SETTINGS_KEY_WINDOW_POSITION "window-position"
#define SETTINGS_KEY_WINDOW_SIZE "window-size"
#define SETTINGS_KEY_SIDEBAR_WIDTH "sidebar-width"
+#define SETTINGS_KEY_STARTUP_MODE "startup-mode"
#define GTK_FILE_CHOOSER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_FILE_CHOOSER, GtkFileChooserIface))
typedef struct _GtkFileChooserIface GtkFileChooserIface;
-typedef struct _GtkFileChooserDefaultPrivate GtkFileChooserDefaultPrivate;
struct _GtkFileChooserIface
{
@@ -101,58 +102,6 @@ gboolean _gtk_file_chooser_remove_shortcut_folder (GtkFileChooser *cho
GError **error);
GSList * _gtk_file_chooser_list_shortcut_folder_files (GtkFileChooser *chooser);
-/* GtkFileChooserDialog private */
-
-struct _GtkFileChooserDialogPrivate
-{
- GtkWidget *widget;
-
- /* for use with GtkFileChooserEmbed */
- gboolean response_requested;
-};
-
-
-/* GtkFileChooserWidget private */
-
-struct _GtkFileChooserWidgetPrivate
-{
- GtkWidget *impl;
-
- char *file_system;
-};
-
-
-/* GtkFileChooserDefault private */
-
-typedef enum {
- LOAD_EMPTY, /* There is no model */
- LOAD_PRELOAD, /* Model is loading and a timer is running; model isn't inserted into the tree yet */
- LOAD_LOADING, /* Timeout expired, model is inserted into the tree, but not fully loaded yet */
- LOAD_FINISHED /* Model is fully loaded and inserted into the tree */
-} LoadState;
-
-typedef enum {
- RELOAD_EMPTY, /* No folder has been set */
- RELOAD_HAS_FOLDER /* We have a folder, although it may not be completely loaded yet; no need to reload */
-} ReloadState;
-
-typedef enum {
- LOCATION_MODE_PATH_BAR,
- LOCATION_MODE_FILENAME_ENTRY
-} LocationMode;
-
-typedef enum {
- OPERATION_MODE_BROWSE,
- OPERATION_MODE_SEARCH,
- OPERATION_MODE_RECENT
-} OperationMode;
-
-struct _GtkFileChooserDefault
-{
- GtkBox parent_instance;
-
- GtkFileChooserDefaultPrivate *priv;
-};
G_END_DECLS
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 011fe6a3a0..bce30977ba 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -45,11 +45,13 @@
* #GtkFileChooser.
*/
+struct _GtkFileChooserWidgetPrivate
+{
+ GtkWidget *impl;
+};
#define GTK_FILE_CHOOSER_WIDGET_GET_PRIVATE(o) (GTK_FILE_CHOOSER_WIDGET (o)->priv)
-static void gtk_file_chooser_widget_finalize (GObject *object);
-
static GObject* gtk_file_chooser_widget_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params);
@@ -76,7 +78,6 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gobject_class->constructor = gtk_file_chooser_widget_constructor;
gobject_class->set_property = gtk_file_chooser_widget_set_property;
gobject_class->get_property = gtk_file_chooser_widget_get_property;
- gobject_class->finalize = gtk_file_chooser_widget_finalize;
_gtk_file_chooser_install_properties (gobject_class);
@@ -94,16 +95,6 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *chooser_widget)
GTK_ORIENTATION_VERTICAL);
}
-static void
-gtk_file_chooser_widget_finalize (GObject *object)
-{
- GtkFileChooserWidget *chooser = GTK_FILE_CHOOSER_WIDGET (object);
-
- g_free (chooser->priv->file_system);
-
- G_OBJECT_CLASS (gtk_file_chooser_widget_parent_class)->finalize (object);
-}
-
static GObject*
gtk_file_chooser_widget_constructor (GType type,
guint n_construct_properties,
diff --git a/gtk/gtkfilesystem.c b/gtk/gtkfilesystem.c
index 2fdfa3df9d..186992ca0e 100644
--- a/gtk/gtkfilesystem.c
+++ b/gtk/gtkfilesystem.c
@@ -55,7 +55,6 @@ enum {
};
enum {
- BOOKMARKS_CHANGED,
VOLUMES_CHANGED,
FS_LAST_SIGNAL
};
@@ -81,11 +80,6 @@ struct GtkFileSystemPrivate
* of type GDrive, GVolume and GMount
*/
GSList *volumes;
-
- /* This list contains GtkFileSystemBookmark structs */
- GSList *bookmarks;
-
- GFileMonitor *bookmarks_monitor;
};
struct AsyncFuncData
@@ -99,24 +93,9 @@ struct AsyncFuncData
gpointer data;
};
-struct GtkFileSystemBookmark
-{
- GFile *file;
- gchar *label;
-};
-
G_DEFINE_TYPE (GtkFileSystem, _gtk_file_system, G_TYPE_OBJECT)
-/* GtkFileSystemBookmark methods */
-void
-_gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark)
-{
- g_object_unref (bookmark->file);
- g_free (bookmark->label);
- g_slice_free (GtkFileSystemBookmark, bookmark);
-}
-
/* GtkFileSystem methods */
static void
volumes_changed (GVolumeMonitor *volume_monitor,
@@ -158,41 +137,11 @@ gtk_file_system_dispose (GObject *object)
}
static void
-gtk_file_system_finalize (GObject *object)
-{
- GtkFileSystem *file_system = GTK_FILE_SYSTEM (object);
- GtkFileSystemPrivate *priv = file_system->priv;
-
- DEBUG ("finalize");
-
- if (priv->bookmarks_monitor)
- g_object_unref (priv->bookmarks_monitor);
-
- if (priv->bookmarks)
- {
- g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
- g_slist_free (priv->bookmarks);
- }
-
- G_OBJECT_CLASS (_gtk_file_system_parent_class)->finalize (object);
-}
-
-static void
_gtk_file_system_class_init (GtkFileSystemClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->dispose = gtk_file_system_dispose;
- object_class->finalize = gtk_file_system_finalize;
-
- fs_signals[BOOKMARKS_CHANGED] =
- g_signal_new ("bookmarks-changed",
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkFileSystemClass, bookmarks_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
fs_signals[VOLUMES_CHANGED] =
g_signal_new ("volumes-changed",
@@ -206,155 +155,6 @@ _gtk_file_system_class_init (GtkFileSystemClass *class)
g_type_class_add_private (object_class, sizeof (GtkFileSystemPrivate));
}
-static GFile *
-get_legacy_bookmarks_file (void)
-{
- GFile *file;
- gchar *filename;
-
- filename = g_build_filename (g_get_home_dir (), ".gtk-bookmarks", NULL);
- file = g_file_new_for_path (filename);
- g_free (filename);
-
- return file;
-}
-
-static GFile *
-get_bookmarks_file (void)
-{
- GFile *file;
- gchar *filename;
-
- filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
- file = g_file_new_for_path (filename);
- g_free (filename);
-
- return file;
-}
-
-static GSList *
-read_bookmarks (GFile *file)
-{
- gchar *contents;
- gchar **lines, *space;
- GSList *bookmarks = NULL;
- gint i;
-
- if (!g_file_load_contents (file, NULL, &contents,
- NULL, NULL, NULL))
- return NULL;
-
- lines = g_strsplit (contents, "\n", -1);
-
- for (i = 0; lines[i]; i++)
- {
- GtkFileSystemBookmark *bookmark;
-
- if (!*lines[i])
- continue;
-
- if (!g_utf8_validate (lines[i], -1, NULL))
- continue;
-
- bookmark = g_slice_new0 (GtkFileSystemBookmark);
-
- if ((space = strchr (lines[i], ' ')) != NULL)
- {
- space[0] = '\0';
- bookmark->label = g_strdup (space + 1);
- }
-
- bookmark->file = g_file_new_for_uri (lines[i]);
- bookmarks = g_slist_prepend (bookmarks, bookmark);
- }
-
- bookmarks = g_slist_reverse (bookmarks);
- g_strfreev (lines);
- g_free (contents);
-
- return bookmarks;
-}
-
-static void
-save_bookmarks (GFile *bookmarks_file,
- GSList *bookmarks)
-{
- GError *error = NULL;
- GString *contents;
- GSList *l;
- GFile *parent_file;
- gchar *path;
-
- contents = g_string_new ("");
-
- for (l = bookmarks; l; l = l->next)
- {
- GtkFileSystemBookmark *bookmark = l->data;
- gchar *uri;
-
- uri = g_file_get_uri (bookmark->file);
- if (!uri)
- continue;
-
- g_string_append (contents, uri);
-
- if (bookmark->label)
- g_string_append_printf (contents, " %s", bookmark->label);
-
- g_string_append_c (contents, '\n');
- g_free (uri);
- }
-
- parent_file = g_file_get_parent (bookmarks_file);
- path = g_file_get_path (parent_file);
- if (g_mkdir_with_parents (path, 0700) == 0)
- {
- if (!g_file_replace_contents (bookmarks_file,
- contents->str,
- strlen (contents->str),
- NULL, FALSE, 0, NULL,
- NULL, &error))
- {
- g_critical ("%s", error->message);
- g_error_free (error);
- }
- }
- g_free (path);
- g_object_unref (parent_file);
- g_string_free (contents, TRUE);
-}
-
-static void
-bookmarks_file_changed (GFileMonitor *monitor,
- GFile *file,
- GFile *other_file,
- GFileMonitorEvent event,
- gpointer data)
-{
- GtkFileSystem *file_system = GTK_FILE_SYSTEM (data);
- GtkFileSystemPrivate *priv = file_system->priv;
-
- switch (event)
- {
- case G_FILE_MONITOR_EVENT_CHANGED:
- case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
- case G_FILE_MONITOR_EVENT_CREATED:
- case G_FILE_MONITOR_EVENT_DELETED:
- g_slist_foreach (priv->bookmarks, (GFunc) _gtk_file_system_bookmark_free, NULL);
- g_slist_free (priv->bookmarks);
-
- priv->bookmarks = read_bookmarks (file);
-
- gdk_threads_enter ();
- g_signal_emit (data, fs_signals[BOOKMARKS_CHANGED], 0);
- gdk_threads_leave ();
- break;
- default:
- /* ignore at the moment */
- break;
- }
-}
-
static gboolean
mount_referenced_by_volume_activation_root (GList *volumes, GMount *mount)
{
@@ -533,8 +333,6 @@ static void
_gtk_file_system_init (GtkFileSystem *file_system)
{
GtkFileSystemPrivate *priv;
- GFile *bookmarks_file;
- GError *error = NULL;
DEBUG ("init");
@@ -564,35 +362,6 @@ _gtk_file_system_init (GtkFileSystem *file_system)
G_CALLBACK (volumes_changed), file_system);
g_signal_connect (priv->volume_monitor, "drive-changed",
G_CALLBACK (volumes_changed), file_system);
-
- /* Bookmarks */
- bookmarks_file = get_bookmarks_file ();
- priv->bookmarks = read_bookmarks (bookmarks_file);
- if (!priv->bookmarks)
- {
- GFile *legacy_bookmarks_file;
-
- /* Read the legacy one and write it to the new one */
- legacy_bookmarks_file = get_legacy_bookmarks_file ();
- priv->bookmarks = read_bookmarks (legacy_bookmarks_file);
- save_bookmarks (bookmarks_file, priv->bookmarks);
-
- g_object_unref (legacy_bookmarks_file);
- }
-
- priv->bookmarks_monitor = g_file_monitor_file (bookmarks_file,
- G_FILE_MONITOR_NONE,
- NULL, &error);
- if (error)
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- }
- else
- g_signal_connect (priv->bookmarks_monitor, "changed",
- G_CALLBACK (bookmarks_file_changed), file_system);
-
- g_object_unref (bookmarks_file);
}
/* GtkFileSystem public methods */
@@ -622,29 +391,6 @@ _gtk_file_system_list_volumes (GtkFileSystem *file_system)
return list;
}
-GSList *
-_gtk_file_system_list_bookmarks (GtkFileSystem *file_system)
-{
- GtkFileSystemPrivate *priv = file_system->priv;
- GSList *bookmarks, *files = NULL;
-
- DEBUG ("list_bookmarks");
-
- bookmarks = priv->bookmarks;
-
- while (bookmarks)
- {
- GtkFileSystemBookmark *bookmark;
-
- bookmark = bookmarks->data;
- bookmarks = bookmarks->next;
-
- files = g_slist_prepend (files, g_object_ref (bookmark->file));
- }
-
- return g_slist_reverse (files);
-}
-
static void
free_async_data (AsyncFuncData *async_data)
{
@@ -871,185 +617,6 @@ _gtk_file_system_mount_enclosing_volume (GtkFileSystem *file
return cancellable;
}
-gboolean
-_gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
- GFile *file,
- gint position,
- GError **error)
-{
- GtkFileSystemPrivate *priv = file_system->priv;
- GSList *bookmarks;
- GtkFileSystemBookmark *bookmark;
- gboolean result = TRUE;
- GFile *bookmarks_file;
-
- bookmarks = priv->bookmarks;
-
- while (bookmarks)
- {
- bookmark = bookmarks->data;
- bookmarks = bookmarks->next;
-
- if (g_file_equal (bookmark->file, file))
- {
- /* File is already in bookmarks */
- result = FALSE;
- break;
- }
- }
-
- if (!result)
- {
- gchar *uri = g_file_get_uri (file);
-
- g_set_error (error,
- GTK_FILE_CHOOSER_ERROR,
- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
- "%s already exists in the bookmarks list",
- uri);
-
- g_free (uri);
-
- return FALSE;
- }
-
- bookmark = g_slice_new0 (GtkFileSystemBookmark);
- bookmark->file = g_object_ref (file);
-
- priv->bookmarks = g_slist_insert (priv->bookmarks, bookmark, position);
-
- bookmarks_file = get_bookmarks_file ();
- save_bookmarks (bookmarks_file, priv->bookmarks);
- g_object_unref (bookmarks_file);
-
- g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
-
- return TRUE;
-}
-
-gboolean
-_gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
- GFile *file,
- GError **error)
-{
- GtkFileSystemPrivate *priv = file_system->priv;
- GtkFileSystemBookmark *bookmark;
- GSList *bookmarks;
- gboolean result = FALSE;
- GFile *bookmarks_file;
-
- if (!priv->bookmarks)
- return FALSE;
-
- bookmarks = priv->bookmarks;
-
- while (bookmarks)
- {
- bookmark = bookmarks->data;
-
- if (g_file_equal (bookmark->file, file))
- {
- result = TRUE;
- priv->bookmarks = g_slist_remove_link (priv->bookmarks, bookmarks);
- _gtk_file_system_bookmark_free (bookmark);
- g_slist_free_1 (bookmarks);
- break;
- }
-
- bookmarks = bookmarks->next;
- }
-
- if (!result)
- {
- gchar *uri = g_file_get_uri (file);
-
- g_set_error (error,
- GTK_FILE_CHOOSER_ERROR,
- GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
- "%s does not exist in the bookmarks list",
- uri);
-
- g_free (uri);
-
- return FALSE;
- }
-
- bookmarks_file = get_bookmarks_file ();
- save_bookmarks (bookmarks_file, priv->bookmarks);
- g_object_unref (bookmarks_file);
-
- g_signal_emit (file_system, fs_signals[BOOKMARKS_CHANGED], 0);
-
- return TRUE;
-}
-
-gchar *
-_gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
- GFile *file)
-{
- GtkFileSystemPrivate *priv = file_system->priv;
- GSList *bookmarks;
- gchar *label = NULL;
-
- DEBUG ("get_bookmark_label");
-
- bookmarks = priv->bookmarks;
-
- while (bookmarks)
- {
- GtkFileSystemBookmark *bookmark;
-
- bookmark = bookmarks->data;
- bookmarks = bookmarks->next;
-
- if (g_file_equal (file, bookmark->file))
- {
- label = g_strdup (bookmark->label);
- break;
- }
- }
-
- return label;
-}
-
-void
-_gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
- GFile *file,
- const gchar *label)
-{
- GtkFileSystemPrivate *priv = file_system->priv;
- gboolean changed = FALSE;
- GFile *bookmarks_file;
- GSList *bookmarks;
-
- DEBUG ("set_bookmark_label");
-
- bookmarks = priv->bookmarks;
-
- while (bookmarks)
- {
- GtkFileSystemBookmark *bookmark;
-
- bookmark = bookmarks->data;
- bookmarks = bookmarks->next;
-
- if (g_file_equal (file, bookmark->file))
- {
- g_free (bookmark->label);
- bookmark->label = g_strdup (label);
- changed = TRUE;
- break;
- }
- }
-
- bookmarks_file = get_bookmarks_file ();
- save_bookmarks (bookmarks_file, priv->bookmarks);
- g_object_unref (bookmarks_file);
-
- if (changed)
- g_signal_emit_by_name (file_system, "bookmarks-changed", 0);
-}
-
GtkFileSystemVolume *
_gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
GFile *file)
diff --git a/gtk/gtkfilesystem.h b/gtk/gtkfilesystem.h
index 03782d6f7f..c24ae29623 100644
--- a/gtk/gtkfilesystem.h
+++ b/gtk/gtkfilesystem.h
@@ -37,7 +37,6 @@ typedef struct GtkFileSystemClass GtkFileSystemClass;
typedef struct GtkFileSystemVolume GtkFileSystemVolume; /* opaque struct */
-typedef struct GtkFileSystemBookmark GtkFileSystemBookmark; /* opaque struct */
struct GtkFileSystem
@@ -51,7 +50,6 @@ struct GtkFileSystemClass
{
GObjectClass parent_class;
- void (*bookmarks_changed) (GtkFileSystem *file_system);
void (*volumes_changed) (GtkFileSystem *file_system);
};
@@ -71,7 +69,6 @@ GType _gtk_file_system_get_type (void) G_GNUC_CONST;
GtkFileSystem * _gtk_file_system_new (void);
GSList * _gtk_file_system_list_volumes (GtkFileSystem *file_system);
-GSList * _gtk_file_system_list_bookmarks (GtkFileSystem *file_system);
GCancellable * _gtk_file_system_get_info (GtkFileSystem *file_system,
GFile *file,
@@ -89,20 +86,6 @@ GCancellable * _gtk_file_system_mount_enclosing_volume (GtkFileSystem
GtkFileSystemVolumeMountCallback callback,
gpointer data);
-gboolean _gtk_file_system_insert_bookmark (GtkFileSystem *file_system,
- GFile *file,
- gint position,
- GError **error);
-gboolean _gtk_file_system_remove_bookmark (GtkFileSystem *file_system,
- GFile *file,
- GError **error);
-
-gchar * _gtk_file_system_get_bookmark_label (GtkFileSystem *file_system,
- GFile *file);
-void _gtk_file_system_set_bookmark_label (GtkFileSystem *file_system,
- GFile *file,
- const gchar *label);
-
GtkFileSystemVolume * _gtk_file_system_get_volume_for_file (GtkFileSystem *file_system,
GFile *file);
@@ -118,9 +101,6 @@ GdkPixbuf * _gtk_file_system_volume_render_icon (GtkFileSystemVol
GtkFileSystemVolume *_gtk_file_system_volume_ref (GtkFileSystemVolume *volume);
void _gtk_file_system_volume_unref (GtkFileSystemVolume *volume);
-/* GtkFileSystemBookmark methods */
-void _gtk_file_system_bookmark_free (GtkFileSystemBookmark *bookmark);
-
/* GFileInfo helper functions */
GdkPixbuf * _gtk_file_info_render_icon (GFileInfo *info,
GtkWidget *widget,
diff --git a/gtk/gtkgladecatalog.c b/gtk/gtkgladecatalog.c
index 310aa2b84c..30e0e6cfef 100644
--- a/gtk/gtkgladecatalog.c
+++ b/gtk/gtkgladecatalog.c
@@ -30,7 +30,6 @@
/* Some forward declarations of internal types */
GType _gtk_scale_button_scale_get_type (void);
-GType _shortcuts_pane_model_filter_get_type (void);
/* This function is referred to in gtk/glade/gtk-private-widgets.xml
* and is used to ensure the private types for use in Glade while
@@ -44,7 +43,6 @@ gtk_glade_catalog_init (const gchar *catalog_name)
g_type_ensure (GTK_TYPE_COLOR_PLANE);
g_type_ensure (GTK_TYPE_COLOR_SCALE);
g_type_ensure (_gtk_scale_button_scale_get_type ());
- g_type_ensure (_shortcuts_pane_model_filter_get_type ());
#ifdef G_OS_UNIX
g_type_ensure (GTK_TYPE_PRINTER_OPTION_WIDGET);
diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list
index 14d0519023..31977fe845 100644
--- a/gtk/gtkmarshalers.list
+++ b/gtk/gtkmarshalers.list
@@ -83,12 +83,15 @@ VOID:OBJECT,BOOLEAN
VOID:OBJECT,BOXED,BOXED
VOID:OBJECT,BOXED,UINT,UINT
VOID:OBJECT,BOXED,BOOLEAN,BOOLEAN
+VOID:OBJECT,ENUM
+VOID:OBJECT,FLAGS
VOID:OBJECT,INT
VOID:OBJECT,INT,OBJECT
VOID:OBJECT,INT,INT
VOID:OBJECT,INT,INT,BOXED,UINT,UINT
VOID:OBJECT,OBJECT
VOID:OBJECT,POINTER
+VOID:OBJECT,POINTER,INT
VOID:OBJECT,STRING
VOID:OBJECT,STRING,STRING
VOID:OBJECT,UINT
@@ -97,6 +100,7 @@ VOID:OBJECT,STRING
VOID:OBJECT,OBJECT,STRING
VOID:OBJECT,OBJECT,OBJECT
VOID:OBJECT,OBJECT,BOXED,STRING
+VOID:OBJECT,OBJECT,POINTER,POINTER
VOID:POINTER
VOID:POINTER,INT
VOID:POINTER,BOOLEAN
@@ -120,3 +124,7 @@ VOID:UINT,UINT
VOID:VOID
OBJECT:OBJECT,INT,INT
VOID:POINTER,POINTER,POINTER,POINTER,STRING
+VOID:OBJECT,STRING,POINTER,POINTER
+INT:INT
+VOID:POINTER,STRING,INT
+INT:OBJECT,OBJECT,POINTER
diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c
new file mode 100644
index 0000000000..98cd47f1d8
--- /dev/null
+++ b/gtk/gtkplacessidebar.c
@@ -0,0 +1,4335 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * GtkPlacesSidebar - sidebar widget for places in the filesystem
+ *
+ * This code comes from Nautilus, GNOME's file manager.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Mr Jamie McCracken (jamiemcc at blueyonder dot co dot uk)
+ * Cosimo Cecchi <cosimoc@gnome.org>
+ * Federico Mena Quintero <federico@gnome.org>
+ *
+ */
+
+/* TODO:
+ *
+ * * Fix instances of "#if DO_NOT_COMPILE"
+ *
+ * * Fix instances of "#if 0"
+ *
+ * * Fix FIXMEs
+ *
+ * * Grep for "NULL-GError" and see if they should be taken care of
+ *
+ * * Although we do g_mount_unmount_with_operation(), Nautilus used to do
+ * nautilus_file_operations_unmount_mount_full() to unmount a volume. With
+ * that, Nautilus does the "volume has trash, empty it first?" dance. Cosimo
+ * suggests that this logic should be part of GtkMountOperation, which can
+ * have Unix-specific code for emptying trash.
+ *
+ * * Sync nautilus commit 17a85b78acc78b573c2e1776b348ed348e19adb7
+ *
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "gdk/gdkkeysyms.h"
+#include "gtkbookmarksmanager.h"
+#include "gtkcelllayout.h"
+#include "gtkcellrenderertext.h"
+#include "gtkcellrendererpixbuf.h"
+#include "gtkfilechooserprivate.h"
+#include "gtkicontheme.h"
+#include "gtkimagemenuitem.h"
+#include "gtkintl.h"
+#include "gtkmain.h"
+#include "gtkmarshalers.h"
+#include "gtkmenuitem.h"
+#include "gtkmountoperation.h"
+#include "gtkplacessidebar.h"
+#include "gtkscrolledwindow.h"
+#include "gtkseparatormenuitem.h"
+#include "gtksettings.h"
+#include "gtkstock.h"
+#include "gtktrashmonitor.h"
+#include "gtktreeselection.h"
+#include "gtktreednd.h"
+#include "gtktypebuiltins.h"
+#include "gtkwindow.h"
+
+/**
+ * SECTION:gtkplacessidebar
+ * @Short_description: Sidebar that displays frequently-used places in the file system
+ * @Title: GtkPlacesSidebar
+ * @See_also: #GtkFileChooser
+ *
+ * #GtkPlacesSidebar is a widget that displays a list of frequently-used places in the
+ * file system: the user's home directory, the user's bookmarks, and volumes and drives.
+ * This widget is used as a sidebar in #GtkFileChooser and may be used by file managers
+ * and similar programs.
+ *
+ * The places sidebar displays drives and volumes, and will automatically mount
+ * or unmount them when the user selects them.
+ *
+ * Applications can hook to various signals in the places sidebar to customize
+ * its behavior. For example, they can add extra commands to the context menu
+ * of the sidebar.
+ *
+ * While bookmarks are completely in control of the user, the places sidebar also
+ * allows individual applications to provide extra shortcut folders that are unique
+ * to each application. For example, a Paint program may want to add a shortcut
+ * for a Clipart folder. You can do this with gtk_places_sidebar_add_shortcut().
+ *
+ * To make use of the places sidebar, an application at least needs to connect
+ * to the #GtkPlacesSidebar::open-location signal. This is emitted when the
+ * user selects in the sidebar a location to open. The application should also
+ * call gtk_places_sidebar_set_location() when it changes the currently-viewed
+ * location.
+ */
+
+#define EJECT_BUTTON_XPAD 6
+#define ICON_CELL_XPAD 6
+
+#define DO_NOT_COMPILE 0
+
+struct _GtkPlacesSidebar {
+ GtkScrolledWindow parent;
+
+ GtkTreeView *tree_view;
+ GtkCellRenderer *eject_icon_cell_renderer;
+ GtkListStore *store;
+ GtkBookmarksManager *bookmarks_manager;
+ GVolumeMonitor *volume_monitor;
+ GtkTrashMonitor *trash_monitor;
+
+ gulong trash_monitor_changed_id;
+
+ gboolean devices_header_added;
+ gboolean bookmarks_header_added;
+
+ /* DnD */
+ GList *drag_list; /* list of GFile */
+ gboolean drag_data_received;
+ int drag_data_info;
+ gboolean drop_occured;
+
+ GtkWidget *popup_menu;
+
+ /* volume mounting - delayed open process */
+ gboolean mounting;
+ GtkPlacesOpenFlags go_to_after_mount_open_flags;
+
+ GSList *shortcuts;
+
+ GDBusProxy *hostnamed_proxy;
+ GCancellable *hostnamed_cancellable;
+ char *hostname;
+
+ GtkPlacesOpenFlags open_flags;
+
+ guint show_desktop : 1;
+};
+
+struct _GtkPlacesSidebarClass {
+ GtkScrolledWindowClass parent;
+
+ void (* open_location) (GtkPlacesSidebar *sidebar,
+ GFile *location,
+ GtkPlacesOpenFlags open_flags);
+ void (* populate_popup) (GtkPlacesSidebar *sidebar,
+ GtkMenu *menu,
+ GFile *selected_item);
+ void (* show_error_message) (GtkPlacesSidebar *sidebar,
+ const char *primary,
+ const char *secondary);
+ GdkDragAction (* drag_action_requested) (GtkPlacesSidebar *sidebar,
+ GdkDragContext *context,
+ GFile *dest_file,
+ GList *source_file_list);
+ GdkDragAction (* drag_action_ask) (GtkPlacesSidebar *sidebar,
+ GdkDragAction actions);
+ void (* drag_perform_drop) (GtkPlacesSidebar *sidebar,
+ GFile *dest_file,
+ GList *source_file_list,
+ GdkDragAction action);
+};
+
+enum {
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE,
+ PLACES_SIDEBAR_COLUMN_URI,
+ PLACES_SIDEBAR_COLUMN_DRIVE,
+ PLACES_SIDEBAR_COLUMN_VOLUME,
+ PLACES_SIDEBAR_COLUMN_MOUNT,
+ PLACES_SIDEBAR_COLUMN_NAME,
+ PLACES_SIDEBAR_COLUMN_GICON,
+ PLACES_SIDEBAR_COLUMN_INDEX,
+ PLACES_SIDEBAR_COLUMN_EJECT,
+ PLACES_SIDEBAR_COLUMN_NO_EJECT,
+ PLACES_SIDEBAR_COLUMN_BOOKMARK,
+ PLACES_SIDEBAR_COLUMN_TOOLTIP,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE,
+ PLACES_SIDEBAR_COLUMN_HEADING_TEXT,
+
+ PLACES_SIDEBAR_COLUMN_COUNT
+};
+
+typedef enum {
+ PLACES_BUILT_IN,
+ PLACES_XDG_DIR,
+ PLACES_MOUNTED_VOLUME,
+ PLACES_BOOKMARK,
+ PLACES_HEADING,
+} PlaceType;
+
+typedef enum {
+ SECTION_DEVICES,
+ SECTION_BOOKMARKS,
+ SECTION_COMPUTER,
+ SECTION_NETWORK,
+} SectionType;
+
+enum {
+ OPEN_LOCATION,
+ POPULATE_POPUP,
+ SHOW_ERROR_MESSAGE,
+ DRAG_ACTION_REQUESTED,
+ DRAG_ACTION_ASK,
+ DRAG_PERFORM_DROP,
+ LAST_SIGNAL,
+};
+
+enum {
+ PROP_LOCATION = 1,
+ PROP_OPEN_FLAGS,
+ PROP_SHOW_DESKTOP,
+ NUM_PROPERTIES,
+};
+
+/* Names for themed icons */
+#define ICON_NAME_HOME "user-home-symbolic"
+#define ICON_NAME_DESKTOP "user-desktop"
+#define ICON_NAME_FILESYSTEM "drive-harddisk-symbolic"
+#define ICON_NAME_EJECT "media-eject-symbolic"
+#define ICON_NAME_NETWORK "network-workgroup-symbolic"
+
+#define ICON_NAME_FOLDER_DESKTOP "user-desktop"
+#define ICON_NAME_FOLDER_DOCUMENTS "folder-documents-symbolic"
+#define ICON_NAME_FOLDER_DOWNLOAD "folder-download-symbolic"
+#define ICON_NAME_FOLDER_MUSIC "folder-music-symbolic"
+#define ICON_NAME_FOLDER_PICTURES "folder-pictures-symbolic"
+#define ICON_NAME_FOLDER_PUBLIC_SHARE "folder-publicshare-symbolic"
+#define ICON_NAME_FOLDER_TEMPLATES "folder-templates-symbolic"
+#define ICON_NAME_FOLDER_VIDEOS "folder-videos-symbolic"
+#define ICON_NAME_FOLDER_SAVED_SEARCH "folder-saved-search-symbolic"
+
+static guint places_sidebar_signals [LAST_SIGNAL] = { 0 };
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
+
+static void open_selected_bookmark (GtkPlacesSidebar *sidebar,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkPlacesOpenFlags open_flags);
+static gboolean eject_or_unmount_bookmark (GtkPlacesSidebar *sidebar,
+ GtkTreePath *path);
+static gboolean eject_or_unmount_selection (GtkPlacesSidebar *sidebar);
+static void check_unmount_and_eject (GMount *mount,
+ GVolume *volume,
+ GDrive *drive,
+ gboolean *show_unmount,
+ gboolean *show_eject);
+
+/* Identifiers for target types */
+enum {
+ GTK_TREE_MODEL_ROW,
+ TEXT_URI_LIST
+};
+
+/* Target types for dragging from the shortcuts list */
+static const GtkTargetEntry dnd_source_targets[] = {
+ { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
+};
+
+/* Target types for dropping into the shortcuts list */
+static const GtkTargetEntry dnd_drop_targets [] = {
+ { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
+ { "text/uri-list", 0, TEXT_URI_LIST }
+};
+
+/* Drag and drop interface declarations */
+typedef struct {
+ GtkListStore parent;
+
+ GtkPlacesSidebar *sidebar;
+} ShortcutsModel;
+
+typedef struct {
+ GtkListStoreClass parent_class;
+} ShortcutsModelClass;
+
+#define SHORTCUTS_MODEL_TYPE (shortcuts_model_get_type ())
+#define SHORTCUTS_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_MODEL_TYPE, ShortcutsModel))
+
+static GType shortcuts_model_get_type (void);
+static void shortcuts_model_drag_source_iface_init (GtkTreeDragSourceIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (ShortcutsModel,
+ shortcuts_model,
+ GTK_TYPE_LIST_STORE,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+ shortcuts_model_drag_source_iface_init));
+
+static GtkListStore *shortcuts_model_new (GtkPlacesSidebar *sidebar);
+
+G_DEFINE_TYPE (GtkPlacesSidebar, gtk_places_sidebar, GTK_TYPE_SCROLLED_WINDOW);
+
+static void
+emit_open_location (GtkPlacesSidebar *sidebar, GFile *location, GtkPlacesOpenFlags open_flags)
+{
+ if ((open_flags & sidebar->open_flags) == 0)
+ open_flags = GTK_PLACES_OPEN_NORMAL;
+
+ g_signal_emit (sidebar, places_sidebar_signals[OPEN_LOCATION], 0,
+ location, open_flags);
+}
+
+static void
+emit_populate_popup (GtkPlacesSidebar *sidebar, GtkMenu *menu, GFile *selected_item)
+{
+ g_signal_emit (sidebar, places_sidebar_signals[POPULATE_POPUP], 0,
+ menu, selected_item);
+}
+
+static void
+emit_show_error_message (GtkPlacesSidebar *sidebar, const char *primary, const char *secondary)
+{
+ g_signal_emit (sidebar, places_sidebar_signals[SHOW_ERROR_MESSAGE], 0,
+ primary, secondary);
+}
+
+static GdkDragAction
+emit_drag_action_requested (GtkPlacesSidebar *sidebar,
+ GdkDragContext *context,
+ GFile *dest_file,
+ GList *source_file_list)
+{
+ GdkDragAction ret_action;
+
+ ret_action = 0;
+
+ g_signal_emit (sidebar, places_sidebar_signals[DRAG_ACTION_REQUESTED], 0,
+ context,
+ dest_file,
+ source_file_list,
+ &ret_action);
+
+ return ret_action;
+}
+
+static GdkDragAction
+emit_drag_action_ask (GtkPlacesSidebar *sidebar,
+ GdkDragAction actions)
+{
+ GdkDragAction ret_action;
+
+ ret_action = 0;
+
+ g_signal_emit (sidebar, places_sidebar_signals[DRAG_ACTION_ASK], 0,
+ actions,
+ &ret_action);
+ return ret_action;
+}
+
+static void
+emit_drag_perform_drop (GtkPlacesSidebar *sidebar,
+ GFile *dest_file,
+ GList *source_file_list,
+ GdkDragAction action)
+{
+ g_signal_emit (sidebar, places_sidebar_signals[DRAG_PERFORM_DROP], 0,
+ dest_file,
+ source_file_list,
+ action);
+}
+
+static gint
+get_icon_size (GtkPlacesSidebar *sidebar)
+{
+ GtkSettings *settings;
+ gint width, height;
+
+ settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (sidebar)));
+
+ if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, &width, &height))
+ return MAX (width, height);
+ else
+ return 16;
+}
+
+static GtkTreeIter
+add_heading (GtkPlacesSidebar *sidebar,
+ SectionType section_type,
+ const gchar *title)
+{
+ GtkTreeIter iter;
+
+ gtk_list_store_append (sidebar->store, &iter);
+ gtk_list_store_set (sidebar->store, &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, PLACES_HEADING,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, section_type,
+ PLACES_SIDEBAR_COLUMN_HEADING_TEXT, title,
+ PLACES_SIDEBAR_COLUMN_EJECT, FALSE,
+ PLACES_SIDEBAR_COLUMN_NO_EJECT, TRUE,
+ -1);
+
+ return iter;
+}
+
+static void
+check_heading_for_section (GtkPlacesSidebar *sidebar,
+ SectionType section_type)
+{
+ switch (section_type) {
+ case SECTION_DEVICES:
+ if (!sidebar->devices_header_added) {
+ add_heading (sidebar, SECTION_DEVICES,
+ _("Devices"));
+ sidebar->devices_header_added = TRUE;
+ }
+
+ break;
+ case SECTION_BOOKMARKS:
+ if (!sidebar->bookmarks_header_added) {
+ add_heading (sidebar, SECTION_BOOKMARKS,
+ _("Bookmarks"));
+ sidebar->bookmarks_header_added = TRUE;
+ }
+
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+add_place (GtkPlacesSidebar *sidebar,
+ PlaceType place_type,
+ SectionType section_type,
+ const char *name,
+ GIcon *icon,
+ const char *uri,
+ GDrive *drive,
+ GVolume *volume,
+ GMount *mount,
+ const int index,
+ const char *tooltip)
+{
+ GtkTreeIter iter;
+ gboolean show_eject, show_unmount;
+ gboolean show_eject_button;
+
+ check_heading_for_section (sidebar, section_type);
+
+ check_unmount_and_eject (mount, volume, drive,
+ &show_unmount, &show_eject);
+
+ if (show_unmount || show_eject) {
+ g_assert (place_type != PLACES_BOOKMARK);
+ }
+
+ if (mount == NULL) {
+ show_eject_button = FALSE;
+ } else {
+ show_eject_button = (show_unmount || show_eject);
+ }
+
+ gtk_list_store_append (sidebar->store, &iter);
+ gtk_list_store_set (sidebar->store, &iter,
+ PLACES_SIDEBAR_COLUMN_GICON, icon,
+ PLACES_SIDEBAR_COLUMN_NAME, name,
+ PLACES_SIDEBAR_COLUMN_URI, uri,
+ PLACES_SIDEBAR_COLUMN_DRIVE, drive,
+ PLACES_SIDEBAR_COLUMN_VOLUME, volume,
+ PLACES_SIDEBAR_COLUMN_MOUNT, mount,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, place_type,
+ PLACES_SIDEBAR_COLUMN_INDEX, index,
+ PLACES_SIDEBAR_COLUMN_EJECT, show_eject_button,
+ PLACES_SIDEBAR_COLUMN_NO_EJECT, !show_eject_button,
+ PLACES_SIDEBAR_COLUMN_BOOKMARK, place_type != PLACES_BOOKMARK,
+ PLACES_SIDEBAR_COLUMN_TOOLTIP, tooltip,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, section_type,
+ -1);
+}
+
+static GIcon *
+special_directory_get_gicon (GUserDirectory directory)
+{
+#define ICON_CASE(x) \
+ case G_USER_DIRECTORY_ ## x: \
+ return g_themed_icon_new (ICON_NAME_FOLDER_ ## x);
+
+ switch (directory) {
+
+ ICON_CASE (DOCUMENTS);
+ ICON_CASE (DOWNLOAD);
+ ICON_CASE (MUSIC);
+ ICON_CASE (PICTURES);
+ ICON_CASE (PUBLIC_SHARE);
+ ICON_CASE (TEMPLATES);
+ ICON_CASE (VIDEOS);
+
+ default:
+ return g_themed_icon_new ("folder-symbolic");
+ }
+
+#undef ICON_CASE
+}
+
+static gboolean
+recent_files_setting_is_enabled (GtkPlacesSidebar *sidebar)
+{
+ GtkSettings *settings;
+ gboolean enabled;
+
+ if (gtk_widget_has_screen (GTK_WIDGET (sidebar)))
+ settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (sidebar)));
+ else
+ settings = gtk_settings_get_default ();
+
+ g_object_get (settings, "gtk-recent-files-enabled", &enabled, NULL);
+ return enabled;
+}
+
+static gboolean
+recent_scheme_is_supported (void)
+{
+ const char * const *supported;
+ int i;
+
+ supported = g_vfs_get_supported_uri_schemes (g_vfs_get_default ());
+ if (!supported) {
+ return FALSE;
+ }
+
+ for (i = 0; supported[i] != NULL; i++) {
+ if (strcmp ("recent", supported[i]) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+should_show_recent (GtkPlacesSidebar *sidebar)
+{
+ return recent_files_setting_is_enabled (sidebar) && recent_scheme_is_supported ();
+}
+
+static void
+add_special_dirs (GtkPlacesSidebar *sidebar)
+{
+ GList *dirs;
+ int index;
+
+ dirs = NULL;
+ for (index = 0; index < G_USER_N_DIRECTORIES; index++) {
+ const char *path;
+ GFile *root;
+ GIcon *icon;
+ char *name;
+ char *mount_uri;
+ char *tooltip;
+
+ if (!_gtk_bookmarks_manager_get_is_xdg_dir_builtin (index)) {
+ continue;
+ }
+
+ path = g_get_user_special_dir (index);
+
+ /* xdg resets special dirs to the home directory in case
+ * it's not finiding what it expects. We don't want the home
+ * to be added multiple times in that weird configuration.
+ */
+ if (path == NULL
+ || g_strcmp0 (path, g_get_home_dir ()) == 0
+ || g_list_find_custom (dirs, path, (GCompareFunc) g_strcmp0) != NULL) {
+ continue;
+ }
+
+ root = g_file_new_for_path (path);
+
+ name = _gtk_bookmarks_manager_get_bookmark_label (sidebar->bookmarks_manager, root);
+ if (!name) {
+ name = g_file_get_basename (root);
+ }
+
+ icon = special_directory_get_gicon (index);
+ mount_uri = g_file_get_uri (root);
+ tooltip = g_file_get_parse_name (root);
+
+ add_place (sidebar, PLACES_XDG_DIR,
+ SECTION_COMPUTER,
+ name, icon, mount_uri,
+ NULL, NULL, NULL, 0,
+ tooltip);
+ g_free (name);
+ g_object_unref (root);
+ g_object_unref (icon);
+ g_free (mount_uri);
+ g_free (tooltip);
+
+ dirs = g_list_prepend (dirs, (char *)path);
+ }
+
+ g_list_free (dirs);
+}
+
+static char *
+get_home_directory_uri (void)
+{
+ const char *home;
+
+ home = g_get_home_dir ();
+ if (!home)
+ return NULL;
+
+ return g_strconcat ("file://", home, NULL);
+}
+
+static char *
+get_desktop_directory_uri (void)
+{
+ const char *name;
+
+ name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
+ /* "To disable a directory, point it to the homedir."
+ * See http://freedesktop.org/wiki/Software/xdg-user-dirs
+ **/
+ if (!g_strcmp0 (name, g_get_home_dir ())) {
+ return NULL;
+ } else {
+ return g_strconcat ("file://", name, NULL);
+ }
+}
+
+static void
+add_application_shortcuts (GtkPlacesSidebar *sidebar)
+{
+ GSList *l;
+
+ for (l = sidebar->shortcuts; l; l = l->next) {
+ GFile *file;
+ GFileInfo *info;
+
+ file = G_FILE (l->data);
+
+ /* FIXME: we are getting file info synchronously. We may want to do it async at some point. */
+ info = g_file_query_info (file,
+ "standard::display-name,standard::symbolic-icon",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL); /* NULL-GError */
+
+ if (info) {
+ char *uri;
+ char *tooltip;
+ const char *name;
+ GIcon *icon;
+
+ name = g_file_info_get_display_name (info);
+ icon = g_file_info_get_symbolic_icon (info);
+
+ uri = g_file_get_uri (file);
+ tooltip = g_file_get_parse_name (file);
+
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_COMPUTER,
+ name, icon, uri,
+ NULL, NULL, NULL, 0,
+ tooltip);
+
+ g_free (uri);
+ g_free (tooltip);
+
+ g_object_unref (info);
+ }
+ }
+}
+
+static gboolean
+get_selected_iter (GtkPlacesSidebar *sidebar,
+ GtkTreeIter *iter)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (sidebar->tree_view);
+
+ return gtk_tree_selection_get_selected (selection, NULL, iter);
+}
+
+static void
+update_places (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GVolumeMonitor *volume_monitor;
+ GList *mounts, *l, *ll;
+ GMount *mount;
+ GList *drives;
+ GDrive *drive;
+ GList *volumes;
+ GVolume *volume;
+ GSList *bookmarks, *sl;
+ int index;
+ char *original_uri, *mount_uri, *name, *identifier;
+ char *home_uri;
+ char *bookmark_name;
+ GIcon *icon;
+ GFile *root;
+ char *tooltip;
+ GList *network_mounts, *network_volumes;
+
+ /* save original selection */
+ if (get_selected_iter (sidebar, &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store),
+ &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &original_uri, -1);
+ } else
+ original_uri = NULL;
+
+ gtk_list_store_clear (sidebar->store);
+
+ sidebar->devices_header_added = FALSE;
+ sidebar->bookmarks_header_added = FALSE;
+
+ network_mounts = network_volumes = NULL;
+ volume_monitor = sidebar->volume_monitor;
+
+ /* add built in bookmarks */
+
+ add_heading (sidebar, SECTION_COMPUTER,
+ _("Places"));
+
+ if (should_show_recent (sidebar)) {
+ mount_uri = "recent:///"; /* No need to strdup */
+ icon = g_themed_icon_new ("document-open-recent-symbolic");
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_COMPUTER,
+ _("Recent"), icon, mount_uri,
+ NULL, NULL, NULL, 0,
+ _("Recent files"));
+ g_object_unref (icon);
+ }
+
+ /* home folder */
+ home_uri = get_home_directory_uri ();
+ icon = g_themed_icon_new (ICON_NAME_HOME);
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_COMPUTER,
+ _("Home"), icon,
+ home_uri, NULL, NULL, NULL, 0,
+ _("Open your personal folder"));
+ g_object_unref (icon);
+ g_free (home_uri);
+
+ if (sidebar->show_desktop) {
+ /* desktop */
+ mount_uri = get_desktop_directory_uri ();
+ icon = g_themed_icon_new (ICON_NAME_DESKTOP);
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_COMPUTER,
+ _("Desktop"), icon,
+ mount_uri, NULL, NULL, NULL, 0,
+ _("Open the contents of your desktop in a folder"));
+ g_object_unref (icon);
+ g_free (mount_uri);
+ }
+
+ /* XDG directories */
+ add_special_dirs (sidebar);
+
+ /* Trash */
+ mount_uri = "trash:///"; /* No need to strdup */
+ icon = _gtk_trash_monitor_get_icon (sidebar->trash_monitor);
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_COMPUTER,
+ _("Trash"), icon, mount_uri,
+ NULL, NULL, NULL, 0,
+ _("Open the trash"));
+ g_object_unref (icon);
+
+ /* Application-side shortcuts */
+ add_application_shortcuts (sidebar);
+
+ /* go through all connected drives */
+ drives = g_volume_monitor_get_connected_drives (volume_monitor);
+
+ for (l = drives; l != NULL; l = l->next) {
+ drive = l->data;
+
+ volumes = g_drive_get_volumes (drive);
+ if (volumes != NULL) {
+ for (ll = volumes; ll != NULL; ll = ll->next) {
+ volume = ll->data;
+ identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
+
+ if (g_strcmp0 (identifier, "network") == 0) {
+ g_free (identifier);
+ network_volumes = g_list_prepend (network_volumes, volume);
+ continue;
+ }
+ g_free (identifier);
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL) {
+ /* Show mounted volume in the sidebar */
+ icon = g_mount_get_symbolic_icon (mount);
+ root = g_mount_get_default_location (mount);
+ mount_uri = g_file_get_uri (root);
+ name = g_mount_get_name (mount);
+ tooltip = g_file_get_parse_name (root);
+
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_DEVICES,
+ name, icon, mount_uri,
+ drive, volume, mount, 0, tooltip);
+ g_object_unref (root);
+ g_object_unref (mount);
+ g_object_unref (icon);
+ g_free (tooltip);
+ g_free (name);
+ g_free (mount_uri);
+ } else {
+ /* Do show the unmounted volumes in the sidebar;
+ * this is so the user can mount it (in case automounting
+ * is off).
+ *
+ * Also, even if automounting is enabled, this gives a visual
+ * cue that the user should remember to yank out the media if
+ * he just unmounted it.
+ */
+ icon = g_volume_get_symbolic_icon (volume);
+ name = g_volume_get_name (volume);
+ tooltip = g_strdup_printf (_("Mount and open %s"), name);
+
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_DEVICES,
+ name, icon, NULL,
+ drive, volume, NULL, 0, tooltip);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (tooltip);
+ }
+ g_object_unref (volume);
+ }
+ g_list_free (volumes);
+ } else {
+ if (g_drive_is_media_removable (drive) && !g_drive_is_media_check_automatic (drive)) {
+ /* If the drive has no mountable volumes and we cannot detect media change.. we
+ * display the drive in the sidebar so the user can manually poll the drive by
+ * right clicking and selecting "Rescan..."
+ *
+ * This is mainly for drives like floppies where media detection doesn't
+ * work.. but it's also for human beings who like to turn off media detection
+ * in the OS to save battery juice.
+ */
+ icon = g_drive_get_symbolic_icon (drive);
+ name = g_drive_get_name (drive);
+ tooltip = g_strdup_printf (_("Mount and open %s"), name);
+
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_DEVICES,
+ name, icon, NULL,
+ drive, NULL, NULL, 0, tooltip);
+ g_object_unref (icon);
+ g_free (tooltip);
+ g_free (name);
+ }
+ }
+ g_object_unref (drive);
+ }
+ g_list_free (drives);
+
+ /* add all volumes that is not associated with a drive */
+ volumes = g_volume_monitor_get_volumes (volume_monitor);
+ for (l = volumes; l != NULL; l = l->next) {
+ volume = l->data;
+ drive = g_volume_get_drive (volume);
+ if (drive != NULL) {
+ g_object_unref (volume);
+ g_object_unref (drive);
+ continue;
+ }
+
+ identifier = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_CLASS);
+
+ if (g_strcmp0 (identifier, "network") == 0) {
+ g_free (identifier);
+ network_volumes = g_list_prepend (network_volumes, volume);
+ continue;
+ }
+ g_free (identifier);
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL) {
+ icon = g_mount_get_symbolic_icon (mount);
+ root = g_mount_get_default_location (mount);
+ mount_uri = g_file_get_uri (root);
+ tooltip = g_file_get_parse_name (root);
+ g_object_unref (root);
+ name = g_mount_get_name (mount);
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_DEVICES,
+ name, icon, mount_uri,
+ NULL, volume, mount, 0, tooltip);
+ g_object_unref (mount);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (tooltip);
+ g_free (mount_uri);
+ } else {
+ /* see comment above in why we add an icon for an unmounted mountable volume */
+ icon = g_volume_get_symbolic_icon (volume);
+ name = g_volume_get_name (volume);
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_DEVICES,
+ name, icon, NULL,
+ NULL, volume, NULL, 0, name);
+ g_object_unref (icon);
+ g_free (name);
+ }
+ g_object_unref (volume);
+ }
+ g_list_free (volumes);
+
+ /* file system root */
+
+ mount_uri = "file:///"; /* No need to strdup */
+ icon = g_themed_icon_new (ICON_NAME_FILESYSTEM);
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_DEVICES,
+ sidebar->hostname, icon,
+ mount_uri, NULL, NULL, NULL, 0,
+ _("Open the contents of the File System"));
+ g_object_unref (icon);
+
+ /* add mounts that has no volume (/etc/mtab mounts, ftp, sftp,...) */
+ mounts = g_volume_monitor_get_mounts (volume_monitor);
+
+ for (l = mounts; l != NULL; l = l->next) {
+ mount = l->data;
+ if (g_mount_is_shadowed (mount)) {
+ g_object_unref (mount);
+ continue;
+ }
+ volume = g_mount_get_volume (mount);
+ if (volume != NULL) {
+ g_object_unref (volume);
+ g_object_unref (mount);
+ continue;
+ }
+ root = g_mount_get_default_location (mount);
+
+ if (!g_file_is_native (root)) {
+ network_mounts = g_list_prepend (network_mounts, mount);
+ g_object_unref (root);
+ continue;
+ }
+
+ icon = g_mount_get_symbolic_icon (mount);
+ mount_uri = g_file_get_uri (root);
+ name = g_mount_get_name (mount);
+ tooltip = g_file_get_parse_name (root);
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_COMPUTER,
+ name, icon, mount_uri,
+ NULL, NULL, mount, 0, tooltip);
+ g_object_unref (root);
+ g_object_unref (mount);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (mount_uri);
+ g_free (tooltip);
+ }
+ g_list_free (mounts);
+
+ /* add bookmarks */
+
+ bookmarks = _gtk_bookmarks_manager_list_bookmarks (sidebar->bookmarks_manager);
+
+ for (sl = bookmarks, index = 0; sl; sl = sl->next, index++) {
+ GFileInfo *info;
+
+ root = sl->data;
+
+#if 0
+ /* FIXME: remove this? If we *do* show bookmarks for nonexistent files, the user will eventually clean them up */
+ if (!nautilus_bookmark_get_exists (bookmark)) {
+ continue;
+ }
+#endif
+
+ if (_gtk_bookmarks_manager_get_is_builtin (sidebar->bookmarks_manager, root)) {
+ continue;
+ }
+
+ /* FIXME: we are getting file info synchronously. We may want to do it async at some point. */
+ info = g_file_query_info (root,
+ "standard::display-name,standard::symbolic-icon",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL); /* NULL-GError */
+
+ if (info) {
+ bookmark_name = _gtk_bookmarks_manager_get_bookmark_label (sidebar->bookmarks_manager, root);
+
+ if (bookmark_name == NULL)
+ bookmark_name = g_strdup (g_file_info_get_display_name (info));
+
+ icon = g_file_info_get_symbolic_icon (info);
+
+ mount_uri = g_file_get_uri (root);
+ tooltip = g_file_get_parse_name (root);
+
+ add_place (sidebar, PLACES_BOOKMARK,
+ SECTION_BOOKMARKS,
+ bookmark_name, icon, mount_uri,
+ NULL, NULL, NULL, index,
+ tooltip);
+
+ g_free (mount_uri);
+ g_free (tooltip);
+ g_free (bookmark_name);
+
+ g_object_unref (info);
+ }
+ }
+
+ g_slist_foreach (bookmarks, (GFunc) g_object_unref, NULL);
+ g_slist_free (bookmarks);
+
+ /* network */
+ add_heading (sidebar, SECTION_NETWORK,
+ _("Network"));
+
+ mount_uri = "network:///"; /* No need to strdup */
+ icon = g_themed_icon_new (ICON_NAME_NETWORK);
+ add_place (sidebar, PLACES_BUILT_IN,
+ SECTION_NETWORK,
+ _("Browse Network"), icon,
+ mount_uri, NULL, NULL, NULL, 0,
+ _("Browse the contents of the network"));
+ g_object_unref (icon);
+
+ network_volumes = g_list_reverse (network_volumes);
+ for (l = network_volumes; l != NULL; l = l->next) {
+ volume = l->data;
+ mount = g_volume_get_mount (volume);
+
+ if (mount != NULL) {
+ network_mounts = g_list_prepend (network_mounts, mount);
+ continue;
+ } else {
+ icon = g_volume_get_symbolic_icon (volume);
+ name = g_volume_get_name (volume);
+ tooltip = g_strdup_printf (_("Mount and open %s"), name);
+
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_NETWORK,
+ name, icon, NULL,
+ NULL, volume, NULL, 0, tooltip);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (tooltip);
+ }
+ }
+
+ g_list_free_full (network_volumes, g_object_unref);
+
+ network_mounts = g_list_reverse (network_mounts);
+ for (l = network_mounts; l != NULL; l = l->next) {
+ mount = l->data;
+ root = g_mount_get_default_location (mount);
+ icon = g_mount_get_symbolic_icon (mount);
+ mount_uri = g_file_get_uri (root);
+ name = g_mount_get_name (mount);
+ tooltip = g_file_get_parse_name (root);
+ add_place (sidebar, PLACES_MOUNTED_VOLUME,
+ SECTION_NETWORK,
+ name, icon, mount_uri,
+ NULL, NULL, mount, 0, tooltip);
+ g_object_unref (root);
+ g_object_unref (mount);
+ g_object_unref (icon);
+ g_free (name);
+ g_free (mount_uri);
+ g_free (tooltip);
+ }
+
+ g_list_free_full (network_mounts, g_object_unref);
+
+ /* restore original selection */
+ if (original_uri) {
+ GFile *restore;
+
+ restore = g_file_new_for_uri (original_uri);
+ gtk_places_sidebar_set_location (sidebar, restore);
+ g_object_unref (restore);
+
+ g_free (original_uri);
+ }
+}
+
+static void
+mount_added_callback (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+mount_removed_callback (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+mount_changed_callback (GVolumeMonitor *volume_monitor,
+ GMount *mount,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+volume_added_callback (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+volume_removed_callback (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+volume_changed_callback (GVolumeMonitor *volume_monitor,
+ GVolume *volume,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+drive_disconnected_callback (GVolumeMonitor *volume_monitor,
+ GDrive *drive,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+drive_connected_callback (GVolumeMonitor *volume_monitor,
+ GDrive *drive,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static void
+drive_changed_callback (GVolumeMonitor *volume_monitor,
+ GDrive *drive,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+static gboolean
+over_eject_button (GtkPlacesSidebar *sidebar,
+ gint x,
+ gint y,
+ GtkTreePath **path)
+{
+ GtkTreeViewColumn *column;
+ int width, x_offset, hseparator;
+ int eject_button_size;
+ gboolean show_eject;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ *path = NULL;
+ model = gtk_tree_view_get_model (sidebar->tree_view);
+
+ if (gtk_tree_view_get_path_at_pos (sidebar->tree_view,
+ x, y,
+ path, &column, NULL, NULL)) {
+
+ gtk_tree_model_get_iter (model, &iter, *path);
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_EJECT, &show_eject,
+ -1);
+
+ if (!show_eject) {
+ goto out;
+ }
+
+
+ gtk_widget_style_get (GTK_WIDGET (sidebar->tree_view),
+ "horizontal-separator", &hseparator,
+ NULL);
+
+ /* Reload cell attributes for this particular row */
+ gtk_tree_view_column_cell_set_cell_data (column,
+ model, &iter, FALSE, FALSE);
+
+ gtk_tree_view_column_cell_get_position (column,
+ sidebar->eject_icon_cell_renderer,
+ &x_offset, &width);
+
+ eject_button_size = get_icon_size (sidebar);
+
+ /* This is kinda weird, but we have to do it to workaround gtk+ expanding
+ * the eject cell renderer (even thought we told it not to) and we then
+ * had to set it right-aligned */
+ x_offset += width - hseparator - EJECT_BUTTON_XPAD - eject_button_size;
+
+ if (x - x_offset >= 0 &&
+ x - x_offset <= eject_button_size) {
+ return TRUE;
+ }
+ }
+
+ out:
+ if (*path != NULL) {
+ gtk_tree_path_free (*path);
+ *path = NULL;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+clicked_eject_button (GtkPlacesSidebar *sidebar,
+ GtkTreePath **path)
+{
+ GdkEvent *event = gtk_get_current_event ();
+ GdkEventButton *button_event = (GdkEventButton *) event;
+
+ if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_BUTTON_RELEASE) &&
+ over_eject_button (sidebar, button_event->x, button_event->y, path)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+pos_is_into_or_before (GtkTreeViewDropPosition pos)
+{
+ return (pos == GTK_TREE_VIEW_DROP_BEFORE || pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE);
+}
+
+/* Computes the appropriate row and position for dropping */
+static gboolean
+compute_drop_position (GtkTreeView *tree_view,
+ int x,
+ int y,
+ GtkTreePath **path,
+ GtkTreeViewDropPosition *pos,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ PlaceType place_type;
+ SectionType section_type;
+ gboolean drop_possible;
+
+ if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
+ x, y,
+ path, pos)) {
+ return FALSE;
+ }
+
+ model = gtk_tree_view_get_model (tree_view);
+
+ gtk_tree_model_get_iter (model, &iter, *path);
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
+ -1);
+
+ drop_possible = TRUE;
+
+ /* Never drop on headings, but special case the bookmarks heading,
+ * so we can drop bookmarks in between it and the first bookmark.
+ */
+ if (place_type == PLACES_HEADING
+ && section_type != SECTION_BOOKMARKS)
+ drop_possible = FALSE;
+
+ /* Dragging a bookmark? */
+ if (sidebar->drag_data_received
+ && sidebar->drag_data_info == GTK_TREE_MODEL_ROW) {
+ /* Don't allow reordering bookmarks into non-bookmark areas */
+ if (section_type != SECTION_BOOKMARKS)
+ drop_possible = FALSE;
+
+ /* Bookmarks can only be reordered. Disallow dropping directly into them; only allow dropping between them. */
+ if (place_type == PLACES_HEADING) {
+ if (pos_is_into_or_before (*pos))
+ drop_possible = FALSE;
+ else
+ *pos = GTK_TREE_VIEW_DROP_AFTER;
+ } else {
+ if (pos_is_into_or_before (*pos))
+ *pos = GTK_TREE_VIEW_DROP_BEFORE;
+ else
+ *pos = GTK_TREE_VIEW_DROP_AFTER;
+ }
+ } else {
+ /* Dragging a file */
+
+ /* Outside the bookmarks section, URIs can only be dropped
+ * directly into places items. Inside the bookmarks section,
+ * they can be dropped between items (to create new bookmarks)
+ * or in items themselves (to request a move/copy file
+ * operation).
+ */
+ if (section_type != SECTION_BOOKMARKS)
+ *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
+ else {
+ if (place_type == PLACES_HEADING) {
+ if (pos_is_into_or_before (*pos))
+ drop_possible = FALSE;
+ else
+ *pos = GTK_TREE_VIEW_DROP_AFTER;
+ }
+ }
+ }
+
+ /* Disallow drops on recent:/// */
+ if (place_type == PLACES_BUILT_IN) {
+ char *uri;
+
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ if (strcmp (uri, "recent:///") == 0)
+ drop_possible = FALSE;
+
+ g_free (uri);
+ }
+
+ if (!drop_possible) {
+ gtk_tree_path_free (*path);
+ *path = NULL;
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+get_drag_data (GtkTreeView *tree_view,
+ GdkDragContext *context,
+ unsigned int time)
+{
+ GdkAtom target;
+
+ target = gtk_drag_dest_find_target (GTK_WIDGET (tree_view),
+ context,
+ NULL);
+
+ if (target == GDK_NONE) {
+ return FALSE;
+ }
+
+ gtk_drag_get_data (GTK_WIDGET (tree_view),
+ context, target, time);
+
+ return TRUE;
+}
+
+static void
+free_drag_data (GtkPlacesSidebar *sidebar)
+{
+ sidebar->drag_data_received = FALSE;
+
+ if (sidebar->drag_list) {
+ g_list_free_full (sidebar->drag_list, g_object_unref);
+ sidebar->drag_list = NULL;
+ }
+}
+
+static gboolean
+drag_motion_callback (GtkTreeView *tree_view,
+ GdkDragContext *context,
+ int x,
+ int y,
+ unsigned int time,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreePath *path;
+ GtkTreeViewDropPosition pos;
+ int action;
+ GtkTreeIter iter;
+ gboolean res;
+
+ action = 0;
+
+ if (!sidebar->drag_data_received) {
+ if (!get_drag_data (tree_view, context, time)) {
+ goto out;
+ }
+ }
+
+ path = NULL;
+ res = compute_drop_position (tree_view, x, y, &path, &pos, sidebar);
+
+ if (!res) {
+ goto out;
+ }
+
+ if (sidebar->drag_data_received &&
+ sidebar->drag_data_info == GTK_TREE_MODEL_ROW) {
+ /* Dragging bookmarks always moves them to another position in the bookmarks list */
+ action = GDK_ACTION_MOVE;
+ } else {
+ /* URIs are being dragged. See if the caller wants to handle a
+ * file move/copy operation itself, or if we should only try to
+ * create bookmarks out of the dragged URIs.
+ */
+ if (sidebar->drag_list != NULL) {
+ SectionType section_type;
+ PlaceType place_type;
+ gboolean drop_as_bookmarks;
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store),
+ &iter, path);
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store),
+ &iter,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ -1);
+
+ drop_as_bookmarks = FALSE;
+
+ if (section_type == SECTION_BOOKMARKS) {
+ if (pos == GTK_TREE_VIEW_DROP_BEFORE || pos == GTK_TREE_VIEW_DROP_AFTER) {
+ action = GDK_ACTION_COPY;
+ drop_as_bookmarks = TRUE;
+ }
+ }
+
+ if (!drop_as_bookmarks) {
+ char *uri;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store),
+ &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ if (uri != NULL) {
+ GFile *dest_file = g_file_new_for_uri (uri);
+
+ action = emit_drag_action_requested (sidebar, context, dest_file, sidebar->drag_list);
+
+ g_object_unref (dest_file);
+ g_free (uri);
+ } /* uri may be NULL for unmounted volumes, for example, so we don't allow drops there */
+ }
+ }
+ }
+
+ out:
+ if (action != 0)
+ gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
+ else
+ gtk_tree_view_set_drag_dest_row (tree_view, NULL, pos);
+
+ if (path != NULL) {
+ gtk_tree_path_free (path);
+ }
+
+ g_signal_stop_emission_by_name (tree_view, "drag-motion");
+
+ gdk_drag_status (context, action, time);
+
+ return TRUE;
+}
+
+static void
+drag_leave_callback (GtkTreeView *tree_view,
+ GdkDragContext *context,
+ unsigned int time,
+ GtkPlacesSidebar *sidebar)
+{
+ free_drag_data (sidebar);
+ gtk_tree_view_set_drag_dest_row (tree_view, NULL, 0);
+ g_signal_stop_emission_by_name (tree_view, "drag-leave");
+}
+
+/* Takes an array of URIs and turns it into a list of GFile */
+static GList *
+build_file_list_from_uris (const char **uris)
+{
+ GList *result;
+ int i;
+
+ result = NULL;
+ for (i = 0; uris[i]; i++) {
+ GFile *file;
+
+ file = g_file_new_for_uri (uris[i]);
+ result = g_list_prepend (result, file);
+ }
+
+ return g_list_reverse (result);
+}
+
+/* Reorders the selected bookmark to the specified position */
+static void
+reorder_bookmarks (GtkPlacesSidebar *sidebar,
+ int new_position)
+{
+ GtkTreeIter iter;
+ char *uri;
+ GFile *file;
+
+ /* Get the selected path */
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ file = g_file_new_for_uri (uri);
+ _gtk_bookmarks_manager_reorder_bookmark (sidebar->bookmarks_manager, file, new_position, NULL); /* NULL-GError */
+
+ g_object_unref (file);
+ g_free (uri);
+}
+
+/* Creates bookmarks for the specified files at the given position in the bookmarks list */
+static void
+drop_files_as_bookmarks (GtkPlacesSidebar *sidebar,
+ GList *files,
+ int position)
+{
+ GList *l;
+
+ for (l = files; l; l = l->next) {
+ GFile *f = G_FILE (l->data);
+
+ _gtk_bookmarks_manager_insert_bookmark (sidebar->bookmarks_manager, f, position++, NULL); /* NULL-GError */
+ }
+}
+
+static void
+drag_data_received_callback (GtkWidget *widget,
+ GdkDragContext *context,
+ int x,
+ int y,
+ GtkSelectionData *selection_data,
+ unsigned int info,
+ unsigned int time,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeView *tree_view;
+ GtkTreePath *tree_path;
+ GtkTreeViewDropPosition tree_pos;
+ GtkTreeIter iter;
+ int position;
+ GtkTreeModel *model;
+ PlaceType place_type;
+ SectionType section_type;
+ gboolean success;
+
+ tree_view = GTK_TREE_VIEW (widget);
+
+ if (!sidebar->drag_data_received) {
+ if (gtk_selection_data_get_target (selection_data) != GDK_NONE &&
+ info == TEXT_URI_LIST) {
+ char **uris;
+
+ uris = gtk_selection_data_get_uris (selection_data);
+ sidebar->drag_list = build_file_list_from_uris ((const char **) uris);
+ g_strfreev (uris);
+ } else {
+ sidebar->drag_list = NULL;
+ }
+ sidebar->drag_data_received = TRUE;
+ sidebar->drag_data_info = info;
+ }
+
+ g_signal_stop_emission_by_name (widget, "drag-data-received");
+
+ if (!sidebar->drop_occured) {
+ return;
+ }
+
+ /* Compute position */
+ success = compute_drop_position (tree_view, x, y, &tree_path, &tree_pos, sidebar);
+ if (!success) {
+ goto out;
+ }
+
+ success = FALSE;
+
+ if (sidebar->drag_data_info == GTK_TREE_MODEL_ROW) {
+ /* A bookmark got reordered */
+
+ model = gtk_tree_view_get_model (tree_view);
+
+ if (!gtk_tree_model_get_iter (model, &iter, tree_path)) {
+ goto out;
+ }
+
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ PLACES_SIDEBAR_COLUMN_INDEX, &position,
+ -1);
+
+ if (section_type != SECTION_BOOKMARKS) {
+ goto out;
+ }
+
+ if (place_type == PLACES_HEADING)
+ position = 0;
+ else if (tree_pos == GTK_TREE_VIEW_DROP_AFTER)
+ position++;
+
+ reorder_bookmarks (sidebar, position);
+ success = TRUE;
+ } else {
+ /* Dropping URIs! */
+
+ GdkDragAction real_action;
+ char **uris;
+ GList *source_file_list;
+
+ /* file transfer requested */
+ real_action = gdk_drag_context_get_selected_action (context);
+
+ if (real_action == GDK_ACTION_ASK)
+ real_action = emit_drag_action_ask (sidebar, gdk_drag_context_get_actions (context));
+
+ if (real_action > 0) {
+ char *uri;
+ GFile *dest_file;
+ gboolean drop_as_bookmarks;
+
+ model = gtk_tree_view_get_model (tree_view);
+
+ gtk_tree_model_get_iter (model, &iter, tree_path);
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ PLACES_SIDEBAR_COLUMN_INDEX, &position,
+ -1);
+
+ drop_as_bookmarks = FALSE;
+
+ uris = gtk_selection_data_get_uris (selection_data);
+ source_file_list = build_file_list_from_uris ((const char **) uris);
+
+ if (section_type == SECTION_BOOKMARKS) {
+ if (place_type == PLACES_HEADING) {
+ position = 0;
+ tree_pos = GTK_TREE_VIEW_DROP_BEFORE;
+ }
+
+ if (tree_pos == GTK_TREE_VIEW_DROP_AFTER)
+ position++;
+
+ if (tree_pos == GTK_TREE_VIEW_DROP_BEFORE
+ || tree_pos == GTK_TREE_VIEW_DROP_AFTER) {
+ drop_files_as_bookmarks (sidebar, source_file_list, position);
+ success = TRUE;
+ drop_as_bookmarks = TRUE;
+ }
+ }
+
+ if (!drop_as_bookmarks) {
+ gtk_tree_model_get_iter (model, &iter, tree_path);
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ dest_file = g_file_new_for_uri (uri);
+
+ emit_drag_perform_drop (sidebar, dest_file, source_file_list, real_action);
+ success = TRUE;
+
+ g_object_unref (dest_file);
+ g_free (uri);
+ }
+
+ g_list_free_full (source_file_list, g_object_unref);
+ g_strfreev (uris);
+ }
+ }
+
+out:
+ sidebar->drop_occured = FALSE;
+ free_drag_data (sidebar);
+ gtk_drag_finish (context, success, FALSE, time);
+
+ gtk_tree_path_free (tree_path);
+}
+
+static gboolean
+drag_drop_callback (GtkTreeView *tree_view,
+ GdkDragContext *context,
+ int x,
+ int y,
+ unsigned int time,
+ GtkPlacesSidebar *sidebar)
+{
+ gboolean retval = FALSE;
+ sidebar->drop_occured = TRUE;
+ retval = get_drag_data (tree_view, context, time);
+ g_signal_stop_emission_by_name (tree_view, "drag-drop");
+ return retval;
+}
+
+/* Callback used when the file list's popup menu is detached */
+static void
+bookmarks_popup_menu_detach_cb (GtkWidget *attach_widget,
+ GtkMenu *menu)
+{
+ GtkPlacesSidebar *sidebar;
+
+ sidebar = GTK_PLACES_SIDEBAR (attach_widget);
+
+ sidebar->popup_menu = NULL;
+}
+static void
+check_unmount_and_eject (GMount *mount,
+ GVolume *volume,
+ GDrive *drive,
+ gboolean *show_unmount,
+ gboolean *show_eject)
+{
+ *show_unmount = FALSE;
+ *show_eject = FALSE;
+
+ if (drive != NULL) {
+ *show_eject = g_drive_can_eject (drive);
+ }
+
+ if (volume != NULL) {
+ *show_eject |= g_volume_can_eject (volume);
+ }
+ if (mount != NULL) {
+ *show_eject |= g_mount_can_eject (mount);
+ *show_unmount = g_mount_can_unmount (mount) && !*show_eject;
+ }
+}
+
+static void
+check_visibility (GMount *mount,
+ GVolume *volume,
+ GDrive *drive,
+ gboolean *show_mount,
+ gboolean *show_unmount,
+ gboolean *show_eject,
+ gboolean *show_rescan,
+ gboolean *show_start,
+ gboolean *show_stop)
+{
+ *show_mount = FALSE;
+ *show_rescan = FALSE;
+ *show_start = FALSE;
+ *show_stop = FALSE;
+
+ check_unmount_and_eject (mount, volume, drive, show_unmount, show_eject);
+
+ if (drive != NULL) {
+ if (g_drive_is_media_removable (drive) &&
+ !g_drive_is_media_check_automatic (drive) &&
+ g_drive_can_poll_for_media (drive))
+ *show_rescan = TRUE;
+
+ *show_start = g_drive_can_start (drive) || g_drive_can_start_degraded (drive);
+ *show_stop = g_drive_can_stop (drive);
+
+ if (*show_stop)
+ *show_unmount = FALSE;
+ }
+
+ if (volume != NULL) {
+ if (mount == NULL)
+ *show_mount = g_volume_can_mount (volume);
+ }
+}
+
+typedef struct {
+ PlaceType type;
+ GDrive *drive;
+ GVolume *volume;
+ GMount *mount;
+ char *uri;
+} SelectionInfo;
+
+static void
+get_selection_info (GtkPlacesSidebar *sidebar, SelectionInfo *info)
+{
+ GtkTreeIter iter;
+
+ info->type = PLACES_BUILT_IN;
+ info->drive = NULL;
+ info->volume = NULL;
+ info->mount = NULL;
+ info->uri = NULL;
+
+ if (get_selected_iter (sidebar, &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &info->type,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &info->drive,
+ PLACES_SIDEBAR_COLUMN_VOLUME, &info->volume,
+ PLACES_SIDEBAR_COLUMN_MOUNT, &info->mount,
+ PLACES_SIDEBAR_COLUMN_URI, &info->uri,
+ -1);
+ }
+}
+
+static void
+free_selection_info (SelectionInfo *info)
+{
+ g_clear_object (&info->drive);
+ g_clear_object (&info->volume);
+ g_clear_object (&info->mount);
+
+ g_clear_pointer (&info->uri, g_free);
+}
+
+typedef struct {
+ GtkWidget *add_shortcut_item;
+ GtkWidget *remove_item;
+ GtkWidget *rename_item;
+ GtkWidget *separator_item;
+ GtkWidget *mount_item;
+ GtkWidget *unmount_item;
+ GtkWidget *eject_item;
+ GtkWidget *rescan_item;
+ GtkWidget *start_item;
+ GtkWidget *stop_item;
+} PopupMenuData;
+
+static void
+check_popup_sensitivity (GtkPlacesSidebar *sidebar, PopupMenuData *data, SelectionInfo *info)
+{
+ gboolean show_mount;
+ gboolean show_unmount;
+ gboolean show_eject;
+ gboolean show_rescan;
+ gboolean show_start;
+ gboolean show_stop;
+
+ gtk_widget_set_visible (data->add_shortcut_item, (info->type == PLACES_MOUNTED_VOLUME));
+
+ gtk_widget_set_sensitive (data->remove_item, (info->type == PLACES_BOOKMARK));
+ gtk_widget_set_sensitive (data->rename_item, (info->type == PLACES_BOOKMARK || info->type == PLACES_XDG_DIR));
+
+ check_visibility (info->mount, info->volume, info->drive,
+ &show_mount, &show_unmount, &show_eject, &show_rescan, &show_start, &show_stop);
+
+ gtk_widget_set_visible (data->separator_item, show_mount || show_unmount || show_eject);
+ gtk_widget_set_visible (data->mount_item, show_mount);
+ gtk_widget_set_visible (data->unmount_item, show_unmount);
+ gtk_widget_set_visible (data->eject_item, show_eject);
+ gtk_widget_set_visible (data->rescan_item, show_rescan);
+ gtk_widget_set_visible (data->start_item, show_start);
+ gtk_widget_set_visible (data->stop_item, show_stop);
+
+ /* Adjust start/stop items to reflect the type of the drive */
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Start"));
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Stop"));
+ if ((show_start || show_stop) && info->drive != NULL) {
+ switch (g_drive_get_start_stop_type (info->drive)) {
+ case G_DRIVE_START_STOP_TYPE_SHUTDOWN:
+ /* start() for type G_DRIVE_START_STOP_TYPE_SHUTDOWN is normally not used */
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Power On"));
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Safely Remove Drive"));
+ break;
+ case G_DRIVE_START_STOP_TYPE_NETWORK:
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Connect Drive"));
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Disconnect Drive"));
+ break;
+ case G_DRIVE_START_STOP_TYPE_MULTIDISK:
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Start Multi-disk Device"));
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Stop Multi-disk Device"));
+ break;
+ case G_DRIVE_START_STOP_TYPE_PASSWORD:
+ /* stop() for type G_DRIVE_START_STOP_TYPE_PASSWORD is normally not used */
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->start_item), _("_Unlock Drive"));
+ gtk_menu_item_set_label (GTK_MENU_ITEM (data->stop_item), _("_Lock Drive"));
+ break;
+
+ default:
+ case G_DRIVE_START_STOP_TYPE_UNKNOWN:
+ /* uses defaults set above */
+ break;
+ }
+ }
+}
+
+static void
+drive_start_from_bookmark_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = GTK_PLACES_SIDEBAR (user_data);
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to start %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+}
+
+/* Callback from g_volume_mount() */
+static void
+volume_mount_cb (GObject *source_object, GAsyncResult *result, gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
+ GVolume *volume;
+ GError *error;
+ char *primary;
+ char *name;
+ GMount *mount;
+
+ volume = G_VOLUME (source_object);
+
+ error = NULL;
+ if (!g_volume_mount_finish (volume, result, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED &&
+ error->code != G_IO_ERROR_ALREADY_MOUNTED) {
+ name = g_volume_get_name (G_VOLUME (source_object));
+ primary = g_strdup_printf (_("Unable to access “%s”"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ sidebar->mounting = FALSE;
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL) {
+ GFile *location;
+
+ location = g_mount_get_default_location (mount);
+ emit_open_location (sidebar, location, sidebar->go_to_after_mount_open_flags);
+
+ g_object_unref (G_OBJECT (location));
+ g_object_unref (G_OBJECT (mount));
+ }
+
+ g_object_unref (sidebar);
+}
+
+/* This was nautilus_file_operations_mount_volume_full() */
+static void
+mount_volume (GtkPlacesSidebar *sidebar, GVolume *volume)
+{
+ GMountOperation *mount_op;
+
+ mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+ g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
+
+ g_object_ref (sidebar);
+ g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, sidebar);
+}
+
+static void
+open_selected_bookmark (GtkPlacesSidebar *sidebar,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GtkPlacesOpenFlags open_flags)
+{
+ GFile *location;
+ char *uri;
+
+ if (!iter) {
+ return;
+ }
+
+ gtk_tree_model_get (model, iter, PLACES_SIDEBAR_COLUMN_URI, &uri, -1);
+
+ if (uri != NULL) {
+ location = g_file_new_for_uri (uri);
+ emit_open_location (sidebar, location, open_flags);
+
+ g_object_unref (location);
+ g_free (uri);
+
+ } else {
+ GDrive *drive;
+ GVolume *volume;
+
+ gtk_tree_model_get (model, iter,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
+ PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
+ -1);
+
+ if (volume != NULL && !sidebar->mounting) {
+ sidebar->mounting = TRUE;
+
+ sidebar->go_to_after_mount_open_flags = open_flags;
+
+ mount_volume (sidebar, volume);
+ } else if (volume == NULL && drive != NULL &&
+ (g_drive_can_start (drive) || g_drive_can_start_degraded (drive))) {
+ GMountOperation *mount_op;
+
+ mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+ g_drive_start (drive, G_DRIVE_START_NONE, mount_op, NULL, drive_start_from_bookmark_cb, sidebar);
+ g_object_unref (mount_op);
+ }
+
+ g_clear_object (&drive);
+ g_clear_object (&volume);
+ }
+}
+
+static void
+open_shortcut_from_menu (GtkPlacesSidebar *sidebar,
+ GtkPlacesOpenFlags open_flags)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *path = NULL;
+
+ model = gtk_tree_view_get_model (sidebar->tree_view);
+ gtk_tree_view_get_cursor (sidebar->tree_view, &path, NULL);
+
+ if (path != NULL && gtk_tree_model_get_iter (model, &iter, path)) {
+ open_selected_bookmark (sidebar, model, &iter, open_flags);
+ }
+
+ gtk_tree_path_free (path);
+}
+
+/* Callback used for the "Open" menu item in the context menu */
+static void
+open_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ open_shortcut_from_menu (sidebar, GTK_PLACES_OPEN_NORMAL);
+}
+
+/* Callback used for the "Open in new tab" menu item in the context menu */
+static void
+open_shortcut_in_new_tab_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ open_shortcut_from_menu (sidebar, GTK_PLACES_OPEN_NEW_TAB);
+}
+
+/* Callback used for the "Open in new window" menu item in the context menu */
+static void
+open_shortcut_in_new_window_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ open_shortcut_from_menu (sidebar, GTK_PLACES_OPEN_NEW_WINDOW);
+}
+
+/* Add bookmark for the selected item - just used from mount points */
+static void
+add_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ char *uri;
+ char *name;
+ GFile *location;
+
+ model = gtk_tree_view_get_model (sidebar->tree_view);
+
+ if (get_selected_iter (sidebar, &iter)) {
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ PLACES_SIDEBAR_COLUMN_NAME, &name,
+ -1);
+
+ if (uri == NULL) {
+ return;
+ }
+
+ location = g_file_new_for_uri (uri);
+ if (_gtk_bookmarks_manager_insert_bookmark (sidebar->bookmarks_manager, location, -1, NULL))
+ _gtk_bookmarks_manager_set_bookmark_label (sidebar->bookmarks_manager, location, name, NULL);
+
+ g_object_unref (location);
+ g_free (uri);
+ g_free (name);
+ }
+}
+
+/* Rename the selected bookmark */
+static void
+rename_selected_bookmark (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell;
+ GList *renderers;
+ PlaceType type;
+
+ if (get_selected_iter (sidebar, &iter)) {
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
+ -1);
+
+ if (type != PLACES_BOOKMARK && type != PLACES_XDG_DIR) {
+ return;
+ }
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
+ column = gtk_tree_view_get_column (GTK_TREE_VIEW (sidebar->tree_view), 0);
+ renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
+ cell = g_list_nth_data (renderers, 6);
+ g_list_free (renderers);
+ g_object_set (cell, "editable", TRUE, NULL);
+ gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (sidebar->tree_view),
+ path, column, cell, TRUE);
+ gtk_tree_path_free (path);
+ }
+}
+
+static void
+rename_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ rename_selected_bookmark (sidebar);
+}
+
+/* Removes the selected bookmarks */
+static void
+remove_selected_bookmarks (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ PlaceType type;
+ char *uri;
+ GFile *file;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
+ -1);
+
+ if (type != PLACES_BOOKMARK) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ file = g_file_new_for_uri (uri);
+ _gtk_bookmarks_manager_remove_bookmark (sidebar->bookmarks_manager, file, NULL);
+
+ g_object_unref (file);
+ g_free (uri);
+}
+
+static void
+remove_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ remove_selected_bookmarks (sidebar);
+}
+
+static void
+mount_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GVolume *volume;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
+ -1);
+
+ if (volume != NULL) {
+ mount_volume (sidebar, volume);
+ g_object_unref (volume);
+ }
+}
+
+/* Callback used from g_mount_unmount_with_operation() */
+static void
+unmount_mount_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
+ GMount *mount;
+ GError *error;
+
+ mount = G_MOUNT (source_object);
+
+ error = NULL;
+ if (!g_mount_unmount_with_operation_finish (mount, result, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ char *name;
+ char *primary;
+
+ name = g_mount_get_name (mount);
+ primary = g_strdup_printf (_("Unable to unmount %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+
+ g_error_free (error);
+ }
+
+ /* FIXME: we need to switch to a path that is available now - $HOME? */
+
+ g_object_unref (sidebar);
+}
+
+static void
+show_unmount_progress_cb (GMountOperation *op,
+ const gchar *message,
+ gint64 time_left,
+ gint64 bytes_left,
+ gpointer user_data)
+{
+ /* FIXME: These are just libnotify notifications, but GTK+ doesn't do notifications right now.
+ * Should we just call D-Bus directly?
+ */
+#if DO_NOT_COMPILE
+ NautilusApplication *app = NAUTILUS_APPLICATION (g_application_get_default ());
+
+ if (bytes_left == 0) {
+ nautilus_application_notify_unmount_done (app, message);
+ } else {
+ nautilus_application_notify_unmount_show (app, message);
+ }
+#endif
+}
+
+static void
+show_unmount_progress_aborted_cb (GMountOperation *op,
+ gpointer user_data)
+{
+ /* FIXME: These are just libnotify notifications, but GTK+ doesn't do notifications right now.
+ * Should we just call D-Bus directly?
+ */
+#if DO_NOT_COMPILE
+ NautilusApplication *app = NAUTILUS_APPLICATION (g_application_get_default ());
+ nautilus_application_notify_unmount_done (app, NULL);
+#endif
+}
+
+static GMountOperation *
+get_unmount_operation (GtkPlacesSidebar *sidebar)
+{
+ GMountOperation *mount_op;
+
+ mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+ g_signal_connect (mount_op, "show-unmount-progress",
+ G_CALLBACK (show_unmount_progress_cb), sidebar);
+ g_signal_connect (mount_op, "aborted",
+ G_CALLBACK (show_unmount_progress_aborted_cb), sidebar);
+
+ return mount_op;
+}
+
+static void
+do_unmount (GMount *mount,
+ GtkPlacesSidebar *sidebar)
+{
+ if (mount != NULL) {
+ GMountOperation *mount_op;
+
+ mount_op = get_unmount_operation (sidebar);
+ g_mount_unmount_with_operation (mount,
+ 0,
+ mount_op,
+ NULL,
+ unmount_mount_cb,
+ g_object_ref (sidebar));
+ g_object_unref (mount_op);
+ }
+}
+
+static void
+do_unmount_selection (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GMount *mount;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
+ -1);
+
+ if (mount != NULL) {
+ do_unmount (mount, sidebar);
+ g_object_unref (mount);
+ }
+}
+
+static void
+unmount_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ do_unmount_selection (sidebar);
+}
+
+static void
+drive_eject_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = user_data;
+
+ error = NULL;
+ if (!g_drive_eject_with_operation_finish (G_DRIVE (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to eject %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ g_object_unref (sidebar);
+}
+
+static void
+volume_eject_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = user_data;
+
+ error = NULL;
+ if (!g_volume_eject_with_operation_finish (G_VOLUME (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_volume_get_name (G_VOLUME (source_object));
+ primary = g_strdup_printf (_("Unable to eject %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ g_object_unref (sidebar);
+}
+
+static void
+mount_eject_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = user_data;
+
+ error = NULL;
+ if (!g_mount_eject_with_operation_finish (G_MOUNT (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_mount_get_name (G_MOUNT (source_object));
+ primary = g_strdup_printf (_("Unable to eject %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ g_object_unref (sidebar);
+}
+
+static void
+do_eject (GMount *mount,
+ GVolume *volume,
+ GDrive *drive,
+ GtkPlacesSidebar *sidebar)
+{
+ GMountOperation *mount_op;
+
+ mount_op = get_unmount_operation (sidebar);
+ if (mount != NULL) {
+ g_mount_eject_with_operation (mount, 0, mount_op, NULL, mount_eject_cb,
+ g_object_ref (sidebar));
+ } else if (volume != NULL) {
+ g_volume_eject_with_operation (volume, 0, mount_op, NULL, volume_eject_cb,
+ g_object_ref (sidebar));
+ } else if (drive != NULL) {
+ g_drive_eject_with_operation (drive, 0, mount_op, NULL, drive_eject_cb,
+ g_object_ref (sidebar));
+ }
+ g_object_unref (mount_op);
+}
+
+static void
+eject_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GMount *mount;
+ GVolume *volume;
+ GDrive *drive;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
+ PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
+ -1);
+
+ do_eject (mount, volume, drive, sidebar);
+}
+
+static gboolean
+eject_or_unmount_bookmark (GtkPlacesSidebar *sidebar,
+ GtkTreePath *path)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean can_unmount, can_eject;
+ GMount *mount;
+ GVolume *volume;
+ GDrive *drive;
+ gboolean ret;
+
+ model = GTK_TREE_MODEL (sidebar->store);
+
+ if (!path) {
+ return FALSE;
+ }
+ if (!gtk_tree_model_get_iter (model, &iter, path)) {
+ return FALSE;
+ }
+
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_MOUNT, &mount,
+ PLACES_SIDEBAR_COLUMN_VOLUME, &volume,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
+ -1);
+
+ ret = FALSE;
+
+ check_unmount_and_eject (mount, volume, drive, &can_unmount, &can_eject);
+ /* if we can eject, it has priority over unmount */
+ if (can_eject) {
+ do_eject (mount, volume, drive, sidebar);
+ ret = TRUE;
+ } else if (can_unmount) {
+ do_unmount (mount, sidebar);
+ ret = TRUE;
+ }
+
+ g_clear_object (&mount);
+ g_clear_object (&volume);
+ g_clear_object (&drive);
+
+ return ret;
+}
+
+static gboolean
+eject_or_unmount_selection (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GtkTreePath *path;
+ gboolean ret;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return FALSE;
+ }
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
+ if (path == NULL) {
+ return FALSE;
+ }
+
+ ret = eject_or_unmount_bookmark (sidebar, path);
+
+ gtk_tree_path_free (path);
+
+ return ret;
+}
+
+static void
+drive_poll_for_media_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = GTK_PLACES_SIDEBAR (user_data);
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to poll %s for media changes"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ /* FIXME: drive_stop_cb() gets a reffed sidebar, and unrefs it. Do we need to do the same here? */
+}
+
+static void
+rescan_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GDrive *drive;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
+ -1);
+
+ if (drive != NULL) {
+ g_drive_poll_for_media (drive, NULL, drive_poll_for_media_cb, sidebar);
+ g_object_unref (drive);
+ }
+}
+
+static void
+drive_start_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = GTK_PLACES_SIDEBAR (user_data);
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to start %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ /* FIXME: drive_stop_cb() gets a reffed sidebar, and unrefs it. Do we need to do the same here? */
+}
+
+static void
+start_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GDrive *drive;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
+ -1);
+
+ if (drive != NULL) {
+ GMountOperation *mount_op;
+
+ mount_op = gtk_mount_operation_new (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sidebar))));
+
+ g_drive_start (drive, G_DRIVE_START_NONE, mount_op, NULL, drive_start_cb, sidebar);
+
+ g_object_unref (mount_op);
+ g_object_unref (drive);
+ }
+}
+
+static void
+drive_stop_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar;
+ GError *error;
+ char *primary;
+ char *name;
+
+ sidebar = user_data;
+
+ error = NULL;
+ if (!g_drive_poll_for_media_finish (G_DRIVE (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_drive_get_name (G_DRIVE (source_object));
+ primary = g_strdup_printf (_("Unable to stop %s"), name);
+ g_free (name);
+ emit_show_error_message (sidebar, primary, error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ g_object_unref (sidebar);
+}
+
+static void
+stop_shortcut_cb (GtkMenuItem *item,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GDrive *drive;
+
+ if (!get_selected_iter (sidebar, &iter)) {
+ return;
+ }
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_DRIVE, &drive,
+ -1);
+
+ if (drive != NULL) {
+ GMountOperation *mount_op;
+
+ mount_op = get_unmount_operation (sidebar);
+ g_drive_stop (drive, G_MOUNT_UNMOUNT_NONE, mount_op, NULL, drive_stop_cb,
+ g_object_ref (sidebar));
+
+ g_object_unref (mount_op);
+ g_object_unref (drive);
+ }
+}
+
+static gboolean
+find_prev_or_next_row (GtkPlacesSidebar *sidebar,
+ GtkTreeIter *iter,
+ gboolean go_up)
+{
+ GtkTreeModel *model = GTK_TREE_MODEL (sidebar->store);
+ gboolean res;
+ int place_type;
+
+ if (go_up) {
+ res = gtk_tree_model_iter_previous (model, iter);
+ } else {
+ res = gtk_tree_model_iter_next (model, iter);
+ }
+
+ if (res) {
+ gtk_tree_model_get (model, iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ -1);
+ if (place_type == PLACES_HEADING) {
+ if (go_up) {
+ res = gtk_tree_model_iter_previous (model, iter);
+ } else {
+ res = gtk_tree_model_iter_next (model, iter);
+ }
+ }
+ }
+
+ return res;
+}
+
+static gboolean
+find_prev_row (GtkPlacesSidebar *sidebar, GtkTreeIter *iter)
+{
+ return find_prev_or_next_row (sidebar, iter, TRUE);
+}
+
+static gboolean
+find_next_row (GtkPlacesSidebar *sidebar, GtkTreeIter *iter)
+{
+ return find_prev_or_next_row (sidebar, iter, FALSE);
+}
+
+static gboolean
+gtk_places_sidebar_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (widget);
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean res;
+
+ res = get_selected_iter (sidebar, &iter);
+
+ if (!res) {
+ gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sidebar->store), &iter);
+ res = find_next_row (sidebar, &iter);
+ if (res) {
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &iter);
+ gtk_tree_view_set_cursor (sidebar->tree_view, path, NULL, FALSE);
+ gtk_tree_path_free (path);
+ }
+ }
+
+ return GTK_WIDGET_CLASS (gtk_places_sidebar_parent_class)->focus (widget, direction);
+}
+
+/* Handler for GtkWidget::key-press-event on the shortcuts list */
+static gboolean
+bookmarks_key_press_event_cb (GtkWidget *widget,
+ GdkEventKey *event,
+ GtkPlacesSidebar *sidebar)
+{
+ guint modifiers;
+ GtkTreeIter selected_iter;
+ GtkTreePath *path;
+
+ if (!get_selected_iter (sidebar, &selected_iter)) {
+ return FALSE;
+ }
+
+ modifiers = gtk_accelerator_get_default_mod_mask ();
+
+ if ((event->keyval == GDK_KEY_Return ||
+ event->keyval == GDK_KEY_KP_Enter ||
+ event->keyval == GDK_KEY_ISO_Enter ||
+ event->keyval == GDK_KEY_space)) {
+
+ GtkPlacesOpenFlags open_flags = GTK_PLACES_OPEN_NORMAL;
+
+ if ((event->state & modifiers) == GDK_SHIFT_MASK) {
+ open_flags = GTK_PLACES_OPEN_NEW_TAB;
+ } else if ((event->state & modifiers) == GDK_CONTROL_MASK) {
+ open_flags = GTK_PLACES_OPEN_NEW_WINDOW;
+ }
+
+ open_selected_bookmark (sidebar, GTK_TREE_MODEL (sidebar->store),
+ &selected_iter, open_flags);
+
+ return TRUE;
+ }
+
+ if (event->keyval == GDK_KEY_Down &&
+ (event->state & modifiers) == GDK_MOD1_MASK) {
+ return eject_or_unmount_selection (sidebar);
+ }
+
+ if (event->keyval == GDK_KEY_Up) {
+ if (find_prev_row (sidebar, &selected_iter)) {
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &selected_iter);
+ gtk_tree_view_set_cursor (sidebar->tree_view, path, NULL, FALSE);
+ gtk_tree_path_free (path);
+ }
+ return TRUE;
+ }
+
+ if (event->keyval == GDK_KEY_Down) {
+ if (find_next_row (sidebar, &selected_iter)) {
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->store), &selected_iter);
+ gtk_tree_view_set_cursor (sidebar->tree_view, path, NULL, FALSE);
+ gtk_tree_path_free (path);
+ }
+ return TRUE;
+ }
+
+ if ((event->keyval == GDK_KEY_Delete
+ || event->keyval == GDK_KEY_KP_Delete)
+ && (event->state & modifiers) == 0) {
+ remove_selected_bookmarks (sidebar);
+ return TRUE;
+ }
+
+ if ((event->keyval == GDK_KEY_F2)
+ && (event->state & modifiers) == 0) {
+ rename_selected_bookmark (sidebar);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GtkMenuItem *
+append_menu_separator (GtkMenu *menu)
+{
+ GtkWidget *menu_item;
+
+ menu_item = gtk_separator_menu_item_new ();
+ gtk_widget_show (menu_item);
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menu_item, -1);
+
+ return GTK_MENU_ITEM (menu_item);
+}
+
+/* Constructs the popup menu for the file list if needed */
+static void
+bookmarks_build_popup_menu (GtkPlacesSidebar *sidebar)
+{
+ PopupMenuData menu_data;
+ GtkWidget *item;
+ SelectionInfo sel_info;
+ GFile *file;
+
+ sidebar->popup_menu = gtk_menu_new ();
+ gtk_menu_attach_to_widget (GTK_MENU (sidebar->popup_menu),
+ GTK_WIDGET (sidebar),
+ bookmarks_popup_menu_detach_cb);
+
+ item = gtk_image_menu_item_new_with_mnemonic (_("_Open"));
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+ gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (open_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ if (sidebar->open_flags & GTK_PLACES_OPEN_NEW_TAB) {
+ item = gtk_menu_item_new_with_mnemonic (_("Open in New _Tab"));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (open_shortcut_in_new_tab_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+ }
+
+ if (sidebar->open_flags & GTK_PLACES_OPEN_NEW_WINDOW) {
+ item = gtk_menu_item_new_with_mnemonic (_("Open in New _Window"));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (open_shortcut_in_new_window_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+ }
+
+ append_menu_separator (GTK_MENU (sidebar->popup_menu));
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Add Bookmark"));
+ menu_data.add_shortcut_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (add_shortcut_cb), sidebar);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_image_menu_item_new_with_label (_("Remove"));
+ menu_data.remove_item = item;
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+ gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
+ g_signal_connect (item, "activate",
+ G_CALLBACK (remove_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_menu_item_new_with_label (_("Rename…"));
+ menu_data.rename_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (rename_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ /* Mount/Unmount/Eject menu items */
+
+ menu_data.separator_item = GTK_WIDGET (append_menu_separator (GTK_MENU (sidebar->popup_menu)));
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Mount"));
+ menu_data.mount_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (mount_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Unmount"));
+ menu_data.unmount_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (unmount_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Eject"));
+ menu_data.eject_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (eject_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Detect Media"));
+ menu_data.rescan_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (rescan_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Start"));
+ menu_data.start_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (start_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Stop"));
+ menu_data.stop_item = item;
+ g_signal_connect (item, "activate",
+ G_CALLBACK (stop_shortcut_cb), sidebar);
+ gtk_widget_show (item);
+ gtk_menu_shell_append (GTK_MENU_SHELL (sidebar->popup_menu), item);
+
+ /* Update everything! */
+
+ get_selection_info (sidebar, &sel_info);
+
+ check_popup_sensitivity (sidebar, &menu_data, &sel_info);
+
+ /* And let the caller spice things up */
+
+ if (sel_info.uri)
+ file = g_file_new_for_uri (sel_info.uri);
+ else
+ file = NULL;
+
+ emit_populate_popup (sidebar, GTK_MENU (sidebar->popup_menu), file);
+
+ g_object_unref (file);
+
+ free_selection_info (&sel_info);
+}
+
+static void
+bookmarks_popup_menu (GtkPlacesSidebar *sidebar,
+ GdkEventButton *event)
+{
+ int button;
+
+ if (sidebar->popup_menu)
+ gtk_widget_destroy (sidebar->popup_menu);
+
+ bookmarks_build_popup_menu (sidebar);
+
+ /* The event button needs to be 0 if we're popping up this menu from
+ * a button release, else a 2nd click outside the menu with any button
+ * other than the one that invoked the menu will be ignored (instead
+ * of dismissing the menu). This is a subtle fragility of the GTK menu code.
+ */
+ if (event) {
+ if (event->type == GDK_BUTTON_RELEASE)
+ button = 0;
+ else
+ button = event->button;
+ } else {
+ button = 0;
+ }
+
+ gtk_menu_popup (GTK_MENU (sidebar->popup_menu), /* menu */
+ NULL, /* parent_menu_shell */
+ NULL, /* parent_menu_item */
+ NULL, /* popup_position_func */
+ NULL, /* popup_position_user_data */
+ button, /* button */
+ event ? event->time : gtk_get_current_event_time ()); /* activate_time */
+}
+
+/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
+static gboolean
+bookmarks_popup_menu_cb (GtkWidget *widget,
+ GtkPlacesSidebar *sidebar)
+{
+ bookmarks_popup_menu (sidebar, NULL);
+ return TRUE;
+}
+
+static gboolean
+bookmarks_button_release_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+ GtkTreeView *tree_view;
+ gboolean ret = FALSE;
+ gboolean res;
+
+ path = NULL;
+
+ if (event->type != GDK_BUTTON_RELEASE) {
+ return TRUE;
+ }
+
+ if (clicked_eject_button (sidebar, &path)) {
+ eject_or_unmount_bookmark (sidebar, path);
+ gtk_tree_path_free (path);
+
+ return FALSE;
+ }
+
+ tree_view = GTK_TREE_VIEW (widget);
+ model = gtk_tree_view_get_model (tree_view);
+
+ if (event->window != gtk_tree_view_get_bin_window (tree_view)) {
+ return FALSE;
+ }
+
+ res = gtk_tree_view_get_path_at_pos (tree_view, (int) event->x, (int) event->y,
+ &path, NULL, NULL, NULL);
+
+ if (!res || path == NULL) {
+ return FALSE;
+ }
+
+ res = gtk_tree_model_get_iter (model, &iter, path);
+ if (!res) {
+ gtk_tree_path_free (path);
+ return FALSE;
+ }
+
+ if (event->button == 1) {
+ open_selected_bookmark (sidebar, model, &iter, 0);
+ } else if (event->button == 2) {
+ GtkPlacesOpenFlags open_flags = GTK_PLACES_OPEN_NORMAL;
+
+ open_flags = ((event->state & GDK_CONTROL_MASK) ?
+ GTK_PLACES_OPEN_NEW_WINDOW :
+ GTK_PLACES_OPEN_NEW_TAB);
+
+ open_selected_bookmark (sidebar, model, &iter, open_flags);
+ ret = TRUE;
+ } else if (event->button == 3) {
+ PlaceType row_type;
+
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &row_type,
+ -1);
+
+ if (row_type != PLACES_HEADING) {
+ bookmarks_popup_menu (sidebar, event);
+ }
+ }
+
+ gtk_tree_path_free (path);
+
+ return ret;
+}
+
+static void
+bookmarks_edited (GtkCellRenderer *cell,
+ gchar *path_string,
+ gchar *new_text,
+ GtkPlacesSidebar *sidebar)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ char *uri;
+ GFile *file;
+
+ g_object_set (cell, "editable", FALSE, NULL);
+
+ path = gtk_tree_path_new_from_string (path_string);
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (sidebar->store), &iter, path);
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+ gtk_tree_path_free (path);
+
+ file = g_file_new_for_uri (uri);
+ if (!_gtk_bookmarks_manager_has_bookmark (sidebar->bookmarks_manager, file)) {
+ _gtk_bookmarks_manager_insert_bookmark (sidebar->bookmarks_manager, file, -1, NULL);
+ }
+
+ _gtk_bookmarks_manager_set_bookmark_label (sidebar->bookmarks_manager, file, new_text, NULL); /* NULL-GError */
+
+ g_object_unref (file);
+ g_free (uri);
+}
+
+static void
+bookmarks_editing_canceled (GtkCellRenderer *cell,
+ GtkPlacesSidebar *sidebar)
+{
+ g_object_set (cell, "editable", FALSE, NULL);
+}
+
+static gboolean
+tree_selection_func (GtkTreeSelection *selection,
+ GtkTreeModel *model,
+ GtkTreePath *path,
+ gboolean path_currently_selected,
+ gpointer user_data)
+{
+ GtkTreeIter iter;
+ PlaceType row_type;
+
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &row_type,
+ -1);
+
+ if (row_type == PLACES_HEADING) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+icon_cell_renderer_func (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ PlaceType type;
+
+ gtk_tree_model_get (model, iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
+ -1);
+
+ if (type == PLACES_HEADING) {
+ g_object_set (cell,
+ "visible", FALSE,
+ NULL);
+ } else {
+ g_object_set (cell,
+ "visible", TRUE,
+ NULL);
+ }
+}
+
+static void
+padding_cell_renderer_func (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ PlaceType type;
+
+ gtk_tree_model_get (model, iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
+ -1);
+
+ if (type == PLACES_HEADING) {
+ g_object_set (cell,
+ "visible", FALSE,
+ "xpad", 0,
+ "ypad", 0,
+ NULL);
+ } else {
+ g_object_set (cell,
+ "visible", TRUE,
+ "xpad", 3,
+ "ypad", 3,
+ NULL);
+ }
+}
+
+static void
+heading_cell_renderer_func (GtkTreeViewColumn *column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ PlaceType type;
+
+ gtk_tree_model_get (model, iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &type,
+ -1);
+
+ if (type == PLACES_HEADING) {
+ g_object_set (cell,
+ "visible", TRUE,
+ NULL);
+ } else {
+ g_object_set (cell,
+ "visible", FALSE,
+ NULL);
+ }
+}
+
+static gint
+places_sidebar_sort_func (GtkTreeModel *model,
+ GtkTreeIter *iter_a,
+ GtkTreeIter *iter_b,
+ gpointer user_data)
+{
+ SectionType section_type_a, section_type_b;
+ PlaceType place_type_a, place_type_b;
+ gint retval = 0;
+
+ gtk_tree_model_get (model, iter_a,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type_a,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type_a,
+ -1);
+ gtk_tree_model_get (model, iter_b,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type_b,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type_b,
+ -1);
+
+ /* fall back to the default order if we're not in the
+ * XDG part of the computer section.
+ */
+ if ((section_type_a == section_type_b) &&
+ (section_type_a == SECTION_COMPUTER) &&
+ (place_type_a == place_type_b) &&
+ (place_type_a == PLACES_XDG_DIR)) {
+ gchar *name_a, *name_b;
+
+ gtk_tree_model_get (model, iter_a,
+ PLACES_SIDEBAR_COLUMN_NAME, &name_a,
+ -1);
+ gtk_tree_model_get (model, iter_b,
+ PLACES_SIDEBAR_COLUMN_NAME, &name_b,
+ -1);
+
+ retval = g_utf8_collate (name_a, name_b);
+
+ g_free (name_a);
+ g_free (name_b);
+ }
+
+ return retval;
+}
+
+static void
+update_hostname (GtkPlacesSidebar *sidebar)
+{
+ GVariant *variant;
+ gsize len;
+ const gchar *hostname;
+
+ if (sidebar->hostnamed_proxy == NULL)
+ return;
+
+ variant = g_dbus_proxy_get_cached_property (sidebar->hostnamed_proxy,
+ "PrettyHostname");
+ if (variant == NULL) {
+ return;
+ }
+
+ hostname = g_variant_get_string (variant, &len);
+ if (len > 0 &&
+ g_strcmp0 (sidebar->hostname, hostname) != 0) {
+ g_free (sidebar->hostname);
+ sidebar->hostname = g_strdup (hostname);
+ update_places (sidebar);
+ }
+
+ g_variant_unref (variant);
+}
+
+static void
+hostname_proxy_new_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GtkPlacesSidebar *sidebar = user_data;
+ GError *error = NULL;
+
+ sidebar->hostnamed_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ g_clear_object (&sidebar->hostnamed_cancellable);
+
+ g_object_unref (sidebar);
+
+ if (error != NULL) {
+ g_debug ("Failed to create D-Bus proxy: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ g_signal_connect_swapped (sidebar->hostnamed_proxy,
+ "g-properties-changed",
+ G_CALLBACK (update_hostname),
+ sidebar);
+ update_hostname (sidebar);
+}
+
+static void
+create_volume_monitor (GtkPlacesSidebar *sidebar)
+{
+ g_assert (sidebar->volume_monitor == NULL);
+
+ sidebar->volume_monitor = g_volume_monitor_get ();
+
+ g_signal_connect_object (sidebar->volume_monitor, "volume_added",
+ G_CALLBACK (volume_added_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "volume_removed",
+ G_CALLBACK (volume_removed_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "volume_changed",
+ G_CALLBACK (volume_changed_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "mount_added",
+ G_CALLBACK (mount_added_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "mount_removed",
+ G_CALLBACK (mount_removed_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "mount_changed",
+ G_CALLBACK (mount_changed_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "drive_disconnected",
+ G_CALLBACK (drive_disconnected_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "drive_connected",
+ G_CALLBACK (drive_connected_callback), sidebar, 0);
+ g_signal_connect_object (sidebar->volume_monitor, "drive_changed",
+ G_CALLBACK (drive_changed_callback), sidebar, 0);
+}
+
+static void
+bookmarks_changed_cb (gpointer data)
+{
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (data);
+
+ update_places (sidebar);
+}
+
+static gboolean
+tree_view_button_press_callback (GtkWidget *tree_view,
+ GdkEventButton *event,
+ gpointer data)
+{
+ GtkTreePath *path;
+ GtkTreeViewColumn *column;
+
+ if (event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+ if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view),
+ event->x, event->y,
+ &path,
+ &column,
+ NULL,
+ NULL)) {
+ gtk_tree_view_row_activated (GTK_TREE_VIEW (tree_view), path, column);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+tree_view_set_activate_on_single_click (GtkTreeView *tree_view)
+{
+ g_signal_connect (tree_view, "button_press_event",
+ G_CALLBACK (tree_view_button_press_callback),
+ NULL);
+}
+
+static void
+trash_monitor_trash_state_changed_cb (GtkTrashMonitor *monitor,
+ GtkPlacesSidebar *sidebar)
+{
+ update_places (sidebar);
+}
+
+
+static void
+gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeView *tree_view;
+ GtkTreeViewColumn *col;
+ GtkCellRenderer *cell;
+ GtkTreeSelection *selection;
+ GIcon *eject;
+
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (sidebar)), GTK_STYLE_CLASS_SIDEBAR);
+
+ create_volume_monitor (sidebar);
+
+ sidebar->open_flags = GTK_PLACES_OPEN_NORMAL;
+
+ sidebar->bookmarks_manager = _gtk_bookmarks_manager_new (bookmarks_changed_cb, sidebar);
+
+ sidebar->trash_monitor = _gtk_trash_monitor_get ();
+ sidebar->trash_monitor_changed_id = g_signal_connect (sidebar->trash_monitor, "trash-state-changed",
+ G_CALLBACK (trash_monitor_trash_state_changed_cb), sidebar);
+
+ sidebar->shortcuts = NULL;
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sidebar),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_hadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
+ gtk_scrolled_window_set_vadjustment (GTK_SCROLLED_WINDOW (sidebar), NULL);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sidebar), GTK_SHADOW_IN);
+
+ gtk_style_context_set_junction_sides (gtk_widget_get_style_context (GTK_WIDGET (sidebar)),
+ GTK_JUNCTION_RIGHT | GTK_JUNCTION_LEFT);
+
+ /* tree view */
+ tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
+ gtk_tree_view_set_headers_visible (tree_view, FALSE);
+
+ col = GTK_TREE_VIEW_COLUMN (gtk_tree_view_column_new ());
+
+ /* initial padding */
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ g_object_set (cell,
+ "xpad", 6,
+ NULL);
+
+ /* headings */
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_attributes (col, cell,
+ "text", PLACES_SIDEBAR_COLUMN_HEADING_TEXT,
+ NULL);
+ g_object_set (cell,
+ "weight", PANGO_WEIGHT_BOLD,
+ "weight-set", TRUE,
+ "ypad", 6,
+ "xpad", 0,
+ NULL);
+ gtk_tree_view_column_set_cell_data_func (col, cell,
+ heading_cell_renderer_func,
+ sidebar, NULL);
+
+ /* icon padding */
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_cell_data_func (col, cell,
+ padding_cell_renderer_func,
+ sidebar, NULL);
+
+ /* icon renderer */
+ cell = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (cell, "follow-state", TRUE, NULL);
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_attributes (col, cell,
+ "gicon", PLACES_SIDEBAR_COLUMN_GICON,
+ NULL);
+ gtk_tree_view_column_set_cell_data_func (col, cell,
+ icon_cell_renderer_func,
+ sidebar, NULL);
+
+ /* eject text renderer */
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (col, cell, TRUE);
+ gtk_tree_view_column_set_attributes (col, cell,
+ "text", PLACES_SIDEBAR_COLUMN_NAME,
+ "visible", PLACES_SIDEBAR_COLUMN_EJECT,
+ NULL);
+ g_object_set (cell,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "ellipsize-set", TRUE,
+ NULL);
+
+ /* eject icon renderer */
+ cell = gtk_cell_renderer_pixbuf_new ();
+ sidebar->eject_icon_cell_renderer = cell;
+ eject = g_themed_icon_new_with_default_fallbacks ("media-eject-symbolic");
+ g_object_set (cell,
+ "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
+ "stock-size", GTK_ICON_SIZE_MENU,
+ "xpad", EJECT_BUTTON_XPAD,
+ /* align right, because for some reason gtk+ expands
+ this even though we tell it not to. */
+ "xalign", 1.0,
+ "follow-state", TRUE,
+ "gicon", eject,
+ NULL);
+ gtk_tree_view_column_pack_start (col, cell, FALSE);
+ gtk_tree_view_column_set_attributes (col, cell,
+ "visible", PLACES_SIDEBAR_COLUMN_EJECT,
+ NULL);
+ g_object_unref (eject);
+
+ /* normal text renderer */
+ cell = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (col, cell, TRUE);
+ g_object_set (G_OBJECT (cell), "editable", FALSE, NULL);
+ gtk_tree_view_column_set_attributes (col, cell,
+ "text", PLACES_SIDEBAR_COLUMN_NAME,
+ "visible", PLACES_SIDEBAR_COLUMN_NO_EJECT,
+ "editable-set", PLACES_SIDEBAR_COLUMN_BOOKMARK,
+ NULL);
+ g_object_set (cell,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ "ellipsize-set", TRUE,
+ NULL);
+
+ g_signal_connect (cell, "edited",
+ G_CALLBACK (bookmarks_edited), sidebar);
+ g_signal_connect (cell, "editing-canceled",
+ G_CALLBACK (bookmarks_editing_canceled), sidebar);
+
+ /* this is required to align the eject buttons to the right */
+ gtk_tree_view_column_set_max_width (GTK_TREE_VIEW_COLUMN (col), 24);
+ gtk_tree_view_append_column (tree_view, col);
+
+ sidebar->store = shortcuts_model_new (sidebar);
+ gtk_tree_view_set_tooltip_column (tree_view, PLACES_SIDEBAR_COLUMN_TOOLTIP);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sidebar->store),
+ PLACES_SIDEBAR_COLUMN_NAME,
+ GTK_SORT_ASCENDING);
+ gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sidebar->store),
+ PLACES_SIDEBAR_COLUMN_NAME,
+ places_sidebar_sort_func,
+ sidebar, NULL);
+
+ gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (sidebar->store));
+ gtk_container_add (GTK_CONTAINER (sidebar), GTK_WIDGET (tree_view));
+ gtk_widget_show (GTK_WIDGET (tree_view));
+ gtk_tree_view_set_enable_search (tree_view, FALSE);
+
+ gtk_widget_show (GTK_WIDGET (sidebar));
+ sidebar->tree_view = tree_view;
+
+ gtk_tree_view_set_search_column (tree_view, PLACES_SIDEBAR_COLUMN_NAME);
+ selection = gtk_tree_view_get_selection (tree_view);
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
+
+ gtk_tree_selection_set_select_function (selection,
+ tree_selection_func,
+ sidebar,
+ NULL);
+
+ gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (tree_view),
+ GDK_BUTTON1_MASK,
+ dnd_source_targets, G_N_ELEMENTS (dnd_source_targets),
+ GDK_ACTION_MOVE);
+ gtk_drag_dest_set (GTK_WIDGET (tree_view),
+ 0,
+ dnd_drop_targets, G_N_ELEMENTS (dnd_drop_targets),
+ GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
+
+ g_signal_connect (tree_view, "key-press-event",
+ G_CALLBACK (bookmarks_key_press_event_cb), sidebar);
+
+ g_signal_connect (tree_view, "drag-motion",
+ G_CALLBACK (drag_motion_callback), sidebar);
+ g_signal_connect (tree_view, "drag-leave",
+ G_CALLBACK (drag_leave_callback), sidebar);
+ g_signal_connect (tree_view, "drag-data-received",
+ G_CALLBACK (drag_data_received_callback), sidebar);
+ g_signal_connect (tree_view, "drag-drop",
+ G_CALLBACK (drag_drop_callback), sidebar);
+
+ g_signal_connect (tree_view, "popup-menu",
+ G_CALLBACK (bookmarks_popup_menu_cb), sidebar);
+ g_signal_connect (tree_view, "button-release-event",
+ G_CALLBACK (bookmarks_button_release_event_cb), sidebar);
+
+ tree_view_set_activate_on_single_click (sidebar->tree_view);
+
+ sidebar->hostname = g_strdup (_("Computer"));
+ sidebar->hostnamed_cancellable = g_cancellable_new ();
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
+ NULL,
+ "org.freedesktop.hostname1",
+ "/org/freedesktop/hostname1",
+ "org.freedesktop.hostname1",
+ sidebar->hostnamed_cancellable,
+ hostname_proxy_new_cb,
+ g_object_ref (sidebar));
+}
+
+static void
+gtk_places_sidebar_set_property (GObject *obj,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (obj);
+
+ switch (property_id) {
+ case PROP_LOCATION:
+ gtk_places_sidebar_set_location (sidebar, g_value_get_object (value));
+ break;
+ case PROP_OPEN_FLAGS:
+ gtk_places_sidebar_set_open_flags (sidebar, g_value_get_flags (value));
+ break;
+ case PROP_SHOW_DESKTOP:
+ gtk_places_sidebar_set_show_desktop (sidebar, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_places_sidebar_get_property (GObject *obj,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (obj);
+
+ switch (property_id) {
+ case PROP_LOCATION:
+ g_value_take_object (value, gtk_places_sidebar_get_location (sidebar));
+ break;
+ case PROP_OPEN_FLAGS:
+ g_value_set_flags (value, gtk_places_sidebar_get_open_flags (sidebar));
+ break;
+ case PROP_SHOW_DESKTOP:
+ g_value_set_boolean (value, gtk_places_sidebar_get_show_desktop (sidebar));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_places_sidebar_dispose (GObject *object)
+{
+ GtkPlacesSidebar *sidebar;
+
+ sidebar = GTK_PLACES_SIDEBAR (object);
+
+ sidebar->tree_view = NULL;
+
+ free_drag_data (sidebar);
+
+ if (sidebar->bookmarks_manager != NULL) {
+ _gtk_bookmarks_manager_free (sidebar->bookmarks_manager);
+ sidebar->bookmarks_manager = NULL;
+ }
+
+ if (sidebar->popup_menu) {
+ gtk_widget_destroy (sidebar->popup_menu);
+ sidebar->popup_menu = NULL;
+ }
+
+ if (sidebar->trash_monitor) {
+ g_signal_handler_disconnect (sidebar->trash_monitor, sidebar->trash_monitor_changed_id);
+ sidebar->trash_monitor_changed_id = 0;
+ g_clear_object (&sidebar->trash_monitor);
+ }
+
+ g_clear_object (&sidebar->store);
+
+ g_slist_free_full (sidebar->shortcuts, g_object_unref);
+ sidebar->shortcuts = NULL;
+
+ if (sidebar->volume_monitor != NULL) {
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ volume_added_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ volume_removed_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ volume_changed_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ mount_added_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ mount_removed_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ mount_changed_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ drive_disconnected_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ drive_connected_callback, sidebar);
+ g_signal_handlers_disconnect_by_func (sidebar->volume_monitor,
+ drive_changed_callback, sidebar);
+
+ g_clear_object (&sidebar->volume_monitor);
+ }
+
+ if (sidebar->hostnamed_cancellable != NULL) {
+ g_cancellable_cancel (sidebar->hostnamed_cancellable);
+ g_clear_object (&sidebar->hostnamed_cancellable);
+ }
+
+ g_clear_object (&sidebar->hostnamed_proxy);
+ g_free (sidebar->hostname);
+ sidebar->hostname = NULL;
+
+ G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->dispose (object);
+}
+
+static void
+gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) class;
+
+ gobject_class->dispose = gtk_places_sidebar_dispose;
+ gobject_class->set_property = gtk_places_sidebar_set_property;
+ gobject_class->get_property = gtk_places_sidebar_get_property;
+
+ GTK_WIDGET_CLASS (class)->focus = gtk_places_sidebar_focus;
+
+ /**
+ * GtkPlacesSidebar::open-location:
+ * @sidebar: the object which received the signal.
+ * @location: #GFile to which the caller should switch.
+ * @open_flags: a single value from #GtkPlacesOpenFlags specifying how the @location should be opened.
+ *
+ * The places sidebar emits this signal when the user selects a location
+ * in it. The calling application should display the contents of that
+ * location; for example, a file manager should show a list of files in
+ * the specified location.
+ *
+ * Since: 3.8
+ */
+ places_sidebar_signals [OPEN_LOCATION] =
+ g_signal_new (I_("open-location"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkPlacesSidebarClass, open_location),
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_FLAGS,
+ G_TYPE_NONE, 2,
+ G_TYPE_OBJECT,
+ GTK_TYPE_PLACES_OPEN_FLAGS);
+
+ /**
+ * GtkPlacesSidebar::populate-popup:
+ * @sidebar: the object which received the signal.
+ * @menu: a #GtkMenu.
+ * @selected_item: #GFile with the item to which the menu should refer.
+ *
+ * The places sidebar emits this signal when the user invokes a contextual
+ * menu on one of its items. In the signal handler, the application may
+ * add extra items to the menu as appropriate. For example, a file manager
+ * may want to add a "Properties" command to the menu.
+ *
+ * It is not necessary to store the @selected_item for each menu item;
+ * during their GtkMenuItem::activate callbacks, the application can use
+ * gtk_places_sidebar_get_location() to get the file to which the item
+ * refers.
+ *
+ * The @menu and all its menu items are destroyed after the user
+ * dismisses the menu. The menu is re-created (and thus, this signal is
+ * emitted) every time the user activates the contextual menu.
+ *
+ * Since: 3.8
+ */
+ places_sidebar_signals [POPULATE_POPUP] =
+ g_signal_new (I_("populate-popup"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkPlacesSidebarClass, populate_popup),
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ G_TYPE_OBJECT,
+ G_TYPE_OBJECT);
+
+ /**
+ * GtkPlacesSidebar::show-error-message:
+ * @sidebar: the object which received the signal.
+ * @primary: primary message with a summary of the error to show.
+ * @secondary: secondary message with details of the error to show.
+ *
+ * The places sidebar emits this signal when it needs the calling
+ * application to present an error message. Most of these messages
+ * refer to mounting or unmounting media, for example, when a drive
+ * cannot be started for some reason.
+ *
+ * Since: 3.8
+ */
+ places_sidebar_signals [SHOW_ERROR_MESSAGE] =
+ g_signal_new (I_("show-error-message"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkPlacesSidebarClass, show_error_message),
+ NULL, NULL,
+ _gtk_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ /**
+ * GtkPlacesSidebar::drag-action-requested:
+ * @sidebar: the object which received the signal.
+ * @context: #GdkDragContext with information about the drag operation
+ * @dest_file: #GFile with the tentative location that is being hovered for a drop
+ * @source_file_list: (element-type GFile) (transfer none): List of #GFile that are being dragged
+ *
+ * When the user starts a drag-and-drop operation and the sidebar needs
+ * to ask the application for which drag action to perform, then the
+ * sidebar will emit this signal.
+ *
+ * The application can evaluate the @context for customary actions, or
+ * it can check the type of the files indicated by @source_file_list against the
+ * possible actions for the destination @dest_file.
+ *
+ * The drag action to use must be the return value of the signal handler.
+ *
+ * Return value: The drag action to use, for example, #GDK_ACTION_COPY
+ * or #GDK_ACTION_MOVE, or 0 if no action is allowed here (i.e. drops
+ * are not allowed in the specified @dest_file).
+ *
+ * Since: 3.8
+ */
+ places_sidebar_signals [DRAG_ACTION_REQUESTED] =
+ g_signal_new (I_("drag-action-requested"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPlacesSidebarClass, drag_action_requested),
+ NULL, NULL,
+ _gtk_marshal_INT__OBJECT_OBJECT_POINTER,
+ G_TYPE_INT, 3,
+ GDK_TYPE_DRAG_CONTEXT,
+ G_TYPE_OBJECT,
+ G_TYPE_POINTER /* GList of GFile */ );
+
+ /**
+ * GtkPlacesSidebar::drag-action-ask:
+ * @sidebar: the object which received the signal.
+ * @actions: Possible drag actions that need to be asked for.
+ *
+ * The places sidebar emits this signal when it needs to ask the application
+ * to pop up a menu to ask the user for which drag action to perform.
+ *
+ * Return value: the final drag action that the sidebar should pass to the drag side
+ * of the drag-and-drop operation.
+ *
+ * Since: 3.8
+ */
+ places_sidebar_signals [DRAG_ACTION_ASK] =
+ g_signal_new (I_("drag-action-ask"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkPlacesSidebarClass, drag_action_ask),
+ NULL, NULL,
+ _gtk_marshal_INT__INT,
+ G_TYPE_INT, 1,
+ G_TYPE_INT);
+
+ /**
+ * GtkPlacesSidebar::drag-perform-drop:
+ * @sidebar: the object which received the signal.
+ * @dest_file: Destination #GFile.
+ * @source_file_list: (element-type GFile) (transfer none): #GList of #GFile that got dropped.
+ * @action: Drop action to perform.
+ *
+ * The places sidebar emits this signal when the user completes a
+ * drag-and-drop operation and one of the sidebar's items is the
+ * destination. This item is in the @dest_file, and the
+ * @source_file_list has the list of files that are dropped into it and
+ * which should be copied/moved/etc. based on the specified @action.
+ *
+ * Since: 3.8
+ */
+ places_sidebar_signals [DRAG_PERFORM_DROP] =
+ g_signal_new (I_("drag-perform-drop"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkPlacesSidebarClass, drag_perform_drop),
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_POINTER_INT,
+ G_TYPE_NONE, 3,
+ G_TYPE_OBJECT,
+ G_TYPE_POINTER, /* GList of GFile */
+ G_TYPE_INT);
+
+ properties[PROP_LOCATION] =
+ g_param_spec_object ("location",
+ P_("Location to select"),
+ P_("The location to highlight in the sidebar"),
+ G_TYPE_FILE,
+ G_PARAM_READWRITE);
+ properties[PROP_OPEN_FLAGS] =
+ g_param_spec_flags ("open-flags",
+ P_("The open modes supported for this widget"),
+ P_("The set of open modes supported for this widget"),
+ GTK_TYPE_PLACES_OPEN_FLAGS,
+ GTK_PLACES_OPEN_NORMAL,
+ G_PARAM_READWRITE);
+ properties[PROP_SHOW_DESKTOP] =
+ g_param_spec_boolean ("show-desktop",
+ P_("Whether to show desktop"),
+ P_("Whether the sidebar includes a builtin shortcut to the desktop folder"),
+ FALSE,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
+}
+
+/**
+ * gtk_places_sidebar_new:
+ *
+ * Creates a new #GtkPlacesSidebar widget. The application should connect
+ * to at least the #GtkPlacesSidebar::open-location signal to be notified
+ * when the user makes a selection in the sidebar.
+ */
+GtkWidget *
+gtk_places_sidebar_new (void)
+{
+ return GTK_WIDGET (g_object_new (gtk_places_sidebar_get_type (), NULL));
+}
+
+
+
+/* Drag and drop interfaces */
+
+/* GtkTreeDragSource::row_draggable implementation for the shortcuts model */
+static gboolean
+shortcuts_model_row_draggable (GtkTreeDragSource *drag_source,
+ GtkTreePath *path)
+{
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ PlaceType place_type;
+ SectionType section_type;
+
+ model = GTK_TREE_MODEL (drag_source);
+
+ gtk_tree_model_get_iter (model, &iter, path);
+ gtk_tree_model_get (model, &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ PLACES_SIDEBAR_COLUMN_SECTION_TYPE, &section_type,
+ -1);
+
+ if (place_type != PLACES_HEADING && section_type == SECTION_BOOKMARKS)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Fill the GtkTreeDragSourceIface vtable */
+static void
+shortcuts_model_class_init (ShortcutsModelClass *klass)
+{
+}
+
+static void
+shortcuts_model_init (ShortcutsModel *model)
+{
+ model->sidebar = NULL;
+}
+
+static void
+shortcuts_model_drag_source_iface_init (GtkTreeDragSourceIface *iface)
+{
+ iface->row_draggable = shortcuts_model_row_draggable;
+}
+
+static GtkListStore *
+shortcuts_model_new (GtkPlacesSidebar *sidebar)
+{
+ ShortcutsModel *model;
+ GType model_types[PLACES_SIDEBAR_COLUMN_COUNT] = {
+ G_TYPE_INT,
+ G_TYPE_STRING,
+ G_TYPE_DRIVE,
+ G_TYPE_VOLUME,
+ G_TYPE_MOUNT,
+ G_TYPE_STRING,
+ G_TYPE_ICON,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
+ G_TYPE_INT,
+ G_TYPE_STRING
+ };
+
+ model = g_object_new (shortcuts_model_get_type (), NULL);
+ model->sidebar = sidebar;
+
+ gtk_list_store_set_column_types (GTK_LIST_STORE (model),
+ PLACES_SIDEBAR_COLUMN_COUNT,
+ model_types);
+
+ return GTK_LIST_STORE (model);
+}
+
+
+
+/* Public methods for GtkPlacesSidebar */
+
+/**
+ * gtk_places_sidebar_set_open_flags:
+ * @sidebar: a places sidebar
+ * @flags: Bitmask of modes in which the calling application can open locations
+ *
+ * Sets the way in which the calling application can open new locations from
+ * the places sidebar. For example, some applications only open locations
+ * "directly" into their main view, while others may support opening locations
+ * in a new notebook tab or a new window.
+ *
+ * This function is used to tell the places @sidebar about the ways in which the
+ * application can open new locations, so that the sidebar can display (or not)
+ * the "Open in new tab" and "Open in new window" menu items as appropriate.
+ *
+ * When the #GtkPlacesSidebar::open-location signal is emitted, its flags
+ * argument will be set to one of the @flags that was passed in
+ * gtk_places_sidebar_set_open_flags().
+ *
+ * Passing 0 for @flags will cause #GTK_PLACES_OPEN_NORMAL to always be sent
+ * to callbacks for the "open-location" signal.
+ *
+ * Since: 3.8
+ */
+void
+gtk_places_sidebar_set_open_flags (GtkPlacesSidebar *sidebar, GtkPlacesOpenFlags flags)
+{
+ g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar));
+
+ if (sidebar->open_flags != flags) {
+ sidebar->open_flags = flags;
+ g_object_notify_by_pspec (G_OBJECT (sidebar), properties[PROP_OPEN_FLAGS]);
+ }
+}
+
+GtkPlacesOpenFlags
+gtk_places_sidebar_get_open_flags (GtkPlacesSidebar *sidebar)
+{
+ g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), 0);
+
+ return sidebar->open_flags;
+}
+
+/**
+ * gtk_places_sidebar_set_location:
+ * @sidebar: a places sidebar
+ * @location: (allow-none): location to select, or #NULL for no current path
+ *
+ * Sets the location that is being shown in the widgets surrounding the
+ * @sidebar, for example, in a folder view in a file manager. In turn, the
+ * @sidebar will highlight that location if it is being shown in the list of
+ * places, or it will unhighlight everything if the @location is not among the
+ * places in the list.
+ *
+ * Since: 3.8
+ */
+void
+gtk_places_sidebar_set_location (GtkPlacesSidebar *sidebar, GFile *location)
+{
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ gboolean valid;
+ char *iter_uri;
+ char *uri;
+
+ g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar));
+
+ selection = gtk_tree_view_get_selection (sidebar->tree_view);
+ gtk_tree_selection_unselect_all (selection);
+
+ if (location == NULL)
+ goto out;
+
+ uri = g_file_get_uri (location);
+
+ valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sidebar->store), &iter);
+ while (valid) {
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &iter_uri,
+ -1);
+ if (iter_uri != NULL) {
+ if (strcmp (iter_uri, uri) == 0) {
+ g_free (iter_uri);
+ gtk_tree_selection_select_iter (selection, &iter);
+ break;
+ }
+ g_free (iter_uri);
+ }
+ valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (sidebar->store), &iter);
+ }
+
+ g_free (uri);
+
+ out:
+ g_object_notify_by_pspec (G_OBJECT (sidebar), properties[PROP_LOCATION]);
+}
+
+/**
+ * gtk_places_sidebar_get_location:
+ * @sidebar: a places sidebar
+ *
+ * Gets the currently-selected location in the @sidebar. This can be #NULL when
+ * nothing is selected, for example, when gtk_places_sidebar_set_location() has
+ * been called with a location that is not among the sidebar's list of places to
+ * show.
+ *
+ * You can use this function to get the selection in the @sidebar. Also, if you
+ * connect to the #GtkPlacesSidebar::popup-menu signal, you can use this
+ * function to get the location that is being referred to during the callbacks
+ * for your menu items.
+ *
+ * Returns: (transfer full): a GFile with the selected location, or #NULL if nothing is visually
+ * selected.
+ *
+ * Since: 3.8
+ */
+GFile *
+gtk_places_sidebar_get_location (GtkPlacesSidebar *sidebar)
+{
+ GtkTreeIter iter;
+ GFile *file;
+
+ g_return_val_if_fail (sidebar != NULL, NULL);
+
+ file = NULL;
+
+ if (get_selected_iter (sidebar, &iter)) {
+ char *uri;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ file = g_file_new_for_uri (uri);
+ g_free (uri);
+ }
+
+ return file;
+}
+
+/**
+ * gtk_places_sidebar_set_show_desktop:
+ * @sidebar: a places sidebar
+ * @show_desktop: whether to show an item for the Desktop folder
+ *
+ * Sets whether the @sidebar should show an item for the Desktop folder; this is off by default.
+ * An application may want to turn this on if the desktop environment actually supports the
+ * notion of a desktop.
+ *
+ * Since: 3.8
+ */
+void
+gtk_places_sidebar_set_show_desktop (GtkPlacesSidebar *sidebar, gboolean show_desktop)
+{
+ g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar));
+
+ show_desktop = !!show_desktop;
+ if (sidebar->show_desktop != show_desktop) {
+ sidebar->show_desktop = show_desktop;
+ update_places (sidebar);
+ g_object_notify_by_pspec (G_OBJECT (sidebar), properties[PROP_SHOW_DESKTOP]);
+ }
+}
+
+/**
+ * gtk_places_sidebar_get_show_desktop:
+ * @sidebar: a places sidebar
+ *
+ * Returns the value previously set with gtk_places_sidebar_set_show_desktop()
+ *
+ * Return value: %TRUE if the sidebar will display a builtin shortcut to the desktop folder.
+ *
+ * Since: 3.8
+ */
+gboolean
+gtk_places_sidebar_get_show_desktop (GtkPlacesSidebar *sidebar)
+{
+ g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), FALSE);
+
+ return sidebar->show_desktop;
+}
+
+static GSList *
+find_shortcut_link (GtkPlacesSidebar *sidebar, GFile *location)
+{
+ GSList *l;
+
+ for (l = sidebar->shortcuts; l; l = l->next) {
+ GFile *shortcut;
+
+ shortcut = G_FILE (l->data);
+ if (g_file_equal (shortcut, location))
+ return l;
+ }
+
+ return NULL;
+}
+
+/**
+ * gtk_places_sidebar_add_shortcut:
+ * @sidebar: a places sidebar
+ * @location: location to add as an application-specific shortcut
+ *
+ * Applications may want to present some folders in the places sidebar if
+ * they could be immediately useful to users. For example, a drawing
+ * program could add a "/usr/share/clipart" location when the sidebar is
+ * being used in an "Insert Clipart" dialog box.
+ *
+ * This function adds the specified @location to a special place for immutable
+ * shortcuts. The shortcuts are application-specific; they are not shared
+ * across applications, and they are not persistent. If this function
+ * is called multiple times with different locations, then they are added
+ * to the sidebar's list in the same order as the function is called.
+ *
+ * Since: 3.8
+ */
+void
+gtk_places_sidebar_add_shortcut (GtkPlacesSidebar *sidebar, GFile *location)
+{
+ g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar));
+ g_return_if_fail (G_IS_FILE (location));
+
+ g_object_ref (location);
+ sidebar->shortcuts = g_slist_append (sidebar->shortcuts, location);
+
+ update_places (sidebar);
+}
+
+/**
+ * gtk_places_sidebar_remove_shortcut:
+ * @sidebar: a places sidebar
+ * @location: location to remove
+ *
+ * Removes an application-specific shortcut that has been previously been
+ * inserted with gtk_places_sidebar_add_shortcut(). If the @location is not a
+ * shortcut in the sidebar, then nothing is done.
+ *
+ * Since: 3.8
+ */
+void
+gtk_places_sidebar_remove_shortcut (GtkPlacesSidebar *sidebar, GFile *location)
+{
+ GSList *link;
+ GFile *shortcut;
+
+ g_return_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar));
+ g_return_if_fail (G_IS_FILE (location));
+
+ link = find_shortcut_link (sidebar, location);
+ if (!link)
+ return;
+
+ shortcut = G_FILE (link->data);
+ g_object_unref (shortcut);
+
+ sidebar->shortcuts = g_slist_delete_link (sidebar->shortcuts, link);
+ update_places (sidebar);
+}
+
+/**
+ * gtk_places_sidebar_list_shortcuts:
+ * @sidebar: a places sidebar
+ *
+ * Return value: (element-type GFile) (transfer full): A #GSList of #GFile of the locations
+ * that have been added as application-specific shortcuts with gtk_places_sidebar_add_shortcut().
+ * To free this list, you can use
+ * |[
+ * g_slist_free_full (list, (GDestroyNotify) g_object_unref);
+ * ]|
+ *
+ * Since: 3.8
+ */
+GSList *
+gtk_places_sidebar_list_shortcuts (GtkPlacesSidebar *sidebar)
+{
+ g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), FALSE);
+
+ return g_slist_copy_deep (sidebar->shortcuts, (GCopyFunc) g_object_ref, NULL);
+}
+
+/**
+ * gtk_places_sidebar_get_nth_bookmark:
+ * @sidebar: a places sidebar
+ * @n: index of the bookmark to query
+ *
+ * This function queries the bookmarks added by the user to the places sidebar,
+ * and returns one of them. This function is used by #GtkFileChooser to implement
+ * the "Alt-1", "Alt-2", etc. shortcuts, which activate the cooresponding bookmark.
+ *
+ * Return value: (transfer full): The bookmark specified by the index @n, or
+ * #NULL if no such index exist. Note that the indices start at 0, even though
+ * the file chooser starts them with the keyboard shortcut "Alt-1".
+ *
+ * Since: 3.8
+ */
+GFile *
+gtk_places_sidebar_get_nth_bookmark (GtkPlacesSidebar *sidebar, int n)
+{
+ GtkTreeIter iter;
+ int k;
+ GFile *file;
+
+ g_return_val_if_fail (GTK_IS_PLACES_SIDEBAR (sidebar), NULL);
+
+ file = NULL;
+
+ if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sidebar->store), &iter)) {
+ k = 0;
+
+ do {
+ PlaceType place_type;
+ char *uri;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (sidebar->store), &iter,
+ PLACES_SIDEBAR_COLUMN_ROW_TYPE, &place_type,
+ PLACES_SIDEBAR_COLUMN_URI, &uri,
+ -1);
+
+ if (place_type == PLACES_BOOKMARK) {
+ if (k == n) {
+ file = g_file_new_for_uri (uri);
+ g_free (uri);
+ break;
+ }
+
+ g_free (uri);
+ k++;
+ }
+ } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (sidebar->store), &iter));
+ }
+
+ return file;
+}
diff --git a/gtk/gtkplacessidebar.h b/gtk/gtkplacessidebar.h
new file mode 100644
index 0000000000..40e33a36ab
--- /dev/null
+++ b/gtk/gtkplacessidebar.h
@@ -0,0 +1,100 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/*
+ * GtkPlacesSidebar - sidebar widget for places in the filesystem
+ *
+ * This code comes from Nautilus, GNOME's file manager.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Authors : Mr Jamie McCracken (jamiemcc at blueyonder dot co dot uk)
+ * Federico Mena Quintero <federico@gnome.org>
+ *
+ */
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_PLACES_SIDEBAR_H__
+#define __GTK_PLACES_SIDEBAR_H__
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_PLACES_SIDEBAR (gtk_places_sidebar_get_type ())
+#define GTK_PLACES_SIDEBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PLACES_SIDEBAR, GtkPlacesSidebar))
+#define GTK_PLACES_SIDEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PLACES_SIDEBAR, GtkPlacesSidebarClass))
+#define GTK_IS_PLACES_SIDEBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PLACES_SIDEBAR))
+#define GTK_IS_PLACES_SIDEBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PLACES_SIDEBAR))
+#define GTK_PLACES_SIDEBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PLACES_SIDEBAR, GtkPlacesSidebarClass))
+
+typedef struct _GtkPlacesSidebar GtkPlacesSidebar;
+typedef struct _GtkPlacesSidebarClass GtkPlacesSidebarClass;
+
+/**
+ * GtkPlacesOpenFlags:
+ * @GTK_PLACES_OPEN_NORMAL: This is the default mode that #GtkPlacesSidebar uses if no other flags
+ * are specified. It indicates that the calling application should open the selected location
+ * in the normal way, for example, in the folder view beside the sidebar.
+ * @GTK_PLACES_OPEN_NEW_TAB: When passed to gtk_places_sidebar_set_open_flags(), this indicates
+ * that the application can open folders selected from the sidebar in new tabs. This value
+ * will be passed to the #GtkPlacesSidebar::open-location signal when the user selects
+ * that a location be opened in a new tab instead of in the standard fashion.
+ * @GTK_PLACES_OPEN_NEW_WINDOW: Similar to @GTK_PLACES_OPEN_NEW_TAB, but indicates that the application
+ * can open folders in new windows.
+ *
+ * These flags serve two purposes. First, the application can call gtk_places_sidebar_set_open_flags()
+ * using these flags as a bitmask. This tells the sidebar that the application is able to open
+ * folders selected from the sidebar in various ways, for example, in new tabs or in new windows in
+ * addition to the normal mode.
+ *
+ * Second, when one of these values gets passed back to the application in the
+ * #GtkPlacesSidebar::open-location signal, it means that the application should
+ * open the selected location in the normal way, in a new tab, or in a new
+ * window. The sidebar takes care of determining the desired way to open the location,
+ * based on the modifier keys that the user is pressing at the time the selection is made.
+ *
+ * If the application never calls gtk_places_sidebar_set_open_flags(), then the sidebar will only
+ * use #GTK_PLACES_OPEN_NORMAL in the #GtkPlacesSidebar::open-location signal. This is the
+ * default mode of operation.
+ */
+typedef enum {
+ GTK_PLACES_OPEN_NORMAL = 1 << 0,
+ GTK_PLACES_OPEN_NEW_TAB = 1 << 1,
+ GTK_PLACES_OPEN_NEW_WINDOW = 1 << 2
+} GtkPlacesOpenFlags;
+
+GType gtk_places_sidebar_get_type (void);
+GtkWidget *gtk_places_sidebar_new (void);
+
+GtkPlacesOpenFlags gtk_places_sidebar_get_open_flags (GtkPlacesSidebar *sidebar);
+void gtk_places_sidebar_set_open_flags (GtkPlacesSidebar *sidebar, GtkPlacesOpenFlags flags);
+
+GFile *gtk_places_sidebar_get_location (GtkPlacesSidebar *sidebar);
+void gtk_places_sidebar_set_location (GtkPlacesSidebar *sidebar, GFile *location);
+
+gboolean gtk_places_sidebar_get_show_desktop (GtkPlacesSidebar *sidebar);
+void gtk_places_sidebar_set_show_desktop (GtkPlacesSidebar *sidebar, gboolean show_desktop);
+
+void gtk_places_sidebar_add_shortcut (GtkPlacesSidebar *sidebar, GFile *location);
+void gtk_places_sidebar_remove_shortcut (GtkPlacesSidebar *sidebar, GFile *location);
+GSList *gtk_places_sidebar_list_shortcuts (GtkPlacesSidebar *sidebar);
+
+GFile *gtk_places_sidebar_get_nth_bookmark (GtkPlacesSidebar *sidebar, int n);
+
+G_END_DECLS
+
+#endif /* __GTK_PLACES_SIDEBAR_H__ */
diff --git a/gtk/gtktrashmonitor.c b/gtk/gtktrashmonitor.c
new file mode 100644
index 0000000000..c61e9db1b1
--- /dev/null
+++ b/gtk/gtktrashmonitor.c
@@ -0,0 +1,267 @@
+/* GTK - The GIMP Toolkit
+ * gtktrashmonitor.h: Monitor the trash:/// folder to see if there is trash or not
+ * Copyright (C) 2011 Suse
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Federico Mena Quintero <federico@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gtkintl.h"
+#include "gtkmarshalers.h"
+#include "gtktrashmonitor.h"
+
+struct _GtkTrashMonitor
+{
+ GObject parent;
+
+ GFileMonitor *file_monitor;
+ gulong file_monitor_changed_id;
+
+ guint has_trash : 1;
+};
+
+struct _GtkTrashMonitorClass
+{
+ GObjectClass parent_class;
+
+ void (* trash_state_changed) (GtkTrashMonitor *monitor);
+};
+
+enum {
+ TRASH_STATE_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (GtkTrashMonitor, _gtk_trash_monitor, G_TYPE_OBJECT)
+
+static GtkTrashMonitor *the_trash_monitor;
+
+#define ICON_NAME_TRASH_EMPTY "user-trash-symbolic"
+#define ICON_NAME_TRASH_FULL "user-trash-full-symbolic"
+
+static void
+gtk_trash_monitor_dispose (GObject *object)
+{
+ GtkTrashMonitor *monitor;
+
+ monitor = GTK_TRASH_MONITOR (object);
+
+ if (monitor->file_monitor)
+ {
+ g_signal_handler_disconnect (monitor->file_monitor, monitor->file_monitor_changed_id);
+ monitor->file_monitor_changed_id = 0;
+
+ g_clear_object (&monitor->file_monitor);
+ }
+
+ G_OBJECT_CLASS (_gtk_trash_monitor_parent_class)->dispose (object);
+}
+
+static void
+_gtk_trash_monitor_class_init (GtkTrashMonitorClass *class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) class;
+
+ gobject_class->dispose = gtk_trash_monitor_dispose;
+
+ signals[TRASH_STATE_CHANGED] =
+ g_signal_new (I_("trash-state-changed"),
+ G_OBJECT_CLASS_TYPE (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkTrashMonitorClass, trash_state_changed),
+ NULL, NULL,
+ _gtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+/* Updates the internal has_trash flag and emits the "trash-state-changed" signal */
+static void
+update_has_trash_and_notify (GtkTrashMonitor *monitor,
+ gboolean has_trash)
+{
+ monitor->has_trash = !!has_trash;
+
+ g_signal_emit (monitor, signals[TRASH_STATE_CHANGED], 0);
+}
+
+static void
+trash_enumerate_next_files_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkTrashMonitor *monitor = GTK_TRASH_MONITOR (user_data);
+ GFileEnumerator *enumerator;
+ GList *infos;
+
+ enumerator = G_FILE_ENUMERATOR (source);
+
+ infos = g_file_enumerator_next_files_finish (enumerator, result, NULL);
+ if (infos)
+ {
+ update_has_trash_and_notify (monitor, TRUE);
+ g_list_free_full (infos, g_object_unref);
+ }
+ else
+ {
+ update_has_trash_and_notify (monitor, FALSE);
+ }
+
+ g_object_unref (monitor); /* was reffed in recompute_trash_state() */
+}
+
+/* Callback used from g_file_enumerate_children_async() - this is what enumerates "trash:///" */
+static void
+trash_enumerate_children_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GtkTrashMonitor *monitor = GTK_TRASH_MONITOR (user_data);
+ GFileEnumerator *enumerator;
+
+ enumerator = g_file_enumerate_children_finish (G_FILE (source), result, NULL);
+ if (enumerator)
+ {
+ g_file_enumerator_next_files_async (enumerator,
+ 1,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ trash_enumerate_next_files_cb,
+ monitor);
+ g_object_unref (enumerator);
+ }
+ else
+ {
+ update_has_trash_and_notify (monitor, FALSE);
+ g_object_unref (monitor); /* was reffed in recompute_trash_state() */
+ }
+}
+
+/* Asynchronously recomputes whether there is trash or not */
+static void
+recompute_trash_state (GtkTrashMonitor *monitor)
+{
+ GFile *file;
+
+ g_object_ref (monitor);
+
+ file = g_file_new_for_uri ("trash:///");
+ g_file_enumerate_children_async (file,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE,
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ trash_enumerate_children_cb,
+ monitor);
+
+ g_object_unref (file);
+}
+
+/* Callback used when the "trash:///" file monitor changes; we just recompute the trash state
+ * whenever something happens.
+ */
+static void
+file_monitor_changed_cb (GFileMonitor *file_monitor,
+ GFile *child,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ GtkTrashMonitor *monitor)
+{
+ recompute_trash_state (monitor);
+}
+
+static void
+_gtk_trash_monitor_init (GtkTrashMonitor *monitor)
+{
+ GFile *file;
+
+ file = g_file_new_for_uri ("trash:///");
+
+ monitor->file_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
+
+ g_object_unref (file);
+
+ if (monitor->file_monitor)
+ monitor->file_monitor_changed_id = g_signal_connect (monitor->file_monitor, "changed",
+ G_CALLBACK (file_monitor_changed_cb), monitor);
+
+ recompute_trash_state (monitor);
+}
+
+/**
+ * _gtk_trash_monitor_get:
+ *
+ * Return value: (transfer full): a new reference to the singleton
+ * #GtkTrashMonitor object. Be sure to call g_object_unref() on it when you are
+ * done with the trash monitor.
+ */
+GtkTrashMonitor *
+_gtk_trash_monitor_get (void)
+{
+ if (the_trash_monitor != NULL)
+ {
+ g_object_ref (the_trash_monitor);
+ }
+ else
+ {
+ the_trash_monitor = g_object_new (GTK_TYPE_TRASH_MONITOR, NULL);
+ g_object_add_weak_pointer (G_OBJECT (the_trash_monitor), (gpointer *) &the_trash_monitor);
+ }
+
+ return the_trash_monitor;
+}
+
+/**
+ * _gtk_trash_monitor_get_icon:
+ * @monitor: a #GtkTrashMonitor
+ *
+ * Return value: (transfer full): the #GIcon that should be used to represent
+ * the state of the trash folder on screen, based on whether there is trash or
+ * not.
+ */
+GIcon *
+_gtk_trash_monitor_get_icon (GtkTrashMonitor *monitor)
+{
+ const char *icon_name;
+
+ g_return_val_if_fail (GTK_IS_TRASH_MONITOR (monitor), NULL);
+
+ if (monitor->has_trash)
+ icon_name = ICON_NAME_TRASH_FULL;
+ else
+ icon_name = ICON_NAME_TRASH_EMPTY;
+
+ return g_themed_icon_new (icon_name);
+}
+
+/**
+ * _gtk_trash_monitor_get_has_trash:
+ * @monitor: a #GtkTrashMonitor
+ *
+ * Return value: #TRUE if there is trash in the trash:/// folder, or #FALSE otherwise.
+ */
+gboolean
+_gtk_trash_monitor_get_has_trash (GtkTrashMonitor *monitor)
+{
+ g_return_val_if_fail (GTK_IS_TRASH_MONITOR (monitor), FALSE);
+
+ return monitor->has_trash;
+}
diff --git a/gtk/gtktrashmonitor.h b/gtk/gtktrashmonitor.h
new file mode 100644
index 0000000000..f458b2bab3
--- /dev/null
+++ b/gtk/gtktrashmonitor.h
@@ -0,0 +1,48 @@
+/* GTK - The GIMP Toolkit
+ * gtktrashmonitor.h: Monitor the trash:/// folder to see if there is trash or not
+ * Copyright (C) 2011 Suse
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Federico Mena Quintero <federico@gnome.org>
+ */
+
+#ifndef __GTK_TRASH_MONITOR_H__
+#define __GTK_TRASH_MONITOR_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_TRASH_MONITOR (_gtk_trash_monitor_get_type ())
+#define GTK_TRASH_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TRASH_MONITOR, GtkTrashMonitor))
+#define GTK_TRASH_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TRASH_MONITOR, GtkTrashMonitorClass))
+#define GTK_IS_TRASH_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TRASH_MONITOR))
+#define GTK_IS_TRASH_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TRASH_MONITOR))
+#define GTK_TRASH_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TRASH_MONITOR, GtkTrashMonitorClass))
+
+typedef struct _GtkTrashMonitor GtkTrashMonitor;
+typedef struct _GtkTrashMonitorClass GtkTrashMonitorClass;
+
+GType _gtk_trash_monitor_get_type (void);
+GtkTrashMonitor *_gtk_trash_monitor_get (void);
+
+GIcon *_gtk_trash_monitor_get_icon (GtkTrashMonitor *monitor);
+
+gboolean _gtk_trash_monitor_get_has_trash (GtkTrashMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __GTK_TRASH_MONITOR_H__ */
diff --git a/gtk/org.gtk.Settings.FileChooser.gschema.xml b/gtk/org.gtk.Settings.FileChooser.gschema.xml
index d7d87058af..f2424e5655 100644
--- a/gtk/org.gtk.Settings.FileChooser.gschema.xml
+++ b/gtk/org.gtk.Settings.FileChooser.gschema.xml
@@ -33,6 +33,11 @@
<value nick='descending' value='1'/>
</enum>
+ <enum id='org.gtk.Settings.FileChooser.StartupMode'>
+ <value nick='recent' value='0'/>
+ <value nick='cwd' value='1'/>
+ </enum>
+
<schema id='org.gtk.Settings.FileChooser' path='/org/gtk/settings/file-chooser/'>
<key name='last-folder-uri' type='s'>
<default>""</default>
@@ -63,6 +68,9 @@
<key name='window-size' type='(ii)'>
<default>(-1, -1)</default>
</key>
+ <key name='startup-mode' enum='org.gtk.Settings.FileChooser.StartupMode'>
+ <default>'recent'</default>
+ </key>
<key name='sidebar-width' type='i'>
<default>148</default>
</key>
diff --git a/gtk/tests/filechooser.c b/gtk/tests/filechooser.c
index 2ca7660bb2..e37babe46d 100644
--- a/gtk/tests/filechooser.c
+++ b/gtk/tests/filechooser.c
@@ -33,7 +33,6 @@
#include <string.h>
#include <glib/gprintf.h>
#include <gtk/gtk.h>
-#include "gtk/gtkfilechooserprivate.h"
#include "gtk/gtkfilechooserdefault.h"
#include "gtk/gtkfilechooserentry.h"
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 763e5c58f2..d97e1bad19 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -57,6 +57,7 @@ gtk/gtkassistant.c
gtk/gtkbbox.c
gtk/gtkbin.c
gtk/gtkbindings.c
+gtk/gtkbookmarksmanager.c
gtk/gtkbox.c
gtk/gtkbubblewindow.c
gtk/gtkbuildable.c