summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoss Burton <ross@openedhand.com>2008-06-13 16:14:42 +0000
committerRoss Burton <ross@openedhand.com>2008-06-13 16:14:42 +0000
commitf12d247cd80b9284050a9daa8cc0faa241aac280 (patch)
tree402c54b66c77b6c12ab239c03f2a750d9058902a
parent4d650a79c62ad0c84868ab4ba4a7361b7d2b530e (diff)
downloadpoky-f12d247cd80b9284050a9daa8cc0faa241aac280.tar.gz
glib,atk,pango,gtk+: add unstable releases and use in poky-bleeding
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@4645 311d38ba-8fff-0310-9ca6-ca027cbcb966
-rw-r--r--meta/conf/distro/poky-bleeding.conf6
-rw-r--r--meta/packages/atk/atk_1.22.0.bb6
-rw-r--r--meta/packages/glib-2.0/glib-2.0-2.17.2/configure-libtool.patch34
-rw-r--r--meta/packages/glib-2.0/glib-2.0-2.17.2/glib-gettextize-dir.patch11
-rw-r--r--meta/packages/glib-2.0/glib-2.0-native_2.17.2.bb50
-rw-r--r--meta/packages/glib-2.0/glib-2.0_2.17.2.bb7
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/cellrenderer-cairo.patch32
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/combo-arrow-size.patch67
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/entry-cairo.patch103
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/filechooser-default.patch9521
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/filechooser-props.patch57
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/filechooser-sizefix.patch35
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/filesystem-volumes.patch198
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/gtklabel-resize-patch10
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/hardcoded_libtool.patch29
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/menu-deactivate.patch51
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/no-demos.patch10
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/pangoxft2.10.6.diff2456
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/range-no-redraw.patch127
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/run-iconcache.patch19
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/toggle-font.diff100
-rw-r--r--meta/packages/gtk+/gtk+-2.13.2/xsettings.patch16
-rw-r--r--meta/packages/gtk+/gtk+_2.13.2.bb47
-rw-r--r--meta/packages/pango/pango-1.21.2/no-tests.patch10
-rw-r--r--meta/packages/pango/pango_1.10.2.bb49
-rw-r--r--meta/packages/pango/pango_1.21.2.bb3
26 files changed, 13005 insertions, 49 deletions
diff --git a/meta/conf/distro/poky-bleeding.conf b/meta/conf/distro/poky-bleeding.conf
index 74b7ca2711..ac6fa452f0 100644
--- a/meta/conf/distro/poky-bleeding.conf
+++ b/meta/conf/distro/poky-bleeding.conf
@@ -1,2 +1,8 @@
1PREFERRED_VERSION_glib-2.0 ?= "2.17.2"
2PREFERRED_VERSION_glib-2.0-native ?= "2.17.2"
3PREFERRED_VERSION_atk ?= "1.22.0"
4PREFERRED_VERSION_pango ?= "1.21.2"
5PREFERRED_VERSION_gtk+ ?= "2.13.2"
6
1require conf/distro/include/poky-floating-revisions.inc 7require conf/distro/include/poky-floating-revisions.inc
2require conf/distro/poky.conf 8require conf/distro/poky.conf
diff --git a/meta/packages/atk/atk_1.22.0.bb b/meta/packages/atk/atk_1.22.0.bb
new file mode 100644
index 0000000000..62669c41fb
--- /dev/null
+++ b/meta/packages/atk/atk_1.22.0.bb
@@ -0,0 +1,6 @@
1require atk.inc
2
3SRC_URI = "http://download.gnome.org/sources/atk/1.22/${PN}-${PV}.tar.bz2"
4
5
6
diff --git a/meta/packages/glib-2.0/glib-2.0-2.17.2/configure-libtool.patch b/meta/packages/glib-2.0/glib-2.0-2.17.2/configure-libtool.patch
new file mode 100644
index 0000000000..3ba79b8986
--- /dev/null
+++ b/meta/packages/glib-2.0/glib-2.0-2.17.2/configure-libtool.patch
@@ -0,0 +1,34 @@
1# Poky renames libtool to $host_alias-libtool.
2# ./$host_alias-libtool isn't created until after configure runs with libtool >= 2.2.2
3# so we can't call # it at this point. We can safely assume a version is available
4# from PATH though
5
6--- glib-2.12.10/configure.in.orig 2006-06-05 13:34:08.000000000 +0100
7+++ glib-2.12.10/configure.in 2006-06-05 13:34:36.000000000 +0100
8@@ -1174,7 +1174,7 @@
9 G_MODULE_LDFLAGS=
10 else
11 export SED
12- G_MODULE_LDFLAGS=`(./libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh`
13+ G_MODULE_LDFLAGS=`($host_alias-libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh`
14 fi
15 dnl G_MODULE_IMPL= don't reset, so cmd-line can override
16 G_MODULE_NEED_USCORE=0
17@@ -1265,7 +1265,7 @@
18 LDFLAGS="$LDFLAGS $G_MODULE_LDFLAGS"
19 dnl *** check for OSF1/5.0 RTLD_GLOBAL brokenness
20 echo "void glib_plugin_test(void) { }" > plugin.c
21- ${SHELL} ./libtool --mode=compile ${CC} -shared \
22+ ${SHELL} $host_alias-libtool --mode=compile ${CC} -shared \
23 -export-dynamic -o plugin.o plugin.c 2>&1 >/dev/null
24 AC_CACHE_CHECK([for RTLD_GLOBAL brokenness],
25 glib_cv_rtldglobal_broken,[
26@@ -1339,7 +1339,7 @@
27
28 AC_MSG_CHECKING(for the suffix of shared libraries)
29 export SED
30-shrext_cmds=`./libtool --config | grep '^shrext_cmds='`
31+shrext_cmds=`$host_alias-libtool --config | grep '^shrext_cmds='`
32 eval $shrext_cmds
33 module=yes eval std_shrext=$shrext_cmds
34 # chop the initial dot
diff --git a/meta/packages/glib-2.0/glib-2.0-2.17.2/glib-gettextize-dir.patch b/meta/packages/glib-2.0/glib-2.0-2.17.2/glib-gettextize-dir.patch
new file mode 100644
index 0000000000..efe3325578
--- /dev/null
+++ b/meta/packages/glib-2.0/glib-2.0-2.17.2/glib-gettextize-dir.patch
@@ -0,0 +1,11 @@
1--- glib-2.10.3/glib-gettextize.in.old 2006-06-21 12:46:45.000000000 +0100
2+++ glib-2.10.3/glib-gettextize.in 2006-06-21 12:48:14.000000000 +0100
3@@ -49,7 +49,7 @@
4 ;;
5 esac
6
7-gettext_dir=$prefix/share/glib-2.0/gettext
8+gettext_dir=@datadir@/glib-2.0/gettext
9
10 while test $# -gt 0; do
11 case "$1" in
diff --git a/meta/packages/glib-2.0/glib-2.0-native_2.17.2.bb b/meta/packages/glib-2.0/glib-2.0-native_2.17.2.bb
new file mode 100644
index 0000000000..e5a2b64c90
--- /dev/null
+++ b/meta/packages/glib-2.0/glib-2.0-native_2.17.2.bb
@@ -0,0 +1,50 @@
1DESCRIPTION = "GLib is a general-purpose utility library, \
2which provides many useful data types, macros, \
3type conversions, string utilities, file utilities, a main \
4loop abstraction, and so on. It works on many \
5UNIX-like platforms, Windows, OS/2 and BeOS."
6LICENSE = "LGPL"
7SECTION = "libs"
8PRIORITY = "optional"
9DEPENDS += "gtk-doc-native"
10PR = "r0"
11
12SRC_URI = "http://download.gnome.org/sources/glib/2.17/glib-${PV}.tar.bz2 \
13 file://glib-gettextize-dir.patch;patch=1 \
14 file://configure-libtool.patch;patch=1 \
15 file://glibconfig-sysdefs.h"
16
17S = "${WORKDIR}/glib-${PV}"
18
19inherit autotools pkgconfig native gettext
20
21FILESDIR = "${@os.path.dirname(bb.data.getVar('FILE',d,1))}/glib-2.0-${PV}"
22
23acpaths = ""
24do_configure_prepend () {
25 install -m 0644 ${WORKDIR}/glibconfig-sysdefs.h .
26}
27
28do_stage () {
29 install -m 0755 gobject/glib-mkenums ${STAGING_BINDIR}/
30 install -m 0755 gobject/.libs/glib-genmarshal ${STAGING_BINDIR}/
31 install -m 0755 glib-gettextize ${STAGING_BINDIR}/
32 oe_libinstall -so -C glib libglib-2.0 ${STAGING_LIBDIR}
33 oe_libinstall -so -C gmodule libgmodule-2.0 ${STAGING_LIBDIR}
34 oe_libinstall -so -C gthread libgthread-2.0 ${STAGING_LIBDIR}
35 oe_libinstall -so -C gobject libgobject-2.0 ${STAGING_LIBDIR}
36 autotools_stage_includes
37 install -d ${STAGING_INCDIR}/glib-2.0/glib
38 install -m 0755 ${S}/glibconfig.h ${STAGING_INCDIR}/glib-2.0/glibconfig.h
39 install -d ${STAGING_DATADIR}/aclocal
40 install -m 0644 ${S}/m4macros/glib-2.0.m4 ${STAGING_DATADIR}/aclocal/glib-2.0.m4
41 install -m 0644 ${S}/m4macros/glib-gettext.m4 ${STAGING_DATADIR}/aclocal/glib-gettext.m4
42 install -d ${STAGING_DATADIR}/glib-2.0/gettext/po
43 install -m 0755 mkinstalldirs ${STAGING_DATADIR}/glib-2.0/gettext/
44 install -m 0644 po/Makefile.in.in ${STAGING_DATADIR}/glib-2.0/gettext/po/
45}
46
47do_install () {
48 :
49}
50
diff --git a/meta/packages/glib-2.0/glib-2.0_2.17.2.bb b/meta/packages/glib-2.0/glib-2.0_2.17.2.bb
new file mode 100644
index 0000000000..677c321e37
--- /dev/null
+++ b/meta/packages/glib-2.0/glib-2.0_2.17.2.bb
@@ -0,0 +1,7 @@
1require glib.inc
2
3PR = "r0"
4
5SRC_URI = "http://ftp.gnome.org/pub/GNOME/sources/glib/2.17/glib-${PV}.tar.bz2 \
6 file://glibconfig-sysdefs.h \
7 file://configure-libtool.patch;patch=1"
diff --git a/meta/packages/gtk+/gtk+-2.13.2/cellrenderer-cairo.patch b/meta/packages/gtk+/gtk+-2.13.2/cellrenderer-cairo.patch
new file mode 100644
index 0000000000..4439e69fb6
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/cellrenderer-cairo.patch
@@ -0,0 +1,32 @@
1Index: gtk/gtkcellrenderer.c
2===================================================================
3RCS file: /cvs/gnome/gtk+/gtk/gtkcellrenderer.c,v
4retrieving revision 1.55
5diff -u -r1.55 gtkcellrenderer.c
6--- gtk/gtkcellrenderer.c 14 May 2006 04:25:28 -0000 1.55
7+++ gtk/gtkcellrenderer.c 30 Jun 2006 10:57:43 -0000
8@@ -551,6 +551,7 @@
9
10 if (cell->cell_background_set && !selected)
11 {
12+#ifdef USE_CAIRO_INTERNALLY
13 cairo_t *cr = gdk_cairo_create (window);
14
15 gdk_cairo_rectangle (cr, background_area);
16@@ -558,6 +559,16 @@
17 cairo_fill (cr);
18
19 cairo_destroy (cr);
20+#else
21+ GdkGC *gc;
22+
23+ gc = gdk_gc_new (window);
24+ gdk_gc_set_rgb_fg_color (gc, &priv->cell_background);
25+ gdk_draw_rectangle (window, gc, TRUE,
26+ background_area->x, background_area->y,
27+ background_area->width, background_area->height);
28+ g_object_unref (gc);
29+#endif
30 }
31
32 GTK_CELL_RENDERER_GET_CLASS (cell)->render (cell,
diff --git a/meta/packages/gtk+/gtk+-2.13.2/combo-arrow-size.patch b/meta/packages/gtk+/gtk+-2.13.2/combo-arrow-size.patch
new file mode 100644
index 0000000000..d44c454ce3
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/combo-arrow-size.patch
@@ -0,0 +1,67 @@
1Index: gtk/gtkcombobox.c
2===================================================================
3RCS file: /cvs/gnome/gtk+/gtk/gtkcombobox.c,v
4retrieving revision 1.185
5diff -u -p -r1.185 gtkcombobox.c
6--- gtk/gtkcombobox.c 12 Oct 2006 13:48:07 -0000 1.185
7+++ gtk/gtkcombobox.c 1 Nov 2006 19:01:09 -0000
8@@ -756,6 +756,25 @@ gtk_combo_box_class_init (GtkComboBoxCla
9 FALSE,
10 GTK_PARAM_READABLE));
11
12+ /**
13+ * GtkComboBox:arrow-size:
14+ *
15+ * Sets the minimum size of the arrow in the combo box. Note
16+ * that the arrow size is coupled to the font size, so in case
17+ * a larger font is used, the arrow will be larger than set
18+ * by arrow size.
19+ *
20+ * Since: 2.12
21+ */
22+ gtk_widget_class_install_style_property (widget_class,
23+ g_param_spec_int ("arrow-size",
24+ P_("Arrow Size"),
25+ P_("The minimum size of the arrow in the combo box"),
26+ 0,
27+ G_MAXINT,
28+ 15,
29+ GTK_PARAM_READABLE));
30+
31 g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate));
32 }
33
34@@ -1897,7 +1916,12 @@ gtk_combo_box_size_request (GtkWidget
35 {
36 gint width, height;
37 gint focus_width, focus_pad;
38+ gint font_size;
39+ gint arrow_size;
40 GtkRequisition bin_req;
41+ PangoContext *context;
42+ PangoFontMetrics *metrics;
43+ PangoFontDescription *font_desc;
44
45 GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
46
47@@ -1910,7 +1934,20 @@ gtk_combo_box_size_request (GtkWidget
48 gtk_widget_style_get (GTK_WIDGET (widget),
49 "focus-line-width", &focus_width,
50 "focus-padding", &focus_pad,
51+ "arrow-size", &arrow_size,
52 NULL);
53+
54+ font_desc = GTK_BIN (widget)->child->style->font_desc;
55+ context = gtk_widget_get_pango_context (widget);
56+ metrics = pango_context_get_metrics (context, font_desc,
57+ pango_context_get_language (context));
58+ font_size = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
59+ pango_font_metrics_get_descent (metrics));
60+ pango_font_metrics_unref (metrics);
61+
62+ arrow_size = MAX (arrow_size, font_size);
63+
64+ gtk_widget_set_size_request (combo_box->priv->arrow, arrow_size, arrow_size);
65
66 if (!combo_box->priv->tree_view)
67 {
diff --git a/meta/packages/gtk+/gtk+-2.13.2/entry-cairo.patch b/meta/packages/gtk+/gtk+-2.13.2/entry-cairo.patch
new file mode 100644
index 0000000000..3313e7f132
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/entry-cairo.patch
@@ -0,0 +1,103 @@
1Index: gtk/gtkentry.c
2===================================================================
3RCS file: /cvs/gnome/gtk+/gtk/gtkentry.c,v
4retrieving revision 1.317
5diff -u -r1.317 gtkentry.c
6--- gtk/gtkentry.c 29 Jun 2006 09:18:05 -0000 1.317
7+++ gtk/gtkentry.c 2 Jul 2006 14:14:24 -0000
8@@ -3337,7 +3337,9 @@
9 if (GTK_WIDGET_DRAWABLE (entry))
10 {
11 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
12+#ifdef USE_CAIRO_INTERNALLY
13 cairo_t *cr;
14+#endif
15 gint x, y;
16 gint start_pos, end_pos;
17
18@@ -3345,23 +3347,35 @@
19
20 get_layout_position (entry, &x, &y);
21
22+#ifdef USE_CAIRO_INTERNALLY
23 cr = gdk_cairo_create (entry->text_area);
24
25 cairo_move_to (cr, x, y);
26 gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
27 pango_cairo_show_layout (cr, layout);
28+#else
29+ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
30+ x, y,
31+ layout);
32+#endif
33
34 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
35 {
36 gint *ranges;
37 gint n_ranges, i;
38 PangoRectangle logical_rect;
39- GdkColor *selection_color, *text_color;
40 GtkBorder inner_border;
41+#ifdef USE_CAIRO_INTERNALLY
42+ GdkColor *selection_color, *text_color;
43+#else
44+ GdkGC *selection_gc, *text_gc;
45+ GdkRegion *clip_region;
46+#endif
47
48 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
49 gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
50
51+#ifdef USE_CAIRO_INTERNALLY
52 if (GTK_WIDGET_HAS_FOCUS (entry))
53 {
54 selection_color = &widget->style->base [GTK_STATE_SELECTED];
55@@ -3390,11 +3404,46 @@
56 cairo_move_to (cr, x, y);
57 gdk_cairo_set_source_color (cr, text_color);
58 pango_cairo_show_layout (cr, layout);
59-
60+#else
61+ if (GTK_WIDGET_HAS_FOCUS (entry))
62+ {
63+ selection_gc = widget->style->base_gc [GTK_STATE_SELECTED];
64+ text_gc = widget->style->text_gc [GTK_STATE_SELECTED];
65+ }
66+ else
67+ {
68+ selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE];
69+ text_gc = widget->style->text_gc [GTK_STATE_ACTIVE];
70+ }
71+
72+ clip_region = gdk_region_new ();
73+ for (i = 0; i < n_ranges; ++i)
74+ {
75+ GdkRectangle rect;
76+
77+ rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i];
78+ rect.y = y;
79+ rect.width = ranges[2 * i + 1];
80+ rect.height = logical_rect.height;
81+
82+ gdk_draw_rectangle (entry->text_area, selection_gc, TRUE,
83+ rect.x, rect.y, rect.width, rect.height);
84+
85+ gdk_region_union_with_rect (clip_region, &rect);
86+ }
87+
88+ gdk_gc_set_clip_region (text_gc, clip_region);
89+ gdk_draw_layout (entry->text_area, text_gc,
90+ x, y,
91+ layout);
92+ gdk_gc_set_clip_region (text_gc, NULL);
93+ gdk_region_destroy (clip_region);
94+#endif
95 g_free (ranges);
96 }
97-
98+#ifdef USE_CAIRO_INTERNALLY
99 cairo_destroy (cr);
100+#endif
101 }
102 }
103
diff --git a/meta/packages/gtk+/gtk+-2.13.2/filechooser-default.patch b/meta/packages/gtk+/gtk+-2.13.2/filechooser-default.patch
new file mode 100644
index 0000000000..146316c9c1
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/filechooser-default.patch
@@ -0,0 +1,9521 @@
1Index: gtk+-2.12.5/gtk/gtkfilechooserdefault.c
2================ ===================================================
3--- gtk+-2.12.5/gtk/gtkfilechooserdefault.c (revision 19337)
4+++ gtk+-2.12.5/gtk/gtkfilechooserdefault.c (working copy)
5@@ -27,12 +27,12 @@
6 #include "gtkcelllayout.h"
7 #include "gtkcellrendererpixbuf.h"
8 #include "gtkcellrenderertext.h"
9+#include "gtkcellrenderertext.h"
10 #include "gtkcheckmenuitem.h"
11 #include "gtkclipboard.h"
12 #include "gtkcombobox.h"
13 #include "gtkentry.h"
14 #include "gtkeventbox.h"
15-#include "gtkexpander.h"
16 #include "gtkfilechooserprivate.h"
17 #include "gtkfilechooserdefault.h"
18 #include "gtkfilechooserembed.h"
19@@ -53,17 +53,13 @@
20 #include "gtkmarshalers.h"
21 #include "gtkmenuitem.h"
22 #include "gtkmessagedialog.h"
23-#include "gtkpathbar.h"
24 #include "gtkprivate.h"
25 #include "gtkradiobutton.h"
26-#include "gtkrecentfilter.h"
27-#include "gtkrecentmanager.h"
28 #include "gtkscrolledwindow.h"
29 #include "gtkseparatormenuitem.h"
30 #include "gtksizegroup.h"
31 #include "gtkstock.h"
32 #include "gtktable.h"
33-#include "gtktooltip.h"
34 #include "gtktreednd.h"
35 #include "gtktreeprivate.h"
36 #include "gtktreeselection.h"
37@@ -81,8 +77,6 @@
38 #include <errno.h>
39 #include <string.h>
40 #include <time.h>
41-#include <sys/stat.h>
42-#include <sys/types.h>
43
44
45 #ifdef HAVE_UNISTD_H
46@@ -92,6 +86,8 @@
47 #include <io.h>
48 #endif
49
50+#define DEFAULT_SPACING 5
51+
52 /* Profiling stuff */
53 #undef PROFILE_FILE_CHOOSER
54 #ifdef PROFILE_FILE_CHOOSER
55@@ -150,6 +145,7 @@
56 #define GTK_FILE_CHOOSER_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
57
58 #define MAX_LOADING_TIME 500
59+#define LONG_CLICK_LENGTH 500
60
61 struct _GtkFileChooserDefaultClass
62 {
63@@ -163,38 +159,12 @@
64 UP_FOLDER,
65 DOWN_FOLDER,
66 HOME_FOLDER,
67- DESKTOP_FOLDER,
68- QUICK_BOOKMARK,
69- LOCATION_TOGGLE_POPUP,
70 SHOW_HIDDEN,
71- SEARCH_SHORTCUT,
72- RECENT_SHORTCUT,
73-
74 LAST_SIGNAL
75 };
76
77 static guint signals[LAST_SIGNAL] = { 0 };
78
79-/* Column numbers for the shortcuts tree. Keep these in sync with shortcuts_model_create() */
80-enum {
81- SHORTCUTS_COL_PIXBUF,
82- SHORTCUTS_COL_NAME,
83- SHORTCUTS_COL_DATA,
84- SHORTCUTS_COL_TYPE,
85- SHORTCUTS_COL_REMOVABLE,
86- SHORTCUTS_COL_PIXBUF_VISIBLE,
87- SHORTCUTS_COL_HANDLE,
88- SHORTCUTS_COL_NUM_COLUMNS
89-};
90-
91-typedef enum {
92- SHORTCUT_TYPE_PATH,
93- SHORTCUT_TYPE_VOLUME,
94- SHORTCUT_TYPE_SEPARATOR,
95- SHORTCUT_TYPE_SEARCH,
96- SHORTCUT_TYPE_RECENT
97-} ShortcutType;
98-
99 /* Column numbers for the file list */
100 enum {
101 FILE_LIST_COL_NAME,
102@@ -203,100 +173,10 @@
103 FILE_LIST_COL_NUM_COLUMNS
104 };
105
106-/* Column numbers for the search model.
107- * Keep this in sync with search_setup_model()
108- */
109-enum {
110- SEARCH_MODEL_COL_PATH,
111- SEARCH_MODEL_COL_DISPLAY_NAME,
112- SEARCH_MODEL_COL_COLLATION_KEY,
113- SEARCH_MODEL_COL_STAT,
114- SEARCH_MODEL_COL_HANDLE,
115- SEARCH_MODEL_COL_PIXBUF,
116- SEARCH_MODEL_COL_MIME_TYPE,
117- SEARCH_MODEL_COL_IS_FOLDER,
118- SEARCH_MODEL_COL_NUM_COLUMNS
119-};
120-
121-enum {
122- RECENT_MODEL_COL_PATH,
123- RECENT_MODEL_COL_DISPLAY_NAME,
124- RECENT_MODEL_COL_INFO,
125- RECENT_MODEL_COL_IS_FOLDER,
126- RECENT_MODEL_COL_HANDLE,
127- RECENT_MODEL_COL_NUM_COLUMNS
128-};
129-
130-/* Identifiers for target types */
131-enum {
132- GTK_TREE_MODEL_ROW,
133- TEXT_URI_LIST
134-};
135-
136-/* Target types for dragging from the shortcuts list */
137-static const GtkTargetEntry shortcuts_source_targets[] = {
138- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
139-};
140-
141-static const int num_shortcuts_source_targets = G_N_ELEMENTS (shortcuts_source_targets);
142-
143-/* Target types for dropping into the shortcuts list */
144-static const GtkTargetEntry shortcuts_dest_targets[] = {
145- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
146- { "text/uri-list", 0, TEXT_URI_LIST }
147-};
148-
149-static const int num_shortcuts_dest_targets = G_N_ELEMENTS (shortcuts_dest_targets);
150-
151-/* Target types for DnD from the file list */
152-static const GtkTargetEntry file_list_source_targets[] = {
153- { "text/uri-list", 0, TEXT_URI_LIST }
154-};
155-
156-static const int num_file_list_source_targets = G_N_ELEMENTS (file_list_source_targets);
157-
158-/* Target types for dropping into the file list */
159-static const GtkTargetEntry file_list_dest_targets[] = {
160- { "text/uri-list", 0, TEXT_URI_LIST }
161-};
162-
163-static const int num_file_list_dest_targets = G_N_ELEMENTS (file_list_dest_targets);
164-
165-/* Target types for dragging from the recent files list */
166-static const GtkTargetEntry recent_list_source_targets[] = {
167- { "text/uri-list", 0, TEXT_URI_LIST }
168-};
169-
170-static const int num_recent_list_source_targets = G_N_ELEMENTS (recent_list_source_targets);
171-
172-static gboolean
173-search_is_possible (GtkFileChooserDefault *impl)
174-{
175- if (impl->search_engine == NULL)
176- impl->search_engine = _gtk_search_engine_new ();
177-
178- return impl->search_engine != NULL;
179-}
180-
181-/* Interesting places in the shortcuts bar */
182-typedef enum {
183- SHORTCUTS_SEARCH,
184- SHORTCUTS_RECENT,
185- SHORTCUTS_RECENT_SEPARATOR,
186- SHORTCUTS_HOME,
187- SHORTCUTS_DESKTOP,
188- SHORTCUTS_VOLUMES,
189- SHORTCUTS_SHORTCUTS,
190- SHORTCUTS_BOOKMARKS_SEPARATOR,
191- SHORTCUTS_BOOKMARKS,
192- SHORTCUTS_CURRENT_FOLDER_SEPARATOR,
193- SHORTCUTS_CURRENT_FOLDER
194-} ShortcutsIndex;
195-
196 /* Icon size for if we can't get it from the theme */
197-#define FALLBACK_ICON_SIZE 16
198+#define FALLBACK_ICON_SIZE 24
199
200-#define PREVIEW_HBOX_SPACING 12
201+#define LIST_HBOX_SPACING DEFAULT_SPACING
202 #define NUM_LINES 45
203 #define NUM_CHARS 60
204
205@@ -369,52 +248,17 @@
206 static gboolean gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed);
207 static void gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed);
208
209-static void location_popup_handler (GtkFileChooserDefault *impl,
210- const gchar *path);
211-static void location_popup_on_paste_handler (GtkFileChooserDefault *impl);
212-static void location_toggle_popup_handler (GtkFileChooserDefault *impl);
213-static void up_folder_handler (GtkFileChooserDefault *impl);
214-static void down_folder_handler (GtkFileChooserDefault *impl);
215-static void home_folder_handler (GtkFileChooserDefault *impl);
216-static void desktop_folder_handler (GtkFileChooserDefault *impl);
217-static void quick_bookmark_handler (GtkFileChooserDefault *impl,
218- gint bookmark_index);
219-static void show_hidden_handler (GtkFileChooserDefault *impl);
220-static void search_shortcut_handler (GtkFileChooserDefault *impl);
221-static void recent_shortcut_handler (GtkFileChooserDefault *impl);
222-static void update_appearance (GtkFileChooserDefault *impl);
223+static void up_folder_handler (GtkFileChooserDefault *impl);
224+static void down_folder_handler (GtkFileChooserDefault *impl);
225+static void home_folder_handler (GtkFileChooserDefault *impl);
226+static void show_hidden_handler (GtkFileChooserDefault *impl);
227+static void update_appearance (GtkFileChooserDefault *impl);
228
229-static void set_current_filter (GtkFileChooserDefault *impl,
230- GtkFileFilter *filter);
231-static void check_preview_change (GtkFileChooserDefault *impl);
232-
233 static void filter_combo_changed (GtkComboBox *combo_box,
234 GtkFileChooserDefault *impl);
235-static void shortcuts_row_activated_cb (GtkTreeView *tree_view,
236- GtkTreePath *path,
237- GtkTreeViewColumn *column,
238- GtkFileChooserDefault *impl);
239
240-static gboolean shortcuts_key_press_event_cb (GtkWidget *widget,
241- GdkEventKey *event,
242- GtkFileChooserDefault *impl);
243-
244-static gboolean shortcuts_select_func (GtkTreeSelection *selection,
245- GtkTreeModel *model,
246- GtkTreePath *path,
247- gboolean path_currently_selected,
248- gpointer data);
249-static gboolean shortcuts_get_selected (GtkFileChooserDefault *impl,
250- GtkTreeIter *iter);
251-static void shortcuts_activate_iter (GtkFileChooserDefault *impl,
252- GtkTreeIter *iter);
253-static int shortcuts_get_index (GtkFileChooserDefault *impl,
254- ShortcutsIndex where);
255-static int shortcut_find_position (GtkFileChooserDefault *impl,
256- const GtkFilePath *path);
257-
258-static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl);
259-
260+static void set_current_filter (GtkFileChooserDefault *impl,
261+ GtkFileFilter *filter);
262 static gboolean list_select_func (GtkTreeSelection *selection,
263 GtkTreeModel *model,
264 GtkTreePath *path,
265@@ -433,19 +277,6 @@
266 GtkTreeIter *iter,
267 gpointer user_data);
268
269-static void path_bar_clicked (GtkPathBar *path_bar,
270- GtkFilePath *file_path,
271- GtkFilePath *child_path,
272- gboolean child_is_hidden,
273- GtkFileChooserDefault *impl);
274-
275-static void add_bookmark_button_clicked_cb (GtkButton *button,
276- GtkFileChooserDefault *impl);
277-static void remove_bookmark_button_clicked_cb (GtkButton *button,
278- GtkFileChooserDefault *impl);
279-static void save_folder_combo_changed_cb (GtkComboBox *combo,
280- GtkFileChooserDefault *impl);
281-
282 static void list_icon_data_func (GtkTreeViewColumn *tree_column,
283 GtkCellRenderer *cell,
284 GtkTreeModel *tree_model,
285@@ -477,115 +308,8 @@
286
287 static void location_button_toggled_cb (GtkToggleButton *toggle,
288 GtkFileChooserDefault *impl);
289-static void location_switch_to_path_bar (GtkFileChooserDefault *impl);
290+static void settings_load (GtkFileChooserDefault *impl);
291
292-static void search_stop_searching (GtkFileChooserDefault *impl,
293- gboolean remove_query);
294-static void search_clear_model (GtkFileChooserDefault *impl,
295- gboolean remove_from_treeview);
296-static gboolean search_should_respond (GtkFileChooserDefault *impl);
297-static void search_switch_to_browse_mode (GtkFileChooserDefault *impl);
298-static GSList *search_get_selected_paths (GtkFileChooserDefault *impl);
299-static void search_entry_activate_cb (GtkEntry *entry,
300- gpointer data);
301-static void settings_load (GtkFileChooserDefault *impl);
302-static void search_get_valid_child_iter (GtkFileChooserDefault *impl,
303- GtkTreeIter *child_iter,
304- GtkTreeIter *iter);
305-
306-static void recent_manager_update (GtkFileChooserDefault *impl);
307-static void recent_stop_loading (GtkFileChooserDefault *impl);
308-static void recent_clear_model (GtkFileChooserDefault *impl,
309- gboolean remove_from_treeview);
310-static gboolean recent_should_respond (GtkFileChooserDefault *impl);
311-static void recent_switch_to_browse_mode (GtkFileChooserDefault *impl);
312-static GSList * recent_get_selected_paths (GtkFileChooserDefault *impl);
313-static void recent_get_valid_child_iter (GtkFileChooserDefault *impl,
314- GtkTreeIter *child_iter,
315- GtkTreeIter *iter);
316-
317-
318-
319-
320-/* Drag and drop interface declarations */
321-
322-typedef struct {
323- GtkTreeModelFilter parent;
324-
325- GtkFileChooserDefault *impl;
326-} ShortcutsPaneModelFilter;
327-
328-typedef struct {
329- GtkTreeModelFilterClass parent_class;
330-} ShortcutsPaneModelFilterClass;
331-
332-#define SHORTCUTS_PANE_MODEL_FILTER_TYPE (_shortcuts_pane_model_filter_get_type ())
333-#define SHORTCUTS_PANE_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_PANE_MODEL_FILTER_TYPE, ShortcutsPaneModelFilter))
334-
335-static void shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
336-
337-G_DEFINE_TYPE_WITH_CODE (ShortcutsPaneModelFilter,
338- _shortcuts_pane_model_filter,
339- GTK_TYPE_TREE_MODEL_FILTER,
340- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
341- shortcuts_pane_model_filter_drag_source_iface_init))
342-
343-static GtkTreeModel *shortcuts_pane_model_filter_new (GtkFileChooserDefault *impl,
344- GtkTreeModel *child_model,
345- GtkTreePath *root);
346-
347-
348-typedef struct {
349- GtkTreeModelSort parent;
350-
351- GtkFileChooserDefault *impl;
352-} RecentModelSort;
353-
354-typedef struct {
355- GtkTreeModelSortClass parent_class;
356-} RecentModelSortClass;
357-
358-#define RECENT_MODEL_SORT_TYPE (_recent_model_sort_get_type ())
359-#define RECENT_MODEL_SORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RECENT_MODEL_SORT_TYPE, RecentModelSort))
360-
361-static void recent_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface);
362-
363-G_DEFINE_TYPE_WITH_CODE (RecentModelSort,
364- _recent_model_sort,
365- GTK_TYPE_TREE_MODEL_SORT,
366- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
367- recent_model_sort_drag_source_iface_init));
368-
369-static GtkTreeModel *recent_model_sort_new (GtkFileChooserDefault *impl,
370- GtkTreeModel *child_model);
371-
372-
373-typedef struct {
374- GtkTreeModelSort parent;
375-
376- GtkFileChooserDefault *impl;
377-} SearchModelSort;
378-
379-typedef struct {
380- GtkTreeModelSortClass parent_class;
381-} SearchModelSortClass;
382-
383-#define SEARCH_MODEL_SORT_TYPE (_search_model_sort_get_type ())
384-#define SEARCH_MODEL_SORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEARCH_MODEL_SORT_TYPE, SearchModelSort))
385-
386-static void search_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface);
387-
388-G_DEFINE_TYPE_WITH_CODE (SearchModelSort,
389- _search_model_sort,
390- GTK_TYPE_TREE_MODEL_SORT,
391- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
392- search_model_sort_drag_source_iface_init));
393-
394-static GtkTreeModel *search_model_sort_new (GtkFileChooserDefault *impl,
395- GtkTreeModel *child_model);
396-
397-
398-
399 G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_VBOX,
400 G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
401 gtk_file_chooser_default_iface_init)
402@@ -595,13 +319,9 @@
403 static void
404 _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
405 {
406- static const guint quick_bookmark_keyvals[10] = {
407- GDK_1, GDK_2, GDK_3, GDK_4, GDK_5, GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
408- };
409 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
410 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
411 GtkBindingSet *binding_set;
412- int i;
413
414 gobject_class->finalize = gtk_file_chooser_default_finalize;
415 gobject_class->constructor = gtk_file_chooser_default_constructor;
416@@ -621,7 +341,7 @@
417 _gtk_binding_signal_new (I_("location-popup"),
418 G_OBJECT_CLASS_TYPE (class),
419 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
420- G_CALLBACK (location_popup_handler),
421+ NULL,
422 NULL, NULL,
423 _gtk_marshal_VOID__STRING,
424 G_TYPE_NONE, 1, G_TYPE_STRING);
425@@ -629,18 +349,10 @@
426 _gtk_binding_signal_new ("location-popup-on-paste",
427 G_OBJECT_CLASS_TYPE (class),
428 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
429- G_CALLBACK (location_popup_on_paste_handler),
430+ NULL,
431 NULL, NULL,
432 _gtk_marshal_VOID__VOID,
433 G_TYPE_NONE, 0);
434- signals[LOCATION_TOGGLE_POPUP] =
435- _gtk_binding_signal_new (I_("location-toggle-popup"),
436- G_OBJECT_CLASS_TYPE (class),
437- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
438- G_CALLBACK (location_toggle_popup_handler),
439- NULL, NULL,
440- _gtk_marshal_VOID__VOID,
441- G_TYPE_NONE, 0);
442 signals[UP_FOLDER] =
443 _gtk_binding_signal_new (I_("up-folder"),
444 G_OBJECT_CLASS_TYPE (class),
445@@ -665,22 +377,6 @@
446 NULL, NULL,
447 _gtk_marshal_VOID__VOID,
448 G_TYPE_NONE, 0);
449- signals[DESKTOP_FOLDER] =
450- _gtk_binding_signal_new (I_("desktop-folder"),
451- G_OBJECT_CLASS_TYPE (class),
452- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
453- G_CALLBACK (desktop_folder_handler),
454- NULL, NULL,
455- _gtk_marshal_VOID__VOID,
456- G_TYPE_NONE, 0);
457- signals[QUICK_BOOKMARK] =
458- _gtk_binding_signal_new (I_("quick-bookmark"),
459- G_OBJECT_CLASS_TYPE (class),
460- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
461- G_CALLBACK (quick_bookmark_handler),
462- NULL, NULL,
463- _gtk_marshal_VOID__INT,
464- G_TYPE_NONE, 1, G_TYPE_INT);
465 signals[SHOW_HIDDEN] =
466 _gtk_binding_signal_new ("show-hidden",
467 G_OBJECT_CLASS_TYPE (class),
468@@ -689,22 +385,6 @@
469 NULL, NULL,
470 _gtk_marshal_VOID__VOID,
471 G_TYPE_NONE, 0);
472- signals[SEARCH_SHORTCUT] =
473- _gtk_binding_signal_new ("search-shortcut",
474- G_OBJECT_CLASS_TYPE (class),
475- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
476- G_CALLBACK (search_shortcut_handler),
477- NULL, NULL,
478- _gtk_marshal_VOID__VOID,
479- G_TYPE_NONE, 0);
480- signals[RECENT_SHORTCUT] =
481- _gtk_binding_signal_new ("recent-shortcut",
482- G_OBJECT_CLASS_TYPE (class),
483- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
484- G_CALLBACK (recent_shortcut_handler),
485- NULL, NULL,
486- _gtk_marshal_VOID__VOID,
487- G_TYPE_NONE, 0);
488
489 binding_set = gtk_binding_set_by_class (class);
490
491@@ -764,29 +444,11 @@
492 "home-folder",
493 0);
494 gtk_binding_entry_add_signal (binding_set,
495- GDK_d, GDK_MOD1_MASK,
496- "desktop-folder",
497- 0);
498- gtk_binding_entry_add_signal (binding_set,
499 GDK_h, GDK_CONTROL_MASK,
500 "show-hidden",
501 0);
502- gtk_binding_entry_add_signal (binding_set,
503- GDK_s, GDK_MOD1_MASK,
504- "search-shortcut",
505- 0);
506- gtk_binding_entry_add_signal (binding_set,
507- GDK_r, GDK_MOD1_MASK,
508- "recent-shortcut",
509- 0);
510
511- for (i = 0; i < 10; i++)
512- gtk_binding_entry_add_signal (binding_set,
513- quick_bookmark_keyvals[i], GDK_MOD1_MASK,
514- "quick-bookmark",
515- 1, G_TYPE_INT, i);
516-
517 _gtk_file_chooser_install_properties (gobject_class);
518 }
519
520 static void
521@@ -797,7 +465,6 @@
522 iface->select_all = gtk_file_chooser_default_select_all;
523 iface->unselect_all = gtk_file_chooser_default_unselect_all;
524 iface->get_paths = gtk_file_chooser_default_get_paths;
525- iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
526 iface->get_file_system = gtk_file_chooser_default_get_file_system;
527 iface->set_current_folder = gtk_file_chooser_default_set_current_folder;
528 iface->get_current_folder = gtk_file_chooser_default_get_current_folder;
529@@ -805,9 +472,12 @@
530 iface->add_filter = gtk_file_chooser_default_add_filter;
531 iface->remove_filter = gtk_file_chooser_default_remove_filter;
532 iface->list_filters = gtk_file_chooser_default_list_filters;
533+
534+ /* these are only stubs */
535+ iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
536 iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder;
537 iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder;
538- iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders;
539+
540 }
541
542 static void
543@@ -827,87 +497,29 @@
544 access ("MARK: *** CREATE FILE CHOOSER", F_OK);
545 #endif
546 impl->local_only = TRUE;
547- impl->preview_widget_active = TRUE;
548- impl->use_preview_label = TRUE;
549 impl->select_multiple = FALSE;
550 impl->show_hidden = FALSE;
551+ impl->show_create_folder = TRUE;
552 impl->icon_size = FALLBACK_ICON_SIZE;
553 impl->load_state = LOAD_EMPTY;
554 impl->reload_state = RELOAD_EMPTY;
555 impl->pending_select_paths = NULL;
556- impl->location_mode = LOCATION_MODE_PATH_BAR;
557- impl->operation_mode = OPERATION_MODE_BROWSE;
558+ impl->location_mode = LOCATION_MODE_FILENAME_ENTRY;
559+ impl->path_history = NULL;
560
561- gtk_box_set_spacing (GTK_BOX (impl), 12);
562+ gtk_box_set_spacing (GTK_BOX (impl), DEFAULT_SPACING);
563
564 impl->tooltips = gtk_tooltips_new ();
565 g_object_ref_sink (impl->tooltips);
566
567+ if (!impl->root_folder)
568+ impl->root_folder = g_strdup ("/");
569+
570 profile_end ("end", NULL);
571 }
572
573-/* Frees the data columns for the specified iter in the shortcuts model*/
574-static void
575-shortcuts_free_row_data (GtkFileChooserDefault *impl,
576- GtkTreeIter *iter)
577-{
578- gpointer col_data;
579- ShortcutType shortcut_type;
580- GtkFileSystemHandle *handle;
581
582- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
583- SHORTCUTS_COL_DATA, &col_data,
584- SHORTCUTS_COL_TYPE, &shortcut_type,
585- SHORTCUTS_COL_HANDLE, &handle,
586- -1);
587-
588- if (handle)
589- gtk_file_system_cancel_operation (handle);
590-
591- if (!(shortcut_type == SHORTCUT_TYPE_PATH ||
592- shortcut_type == SHORTCUT_TYPE_VOLUME) ||
593- !col_data)
594- return;
595-
596- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
597- {
598- GtkFileSystemVolume *volume;
599-
600- volume = col_data;
601- gtk_file_system_volume_free (impl->file_system, volume);
602- }
603- else
604- {
605- GtkFilePath *path;
606-
607- g_assert (shortcut_type == SHORTCUT_TYPE_PATH);
608-
609- path = col_data;
610- gtk_file_path_free (path);
611- }
612-}
613-
614-/* Frees all the data columns in the shortcuts model */
615 static void
616-shortcuts_free (GtkFileChooserDefault *impl)
617-{
618- GtkTreeIter iter;
619-
620- if (!impl->shortcuts_model)
621- return;
622-
623- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
624- do
625- {
626- shortcuts_free_row_data (impl, &iter);
627- }
628- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter));
629-
630- g_object_unref (impl->shortcuts_model);
631- impl->shortcuts_model = NULL;
632-}
633-
634-static void
635 pending_select_paths_free (GtkFileChooserDefault *impl)
636 {
637 GSList *l;
638@@ -964,19 +576,28 @@
639 }
640
641 static void
642-gtk_file_chooser_default_finalize (GObject *object)
643+path_history_free (GtkFileChooserDefault *impl)
644 {
645- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
646 GSList *l;
647
648- if (impl->shortcuts_pane_filter_model)
649- g_object_unref (impl->shortcuts_pane_filter_model);
650+ for (l = impl->path_history; l; l = l->next)
651+ {
652+ GtkFilePath *path;
653
654- if (impl->shortcuts_combo_filter_model)
655- g_object_unref (impl->shortcuts_combo_filter_model);
656+ path = l->data;
657+ gtk_file_path_free (path);
658+ }
659
660- shortcuts_free (impl);
661+ g_slist_free (impl->path_history);
662+ impl->path_history = NULL;
663+}
664
665+static void
666+gtk_file_chooser_default_finalize (GObject *object)
667+{
668+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
669+ GSList *l;
670+
671 g_object_unref (impl->file_system);
672
673 g_free (impl->browse_files_last_selected_name);
674@@ -999,8 +620,7 @@
675 if (impl->current_folder)
676 gtk_file_path_free (impl->current_folder);
677
678- if (impl->preview_path)
679- gtk_file_path_free (impl->preview_path);
680+ path_history_free (impl);
681
682 load_remove_timer (impl);
683
684@@ -1011,15 +631,18 @@
685 if (impl->sort_model)
686 g_object_unref (impl->sort_model);
687
688- search_clear_model (impl, FALSE);
689- recent_clear_model (impl, FALSE);
690+ if (impl->list_press_path)
691+ {
692+ gtk_tree_path_free (impl->list_press_path);
693+ impl->list_press_path = NULL;
694+ }
695
696- g_free (impl->preview_display_name);
697-
698 g_free (impl->edited_new_text);
699
700 g_object_unref (impl->tooltips);
701
702+ g_free (impl->root_folder);
703+
704 G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->finalize (object);
705 }
706
707@@ -1104,28 +727,6 @@
708 path, error);
709 }
710
711-/* Shows an error dialog about not being able to add a bookmark */
712-static void
713-error_adding_bookmark_dialog (GtkFileChooserDefault *impl,
714- const GtkFilePath *path,
715- GError *error)
716-{
717- error_dialog (impl,
718- _("Could not add a bookmark"),
719- path, error);
720-}
721-
722-/* Shows an error dialog about not being able to remove a bookmark */
723-static void
724-error_removing_bookmark_dialog (GtkFileChooserDefault *impl,
725- const GtkFilePath *path,
726- GError *error)
727-{
728- error_dialog (impl,
729- _("Could not remove bookmark"),
730- path, error);
731-}
732-
733 /* Shows an error dialog about not being able to create a folder */
734 static void
735 error_creating_folder_dialog (GtkFileChooserDefault *impl,
736@@ -1146,9 +747,9 @@
737 GError *error)
738 {
739 error_dialog (impl,
740- _("The folder could not be created, as a file with the same "
741- "name already exists. Try using a different name for the "
742- "folder, or rename the file first."),
743+ _("The folder could not be created, as a file with the same name "
744+ "already exists. Try using a different name for the folder, "
745+ "or rename the file first."),
746 path, error);
747 }
748
749@@ -1175,514 +776,108 @@
750
751 /* Changes folders, displaying an error dialog if this fails */
752 static gboolean
753-change_folder_and_display_error (GtkFileChooserDefault *impl,
754- const GtkFilePath *path,
755- gboolean clear_entry)
756+change_folder (GtkFileChooserDefault *impl, const GtkFilePath *path,
757+ gboolean errormsg)
758 {
759 GError *error;
760 gboolean result;
761 GtkFilePath *path_copy;
762+ gchar * file_name;
763
764 g_return_val_if_fail (path != NULL, FALSE);
765
766- profile_start ("start", (char *) path);
767-
768- /* We copy the path because of this case:
769- *
770- * list_row_activated()
771- * fetches path from model; path belongs to the model (*)
772- * calls change_folder_and_display_error()
773- * calls _gtk_file_chooser_set_current_folder_path()
774- * changing folders fails, sets model to NULL, thus freeing the path in (*)
775- */
776-
777 path_copy = gtk_file_path_copy (path);
778+ file_name = gtk_file_system_path_to_filename (impl->file_system, path_copy);
779
780- error = NULL;
781- result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), path_copy, TRUE, clear_entry, &error);
782+ if (!file_name)
783+ {
784+ gtk_file_path_free (path_copy);
785+ return 0;
786+ }
787
788- if (!result)
789- error_changing_folder_dialog (impl, path_copy, error);
790+ if (impl->root_folder && file_name[0] == '/' && file_name[1] == 0)
791+ {
792+ /* If changing to / and we have root_folder, change into it instead */
793+ gtk_file_path_free (path_copy);
794+ path_copy = gtk_file_system_filename_to_path (impl->file_system,
795+ impl->root_folder);
796
797- gtk_file_path_free (path_copy);
798+ gtk_widget_set_sensitive (impl->up_button, FALSE);
799+ }
800+ else if (impl->root_folder &&
801+ strcmp (file_name, impl->root_folder) &&
802+ !strncmp (file_name, impl->root_folder, strlen (file_name)))
803+ {
804+ /* refuse to change below the root */
805+ gtk_file_path_free (path_copy);
806+ g_free (file_name);
807+ return 0;
808+ }
809+ else if (!strcmp (file_name, impl->root_folder))
810+ {
811+ gtk_widget_set_sensitive (impl->up_button, FALSE);
812+ }
813+ else if (impl->current_folder && !strcmp (file_name, "/media"))
814+ {
815+ /* Asked to changed into /media -- if we are already in a media
816+ * child folder, we refuse, but if we are in the root, we permit this
817+ */
818+ gchar *name =
819+ gtk_file_system_path_to_filename (impl->file_system,
820+ impl->current_folder);
821
822- profile_end ("end", (char *) path);
823+ if (name && !strncmp (name, "/media", 6))
824+ {
825+ g_free (name);
826+ gtk_file_path_free (path_copy);
827+ g_free (file_name);
828+ return 0;
829+ }
830
831- return result;
832-}
833-
834-static void
835-update_preview_widget_visibility (GtkFileChooserDefault *impl)
836-{
837- if (impl->use_preview_label)
838- {
839- if (!impl->preview_label)
840- {
841- impl->preview_label = gtk_label_new (impl->preview_display_name);
842- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_label, FALSE, FALSE, 0);
843- gtk_box_reorder_child (GTK_BOX (impl->preview_box), impl->preview_label, 0);
844- gtk_label_set_ellipsize (GTK_LABEL (impl->preview_label), PANGO_ELLIPSIZE_MIDDLE);
845- gtk_widget_show (impl->preview_label);
846- }
847- }
848+ gtk_widget_set_sensitive (impl->up_button, TRUE);
849+ }
850+ else if (!strncmp (file_name, "/media/", 7))
851+ {
852+ /* Changing into a media child -- if it is an immediate child, disable
853+ * the Up button
854+ */
855+ gchar * p = file_name + 7;
856+ gchar * q = strchr (p, '/');
857+ if (!q)
858+ gtk_widget_set_sensitive (impl->up_button, FALSE);
859+ else
860+ gtk_widget_set_sensitive (impl->up_button, TRUE);
861+ }
862 else
863- {
864- if (impl->preview_label)
865- {
866- gtk_widget_destroy (impl->preview_label);
867- impl->preview_label = NULL;
868- }
869- }
870+ {
871+ gtk_widget_set_sensitive (impl->up_button, TRUE);
872+ }
873
874- if (impl->preview_widget_active && impl->preview_widget)
875- gtk_widget_show (impl->preview_box);
876- else
877- gtk_widget_hide (impl->preview_box);
878
879- g_signal_emit_by_name (impl, "default-size-changed");
880-}
881+ error = NULL;
882+ result = _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), path_copy, &error);
883
884-static void
885-set_preview_widget (GtkFileChooserDefault *impl,
886- GtkWidget *preview_widget)
887-{
888- if (preview_widget == impl->preview_widget)
889- return;
890+ if (errormsg && !result)
891+ error_changing_folder_dialog (impl, path_copy, error);
892
893- if (impl->preview_widget)
894- gtk_container_remove (GTK_CONTAINER (impl->preview_box),
895- impl->preview_widget);
896+ gtk_label_set_text (GTK_LABEL (impl->location_label), file_name);
897
898- impl->preview_widget = preview_widget;
899- if (impl->preview_widget)
900- {
901- gtk_widget_show (impl->preview_widget);
902- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_widget, TRUE, TRUE, 0);
903- gtk_box_reorder_child (GTK_BOX (impl->preview_box),
904- impl->preview_widget,
905- (impl->use_preview_label && impl->preview_label) ? 1 : 0);
906- }
907+ gtk_file_path_free (path_copy);
908+ g_free (file_name);
909
910- update_preview_widget_visibility (impl);
911+ return result;
912 }
913
914-/* Renders a "Search" icon at an appropriate size for a tree view */
915-static GdkPixbuf *
916-render_search_icon (GtkFileChooserDefault *impl)
917+static gboolean
918+change_folder_and_display_error (GtkFileChooserDefault *impl,
919+ const GtkFilePath *path)
920 {
921- return gtk_widget_render_icon (GTK_WIDGET (impl), GTK_STOCK_FIND, GTK_ICON_SIZE_MENU, NULL);
922+ return change_folder (impl, path, TRUE);
923 }
924
925-static GdkPixbuf *
926-render_recent_icon (GtkFileChooserDefault *impl)
927-{
928- GtkIconTheme *theme;
929- GdkPixbuf *retval;
930
931- if (gtk_widget_has_screen (GTK_WIDGET (impl)))
932- theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
933- else
934- theme = gtk_icon_theme_get_default ();
935-
936- retval = gtk_icon_theme_load_icon (theme, "document-open-recent",
937- impl->icon_size, 0,
938- NULL);
939-
940- /* fallback */
941- if (!retval)
942- retval = gtk_widget_render_icon (GTK_WIDGET (impl), GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
943-
944- return retval;
945-}
946-
947-
948-/* Re-reads all the icons for the shortcuts, used when the theme changes */
949-struct ReloadIconsData
950-{
951- GtkFileChooserDefault *impl;
952- GtkTreeRowReference *row_ref;
953-};
954-
955-static void
956-shortcuts_reload_icons_get_info_cb (GtkFileSystemHandle *handle,
957- const GtkFileInfo *info,
958- const GError *error,
959- gpointer user_data)
960-{
961- GdkPixbuf *pixbuf;
962- GtkTreeIter iter;
963- GtkTreePath *path;
964- gboolean cancelled = handle->cancelled;
965- struct ReloadIconsData *data = user_data;
966-
967- if (!g_slist_find (data->impl->reload_icon_handles, handle))
968- goto out;
969-
970- data->impl->reload_icon_handles = g_slist_remove (data->impl->reload_icon_handles, handle);
971-
972- if (cancelled || error)
973- goto out;
974-
975- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->impl),
976- data->impl->icon_size, NULL);
977-
978- path = gtk_tree_row_reference_get_path (data->row_ref);
979- gtk_tree_model_get_iter (GTK_TREE_MODEL (data->impl->shortcuts_model), &iter, path);
980- gtk_list_store_set (data->impl->shortcuts_model, &iter,
981- SHORTCUTS_COL_PIXBUF, pixbuf,
982- -1);
983- gtk_tree_path_free (path);
984-
985- if (pixbuf)
986- g_object_unref (pixbuf);
987-
988-out:
989- gtk_tree_row_reference_free (data->row_ref);
990- g_object_unref (data->impl);
991- g_free (data);
992-
993- g_object_unref (handle);
994-}
995-
996-static void
997-shortcuts_reload_icons (GtkFileChooserDefault *impl)
998-{
999- GSList *l;
1000- GtkTreeIter iter;
1001-
1002- profile_start ("start", NULL);
1003-
1004- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
1005- goto out;
1006-
1007- for (l = impl->reload_icon_handles; l; l = l->next)
1008- {
1009- GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data);
1010- gtk_file_system_cancel_operation (handle);
1011- }
1012- g_slist_free (impl->reload_icon_handles);
1013- impl->reload_icon_handles = NULL;
1014-
1015- do
1016- {
1017- gpointer data;
1018- ShortcutType shortcut_type;
1019- gboolean pixbuf_visible;
1020- GdkPixbuf *pixbuf;
1021-
1022- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
1023- SHORTCUTS_COL_DATA, &data,
1024- SHORTCUTS_COL_TYPE, &shortcut_type,
1025- SHORTCUTS_COL_PIXBUF_VISIBLE, &pixbuf_visible,
1026- -1);
1027-
1028- pixbuf = NULL;
1029- if (pixbuf_visible)
1030- {
1031- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
1032- {
1033- GtkFileSystemVolume *volume;
1034-
1035- volume = data;
1036- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
1037- impl->icon_size, NULL);
1038- }
1039- else if (shortcut_type == SHORTCUT_TYPE_PATH)
1040- {
1041- if (gtk_file_system_path_is_local (impl->file_system, (GtkFilePath *)data))
1042- {
1043- const GtkFilePath *path;
1044- struct ReloadIconsData *info;
1045- GtkTreePath *tree_path;
1046- GtkFileSystemHandle *handle;
1047-
1048- path = data;
1049-
1050- info = g_new0 (struct ReloadIconsData, 1);
1051- info->impl = g_object_ref (impl);
1052- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
1053- info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), tree_path);
1054- gtk_tree_path_free (tree_path);
1055-
1056- handle = gtk_file_system_get_info (impl->file_system, path,
1057- GTK_FILE_INFO_ICON,
1058- shortcuts_reload_icons_get_info_cb,
1059- info);
1060- impl->reload_icon_handles = g_slist_append (impl->reload_icon_handles, handle);
1061- }
1062- else
1063- {
1064- GtkIconTheme *icon_theme;
1065-
1066- /* Don't call get_info for remote paths to avoid latency and
1067- * auth dialogs.
1068- * If we switch to a better bookmarks file format (XBEL), we
1069- * should use mime info to get a better icon.
1070- */
1071- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
1072- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share",
1073- impl->icon_size, 0, NULL);
1074- }
1075- }
1076- else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
1077- {
1078- pixbuf = render_search_icon (impl);
1079- }
1080- else if (shortcut_type == SHORTCUT_TYPE_RECENT)
1081- {
1082- pixbuf = render_recent_icon (impl);
1083- }
1084-
1085- gtk_list_store_set (impl->shortcuts_model, &iter,
1086- SHORTCUTS_COL_PIXBUF, pixbuf,
1087- -1);
1088-
1089- if (pixbuf)
1090- g_object_unref (pixbuf);
1091-
1092- }
1093- }
1094- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model),&iter));
1095-
1096- out:
1097-
1098- profile_end ("end", NULL);
1099-}
1100-
1101-static void
1102-shortcuts_find_folder (GtkFileChooserDefault *impl,
1103- GtkFilePath *folder)
1104-{
1105- GtkTreeSelection *selection;
1106- int pos;
1107- GtkTreePath *path;
1108-
1109- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
1110-
1111- g_assert (folder != NULL);
1112- pos = shortcut_find_position (impl, folder);
1113- if (pos == -1)
1114- {
1115- gtk_tree_selection_unselect_all (selection);
1116- return;
1117- }
1118-
1119- path = gtk_tree_path_new_from_indices (pos, -1);
1120- gtk_tree_selection_select_path (selection, path);
1121- gtk_tree_path_free (path);
1122-}
1123-
1124-/* If a shortcut corresponds to the current folder, selects it */
1125-static void
1126-shortcuts_find_current_folder (GtkFileChooserDefault *impl)
1127-{
1128- shortcuts_find_folder (impl, impl->current_folder);
1129-}
1130-
1131-/* Removes the specified number of rows from the shortcuts list */
1132-static void
1133-shortcuts_remove_rows (GtkFileChooserDefault *impl,
1134- int start_row,
1135- int n_rows)
1136-{
1137- GtkTreePath *path;
1138-
1139- path = gtk_tree_path_new_from_indices (start_row, -1);
1140-
1141- for (; n_rows; n_rows--)
1142- {
1143- GtkTreeIter iter;
1144-
1145- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path))
1146- g_assert_not_reached ();
1147-
1148- shortcuts_free_row_data (impl, &iter);
1149- gtk_list_store_remove (impl->shortcuts_model, &iter);
1150- }
1151-
1152- gtk_tree_path_free (path);
1153-}
1154-
1155-static void
1156-shortcuts_update_count (GtkFileChooserDefault *impl,
1157- ShortcutsIndex type,
1158- gint value)
1159-{
1160- switch (type)
1161- {
1162- case SHORTCUTS_HOME:
1163- if (value < 0)
1164- impl->has_home = FALSE;
1165- else
1166- impl->has_home = TRUE;
1167- break;
1168-
1169- case SHORTCUTS_DESKTOP:
1170- if (value < 0)
1171- impl->has_desktop = FALSE;
1172- else
1173- impl->has_desktop = TRUE;
1174- break;
1175-
1176- case SHORTCUTS_VOLUMES:
1177- impl->num_volumes += value;
1178- break;
1179-
1180- case SHORTCUTS_SHORTCUTS:
1181- impl->num_shortcuts += value;
1182- break;
1183-
1184- case SHORTCUTS_BOOKMARKS:
1185- impl->num_bookmarks += value;
1186- break;
1187-
1188- case SHORTCUTS_CURRENT_FOLDER:
1189- if (value < 0)
1190- impl->shortcuts_current_folder_active = FALSE;
1191- else
1192- impl->shortcuts_current_folder_active = TRUE;
1193- break;
1194-
1195- default:
1196- /* nothing */
1197- break;
1198- }
1199-}
1200-
1201-struct ShortcutsInsertRequest
1202-{
1203- GtkFileChooserDefault *impl;
1204- GtkFilePath *parent_path;
1205- GtkFilePath *path;
1206- int pos;
1207- char *label_copy;
1208- GtkTreeRowReference *row_ref;
1209- ShortcutsIndex type;
1210- gboolean name_only;
1211- gboolean removable;
1212-};
1213-
1214-static void
1215-get_file_info_finished (GtkFileSystemHandle *handle,
1216- const GtkFileInfo *info,
1217- const GError *error,
1218- gpointer data)
1219-{
1220- gint pos = -1;
1221- gboolean cancelled = handle->cancelled;
1222- GdkPixbuf *pixbuf;
1223- GtkTreePath *path;
1224- GtkTreeIter iter;
1225- GtkFileSystemHandle *model_handle;
1226- struct ShortcutsInsertRequest *request = data;
1227-
1228- path = gtk_tree_row_reference_get_path (request->row_ref);
1229- if (!path)
1230- /* Handle doesn't exist anymore in the model */
1231- goto out;
1232-
1233- pos = gtk_tree_path_get_indices (path)[0];
1234- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->shortcuts_model),
1235- &iter, path);
1236- gtk_tree_path_free (path);
1237-
1238- /* validate handle, else goto out */
1239- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->shortcuts_model), &iter,
1240- SHORTCUTS_COL_HANDLE, &model_handle,
1241- -1);
1242- if (handle != model_handle)
1243- goto out;
1244-
1245- /* set the handle to NULL in the model (we unref later on) */
1246- gtk_list_store_set (request->impl->shortcuts_model, &iter,
1247- SHORTCUTS_COL_HANDLE, NULL,
1248- -1);
1249-
1250- if (cancelled)
1251- goto out;
1252-
1253- if (!info)
1254- {
1255- gtk_list_store_remove (request->impl->shortcuts_model, &iter);
1256- shortcuts_update_count (request->impl, request->type, -1);
1257-
1258- if (request->type == SHORTCUTS_HOME)
1259- {
1260- const char *home = g_get_home_dir ();
1261- GtkFilePath *home_path;
1262-
1263- home_path = gtk_file_system_filename_to_path (request->impl->file_system, home);
1264- error_getting_info_dialog (request->impl, home_path, g_error_copy (error));
1265- gtk_file_path_free (home_path);
1266- }
1267- else if (request->type == SHORTCUTS_CURRENT_FOLDER)
1268- {
1269- /* Remove the current folder separator */
1270- gint separator_pos = shortcuts_get_index (request->impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1271- shortcuts_remove_rows (request->impl, separator_pos, 1);
1272- }
1273-
1274- goto out;
1275- }
1276-
1277- if (!request->label_copy)
1278- request->label_copy = g_strdup (gtk_file_info_get_display_name (info));
1279- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
1280- request->impl->icon_size, NULL);
1281-
1282- gtk_list_store_set (request->impl->shortcuts_model, &iter,
1283- SHORTCUTS_COL_PIXBUF, pixbuf,
1284- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1285- SHORTCUTS_COL_NAME, request->label_copy,
1286- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_PATH,
1287- SHORTCUTS_COL_REMOVABLE, request->removable,
1288- -1);
1289-
1290- if (request->impl->shortcuts_pane_filter_model)
1291- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_pane_filter_model));
1292-
1293- if (request->impl->shortcuts_combo_filter_model)
1294- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_combo_filter_model));
1295-
1296- if (request->type == SHORTCUTS_CURRENT_FOLDER &&
1297- request->impl->save_folder_combo != NULL)
1298- {
1299- /* The current folder is updated via _activate_iter(), don't
1300- * have save_folder_combo_changed_cb() call _activate_iter()
1301- * again.
1302- */
1303- g_signal_handlers_block_by_func (request->impl->save_folder_combo,
1304- G_CALLBACK (save_folder_combo_changed_cb),
1305- request->impl);
1306-
1307- if (request->impl->has_search)
1308- pos -= 1;
1309-
1310- if (request->impl->has_recent)
1311- pos -= 2;
1312-
1313- gtk_combo_box_set_active (GTK_COMBO_BOX (request->impl->save_folder_combo), pos);
1314- g_signal_handlers_unblock_by_func (request->impl->save_folder_combo,
1315- G_CALLBACK (save_folder_combo_changed_cb),
1316- request->impl);
1317- }
1318-
1319- if (pixbuf)
1320- g_object_unref (pixbuf);
1321-
1322-out:
1323- g_object_unref (request->impl);
1324- gtk_file_path_free (request->parent_path);
1325- gtk_file_path_free (request->path);
1326- gtk_tree_row_reference_free (request->row_ref);
1327- g_free (request->label_copy);
1328- g_free (request);
1329-
1330- g_object_unref (handle);
1331-}
1332-
1333 /* FIXME: GtkFileSystem needs a function to split a remote path
1334- * into hostname and path components, or maybe just have a
1335+ * into hostname and path components, or maybe just have a
1336 * gtk_file_system_path_get_display_name().
1337 *
1338 * This function is also used in gtkfilechooserbutton.c
1339@@ -1692,11 +887,11 @@
1340 {
1341 const gchar *path, *start, *end, *p;
1342 gchar *host, *label;
1343-
1344+
1345 start = strstr (uri, "://");
1346 start += 3;
1347 path = strchr (start, '/');
1348-
1349+
1350 if (path)
1351 end = path;
1352 else
1353@@ -1711,719 +906,25 @@
1354 {
1355 start = p + 1;
1356 }
1357-
1358+
1359 p = strchr (start, ':');
1360 if (p && p < end)
1361 end = p;
1362-
1363+
1364 host = g_strndup (start, end - start);
1365
1366- /* Translators: the first string is a path and the second string
1367- * is a hostname. Nautilus and the panel contain the same string
1368- * to translate.
1369+ /* Translators: the first string is a path and the second string
1370+ * is a hostname. Nautilus and the panel contain the same string
1371+ * to translate.
1372 */
1373 label = g_strdup_printf (_("%1$s on %2$s"), path, host);
1374-
1375+
1376 g_free (host);
1377
1378 return label;
1379 }
1380
1381-/* Inserts a path in the shortcuts tree, making a copy of it; alternatively,
1382- * inserts a volume. A position of -1 indicates the end of the tree.
1383- */
1384-static void
1385-shortcuts_insert_path (GtkFileChooserDefault *impl,
1386- int pos,
1387- ShortcutType shortcut_type,
1388- GtkFileSystemVolume *volume,
1389- const GtkFilePath *path,
1390- const char *label,
1391- gboolean removable,
1392- ShortcutsIndex type)
1393-{
1394- char *label_copy;
1395- GdkPixbuf *pixbuf = NULL;
1396- gpointer data = NULL;
1397- GtkTreeIter iter;
1398- GtkIconTheme *icon_theme;
1399
1400- profile_start ("start", (shortcut_type == SHORTCUT_TYPE_VOLUME) ? "volume"
1401- : ((shortcut_type == SHORTCUT_TYPE_PATH) ? (char *) path : NULL));
1402-
1403- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
1404- {
1405- data = volume;
1406- label_copy = gtk_file_system_volume_get_display_name (impl->file_system, volume);
1407- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
1408- impl->icon_size, NULL);
1409- }
1410- else if (shortcut_type == SHORTCUT_TYPE_PATH)
1411- {
1412- if (gtk_file_system_path_is_local (impl->file_system, path))
1413- {
1414- struct ShortcutsInsertRequest *request;
1415- GtkFileSystemHandle *handle;
1416- GtkTreePath *p;
1417-
1418- request = g_new0 (struct ShortcutsInsertRequest, 1);
1419- request->impl = g_object_ref (impl);
1420- request->path = gtk_file_path_copy (path);
1421- request->name_only = TRUE;
1422- request->removable = removable;
1423- request->pos = pos;
1424- request->type = type;
1425- if (label)
1426- request->label_copy = g_strdup (label);
1427-
1428- if (pos == -1)
1429- gtk_list_store_append (impl->shortcuts_model, &iter);
1430- else
1431- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
1432-
1433- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
1434- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), p);
1435- gtk_tree_path_free (p);
1436-
1437- handle = gtk_file_system_get_info (request->impl->file_system, request->path,
1438- GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN | GTK_FILE_INFO_ICON,
1439- get_file_info_finished, request);
1440-
1441- gtk_list_store_set (impl->shortcuts_model, &iter,
1442- SHORTCUTS_COL_DATA, gtk_file_path_copy (path),
1443- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_PATH,
1444- SHORTCUTS_COL_HANDLE, handle,
1445- -1);
1446-
1447- shortcuts_update_count (impl, type, 1);
1448-
1449- return;
1450- }
1451- else
1452- {
1453- /* Don't call get_info for remote paths to avoid latency and
1454- * auth dialogs.
1455- */
1456- data = gtk_file_path_copy (path);
1457- if (label)
1458- label_copy = g_strdup (label);
1459- else
1460- {
1461- gchar *uri;
1462-
1463- uri = gtk_file_system_path_to_uri (impl->file_system, path);
1464-
1465- label_copy = _gtk_file_chooser_label_for_uri (uri);
1466-
1467- g_free (uri);
1468- }
1469-
1470- /* If we switch to a better bookmarks file format (XBEL), we
1471- * should use mime info to get a better icon.
1472- */
1473- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
1474- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-share",
1475- impl->icon_size, 0, NULL);
1476- }
1477- }
1478- else
1479- {
1480- g_assert_not_reached ();
1481-
1482- return;
1483- }
1484-
1485- if (pos == -1)
1486- gtk_list_store_append (impl->shortcuts_model, &iter);
1487- else
1488- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
1489-
1490- shortcuts_update_count (impl, type, 1);
1491-
1492- gtk_list_store_set (impl->shortcuts_model, &iter,
1493- SHORTCUTS_COL_PIXBUF, pixbuf,
1494- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1495- SHORTCUTS_COL_NAME, label_copy,
1496- SHORTCUTS_COL_DATA, data,
1497- SHORTCUTS_COL_TYPE, shortcut_type,
1498- SHORTCUTS_COL_REMOVABLE, removable,
1499- SHORTCUTS_COL_HANDLE, NULL,
1500- -1);
1501-
1502- if (impl->shortcuts_pane_filter_model)
1503- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
1504-
1505- if (impl->shortcuts_combo_filter_model)
1506- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
1507-
1508- if (type == SHORTCUTS_CURRENT_FOLDER && impl->save_folder_combo != NULL)
1509- {
1510- /* The current folder is updated via _activate_iter(), don't
1511- * have save_folder_combo_changed_cb() call _activate_iter()
1512- * again.
1513- */
1514- gint combo_pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
1515-
1516- if (impl->has_search)
1517- combo_pos -= 1;
1518-
1519- if (impl->has_recent)
1520- combo_pos -= 2;
1521-
1522- g_signal_handlers_block_by_func (impl->save_folder_combo,
1523- G_CALLBACK (save_folder_combo_changed_cb),
1524- impl);
1525-
1526- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), combo_pos);
1527- g_signal_handlers_unblock_by_func (impl->save_folder_combo,
1528- G_CALLBACK (save_folder_combo_changed_cb),
1529- impl);
1530- }
1531-
1532- g_free (label_copy);
1533-
1534- if (pixbuf)
1535- g_object_unref (pixbuf);
1536-
1537- profile_end ("end", NULL);
1538-}
1539-
1540-static void
1541-shortcuts_append_search (GtkFileChooserDefault *impl)
1542-{
1543- GdkPixbuf *pixbuf;
1544- GtkTreeIter iter;
1545-
1546- pixbuf = render_search_icon (impl);
1547-
1548- gtk_list_store_append (impl->shortcuts_model, &iter);
1549- gtk_list_store_set (impl->shortcuts_model, &iter,
1550- SHORTCUTS_COL_PIXBUF, pixbuf,
1551- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1552- SHORTCUTS_COL_NAME, _("Search"),
1553- SHORTCUTS_COL_DATA, NULL,
1554- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_SEARCH,
1555- SHORTCUTS_COL_REMOVABLE, FALSE,
1556- -1);
1557-
1558- if (pixbuf)
1559- g_object_unref (pixbuf);
1560-
1561- impl->has_search = TRUE;
1562-}
1563-
1564-static void
1565-shortcuts_append_recent (GtkFileChooserDefault *impl)
1566-{
1567- GdkPixbuf *pixbuf;
1568- GtkTreeIter iter;
1569-
1570- pixbuf = render_recent_icon (impl);
1571-
1572- gtk_list_store_append (impl->shortcuts_model, &iter);
1573- gtk_list_store_set (impl->shortcuts_model, &iter,
1574- SHORTCUTS_COL_PIXBUF, pixbuf,
1575- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1576- SHORTCUTS_COL_NAME, _("Recently Used"),
1577- SHORTCUTS_COL_DATA, NULL,
1578- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_RECENT,
1579- SHORTCUTS_COL_REMOVABLE, FALSE,
1580- -1);
1581-
1582- if (pixbuf)
1583- g_object_unref (pixbuf);
1584-
1585- impl->has_recent = TRUE;
1586-}
1587-
1588-/* Appends an item for the user's home directory to the shortcuts model */
1589-static void
1590-shortcuts_append_home (GtkFileChooserDefault *impl)
1591-{
1592- const char *home;
1593- GtkFilePath *home_path;
1594-
1595- profile_start ("start", NULL);
1596-
1597- home = g_get_home_dir ();
1598- if (home == NULL)
1599- {
1600- profile_end ("end - no home directory!?", NULL);
1601- return;
1602- }
1603-
1604- home_path = gtk_file_system_filename_to_path (impl->file_system, home);
1605-
1606- shortcuts_insert_path (impl, -1, SHORTCUT_TYPE_PATH, NULL, home_path, NULL, FALSE, SHORTCUTS_HOME);
1607- impl->has_home = TRUE;
1608-
1609- gtk_file_path_free (home_path);
1610-
1611- profile_end ("end", NULL);
1612-}
1613-
1614-/* Appends the ~/Desktop directory to the shortcuts model */
1615-static void
1616-shortcuts_append_desktop (GtkFileChooserDefault *impl)
1617-{
1618- const char *name;
1619- GtkFilePath *path;
1620-
1621- profile_start ("start", NULL);
1622-
1623- name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
1624- path = gtk_file_system_filename_to_path (impl->file_system, name);
1625- shortcuts_insert_path (impl, -1, SHORTCUT_TYPE_PATH, NULL, path, _("Desktop"), FALSE, SHORTCUTS_DESKTOP);
1626- impl->has_desktop = TRUE;
1627-
1628- /* We do not actually pop up an error dialog if there is no desktop directory
1629- * because some people may really not want to have one.
1630- */
1631-
1632- gtk_file_path_free (path);
1633-
1634- profile_end ("end", NULL);
1635-}
1636-
1637-/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */
1638-static int
1639-shortcuts_append_paths (GtkFileChooserDefault *impl,
1640- GSList *paths)
1641-{
1642- int start_row;
1643- int num_inserted;
1644- gchar *label;
1645-
1646- profile_start ("start", NULL);
1647-
1648- /* As there is no separator now, we want to start there.
1649- */
1650- start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
1651- num_inserted = 0;
1652-
1653- for (; paths; paths = paths->next)
1654- {
1655- GtkFilePath *path;
1656-
1657- path = paths->data;
1658-
1659- if (impl->local_only &&
1660- !gtk_file_system_path_is_local (impl->file_system, path))
1661- continue;
1662-
1663- label = gtk_file_system_get_bookmark_label (impl->file_system, path);
1664-
1665- /* NULL GError, but we don't really want to show error boxes here */
1666- shortcuts_insert_path (impl, start_row + num_inserted, SHORTCUT_TYPE_PATH, NULL, path, label, TRUE, SHORTCUTS_BOOKMARKS);
1667- num_inserted++;
1668-
1669- g_free (label);
1670- }
1671-
1672- profile_end ("end", NULL);
1673-
1674- return num_inserted;
1675-}
1676-
1677-/* Returns the index for the corresponding item in the shortcuts bar */
1678-static int
1679-shortcuts_get_index (GtkFileChooserDefault *impl,
1680- ShortcutsIndex where)
1681-{
1682- int n;
1683-
1684- n = 0;
1685-
1686- if (where == SHORTCUTS_SEARCH)
1687- goto out;
1688-
1689- n += impl->has_search ? 1 : 0;
1690-
1691- if (where == SHORTCUTS_RECENT)
1692- goto out;
1693-
1694- n += impl->has_recent ? 1 : 0;
1695-
1696- if (where == SHORTCUTS_RECENT_SEPARATOR)
1697- goto out;
1698-
1699- n += impl->has_recent ? 1 : 0;
1700-
1701- if (where == SHORTCUTS_HOME)
1702- goto out;
1703-
1704- n += impl->has_home ? 1 : 0;
1705-
1706- if (where == SHORTCUTS_DESKTOP)
1707- goto out;
1708-
1709- n += impl->has_desktop ? 1 : 0;
1710-
1711- if (where == SHORTCUTS_VOLUMES)
1712- goto out;
1713-
1714- n += impl->num_volumes;
1715-
1716- if (where == SHORTCUTS_SHORTCUTS)
1717- goto out;
1718-
1719- n += impl->num_shortcuts;
1720-
1721- if (where == SHORTCUTS_BOOKMARKS_SEPARATOR)
1722- goto out;
1723-
1724- /* If there are no bookmarks there won't be a separator */
1725- n += (impl->num_bookmarks > 0) ? 1 : 0;
1726-
1727- if (where == SHORTCUTS_BOOKMARKS)
1728- goto out;
1729-
1730- n += impl->num_bookmarks;
1731-
1732- if (where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR)
1733- goto out;
1734-
1735- n += 1;
1736-
1737- if (where == SHORTCUTS_CURRENT_FOLDER)
1738- goto out;
1739-
1740- g_assert_not_reached ();
1741-
1742- out:
1743-
1744- return n;
1745-}
1746-
1747-/* Adds all the file system volumes to the shortcuts model */
1748-static void
1749-shortcuts_add_volumes (GtkFileChooserDefault *impl)
1750-{
1751- int start_row;
1752- GSList *list, *l;
1753- int n;
1754- gboolean old_changing_folders;
1755-
1756- profile_start ("start", NULL);
1757-
1758-
1759- old_changing_folders = impl->changing_folder;
1760- impl->changing_folder = TRUE;
1761-
1762- start_row = shortcuts_get_index (impl, SHORTCUTS_VOLUMES);
1763- shortcuts_remove_rows (impl, start_row, impl->num_volumes);
1764- impl->num_volumes = 0;
1765-
1766- list = gtk_file_system_list_volumes (impl->file_system);
1767-
1768- n = 0;
1769-
1770- for (l = list; l; l = l->next)
1771- {
1772- GtkFileSystemVolume *volume;
1773-
1774- volume = l->data;
1775-
1776- if (impl->local_only)
1777- {
1778- if (gtk_file_system_volume_get_is_mounted (impl->file_system, volume))
1779- {
1780- GtkFilePath *base_path;
1781-
1782- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
1783- if (base_path != NULL)
1784- {
1785- gboolean is_local = gtk_file_system_path_is_local (impl->file_system, base_path);
1786- gtk_file_path_free (base_path);
1787-
1788- if (!is_local)
1789- {
1790- gtk_file_system_volume_free (impl->file_system, volume);
1791- continue;
1792- }
1793- }
1794- }
1795- }
1796-
1797- shortcuts_insert_path (impl, start_row + n, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_VOLUMES);
1798- n++;
1799- }
1800-
1801- impl->num_volumes = n;
1802- g_slist_free (list);
1803-
1804- if (impl->shortcuts_pane_filter_model)
1805- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
1806-
1807- if (impl->shortcuts_combo_filter_model)
1808- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
1809-
1810- impl->changing_folder = old_changing_folders;
1811-
1812- profile_end ("end", NULL);
1813-}
1814-
1815-/* Inserts a separator node in the shortcuts list */
1816-static void
1817-shortcuts_insert_separator (GtkFileChooserDefault *impl,
1818- ShortcutsIndex where)
1819-{
1820- GtkTreeIter iter;
1821-
1822- g_assert (where == SHORTCUTS_RECENT_SEPARATOR ||
1823- where == SHORTCUTS_BOOKMARKS_SEPARATOR ||
1824- where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1825-
1826- gtk_list_store_insert (impl->shortcuts_model, &iter,
1827- shortcuts_get_index (impl, where));
1828- gtk_list_store_set (impl->shortcuts_model, &iter,
1829- SHORTCUTS_COL_PIXBUF, NULL,
1830- SHORTCUTS_COL_PIXBUF_VISIBLE, FALSE,
1831- SHORTCUTS_COL_NAME, NULL,
1832- SHORTCUTS_COL_DATA, NULL,
1833- SHORTCUTS_COL_TYPE, SHORTCUT_TYPE_SEPARATOR,
1834- -1);
1835-}
1836-
1837-/* Updates the list of bookmarks */
1838-static void
1839-shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
1840-{
1841- GSList *bookmarks;
1842- gboolean old_changing_folders;
1843- GtkTreeIter iter;
1844- GtkFilePath *list_selected = NULL;
1845- GtkFilePath *combo_selected = NULL;
1846- ShortcutType shortcut_type;
1847- gpointer col_data;
1848-
1849- profile_start ("start", NULL);
1850-
1851- old_changing_folders = impl->changing_folder;
1852- impl->changing_folder = TRUE;
1853-
1854- if (shortcuts_get_selected (impl, &iter))
1855- {
1856- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model),
1857- &iter,
1858- SHORTCUTS_COL_DATA, &col_data,
1859- SHORTCUTS_COL_TYPE, &shortcut_type,
1860- -1);
1861-
1862- if (col_data && shortcut_type == SHORTCUT_TYPE_PATH)
1863- list_selected = gtk_file_path_copy (col_data);
1864- }
1865-
1866- if (impl->save_folder_combo &&
1867- gtk_combo_box_get_active_iter (GTK_COMBO_BOX (impl->save_folder_combo),
1868- &iter))
1869- {
1870- GtkTreeIter child_iter;
1871-
1872- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model),
1873- &child_iter,
1874- &iter);
1875- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model),
1876- &child_iter,
1877- SHORTCUTS_COL_DATA, &col_data,
1878- SHORTCUTS_COL_TYPE, &shortcut_type,
1879- -1);
1880-
1881- if (col_data && shortcut_type == SHORTCUT_TYPE_PATH)
1882- combo_selected = gtk_file_path_copy (col_data);
1883- }
1884-
1885- if (impl->num_bookmarks > 0)
1886- shortcuts_remove_rows (impl,
1887- shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR),
1888- impl->num_bookmarks + 1);
1889-
1890- impl->num_bookmarks = 0;
1891-
1892- bookmarks = gtk_file_system_list_bookmarks (impl->file_system);
1893- shortcuts_append_paths (impl, bookmarks);
1894- gtk_file_paths_free (bookmarks);
1895-
1896- if (impl->num_bookmarks > 0)
1897- shortcuts_insert_separator (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
1898-
1899- if (impl->shortcuts_pane_filter_model)
1900- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model));
1901-
1902- if (impl->shortcuts_combo_filter_model)
1903- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model));
1904-
1905- if (list_selected)
1906- {
1907- shortcuts_find_folder (impl, list_selected);
1908- gtk_file_path_free (list_selected);
1909- }
1910-
1911- if (combo_selected)
1912- {
1913- gint pos;
1914-
1915- pos = shortcut_find_position (impl, combo_selected);
1916- if (pos != -1)
1917- {
1918- if (impl->has_search)
1919- pos -= 1;
1920-
1921- if (impl->has_recent)
1922- pos -= 2;
1923-
1924- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos);
1925- }
1926-
1927- gtk_file_path_free (combo_selected);
1928- }
1929-
1930- impl->changing_folder = old_changing_folders;
1931-
1932- profile_end ("end", NULL);
1933-}
1934-
1935-/* Appends a separator and a row to the shortcuts list for the current folder */
1936-static void
1937-shortcuts_add_current_folder (GtkFileChooserDefault *impl)
1938-{
1939- int pos;
1940- gboolean success;
1941-
1942- g_assert (!impl->shortcuts_current_folder_active);
1943-
1944- success = TRUE;
1945-
1946- g_assert (impl->current_folder != NULL);
1947-
1948- pos = shortcut_find_position (impl, impl->current_folder);
1949- if (pos == -1)
1950- {
1951- GtkFileSystemVolume *volume;
1952- GtkFilePath *base_path;
1953-
1954- /* Separator */
1955-
1956- shortcuts_insert_separator (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1957-
1958- /* Item */
1959-
1960- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
1961-
1962- volume = gtk_file_system_get_volume_for_path (impl->file_system, impl->current_folder);
1963- if (volume)
1964- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
1965- else
1966- base_path = NULL;
1967-
1968- if (base_path &&
1969- strcmp (gtk_file_path_get_string (base_path), gtk_file_path_get_string (impl->current_folder)) == 0)
1970- {
1971- shortcuts_insert_path (impl, pos, SHORTCUT_TYPE_VOLUME, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
1972- }
1973- else
1974- {
1975- shortcuts_insert_path (impl, pos, SHORTCUT_TYPE_PATH, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
1976- if (volume)
1977- gtk_file_system_volume_free (impl->file_system, volume);
1978- }
1979-
1980- if (base_path)
1981- gtk_file_path_free (base_path);
1982- }
1983- else if (impl->save_folder_combo != NULL)
1984- {
1985- if (impl->has_search)
1986- pos -= 1;
1987-
1988- if (impl->has_recent)
1989- pos -= 2; /* + separator */
1990-
1991- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos);
1992- }
1993-}
1994-
1995-/* Updates the current folder row in the shortcuts model */
1996-static void
1997-shortcuts_update_current_folder (GtkFileChooserDefault *impl)
1998-{
1999- int pos;
2000-
2001- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
2002-
2003- if (impl->shortcuts_current_folder_active)
2004- {
2005- shortcuts_remove_rows (impl, pos, 2);
2006- impl->shortcuts_current_folder_active = FALSE;
2007- }
2008-
2009- shortcuts_add_current_folder (impl);
2010-}
2011-
2012-/* Filter function used for the shortcuts filter model */
2013-static gboolean
2014-shortcuts_pane_filter_cb (GtkTreeModel *model,
2015- GtkTreeIter *iter,
2016- gpointer data)
2017-{
2018- GtkFileChooserDefault *impl;
2019- GtkTreePath *path;
2020- int pos;
2021-
2022- impl = GTK_FILE_CHOOSER_DEFAULT (data);
2023-
2024- path = gtk_tree_model_get_path (model, iter);
2025- if (!path)
2026- return FALSE;
2027-
2028- pos = *gtk_tree_path_get_indices (path);
2029- gtk_tree_path_free (path);
2030-
2031- return (pos < shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR));
2032-}
2033-
2034-/* Creates the list model for shortcuts */
2035-static void
2036-shortcuts_model_create (GtkFileChooserDefault *impl)
2037-{
2038- /* Keep this order in sync with the SHORCUTS_COL_* enum values */
2039- impl->shortcuts_model = gtk_list_store_new (SHORTCUTS_COL_NUM_COLUMNS,
2040- GDK_TYPE_PIXBUF, /* pixbuf */
2041- G_TYPE_STRING, /* name */
2042- G_TYPE_POINTER, /* path or volume */
2043- G_TYPE_INT, /* ShortcutType */
2044- G_TYPE_BOOLEAN, /* removable */
2045- G_TYPE_BOOLEAN, /* pixbuf cell visibility */
2046- G_TYPE_POINTER); /* GtkFileSystemHandle */
2047-
2048- if (search_is_possible (impl))
2049- {
2050- shortcuts_append_search (impl);
2051- }
2052-
2053- if (impl->recent_manager)
2054- {
2055- shortcuts_append_recent (impl);
2056- shortcuts_insert_separator (impl, SHORTCUTS_RECENT_SEPARATOR);
2057- }
2058-
2059- if (impl->file_system)
2060- {
2061- shortcuts_append_home (impl);
2062- shortcuts_append_desktop (impl);
2063- shortcuts_add_volumes (impl);
2064- }
2065-
2066- impl->shortcuts_pane_filter_model = shortcuts_pane_model_filter_new (impl,
2067- GTK_TREE_MODEL (impl->shortcuts_model),
2068- NULL);
2069-
2070- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model),
2071- shortcuts_pane_filter_cb,
2072- impl,
2073- NULL);
2074-}
2075-
2076 /* Callback used when the "New Folder" button is clicked */
2077 static void
2078 new_folder_button_clicked (GtkButton *button,
2079@@ -2472,7 +973,7 @@
2080 goto out;
2081
2082 if (!error)
2083- change_folder_and_display_error (impl, path, FALSE);
2084+ change_folder_and_display_error (impl, path);
2085 else
2086 error_creating_folder_dialog (impl, path, g_error_copy (error));
2087
2088@@ -2488,7 +989,7 @@
2089 edited_idle_cb (GtkFileChooserDefault *impl)
2090 {
2091 GDK_THREADS_ENTER ();
2092-
2093+
2094 g_source_destroy (impl->edited_idle);
2095 impl->edited_idle = NULL;
2096
2097@@ -2558,10 +1059,10 @@
2098 const gchar *new_text,
2099 GtkFileChooserDefault *impl)
2100 {
2101- /* work around bug #154921 */
2102- g_object_set (cell_renderer_text,
2103+ /* work around bug #154921 */
2104+ g_object_set (cell_renderer_text,
2105 "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
2106- queue_edited_idle (impl, new_text);
2107+ queue_edited_idle (impl, new_text);
2108 }
2109
2110 /* Callback used from the text cell renderer when the new folder edition gets
2111@@ -2571,10 +1072,10 @@
2112 renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text,
2113 GtkFileChooserDefault *impl)
2114 {
2115- /* work around bug #154921 */
2116- g_object_set (cell_renderer_text,
2117+ /* work around bug #154921 */
2118+ g_object_set (cell_renderer_text,
2119 "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
2120- queue_edited_idle (impl, NULL);
2121+ queue_edited_idle (impl, NULL);
2122 }
2123
2124 /* Creates the widgets for the filter combo box */
2125@@ -2587,253 +1088,9 @@
2126 g_signal_connect (impl->filter_combo, "changed",
2127 G_CALLBACK (filter_combo_changed), impl);
2128
2129- gtk_widget_set_tooltip_text (impl->filter_combo,
2130- _("Select which types of files are shown"));
2131-
2132 return impl->filter_combo;
2133 }
2134
2135-static GtkWidget *
2136-button_new (GtkFileChooserDefault *impl,
2137- const char *text,
2138- const char *stock_id,
2139- gboolean sensitive,
2140- gboolean show,
2141- GCallback callback)
2142-{
2143- GtkWidget *button;
2144- GtkWidget *image;
2145-
2146- button = gtk_button_new_with_mnemonic (text);
2147- image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
2148- gtk_button_set_image (GTK_BUTTON (button), image);
2149-
2150- gtk_widget_set_sensitive (button, sensitive);
2151- g_signal_connect (button, "clicked", callback, impl);
2152-
2153- if (show)
2154- gtk_widget_show (button);
2155-
2156- return button;
2157-}
2158-
2159-/* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */
2160-static int
2161-shortcut_find_position (GtkFileChooserDefault *impl,
2162- const GtkFilePath *path)
2163-{
2164- GtkTreeIter iter;
2165- int i;
2166- int current_folder_separator_idx;
2167-
2168- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
2169- return -1;
2170-
2171- current_folder_separator_idx = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
2172-
2173-#if 0
2174- /* FIXME: is this still needed? */
2175- if (current_folder_separator_idx >= impl->shortcuts_model->length)
2176- return -1;
2177-#endif
2178-
2179- for (i = 0; i < current_folder_separator_idx; i++)
2180- {
2181- gpointer col_data;
2182- ShortcutType shortcut_type;
2183-
2184- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2185- SHORTCUTS_COL_DATA, &col_data,
2186- SHORTCUTS_COL_TYPE, &shortcut_type,
2187- -1);
2188-
2189- if (col_data)
2190- {
2191- if (shortcut_type == SHORTCUT_TYPE_VOLUME)
2192- {
2193- GtkFileSystemVolume *volume;
2194- GtkFilePath *base_path;
2195- gboolean exists;
2196-
2197- volume = col_data;
2198- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
2199-
2200- exists = base_path && strcmp (gtk_file_path_get_string (path),
2201- gtk_file_path_get_string (base_path)) == 0;
2202- g_free (base_path);
2203-
2204- if (exists)
2205- return i;
2206- }
2207- else if (shortcut_type == SHORTCUT_TYPE_PATH)
2208- {
2209- GtkFilePath *model_path;
2210-
2211- model_path = col_data;
2212-
2213- if (model_path && gtk_file_path_compare (model_path, path) == 0)
2214- return i;
2215- }
2216- }
2217-
2218- if (i < current_folder_separator_idx - 1)
2219- {
2220- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
2221- g_assert_not_reached ();
2222- }
2223- }
2224-
2225- return -1;
2226-}
2227-
2228-/* Tries to add a bookmark from a path name */
2229-static gboolean
2230-shortcuts_add_bookmark_from_path (GtkFileChooserDefault *impl,
2231- const GtkFilePath *path,
2232- int pos)
2233-{
2234- GError *error;
2235-
2236- g_return_val_if_fail (path != NULL, FALSE);
2237-
2238- if (shortcut_find_position (impl, path) != -1)
2239- return FALSE;
2240-
2241- error = NULL;
2242- if (!gtk_file_system_insert_bookmark (impl->file_system, path, pos, &error))
2243- {
2244- error_adding_bookmark_dialog (impl, path, error);
2245- return FALSE;
2246- }
2247-
2248- return TRUE;
2249-}
2250-
2251-static void
2252-add_bookmark_foreach_cb (GtkTreeModel *model,
2253- GtkTreePath *path,
2254- GtkTreeIter *iter,
2255- gpointer data)
2256-{
2257- GtkFileChooserDefault *impl;
2258- GtkFileSystemModel *fs_model;
2259- GtkTreeIter child_iter;
2260- const GtkFilePath *file_path;
2261-
2262- impl = (GtkFileChooserDefault *) data;
2263-
2264- switch (impl->operation_mode)
2265- {
2266- case OPERATION_MODE_BROWSE:
2267- fs_model = impl->browse_files_model;
2268- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter);
2269- file_path = _gtk_file_system_model_get_path (fs_model, &child_iter);
2270- break;
2271-
2272- case OPERATION_MODE_SEARCH:
2273- search_get_valid_child_iter (impl, &child_iter, iter);
2274- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
2275- SEARCH_MODEL_COL_PATH, &file_path,
2276- -1);
2277- break;
2278-
2279- case OPERATION_MODE_RECENT:
2280- recent_get_valid_child_iter (impl, &child_iter, iter);
2281- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
2282- RECENT_MODEL_COL_PATH, &file_path,
2283- -1);
2284- break;
2285- }
2286-
2287- shortcuts_add_bookmark_from_path (impl, file_path, -1);
2288-}
2289-
2290-/* Adds a bookmark from the currently selected item in the file list */
2291-static void
2292-bookmarks_add_selected_folder (GtkFileChooserDefault *impl)
2293-{
2294- GtkTreeSelection *selection;
2295-
2296- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2297-
2298- if (gtk_tree_selection_count_selected_rows (selection) == 0)
2299- shortcuts_add_bookmark_from_path (impl, impl->current_folder, -1);
2300- else
2301- gtk_tree_selection_selected_foreach (selection,
2302- add_bookmark_foreach_cb,
2303- impl);
2304-}
2305-
2306-/* Callback used when the "Add bookmark" button is clicked */
2307-static void
2308-add_bookmark_button_clicked_cb (GtkButton *button,
2309- GtkFileChooserDefault *impl)
2310-{
2311- bookmarks_add_selected_folder (impl);
2312-}
2313-
2314-/* Returns TRUE plus an iter in the shortcuts_model if a row is selected;
2315- * returns FALSE if no shortcut is selected.
2316- */
2317-static gboolean
2318-shortcuts_get_selected (GtkFileChooserDefault *impl,
2319- GtkTreeIter *iter)
2320-{
2321- GtkTreeSelection *selection;
2322- GtkTreeIter parent_iter;
2323-
2324- if (!impl->browse_shortcuts_tree_view)
2325- return FALSE;
2326-
2327- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
2328-
2329- if (!gtk_tree_selection_get_selected (selection, NULL, &parent_iter))
2330- return FALSE;
2331-
2332- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model),
2333- iter,
2334- &parent_iter);
2335- return TRUE;
2336-}
2337-
2338-/* Removes the selected bookmarks */
2339-static void
2340-remove_selected_bookmarks (GtkFileChooserDefault *impl)
2341-{
2342- GtkTreeIter iter;
2343- gpointer col_data;
2344- GtkFilePath *path;
2345- gboolean removable;
2346- GError *error;
2347-
2348- if (!shortcuts_get_selected (impl, &iter))
2349- return;
2350-
2351- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2352- SHORTCUTS_COL_DATA, &col_data,
2353- SHORTCUTS_COL_REMOVABLE, &removable,
2354- -1);
2355-
2356- if (!removable)
2357- return;
2358-
2359- g_assert (col_data != NULL);
2360-
2361- path = col_data;
2362-
2363- error = NULL;
2364- if (!gtk_file_system_remove_bookmark (impl->file_system, path, &error))
2365- error_removing_bookmark_dialog (impl, path, error);
2366-}
2367-
2368-/* Callback used when the "Remove bookmark" button is clicked */
2369-static void
2370-remove_bookmark_button_clicked_cb (GtkButton *button,
2371- GtkFileChooserDefault *impl)
2372-{
2373- remove_selected_bookmarks (impl);
2374-}
2375-
2376 struct selection_check_closure {
2377 GtkFileChooserDefault *impl;
2378 int num_selected;
2379@@ -2856,29 +1113,11 @@
2380 closure = data;
2381 closure->num_selected++;
2382
2383- switch (closure->impl->operation_mode)
2384- {
2385- case OPERATION_MODE_BROWSE:
2386- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2387- info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
2388- is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE;
2389- break;
2390+ gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2391
2392- case OPERATION_MODE_SEARCH:
2393- search_get_valid_child_iter (closure->impl, &child_iter, iter);
2394- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter,
2395- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
2396- -1);
2397- break;
2398+ info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
2399+ is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE;
2400
2401- case OPERATION_MODE_RECENT:
2402- recent_get_valid_child_iter (closure->impl, &child_iter, iter);
2403- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter,
2404- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
2405- -1);
2406- break;
2407- }
2408-
2409 closure->all_folders = closure->all_folders && is_folder;
2410 closure->all_files = closure->all_files && !is_folder;
2411 }
2412@@ -2920,1126 +1159,6 @@
2413 const GtkFilePath *path;
2414 };
2415
2416-static void
2417-get_selected_path_foreach_cb (GtkTreeModel *model,
2418- GtkTreePath *path,
2419- GtkTreeIter *iter,
2420- gpointer data)
2421-{
2422- struct get_selected_path_closure *closure;
2423- GtkTreeIter child_iter;
2424-
2425- closure = data;
2426-
2427- switch (closure->impl->operation_mode)
2428- {
2429- case OPERATION_MODE_BROWSE:
2430- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2431- closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter);
2432- break;
2433-
2434- case OPERATION_MODE_SEARCH:
2435- search_get_valid_child_iter (closure->impl, &child_iter, iter);
2436- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->search_model), &child_iter,
2437- SEARCH_MODEL_COL_PATH, &closure->path,
2438- -1);
2439- break;
2440-
2441- case OPERATION_MODE_RECENT:
2442- recent_get_valid_child_iter (closure->impl, &child_iter, iter);
2443- gtk_tree_model_get (GTK_TREE_MODEL (closure->impl->recent_model), &child_iter,
2444- RECENT_MODEL_COL_PATH, &closure->path,
2445- -1);
2446- break;
2447- }
2448-}
2449-
2450-/* Returns a selected path from the file list */
2451-static const GtkFilePath *
2452-get_selected_path (GtkFileChooserDefault *impl)
2453-{
2454- struct get_selected_path_closure closure;
2455- GtkTreeSelection *selection;
2456-
2457- closure.impl = impl;
2458- closure.path = NULL;
2459-
2460- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2461- gtk_tree_selection_selected_foreach (selection,
2462- get_selected_path_foreach_cb,
2463- &closure);
2464-
2465- return closure.path;
2466-}
2467-
2468-typedef struct {
2469- GtkFileChooserDefault *impl;
2470- gchar *tip;
2471-} UpdateTooltipData;
2472-
2473-static void
2474-update_tooltip (GtkTreeModel *model,
2475- GtkTreePath *path,
2476- GtkTreeIter *iter,
2477- gpointer data)
2478-{
2479- UpdateTooltipData *udata = data;
2480- GtkTreeIter child_iter;
2481- const GtkFileInfo *info;
2482-
2483- if (udata->tip == NULL)
2484- {
2485- const gchar *display_name;
2486-
2487- switch (udata->impl->operation_mode)
2488- {
2489- case OPERATION_MODE_BROWSE:
2490- gtk_tree_model_sort_convert_iter_to_child_iter (udata->impl->sort_model,
2491- &child_iter,
2492- iter);
2493- info = _gtk_file_system_model_get_info (udata->impl->browse_files_model, &child_iter);
2494- display_name = gtk_file_info_get_display_name (info);
2495- break;
2496-
2497- case OPERATION_MODE_SEARCH:
2498- search_get_valid_child_iter (udata->impl, &child_iter, iter);
2499- gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->search_model), &child_iter,
2500- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
2501- -1);
2502- break;
2503-
2504- case OPERATION_MODE_RECENT:
2505- recent_get_valid_child_iter (udata->impl, &child_iter, iter);
2506- gtk_tree_model_get (GTK_TREE_MODEL (udata->impl->recent_model), &child_iter,
2507- RECENT_MODEL_COL_DISPLAY_NAME, &display_name,
2508- -1);
2509- break;
2510- }
2511-
2512- udata->tip = g_strdup_printf (_("Add the folder '%s' to the bookmarks"),
2513- display_name);
2514- }
2515-}
2516-
2517-
2518-/* Sensitize the "add bookmark" button if all the selected items are folders, or
2519- * if there are no selected items *and* the current folder is not in the
2520- * bookmarks list. De-sensitize the button otherwise.
2521- */
2522-static void
2523-bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl)
2524-{
2525- gint num_selected;
2526- gboolean all_folders;
2527- gboolean active;
2528- gchar *tip;
2529-
2530- selection_check (impl, &num_selected, NULL, &all_folders);
2531-
2532- if (num_selected == 0)
2533- active = (impl->current_folder != NULL) && (shortcut_find_position (impl, impl->current_folder) == -1);
2534- else if (num_selected == 1)
2535- {
2536- const GtkFilePath *path;
2537-
2538- path = get_selected_path (impl);
2539- active = all_folders && (shortcut_find_position (impl, path) == -1);
2540- }
2541- else
2542- active = all_folders;
2543-
2544- gtk_widget_set_sensitive (impl->browse_shortcuts_add_button, active);
2545-
2546- if (impl->browse_files_popup_menu_add_shortcut_item)
2547- gtk_widget_set_sensitive (impl->browse_files_popup_menu_add_shortcut_item,
2548- (num_selected == 0) ? FALSE : active);
2549-
2550- if (active)
2551- {
2552- if (num_selected == 0)
2553- tip = g_strdup_printf (_("Add the current folder to the bookmarks"));
2554- else if (num_selected > 1)
2555- tip = g_strdup_printf (_("Add the selected folders to the bookmarks"));
2556- else
2557- {
2558- GtkTreeSelection *selection;
2559- UpdateTooltipData data;
2560-
2561- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2562- data.impl = impl;
2563- data.tip = NULL;
2564- gtk_tree_selection_selected_foreach (selection, update_tooltip, &data);
2565- tip = data.tip;
2566- }
2567-
2568- gtk_widget_set_tooltip_text (impl->browse_shortcuts_add_button, tip);
2569- g_free (tip);
2570- }
2571-}
2572-
2573-/* Sets the sensitivity of the "remove bookmark" button depending on whether a
2574- * bookmark row is selected in the shortcuts tree.
2575- */
2576-static void
2577-bookmarks_check_remove_sensitivity (GtkFileChooserDefault *impl)
2578-{
2579- GtkTreeIter iter;
2580- gboolean removable = FALSE;
2581- gchar *name = NULL;
2582-
2583- if (shortcuts_get_selected (impl, &iter))
2584- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2585- SHORTCUTS_COL_REMOVABLE, &removable,
2586- SHORTCUTS_COL_NAME, &name,
2587- -1);
2588-
2589- gtk_widget_set_sensitive (impl->browse_shortcuts_remove_button, removable);
2590-
2591- if (removable)
2592- {
2593- gchar *tip;
2594-
2595- tip = g_strdup_printf (_("Remove the bookmark '%s'"), name);
2596- gtk_widget_set_tooltip_text (impl->browse_shortcuts_remove_button, tip);
2597- g_free (tip);
2598- }
2599-
2600- g_free (name);
2601-}
2602-
2603-static void
2604-shortcuts_check_popup_sensitivity (GtkFileChooserDefault *impl)
2605-{
2606- GtkTreeIter iter;
2607- gboolean removable = FALSE;
2608-
2609- if (impl->browse_shortcuts_popup_menu == NULL)
2610- return;
2611-
2612- if (shortcuts_get_selected (impl, &iter))
2613- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2614- SHORTCUTS_COL_REMOVABLE, &removable,
2615- -1);
2616-
2617- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_remove_item, removable);
2618- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_rename_item, removable);
2619-}
2620-
2621-/* GtkWidget::drag-begin handler for the shortcuts list. */
2622-static void
2623-shortcuts_drag_begin_cb (GtkWidget *widget,
2624- GdkDragContext *context,
2625- GtkFileChooserDefault *impl)
2626-{
2627-#if 0
2628- impl->shortcuts_drag_context = g_object_ref (context);
2629-#endif
2630-}
2631-
2632-#if 0
2633-/* Removes the idle handler for outside drags */
2634-static void
2635-shortcuts_cancel_drag_outside_idle (GtkFileChooserDefault *impl)
2636-{
2637- if (!impl->shortcuts_drag_outside_idle)
2638- return;
2639-
2640- g_source_destroy (impl->shortcuts_drag_outside_idle);
2641- impl->shortcuts_drag_outside_idle = NULL;
2642-}
2643-#endif
2644-
2645-/* GtkWidget::drag-end handler for the shortcuts list. */
2646-static void
2647-shortcuts_drag_end_cb (GtkWidget *widget,
2648- GdkDragContext *context,
2649- GtkFileChooserDefault *impl)
2650-{
2651-#if 0
2652- g_object_unref (impl->shortcuts_drag_context);
2653-
2654- shortcuts_cancel_drag_outside_idle (impl);
2655-
2656- if (!impl->shortcuts_drag_outside)
2657- return;
2658-
2659- gtk_button_clicked (GTK_BUTTON (impl->browse_shortcuts_remove_button));
2660-
2661- impl->shortcuts_drag_outside = FALSE;
2662-#endif
2663-}
2664-
2665-/* GtkWidget::drag-data-delete handler for the shortcuts list. */
2666-static void
2667-shortcuts_drag_data_delete_cb (GtkWidget *widget,
2668- GdkDragContext *context,
2669- GtkFileChooserDefault *impl)
2670-{
2671- g_signal_stop_emission_by_name (widget, "drag_data_delete");
2672-}
2673-
2674-#if 0
2675-/* Creates a suitable drag cursor to indicate that the selected bookmark will be
2676- * deleted or not.
2677- */
2678-static void
2679-shortcuts_drag_set_delete_cursor (GtkFileChooserDefault *impl,
2680- gboolean delete)
2681-{
2682- GtkTreeView *tree_view;
2683- GtkTreeIter iter;
2684- GtkTreePath *path;
2685- GdkPixmap *row_pixmap;
2686- GdkBitmap *mask;
2687- int row_pixmap_y;
2688- int cell_y;
2689-
2690- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view);
2691-
2692- /* Find the selected path and get its drag pixmap */
2693-
2694- if (!shortcuts_get_selected (impl, &iter))
2695- g_assert_not_reached ();
2696-
2697- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
2698-
2699- row_pixmap = gtk_tree_view_create_row_drag_icon (tree_view, path);
2700- gtk_tree_path_free (path);
2701-
2702- mask = NULL;
2703- row_pixmap_y = 0;
2704-
2705- if (delete)
2706- {
2707- GdkPixbuf *pixbuf;
2708-
2709- pixbuf = gtk_widget_render_icon (impl->browse_shortcuts_tree_view,
2710- GTK_STOCK_DELETE,
2711- GTK_ICON_SIZE_DND,
2712- NULL);
2713- if (pixbuf)
2714- {
2715- GdkPixmap *composite;
2716- int row_pixmap_width, row_pixmap_height;
2717- int pixbuf_width, pixbuf_height;
2718- int composite_width, composite_height;
2719- int pixbuf_x, pixbuf_y;
2720- GdkGC *gc, *mask_gc;
2721- GdkColor color;
2722- GdkBitmap *pixbuf_mask;
2723-
2724- /* Create pixmap and mask for composite image */
2725-
2726- gdk_drawable_get_size (row_pixmap, &row_pixmap_width, &row_pixmap_height);
2727- pixbuf_width = gdk_pixbuf_get_width (pixbuf);
2728- pixbuf_height = gdk_pixbuf_get_height (pixbuf);
2729-
2730- composite_width = MAX (row_pixmap_width, pixbuf_width);
2731- composite_height = MAX (row_pixmap_height, pixbuf_height);
2732-
2733- row_pixmap_y = (composite_height - row_pixmap_height) / 2;
2734-
2735- if (gtk_widget_get_direction (impl->browse_shortcuts_tree_view) == GTK_TEXT_DIR_RTL)
2736- pixbuf_x = 0;
2737- else
2738- pixbuf_x = composite_width - pixbuf_width;
2739-
2740- pixbuf_y = (composite_height - pixbuf_height) / 2;
2741-
2742- composite = gdk_pixmap_new (row_pixmap, composite_width, composite_height, -1);
2743- gc = gdk_gc_new (composite);
2744-
2745- mask = gdk_pixmap_new (row_pixmap, composite_width, composite_height, 1);
2746- mask_gc = gdk_gc_new (mask);
2747- color.pixel = 0;
2748- gdk_gc_set_foreground (mask_gc, &color);
2749- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, 0, composite_width, composite_height);
2750-
2751- color.red = 0xffff;
2752- color.green = 0xffff;
2753- color.blue = 0xffff;
2754- gdk_gc_set_rgb_fg_color (gc, &color);
2755- gdk_draw_rectangle (composite, gc, TRUE, 0, 0, composite_width, composite_height);
2756-
2757- /* Composite the row pixmap and the pixbuf */
2758-
2759- gdk_pixbuf_render_pixmap_and_mask_for_colormap
2760- (pixbuf,
2761- gtk_widget_get_colormap (impl->browse_shortcuts_tree_view),
2762- NULL, &pixbuf_mask, 128);
2763- gdk_draw_drawable (mask, mask_gc, pixbuf_mask,
2764- 0, 0,
2765- pixbuf_x, pixbuf_y,
2766- pixbuf_width, pixbuf_height);
2767- g_object_unref (pixbuf_mask);
2768-
2769- gdk_draw_drawable (composite, gc, row_pixmap,
2770- 0, 0,
2771- 0, row_pixmap_y,
2772- row_pixmap_width, row_pixmap_height);
2773- color.pixel = 1;
2774- gdk_gc_set_foreground (mask_gc, &color);
2775- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, row_pixmap_y, row_pixmap_width, row_pixmap_height);
2776-
2777- gdk_draw_pixbuf (composite, gc, pixbuf,
2778- 0, 0,
2779- pixbuf_x, pixbuf_y,
2780- pixbuf_width, pixbuf_height,
2781- GDK_RGB_DITHER_MAX,
2782- 0, 0);
2783-
2784- g_object_unref (pixbuf);
2785- g_object_unref (row_pixmap);
2786-
2787- row_pixmap = composite;
2788- }
2789- }
2790-
2791- /* The hotspot offsets here are copied from gtk_tree_view_drag_begin(), ugh */
2792-
2793- gtk_tree_view_get_path_at_pos (tree_view,
2794- tree_view->priv->press_start_x,
2795- tree_view->priv->press_start_y,
2796- NULL,
2797- NULL,
2798- NULL,
2799- &cell_y);
2800-
2801- gtk_drag_set_icon_pixmap (impl->shortcuts_drag_context,
2802- gdk_drawable_get_colormap (row_pixmap),
2803- row_pixmap,
2804- mask,
2805- tree_view->priv->press_start_x + 1,
2806- row_pixmap_y + cell_y + 1);
2807-
2808- g_object_unref (row_pixmap);
2809- if (mask)
2810- g_object_unref (mask);
2811-}
2812-
2813-/* We set the delete cursor and the shortcuts_drag_outside flag in an idle
2814- * handler so that we can tell apart the drag_leave event that comes right
2815- * before a drag_drop, from a normal drag_leave. We don't want to set the
2816- * cursor nor the flag in the latter case.
2817- */
2818-static gboolean
2819-shortcuts_drag_outside_idle_cb (GtkFileChooserDefault *impl)
2820-{
2821- GDK_THREADS_ENTER ();
2822-
2823- shortcuts_drag_set_delete_cursor (impl, TRUE);
2824- impl->shortcuts_drag_outside = TRUE;
2825-
2826- shortcuts_cancel_drag_outside_idle (impl);
2827-
2828- GDK_THREADS_LEAVE ();
2829-
2830- return FALSE;
2831-}
2832-#endif
2833-
2834-/* GtkWidget::drag-leave handler for the shortcuts list. We unhighlight the
2835- * drop position.
2836- */
2837-static void
2838-shortcuts_drag_leave_cb (GtkWidget *widget,
2839- GdkDragContext *context,
2840- guint time_,
2841- GtkFileChooserDefault *impl)
2842-{
2843-#if 0
2844- if (gtk_drag_get_source_widget (context) == widget && !impl->shortcuts_drag_outside_idle)
2845- {
2846- impl->shortcuts_drag_outside_idle = g_idle_source_new ();
2847- g_source_set_closure (impl->shortcuts_drag_outside_idle,
2848- g_cclosure_new_object (G_CALLBACK (shortcuts_drag_outside_idle_cb),
2849- G_OBJECT (impl)));
2850- g_source_attach (impl->shortcuts_drag_outside_idle, NULL);
2851- }
2852-#endif
2853-
2854- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
2855- NULL,
2856- GTK_TREE_VIEW_DROP_BEFORE);
2857-
2858- g_signal_stop_emission_by_name (widget, "drag_leave");
2859-}
2860-
2861-/* Computes the appropriate row and position for dropping */
2862-static void
2863-shortcuts_compute_drop_position (GtkFileChooserDefault *impl,
2864- int x,
2865- int y,
2866- GtkTreePath **path,
2867- GtkTreeViewDropPosition *pos)
2868-{
2869- GtkTreeView *tree_view;
2870- GtkTreeViewColumn *column;
2871- int cell_y;
2872- GdkRectangle cell;
2873- int row;
2874- int bookmarks_index;
2875-
2876- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view);
2877-
2878- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2879-
2880- if (!gtk_tree_view_get_path_at_pos (tree_view,
2881- x,
2882- y - TREE_VIEW_HEADER_HEIGHT (tree_view),
2883- path,
2884- &column,
2885- NULL,
2886- &cell_y))
2887- {
2888- row = bookmarks_index + impl->num_bookmarks - 1;
2889- *path = gtk_tree_path_new_from_indices (row, -1);
2890- *pos = GTK_TREE_VIEW_DROP_AFTER;
2891- return;
2892- }
2893-
2894- row = *gtk_tree_path_get_indices (*path);
2895- gtk_tree_view_get_background_area (tree_view, *path, column, &cell);
2896- gtk_tree_path_free (*path);
2897-
2898- if (row < bookmarks_index)
2899- {
2900- row = bookmarks_index;
2901- *pos = GTK_TREE_VIEW_DROP_BEFORE;
2902- }
2903- else if (row > bookmarks_index + impl->num_bookmarks - 1)
2904- {
2905- row = bookmarks_index + impl->num_bookmarks - 1;
2906- *pos = GTK_TREE_VIEW_DROP_AFTER;
2907- }
2908- else
2909- {
2910- if (cell_y < cell.height / 2)
2911- *pos = GTK_TREE_VIEW_DROP_BEFORE;
2912- else
2913- *pos = GTK_TREE_VIEW_DROP_AFTER;
2914- }
2915-
2916- *path = gtk_tree_path_new_from_indices (row, -1);
2917-}
2918-
2919-/* GtkWidget::drag-motion handler for the shortcuts list. We basically
2920- * implement the destination side of DnD by hand, due to limitations in
2921- * GtkTreeView's DnD API.
2922- */
2923-static gboolean
2924-shortcuts_drag_motion_cb (GtkWidget *widget,
2925- GdkDragContext *context,
2926- gint x,
2927- gint y,
2928- guint time_,
2929- GtkFileChooserDefault *impl)
2930-{
2931- GtkTreePath *path;
2932- GtkTreeViewDropPosition pos;
2933- GdkDragAction action;
2934-
2935-#if 0
2936- if (gtk_drag_get_source_widget (context) == widget)
2937- {
2938- shortcuts_cancel_drag_outside_idle (impl);
2939-
2940- if (impl->shortcuts_drag_outside)
2941- {
2942- shortcuts_drag_set_delete_cursor (impl, FALSE);
2943- impl->shortcuts_drag_outside = FALSE;
2944- }
2945- }
2946-#endif
2947-
2948- if (context->suggested_action == GDK_ACTION_COPY ||
2949- (context->actions & GDK_ACTION_COPY) != 0)
2950- action = GDK_ACTION_COPY;
2951- else if (context->suggested_action == GDK_ACTION_MOVE ||
2952- (context->actions & GDK_ACTION_MOVE) != 0)
2953- action = GDK_ACTION_MOVE;
2954- else
2955- {
2956- action = 0;
2957- goto out;
2958- }
2959-
2960- shortcuts_compute_drop_position (impl, x, y, &path, &pos);
2961- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), path, pos);
2962- gtk_tree_path_free (path);
2963-
2964- out:
2965-
2966- g_signal_stop_emission_by_name (widget, "drag_motion");
2967-
2968- if (action != 0)
2969- {
2970- gdk_drag_status (context, action, time_);
2971- return TRUE;
2972- }
2973- else
2974- return FALSE;
2975-}
2976-
2977-/* GtkWidget::drag-drop handler for the shortcuts list. */
2978-static gboolean
2979-shortcuts_drag_drop_cb (GtkWidget *widget,
2980- GdkDragContext *context,
2981- gint x,
2982- gint y,
2983- guint time_,
2984- GtkFileChooserDefault *impl)
2985-{
2986-#if 0
2987- shortcuts_cancel_drag_outside_idle (impl);
2988-#endif
2989-
2990- g_signal_stop_emission_by_name (widget, "drag_drop");
2991- return TRUE;
2992-}
2993-
2994-/* Parses a "text/uri-list" string and inserts its URIs as bookmarks */
2995-static void
2996-shortcuts_drop_uris (GtkFileChooserDefault *impl,
2997- const char *data,
2998- int position)
2999-{
3000- gchar **uris;
3001- gint i;
3002-
3003- uris = g_uri_list_extract_uris (data);
3004-
3005- for (i = 0; uris[i]; i++)
3006- {
3007- char *uri;
3008- GtkFilePath *path;
3009-
3010- uri = uris[i];
3011- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3012-
3013- if (path)
3014- {
3015- if (shortcuts_add_bookmark_from_path (impl, path, position))
3016- position++;
3017-
3018- gtk_file_path_free (path);
3019- }
3020- else
3021- {
3022- GError *error = NULL;
3023-
3024- g_set_error (&error,
3025- GTK_FILE_CHOOSER_ERROR,
3026- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
3027- _("Could not add a bookmark for '%s' "
3028- "because it is an invalid path name."),
3029- uri);
3030- error_adding_bookmark_dialog (impl, path, error);
3031- }
3032- }
3033-
3034- g_strfreev (uris);
3035-}
3036-
3037-/* Reorders the selected bookmark to the specified position */
3038-static void
3039-shortcuts_reorder (GtkFileChooserDefault *impl,
3040- int new_position)
3041-{
3042- GtkTreeIter iter;
3043- gpointer col_data;
3044- ShortcutType shortcut_type;
3045- GtkTreePath *path;
3046- int old_position;
3047- int bookmarks_index;
3048- const GtkFilePath *file_path;
3049- GtkFilePath *file_path_copy;
3050- GError *error;
3051- gchar *name;
3052-
3053- /* Get the selected path */
3054-
3055- if (!shortcuts_get_selected (impl, &iter))
3056- g_assert_not_reached ();
3057-
3058- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
3059- old_position = *gtk_tree_path_get_indices (path);
3060- gtk_tree_path_free (path);
3061-
3062- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
3063- old_position -= bookmarks_index;
3064- g_assert (old_position >= 0 && old_position < impl->num_bookmarks);
3065-
3066- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
3067- SHORTCUTS_COL_NAME, &name,
3068- SHORTCUTS_COL_DATA, &col_data,
3069- SHORTCUTS_COL_TYPE, &shortcut_type,
3070- -1);
3071- g_assert (col_data != NULL);
3072- g_assert (shortcut_type == SHORTCUT_TYPE_PATH);
3073-
3074- file_path = col_data;
3075- file_path_copy = gtk_file_path_copy (file_path); /* removal below will free file_path, so we need a copy */
3076-
3077- /* Remove the path from the old position and insert it in the new one */
3078-
3079- if (new_position > old_position)
3080- new_position--;
3081-
3082- if (old_position == new_position)
3083- goto out;
3084-
3085- error = NULL;
3086- if (gtk_file_system_remove_bookmark (impl->file_system, file_path_copy, &error))
3087- {
3088- shortcuts_add_bookmark_from_path (impl, file_path_copy, new_position);
3089- gtk_file_system_set_bookmark_label (impl->file_system, file_path_copy, name);
3090- }
3091- else
3092- error_adding_bookmark_dialog (impl, file_path_copy, error);
3093-
3094- out:
3095-
3096- gtk_file_path_free (file_path_copy);
3097-}
3098-
3099-/* Callback used when we get the drag data for the bookmarks list. We add the
3100- * received URIs as bookmarks if they are folders.
3101- */
3102-static void
3103-shortcuts_drag_data_received_cb (GtkWidget *widget,
3104- GdkDragContext *context,
3105- gint x,
3106- gint y,
3107- GtkSelectionData *selection_data,
3108- guint info,
3109- guint time_,
3110- gpointer data)
3111-{
3112- GtkFileChooserDefault *impl;
3113- GtkTreePath *tree_path;
3114- GtkTreeViewDropPosition tree_pos;
3115- int position;
3116- int bookmarks_index;
3117-
3118- impl = GTK_FILE_CHOOSER_DEFAULT (data);
3119-
3120- /* Compute position */
3121-
3122- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
3123-
3124- shortcuts_compute_drop_position (impl, x, y, &tree_path, &tree_pos);
3125- position = *gtk_tree_path_get_indices (tree_path);
3126- gtk_tree_path_free (tree_path);
3127-
3128- if (tree_pos == GTK_TREE_VIEW_DROP_AFTER)
3129- position++;
3130-
3131- g_assert (position >= bookmarks_index);
3132- position -= bookmarks_index;
3133-
3134- if (selection_data->target == gdk_atom_intern_static_string ("text/uri-list"))
3135- shortcuts_drop_uris (impl, (const char *) selection_data->data, position);
3136- else if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
3137- shortcuts_reorder (impl, position);
3138-
3139- g_signal_stop_emission_by_name (widget, "drag_data_received");
3140-}
3141-
3142-/* Callback used when the selection in the shortcuts tree changes */
3143-static void
3144-shortcuts_selection_changed_cb (GtkTreeSelection *selection,
3145- GtkFileChooserDefault *impl)
3146-{
3147- bookmarks_check_remove_sensitivity (impl);
3148- shortcuts_check_popup_sensitivity (impl);
3149-}
3150-
3151-static gboolean
3152-shortcuts_row_separator_func (GtkTreeModel *model,
3153- GtkTreeIter *iter,
3154- gpointer data)
3155-{
3156- ShortcutType shortcut_type;
3157-
3158- gtk_tree_model_get (model, iter, SHORTCUTS_COL_TYPE, &shortcut_type, -1);
3159-
3160- return shortcut_type == SHORTCUT_TYPE_SEPARATOR;
3161-}
3162-
3163-/* Since GtkTreeView has a keybinding attached to '/', we need to catch
3164- * keypresses before the TreeView gets them.
3165- */
3166-static gboolean
3167-tree_view_keybinding_cb (GtkWidget *tree_view,
3168- GdkEventKey *event,
3169- GtkFileChooserDefault *impl)
3170-{
3171- if ((event->keyval == GDK_slash
3172- || event->keyval == GDK_KP_Divide
3173-#ifdef G_OS_UNIX
3174- || event->keyval == GDK_asciitilde
3175-#endif
3176- ) && ! (event->state & (~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask ())))
3177- {
3178- location_popup_handler (impl, event->string);
3179- return TRUE;
3180- }
3181-
3182- return FALSE;
3183-}
3184-
3185-/* Callback used when the file list's popup menu is detached */
3186-static void
3187-shortcuts_popup_menu_detach_cb (GtkWidget *attach_widget,
3188- GtkMenu *menu)
3189-{
3190- GtkFileChooserDefault *impl;
3191-
3192- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
3193- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
3194-
3195- impl->browse_shortcuts_popup_menu = NULL;
3196- impl->browse_shortcuts_popup_menu_remove_item = NULL;
3197- impl->browse_shortcuts_popup_menu_rename_item = NULL;
3198-}
3199-
3200-static void
3201-remove_shortcut_cb (GtkMenuItem *item,
3202- GtkFileChooserDefault *impl)
3203-{
3204- remove_selected_bookmarks (impl);
3205-}
3206-
3207-/* Rename the selected bookmark */
3208-static void
3209-rename_selected_bookmark (GtkFileChooserDefault *impl)
3210-{
3211- GtkTreeIter iter;
3212- GtkTreePath *path;
3213- GtkTreeViewColumn *column;
3214- GtkCellRenderer *cell;
3215- GList *renderers;
3216-
3217- if (shortcuts_get_selected (impl, &iter))
3218- {
3219- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
3220- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), 0);
3221- renderers = gtk_tree_view_column_get_cell_renderers (column);
3222- cell = g_list_nth_data (renderers, 1);
3223- g_list_free (renderers);
3224- g_object_set (cell, "editable", TRUE, NULL);
3225- gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3226- path, column, cell, TRUE);
3227- gtk_tree_path_free (path);
3228- }
3229-}
3230-
3231-static void
3232-rename_shortcut_cb (GtkMenuItem *item,
3233- GtkFileChooserDefault *impl)
3234-{
3235- rename_selected_bookmark (impl);
3236-}
3237-
3238-/* Constructs the popup menu for the file list if needed */
3239-static void
3240-shortcuts_build_popup_menu (GtkFileChooserDefault *impl)
3241-{
3242- GtkWidget *item;
3243-
3244- if (impl->browse_shortcuts_popup_menu)
3245- return;
3246-
3247- impl->browse_shortcuts_popup_menu = gtk_menu_new ();
3248- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_shortcuts_popup_menu),
3249- impl->browse_shortcuts_tree_view,
3250- shortcuts_popup_menu_detach_cb);
3251-
3252- item = gtk_image_menu_item_new_with_label (_("Remove"));
3253- impl->browse_shortcuts_popup_menu_remove_item = item;
3254- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
3255- gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
3256- g_signal_connect (item, "activate",
3257- G_CALLBACK (remove_shortcut_cb), impl);
3258- gtk_widget_show (item);
3259- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
3260-
3261- item = gtk_menu_item_new_with_label (_("Rename..."));
3262- impl->browse_shortcuts_popup_menu_rename_item = item;
3263- g_signal_connect (item, "activate",
3264- G_CALLBACK (rename_shortcut_cb), impl);
3265- gtk_widget_show (item);
3266- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
3267-
3268- shortcuts_check_popup_sensitivity (impl);
3269-}
3270-
3271-static void
3272-shortcuts_update_popup_menu (GtkFileChooserDefault *impl)
3273-{
3274- shortcuts_build_popup_menu (impl);
3275-}
3276-
3277-static void
3278-popup_position_func (GtkMenu *menu,
3279- gint *x,
3280- gint *y,
3281- gboolean *push_in,
3282- gpointer user_data);
3283-
3284-static void
3285-shortcuts_popup_menu (GtkFileChooserDefault *impl,
3286- GdkEventButton *event)
3287-{
3288- shortcuts_update_popup_menu (impl);
3289- if (event)
3290- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
3291- NULL, NULL, NULL, NULL,
3292- event->button, event->time);
3293- else
3294- {
3295- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
3296- NULL, NULL,
3297- popup_position_func, impl->browse_shortcuts_tree_view,
3298- 0, GDK_CURRENT_TIME);
3299- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu),
3300- FALSE);
3301- }
3302-}
3303-
3304-/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
3305-static gboolean
3306-shortcuts_popup_menu_cb (GtkWidget *widget,
3307- GtkFileChooserDefault *impl)
3308-{
3309- shortcuts_popup_menu (impl, NULL);
3310- return TRUE;
3311-}
3312-
3313-/* Callback used when a button is pressed on the shortcuts list.
3314- * We trap button 3 to bring up a popup menu.
3315- */
3316-static gboolean
3317-shortcuts_button_press_event_cb (GtkWidget *widget,
3318- GdkEventButton *event,
3319- GtkFileChooserDefault *impl)
3320-{
3321- static gboolean in_press = FALSE;
3322- gboolean handled;
3323-
3324- if (in_press)
3325- return FALSE;
3326-
3327- if (event->button != 3)
3328- return FALSE;
3329-
3330- in_press = TRUE;
3331- handled = gtk_widget_event (impl->browse_shortcuts_tree_view, (GdkEvent *) event);
3332- in_press = FALSE;
3333-
3334- if (!handled)
3335- return FALSE;
3336-
3337- shortcuts_popup_menu (impl, event);
3338- return TRUE;
3339-}
3340-
3341-static void
3342-shortcuts_edited (GtkCellRenderer *cell,
3343- gchar *path_string,
3344- gchar *new_text,
3345- GtkFileChooserDefault *impl)
3346-{
3347- GtkTreePath *path;
3348- GtkTreeIter iter;
3349- GtkFilePath *shortcut;
3350-
3351- g_object_set (cell, "editable", FALSE, NULL);
3352-
3353- path = gtk_tree_path_new_from_string (path_string);
3354- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path))
3355- g_assert_not_reached ();
3356-
3357- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
3358- SHORTCUTS_COL_DATA, &shortcut,
3359- -1);
3360- gtk_tree_path_free (path);
3361-
3362- gtk_file_system_set_bookmark_label (impl->file_system, shortcut, new_text);
3363-}
3364-
3365-static void
3366-shortcuts_editing_canceled (GtkCellRenderer *cell,
3367- GtkFileChooserDefault *impl)
3368-{
3369- g_object_set (cell, "editable", FALSE, NULL);
3370-}
3371-
3372-/* Creates the widgets for the shortcuts and bookmarks tree */
3373-static GtkWidget *
3374-shortcuts_list_create (GtkFileChooserDefault *impl)
3375-{
3376- GtkWidget *swin;
3377- GtkTreeSelection *selection;
3378- GtkTreeViewColumn *column;
3379- GtkCellRenderer *renderer;
3380-
3381- /* Scrolled window */
3382-
3383- swin = gtk_scrolled_window_new (NULL, NULL);
3384- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
3385- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3386- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
3387- GTK_SHADOW_IN);
3388- gtk_widget_show (swin);
3389-
3390- /* Tree */
3391-
3392- impl->browse_shortcuts_tree_view = gtk_tree_view_new ();
3393-#ifdef PROFILE_FILE_CHOOSER
3394- g_object_set_data (G_OBJECT (impl->browse_shortcuts_tree_view), "fmq-name", "shortcuts");
3395-#endif
3396- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event",
3397- G_CALLBACK (tree_view_keybinding_cb), impl);
3398- g_signal_connect (impl->browse_shortcuts_tree_view, "popup_menu",
3399- G_CALLBACK (shortcuts_popup_menu_cb), impl);
3400- g_signal_connect (impl->browse_shortcuts_tree_view, "button_press_event",
3401- G_CALLBACK (shortcuts_button_press_event_cb), impl);
3402- /* Accessible object name for the file chooser's shortcuts pane */
3403- atk_object_set_name (gtk_widget_get_accessible (impl->browse_shortcuts_tree_view), _("Places"));
3404-
3405- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), impl->shortcuts_pane_filter_model);
3406-
3407- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3408- GDK_BUTTON1_MASK,
3409- shortcuts_source_targets,
3410- num_shortcuts_source_targets,
3411- GDK_ACTION_MOVE);
3412-
3413- gtk_drag_dest_set (impl->browse_shortcuts_tree_view,
3414- GTK_DEST_DEFAULT_ALL,
3415- shortcuts_dest_targets,
3416- num_shortcuts_dest_targets,
3417- GDK_ACTION_COPY | GDK_ACTION_MOVE);
3418-
3419- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
3420- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
3421- gtk_tree_selection_set_select_function (selection,
3422- shortcuts_select_func,
3423- impl, NULL);
3424-
3425- g_signal_connect (selection, "changed",
3426- G_CALLBACK (shortcuts_selection_changed_cb), impl);
3427-
3428- g_signal_connect (impl->browse_shortcuts_tree_view, "row_activated",
3429- G_CALLBACK (shortcuts_row_activated_cb), impl);
3430-
3431- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event",
3432- G_CALLBACK (shortcuts_key_press_event_cb), impl);
3433-
3434- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_begin",
3435- G_CALLBACK (shortcuts_drag_begin_cb), impl);
3436- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_end",
3437- G_CALLBACK (shortcuts_drag_end_cb), impl);
3438- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_delete",
3439- G_CALLBACK (shortcuts_drag_data_delete_cb), impl);
3440-
3441- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_leave",
3442- G_CALLBACK (shortcuts_drag_leave_cb), impl);
3443- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_motion",
3444- G_CALLBACK (shortcuts_drag_motion_cb), impl);
3445- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_drop",
3446- G_CALLBACK (shortcuts_drag_drop_cb), impl);
3447- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_received",
3448- G_CALLBACK (shortcuts_drag_data_received_cb), impl);
3449-
3450- gtk_container_add (GTK_CONTAINER (swin), impl->browse_shortcuts_tree_view);
3451- gtk_widget_show (impl->browse_shortcuts_tree_view);
3452-
3453- /* Column */
3454-
3455- column = gtk_tree_view_column_new ();
3456- /* Column header for the file chooser's shortcuts pane */
3457- gtk_tree_view_column_set_title (column, _("_Places"));
3458-
3459- renderer = gtk_cell_renderer_pixbuf_new ();
3460- gtk_tree_view_column_pack_start (column, renderer, FALSE);
3461- gtk_tree_view_column_set_attributes (column, renderer,
3462- "pixbuf", SHORTCUTS_COL_PIXBUF,
3463- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
3464- NULL);
3465-
3466- renderer = gtk_cell_renderer_text_new ();
3467- g_signal_connect (renderer, "edited",
3468- G_CALLBACK (shortcuts_edited), impl);
3469- g_signal_connect (renderer, "editing-canceled",
3470- G_CALLBACK (shortcuts_editing_canceled), impl);
3471- gtk_tree_view_column_pack_start (column, renderer, TRUE);
3472- gtk_tree_view_column_set_attributes (column, renderer,
3473- "text", SHORTCUTS_COL_NAME,
3474- NULL);
3475-
3476- gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3477- shortcuts_row_separator_func,
3478- NULL, NULL);
3479-
3480- gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), column);
3481-
3482- return swin;
3483-}
3484-
3485-/* Creates the widgets for the shortcuts/bookmarks pane */
3486-static GtkWidget *
3487-shortcuts_pane_create (GtkFileChooserDefault *impl,
3488- GtkSizeGroup *size_group)
3489-{
3490- GtkWidget *vbox;
3491- GtkWidget *hbox;
3492- GtkWidget *widget;
3493-
3494- vbox = gtk_vbox_new (FALSE, 6);
3495- gtk_widget_show (vbox);
3496-
3497- /* Shortcuts tree */
3498-
3499- widget = shortcuts_list_create (impl);
3500- gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
3501-
3502- /* Box for buttons */
3503-
3504- hbox = gtk_hbox_new (TRUE, 6);
3505- gtk_size_group_add_widget (size_group, hbox);
3506- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
3507- gtk_widget_show (hbox);
3508-
3509- /* Add bookmark button */
3510-
3511- impl->browse_shortcuts_add_button = button_new (impl,
3512- _("_Add"),
3513- GTK_STOCK_ADD,
3514- FALSE,
3515- TRUE,
3516- G_CALLBACK (add_bookmark_button_clicked_cb));
3517- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_add_button, TRUE, TRUE, 0);
3518- gtk_widget_set_tooltip_text (impl->browse_shortcuts_add_button,
3519- _("Add the selected folder to the Bookmarks"));
3520-
3521- /* Remove bookmark button */
3522-
3523- impl->browse_shortcuts_remove_button = button_new (impl,
3524- _("_Remove"),
3525- GTK_STOCK_REMOVE,
3526- FALSE,
3527- TRUE,
3528- G_CALLBACK (remove_bookmark_button_clicked_cb));
3529- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_remove_button, TRUE, TRUE, 0);
3530- gtk_widget_set_tooltip_text (impl->browse_shortcuts_remove_button,
3531- _("Remove the selected bookmark"));
3532-
3533- return vbox;
3534-}
3535-
3536 /* Handles key press events on the file list, so that we can trap Enter to
3537 * activate the default button on our own. Also, checks to see if '/' has been
3538 * pressed. See comment by tree_view_keybinding_cb() for more details.
3539@@ -4056,17 +1175,6 @@
3540
3541 modifiers = gtk_accelerator_get_default_mod_mask ();
3542
3543- if ((event->keyval == GDK_slash
3544- || event->keyval == GDK_KP_Divide
3545-#ifdef G_OS_UNIX
3546- || event->keyval == GDK_asciitilde
3547-#endif
3548- ) && ! (event->state & (~GDK_SHIFT_MASK & modifiers)))
3549- {
3550- location_popup_handler (impl, event->string);
3551- return TRUE;
3552- }
3553-
3554 if ((event->keyval == GDK_Return
3555 || event->keyval == GDK_ISO_Enter
3556 || event->keyval == GDK_KP_Enter
3557@@ -4091,474 +1199,66 @@
3558 return FALSE;
3559 }
3560
3561-/* Callback used when the file list's popup menu is detached */
3562-static void
3563-popup_menu_detach_cb (GtkWidget *attach_widget,
3564- GtkMenu *menu)
3565+static gboolean
3566+list_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
3567 {
3568- GtkFileChooserDefault *impl;
3569+ GtkTreeView * tree = GTK_TREE_VIEW (widget);
3570+ GtkFileChooserDefault *impl = data;
3571+ GtkTreePath *path;
3572
3573- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
3574- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
3575-
3576- impl->browse_files_popup_menu = NULL;
3577- impl->browse_files_popup_menu_add_shortcut_item = NULL;
3578- impl->browse_files_popup_menu_hidden_files_item = NULL;
3579-}
3580-
3581-/* Callback used when the "Add to Bookmarks" menu item is activated */
3582-static void
3583-add_to_shortcuts_cb (GtkMenuItem *item,
3584- GtkFileChooserDefault *impl)
3585-{
3586- bookmarks_add_selected_folder (impl);
3587-}
3588-
3589-/* Callback used when the "Show Hidden Files" menu item is toggled */
3590-static void
3591-show_hidden_toggled_cb (GtkCheckMenuItem *item,
3592- GtkFileChooserDefault *impl)
3593-{
3594- g_object_set (impl,
3595- "show-hidden", gtk_check_menu_item_get_active (item),
3596- NULL);
3597-}
3598-
3599-/* Shows an error dialog about not being able to select a dragged file */
3600-static void
3601-error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl,
3602- const GtkFilePath *path,
3603- GError *error)
3604-{
3605- error_dialog (impl,
3606- _("Could not select file"),
3607- path, error);
3608-}
3609-
3610-static void
3611-file_list_drag_data_select_uris (GtkFileChooserDefault *impl,
3612- gchar **uris)
3613-{
3614- int i;
3615- char *uri;
3616- GtkFileChooser *chooser = GTK_FILE_CHOOSER (impl);
3617-
3618- for (i = 1; uris[i]; i++)
3619+ if (event->type != GDK_BUTTON_PRESS ||
3620+ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y,
3621+ &path, NULL, NULL, NULL))
3622 {
3623- GtkFilePath *path;
3624-
3625- uri = uris[i];
3626- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3627-
3628- if (path)
3629- {
3630- GError *error = NULL;
3631-
3632- gtk_file_chooser_default_select_path (chooser, path, &error);
3633- if (error)
3634- error_selecting_dragged_file_dialog (impl, path, error);
3635-
3636- gtk_file_path_free (path);
3637- }
3638+ return FALSE;
3639 }
3640-}
3641
3642-struct FileListDragData
3643-{
3644- GtkFileChooserDefault *impl;
3645- gchar **uris;
3646- GtkFilePath *path;
3647-};
3648+ impl->list_press_time = event->time;
3649+ impl->list_press_path = path;
3650
3651-static void
3652-file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle,
3653- const GtkFileInfo *info,
3654- const GError *error,
3655- gpointer user_data)
3656-{
3657- gboolean cancelled = handle->cancelled;
3658- struct FileListDragData *data = user_data;
3659- GtkFileChooser *chooser = GTK_FILE_CHOOSER (data->impl);
3660-
3661- if (handle != data->impl->file_list_drag_data_received_handle)
3662- goto out;
3663-
3664- data->impl->file_list_drag_data_received_handle = NULL;
3665-
3666- if (cancelled || error)
3667- goto out;
3668-
3669- if ((data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
3670- data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) &&
3671- data->uris[1] == 0 && !error &&
3672- gtk_file_info_get_is_folder (info))
3673- change_folder_and_display_error (data->impl, data->path, FALSE);
3674- else
3675- {
3676- GError *error = NULL;
3677-
3678- gtk_file_chooser_default_unselect_all (chooser);
3679- gtk_file_chooser_default_select_path (chooser, data->path, &error);
3680- if (error)
3681- error_selecting_dragged_file_dialog (data->impl, data->path, error);
3682- else
3683- browse_files_center_selected_row (data->impl);
3684- }
3685-
3686- if (data->impl->select_multiple)
3687- file_list_drag_data_select_uris (data->impl, data->uris);
3688-
3689-out:
3690- g_object_unref (data->impl);
3691- g_strfreev (data->uris);
3692- gtk_file_path_free (data->path);
3693- g_free (data);
3694-
3695- g_object_unref (handle);
3696+ return FALSE;
3697 }
3698
3699-static void
3700-file_list_drag_data_received_cb (GtkWidget *widget,
3701- GdkDragContext *context,
3702- gint x,
3703- gint y,
3704- GtkSelectionData *selection_data,
3705- guint info,
3706- guint time_,
3707- gpointer data)
3708-{
3709- GtkFileChooserDefault *impl;
3710- GtkFileChooser *chooser;
3711- gchar **uris;
3712- char *uri;
3713- GtkFilePath *path;
3714- GError *error = NULL;
3715-
3716- impl = GTK_FILE_CHOOSER_DEFAULT (data);
3717- chooser = GTK_FILE_CHOOSER (data);
3718-
3719- /* Parse the text/uri-list string, navigate to the first one */
3720- uris = g_uri_list_extract_uris ((const char *) selection_data->data);
3721- if (uris[0])
3722- {
3723- uri = uris[0];
3724- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3725-
3726- if (path)
3727- {
3728- struct FileListDragData *data;
3729-
3730- data = g_new0 (struct FileListDragData, 1);
3731- data->impl = g_object_ref (impl);
3732- data->uris = uris;
3733- data->path = path;
3734-
3735- if (impl->file_list_drag_data_received_handle)
3736- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle);
3737-
3738- impl->file_list_drag_data_received_handle =
3739- gtk_file_system_get_info (impl->file_system, path,
3740- GTK_FILE_INFO_IS_FOLDER,
3741- file_list_drag_data_received_get_info_cb,
3742- data);
3743- goto out;
3744- }
3745- else
3746- {
3747- g_set_error (&error,
3748- GTK_FILE_CHOOSER_ERROR,
3749- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
3750- _("Could not select file '%s' "
3751- "because it is an invalid path name."),
3752- uri);
3753- error_selecting_dragged_file_dialog (impl, NULL, error);
3754- }
3755-
3756- if (impl->select_multiple)
3757- file_list_drag_data_select_uris (impl, uris);
3758- }
3759-
3760- g_strfreev (uris);
3761-
3762-out:
3763- g_signal_stop_emission_by_name (widget, "drag_data_received");
3764-}
3765-
3766-/* Don't do anything with the drag_drop signal */
3767 static gboolean
3768-file_list_drag_drop_cb (GtkWidget *widget,
3769- GdkDragContext *context,
3770- gint x,
3771- gint y,
3772- guint time_,
3773- GtkFileChooserDefault *impl)
3774+list_button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
3775 {
3776- g_signal_stop_emission_by_name (widget, "drag_drop");
3777- return TRUE;
3778-}
3779+ GtkTreeView * tree = GTK_TREE_VIEW (widget);
3780+ GtkFileChooserDefault *impl = data;
3781+ GtkTreePath *path = NULL;
3782+ gboolean retval = FALSE;
3783
3784-/* Disable the normal tree drag motion handler, it makes it look like you're
3785- dropping the dragged item onto a tree item */
3786-static gboolean
3787-file_list_drag_motion_cb (GtkWidget *widget,
3788- GdkDragContext *context,
3789- gint x,
3790- gint y,
3791- guint time_,
3792- GtkFileChooserDefault *impl)
3793-{
3794- g_signal_stop_emission_by_name (widget, "drag_motion");
3795- return TRUE;
3796-}
3797-
3798-/* Constructs the popup menu for the file list if needed */
3799-static void
3800-file_list_build_popup_menu (GtkFileChooserDefault *impl)
3801-{
3802- GtkWidget *item;
3803-
3804- if (impl->browse_files_popup_menu)
3805- return;
3806-
3807- impl->browse_files_popup_menu = gtk_menu_new ();
3808- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_files_popup_menu),
3809- impl->browse_files_tree_view,
3810- popup_menu_detach_cb);
3811-
3812- item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks"));
3813- impl->browse_files_popup_menu_add_shortcut_item = item;
3814- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
3815- gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
3816- gtk_widget_set_sensitive (item, FALSE);
3817- g_signal_connect (item, "activate",
3818- G_CALLBACK (add_to_shortcuts_cb), impl);
3819- gtk_widget_show (item);
3820- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3821-
3822- item = gtk_separator_menu_item_new ();
3823- gtk_widget_show (item);
3824- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3825-
3826- item = gtk_check_menu_item_new_with_mnemonic (_("Show _Hidden Files"));
3827- impl->browse_files_popup_menu_hidden_files_item = item;
3828- g_signal_connect (item, "toggled",
3829- G_CALLBACK (show_hidden_toggled_cb), impl);
3830- gtk_widget_show (item);
3831- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3832-}
3833-
3834-/* Updates the popup menu for the file list, creating it if necessary */
3835-static void
3836-file_list_update_popup_menu (GtkFileChooserDefault *impl)
3837-{
3838- file_list_build_popup_menu (impl);
3839-
3840- /* FIXME - handle OPERATION_MODE_SEARCH and OPERATION_MODE_RECENT */
3841-
3842- /* The sensitivity of the Add to Bookmarks item is set in
3843- * bookmarks_check_add_sensitivity()
3844- */
3845-
3846- g_signal_handlers_block_by_func (impl->browse_files_popup_menu_hidden_files_item,
3847- G_CALLBACK (show_hidden_toggled_cb), impl);
3848- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_hidden_files_item),
3849- impl->show_hidden);
3850- g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_hidden_files_item,
3851- G_CALLBACK (show_hidden_toggled_cb), impl);
3852-}
3853-
3854-static void
3855-popup_position_func (GtkMenu *menu,
3856- gint *x,
3857- gint *y,
3858- gboolean *push_in,
3859- gpointer user_data)
3860-{
3861- GtkWidget *widget = GTK_WIDGET (user_data);
3862- GdkScreen *screen = gtk_widget_get_screen (widget);
3863- GtkRequisition req;
3864- gint monitor_num;
3865- GdkRectangle monitor;
3866-
3867- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
3868-
3869- gdk_window_get_origin (widget->window, x, y);
3870-
3871- gtk_widget_size_request (GTK_WIDGET (menu), &req);
3872-
3873- *x += (widget->allocation.width - req.width) / 2;
3874- *y += (widget->allocation.height - req.height) / 2;
3875-
3876- monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
3877- gtk_menu_set_monitor (menu, monitor_num);
3878- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
3879-
3880- *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
3881- *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
3882-
3883- *push_in = FALSE;
3884-}
3885-
3886-static void
3887-file_list_popup_menu (GtkFileChooserDefault *impl,
3888- GdkEventButton *event)
3889-{
3890- file_list_update_popup_menu (impl);
3891- if (event)
3892- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
3893- NULL, NULL, NULL, NULL,
3894- event->button, event->time);
3895- else
3896+ if (!impl->list_press_time ||
3897+ !impl->list_press_path ||
3898+ event->type != GDK_BUTTON_RELEASE ||
3899+ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y,
3900+ &path, NULL, NULL, NULL))
3901 {
3902- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
3903- NULL, NULL,
3904- popup_position_func, impl->browse_files_tree_view,
3905- 0, GDK_CURRENT_TIME);
3906- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_files_popup_menu),
3907- FALSE);
3908+ goto done;
3909 }
3910
3911-}
3912-
3913-/* Callback used for the GtkWidget::popup-menu signal of the file list */
3914-static gboolean
3915-list_popup_menu_cb (GtkWidget *widget,
3916- GtkFileChooserDefault *impl)
3917-{
3918- file_list_popup_menu (impl, NULL);
3919- return TRUE;
3920-}
3921-
3922-/* Callback used when a button is pressed on the file list. We trap button 3 to
3923- * bring up a popup menu.
3924- */
3925-static gboolean
3926-list_button_press_event_cb (GtkWidget *widget,
3927- GdkEventButton *event,
3928- GtkFileChooserDefault *impl)
3929-{
3930- static gboolean in_press = FALSE;
3931- gboolean handled;
3932-
3933- if (in_press)
3934- return FALSE;
3935-
3936- if (event->button != 3)
3937- return FALSE;
3938-
3939- in_press = TRUE;
3940- handled = gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event);
3941- in_press = FALSE;
3942-
3943- file_list_popup_menu (impl, event);
3944- return TRUE;
3945-}
3946-
3947-/* Sets the sort column IDs for the file list based on the operation mode */
3948-static void
3949-file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
3950-{
3951- int name_id, mtime_id;
3952-
3953- name_id = mtime_id = 0;
3954-
3955- switch (impl->operation_mode)
3956+ if (event->time - impl->list_press_time > LONG_CLICK_LENGTH &&
3957+ !gtk_tree_path_compare (impl->list_press_path, path))
3958 {
3959- case OPERATION_MODE_BROWSE:
3960- name_id = FILE_LIST_COL_NAME;
3961- mtime_id = FILE_LIST_COL_MTIME;
3962- break;
3963- case OPERATION_MODE_SEARCH:
3964- name_id = SEARCH_MODEL_COL_PATH;
3965- mtime_id = SEARCH_MODEL_COL_STAT;
3966- break;
3967- case OPERATION_MODE_RECENT:
3968- name_id = RECENT_MODEL_COL_PATH;
3969- mtime_id = RECENT_MODEL_COL_INFO;
3970- break;
3971+ retval = TRUE;
3972+ list_row_activated (tree, path, NULL, impl);
3973 }
3974
3975- gtk_tree_view_column_set_sort_column_id (impl->list_name_column, name_id);
3976- gtk_tree_view_column_set_sort_column_id (impl->list_mtime_column, mtime_id);
3977-}
3978+ done:
3979+ if (path)
3980+ gtk_tree_path_free (path);
3981
3982-static gboolean
3983-file_list_query_tooltip_cb (GtkWidget *widget,
3984- gint x,
3985- gint y,
3986- gboolean keyboard_tip,
3987- GtkTooltip *tooltip,
3988- gpointer user_data)
3989-{
3990- GtkFileChooserDefault *impl = user_data;
3991- GtkTreeIter iter, child_iter;
3992- GtkTreePath *path = NULL;
3993- GtkFilePath *file_path = NULL;
3994- gchar *filename;
3995+ impl->list_press_time = 0;
3996
3997- if (impl->operation_mode == OPERATION_MODE_BROWSE)
3998- return FALSE;
3999-
4000-
4001- gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (impl->browse_files_tree_view),
4002- &x, &y,
4003- keyboard_tip,
4004- NULL, &path, NULL);
4005-
4006- if (!path)
4007- return FALSE;
4008-
4009- switch (impl->operation_mode)
4010+ if (impl->list_press_path)
4011 {
4012- case OPERATION_MODE_SEARCH:
4013- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path))
4014- {
4015- gtk_tree_path_free (path);
4016- return FALSE;
4017- }
4018-
4019- search_get_valid_child_iter (impl, &child_iter, &iter);
4020- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
4021- SEARCH_MODEL_COL_PATH, &file_path,
4022- -1);
4023- break;
4024-
4025- case OPERATION_MODE_RECENT:
4026- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path))
4027- {
4028- gtk_tree_path_free (path);
4029- return FALSE;
4030- }
4031-
4032- recent_get_valid_child_iter (impl, &child_iter, &iter);
4033- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
4034- RECENT_MODEL_COL_PATH, &file_path,
4035- -1);
4036- break;
4037-
4038- case OPERATION_MODE_BROWSE:
4039- g_assert_not_reached ();
4040- return FALSE;
4041+ gtk_tree_path_free (impl->list_press_path);
4042+ impl->list_press_path = NULL;
4043 }
4044
4045- if (!file_path)
4046- {
4047- gtk_tree_path_free (path);
4048- return FALSE;
4049- }
4050-
4051- filename = gtk_file_system_path_to_filename (impl->file_system, file_path);
4052- gtk_tooltip_set_text (tooltip, filename);
4053- gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (impl->browse_files_tree_view),
4054- tooltip,
4055- path);
4056-
4057- g_free (filename);
4058- gtk_tree_path_free (path);
4059-
4060- return TRUE;
4061+ return FALSE;
4062 }
4063
4064+
4065 /* Creates the widgets for the file list */
4066 static GtkWidget *
4067 create_file_list (GtkFileChooserDefault *impl)
4068@@ -4572,7 +1272,7 @@
4069
4070 swin = gtk_scrolled_window_new (NULL, NULL);
4071 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
4072- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
4073+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
4074 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
4075 GTK_SHADOW_IN);
4076
4077@@ -4588,41 +1288,19 @@
4078 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE);
4079 gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view);
4080
4081- gtk_drag_dest_set (impl->browse_files_tree_view,
4082- GTK_DEST_DEFAULT_ALL,
4083- file_list_dest_targets,
4084- num_file_list_dest_targets,
4085- GDK_ACTION_COPY | GDK_ACTION_MOVE);
4086-
4087 g_signal_connect (impl->browse_files_tree_view, "row_activated",
4088 G_CALLBACK (list_row_activated), impl);
4089 g_signal_connect (impl->browse_files_tree_view, "key_press_event",
4090 G_CALLBACK (trap_activate_cb), impl);
4091- g_signal_connect (impl->browse_files_tree_view, "popup_menu",
4092- G_CALLBACK (list_popup_menu_cb), impl);
4093 g_signal_connect (impl->browse_files_tree_view, "button_press_event",
4094- G_CALLBACK (list_button_press_event_cb), impl);
4095+ G_CALLBACK (list_button_press), impl);
4096+ g_signal_connect (impl->browse_files_tree_view, "button_release_event",
4097+ G_CALLBACK (list_button_release), impl);
4098
4099- g_signal_connect (impl->browse_files_tree_view, "drag_data_received",
4100- G_CALLBACK (file_list_drag_data_received_cb), impl);
4101- g_signal_connect (impl->browse_files_tree_view, "drag_drop",
4102- G_CALLBACK (file_list_drag_drop_cb), impl);
4103- g_signal_connect (impl->browse_files_tree_view, "drag_motion",
4104- G_CALLBACK (file_list_drag_motion_cb), impl);
4105-
4106- g_object_set (impl->browse_files_tree_view, "has-tooltip", TRUE, NULL);
4107- g_signal_connect (impl->browse_files_tree_view, "query-tooltip",
4108- G_CALLBACK (file_list_query_tooltip_cb), impl);
4109-
4110 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
4111 gtk_tree_selection_set_select_function (selection,
4112 list_select_func,
4113 impl, NULL);
4114- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_files_tree_view),
4115- GDK_BUTTON1_MASK,
4116- file_list_source_targets,
4117- num_file_list_source_targets,
4118- GDK_ACTION_COPY);
4119
4120 g_signal_connect (selection, "changed",
4121 G_CALLBACK (list_selection_changed), impl);
4122@@ -4666,7 +1344,6 @@
4123 gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_SIZE);
4124 gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column);
4125 #endif
4126-
4127 /* Modification time column */
4128
4129 column = gtk_tree_view_column_new ();
4130@@ -4677,276 +1354,221 @@
4131 gtk_tree_view_column_pack_start (column, renderer, TRUE);
4132 gtk_tree_view_column_set_cell_data_func (column, renderer,
4133 list_mtime_data_func, impl, NULL);
4134+ gtk_tree_view_column_set_sort_column_id (column, FILE_LIST_COL_MTIME);
4135 gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_files_tree_view), column);
4136- impl->list_mtime_column = column;
4137-
4138- file_list_set_sort_column_ids (impl);
4139-
4140 gtk_widget_show_all (swin);
4141
4142 return swin;
4143 }
4144
4145-static GtkWidget *
4146-create_path_bar (GtkFileChooserDefault *impl)
4147+static void
4148+up_button_clicked_cb (GtkButton *button, gpointer data)
4149 {
4150- GtkWidget *path_bar;
4151+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
4152+ up_folder_handler (impl);
4153+}
4154
4155- path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
4156- _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->file_system);
4157+static void
4158+volume_button_clicked_cb (GtkButton *button, gpointer data)
4159+{
4160+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
4161+ GtkFilePath * path = g_object_get_data (G_OBJECT (button), "file-path");
4162
4163- return path_bar;
4164+ change_folder_and_display_error (impl, path);
4165 }
4166
4167-/* Creates the widgets for the files/folders pane */
4168 static GtkWidget *
4169-file_pane_create (GtkFileChooserDefault *impl,
4170- GtkSizeGroup *size_group)
4171+create_bar (GtkFileChooserDefault *impl)
4172 {
4173- GtkWidget *vbox;
4174- GtkWidget *hbox;
4175- GtkWidget *widget;
4176+ GSList *list, *l;
4177+ int n;
4178+ GtkWidget *bar = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4179+ GtkWidget *img;
4180+ GtkWidget *label;
4181
4182- vbox = gtk_vbox_new (FALSE, 6);
4183- gtk_widget_show (vbox);
4184+ /* first the Up button */
4185+ img = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
4186+ gtk_widget_show (img);
4187
4188- /* Box for lists and preview */
4189+ impl->up_button = gtk_button_new ();
4190+ gtk_container_add (GTK_CONTAINER (impl->up_button), img);
4191+ gtk_widget_show (impl->up_button);
4192+ gtk_widget_set_sensitive (impl->up_button, FALSE);
4193+ gtk_button_set_focus_on_click (GTK_BUTTON (impl->up_button), FALSE);
4194
4195- hbox = gtk_hbox_new (FALSE, PREVIEW_HBOX_SPACING);
4196- gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
4197- gtk_widget_show (hbox);
4198+ g_signal_connect (impl->up_button, "clicked",
4199+ G_CALLBACK (up_button_clicked_cb), impl);
4200+ gtk_box_pack_start (GTK_BOX(bar), impl->up_button, FALSE, FALSE, 0);
4201
4202- /* File list */
4203+ impl->num_volumes = 0;
4204+ list = gtk_file_system_list_volumes (impl->file_system);
4205
4206- widget = create_file_list (impl);
4207- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
4208+ n = 0;
4209
4210- /* Preview */
4211+ for (l = list; l; l = l->next, n++)
4212+ {
4213+ GtkFileSystemVolume *volume;
4214+ GdkPixbuf *pixbuf;
4215+ GtkWidget *button;
4216+ GtkWidget *image;
4217+ GtkFilePath *base_path;
4218+ gchar * file_name = NULL;
4219
4220- impl->preview_box = gtk_vbox_new (FALSE, 12);
4221- gtk_box_pack_start (GTK_BOX (hbox), impl->preview_box, FALSE, FALSE, 0);
4222- /* Don't show preview box initially */
4223+ volume = l->data;
4224+ base_path =
4225+ gtk_file_system_volume_get_base_path (impl->file_system, volume);
4226
4227- /* Filter combo */
4228+ if (impl->local_only)
4229+ {
4230+ gboolean is_local =
4231+ gtk_file_system_path_is_local (impl->file_system, base_path);
4232
4233- impl->filter_combo_hbox = gtk_hbox_new (FALSE, 12);
4234+ if (!is_local)
4235+ {
4236+ gtk_file_path_free (base_path);
4237+ gtk_file_system_volume_free (impl->file_system, volume);
4238+ continue;
4239+ }
4240+ }
4241
4242- widget = filter_create (impl);
4243+#if 0
4244+ label_copy =
4245+ gtk_file_system_volume_get_display_name (impl->file_system, volume);
4246+#endif
4247+ pixbuf =
4248+ gtk_file_system_volume_render_icon (impl->file_system, volume,
4249+ GTK_WIDGET (impl),
4250+ impl->icon_size, NULL);
4251
4252- gtk_widget_show (widget);
4253- gtk_box_pack_end (GTK_BOX (impl->filter_combo_hbox), widget, FALSE, FALSE, 0);
4254+ button = gtk_button_new ();
4255+ image = gtk_image_new_from_pixbuf (pixbuf);
4256+ g_object_unref (G_OBJECT (pixbuf));
4257+ gtk_container_add (GTK_CONTAINER (button), image);
4258+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
4259
4260- gtk_size_group_add_widget (size_group, impl->filter_combo_hbox);
4261- gtk_box_pack_end (GTK_BOX (vbox), impl->filter_combo_hbox, FALSE, FALSE, 0);
4262+ file_name =
4263+ gtk_file_system_path_to_filename (impl->file_system, base_path);
4264
4265- return vbox;
4266-}
4267+ if (file_name && impl->root_folder &&
4268+ strcmp (file_name, impl->root_folder) &&
4269+ !strncmp (file_name, impl->root_folder, strlen (file_name)))
4270+ {
4271+ /* The base path is below the root folder; we replace it with
4272+ * the root folder
4273+ */
4274+ gtk_file_path_free (base_path);
4275+ base_path = gtk_file_system_filename_to_path (impl->file_system,
4276+ impl->root_folder);
4277+ }
4278
4279-/* Callback used when the "Browse for more folders" expander is toggled */
4280-static void
4281-expander_changed_cb (GtkExpander *expander,
4282- GParamSpec *pspec,
4283- GtkFileChooserDefault *impl)
4284-{
4285- impl->expand_folders = gtk_expander_get_expanded(GTK_EXPANDER (impl->save_expander));
4286- update_appearance (impl);
4287-}
4288+ g_free (file_name);
4289+ gtk_widget_show_all (button);
4290
4291-/* Callback used when the selection changes in the save folder combo box */
4292-static void
4293-save_folder_combo_changed_cb (GtkComboBox *combo,
4294- GtkFileChooserDefault *impl)
4295-{
4296- GtkTreeIter iter;
4297+ g_object_set_data (G_OBJECT (button), "file-path", base_path);
4298
4299- if (impl->changing_folder)
4300- return;
4301+ g_signal_connect (button, "clicked",
4302+ G_CALLBACK (volume_button_clicked_cb), impl);
4303
4304- if (gtk_combo_box_get_active_iter (combo, &iter))
4305- {
4306- GtkTreeIter child_iter;
4307-
4308- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model),
4309- &child_iter,
4310- &iter);
4311- shortcuts_activate_iter (impl, &child_iter);
4312- }
4313-}
4314+ gtk_box_pack_start (GTK_BOX(bar), button, FALSE, FALSE, 0);
4315+ }
4316
4317-/* Filter function used to filter out the Search item and its separator.
4318- * Used for the "Save in folder" combo box, so that these items do not appear in it.
4319- */
4320-static gboolean
4321-shortcuts_combo_filter_func (GtkTreeModel *model,
4322- GtkTreeIter *iter,
4323- gpointer data)
4324-{
4325- GtkFileChooserDefault *impl;
4326- GtkTreePath *tree_path;
4327- gint *indices;
4328- int idx;
4329- gboolean retval;
4330+ impl->num_volumes = n;
4331+ g_slist_free (list);
4332
4333- impl = GTK_FILE_CHOOSER_DEFAULT (data);
4334+ label = impl->location_label = gtk_label_new (NULL);
4335+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
4336+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
4337+ gtk_label_set_text (GTK_LABEL (label), impl->root_folder);
4338+ gtk_widget_show (label);
4339+ gtk_box_pack_start (GTK_BOX(bar), label, TRUE, TRUE, 0);
4340
4341- g_assert (model == GTK_TREE_MODEL (impl->shortcuts_model));
4342+ gtk_widget_show (bar);
4343
4344- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), iter);
4345- g_assert (tree_path != NULL);
4346+ return bar;
4347+}
4348
4349- indices = gtk_tree_path_get_indices (tree_path);
4350-
4351- retval = TRUE;
4352-
4353- if (impl->has_search)
4354- {
4355- idx = shortcuts_get_index (impl, SHORTCUTS_SEARCH);
4356- if (idx == indices[0])
4357- retval = FALSE;
4358- }
4359-
4360- if (impl->has_recent)
4361- {
4362- idx = shortcuts_get_index (impl, SHORTCUTS_RECENT);
4363- if (idx == indices[0])
4364- retval = FALSE;
4365- else
4366- {
4367- idx = shortcuts_get_index (impl, SHORTCUTS_RECENT_SEPARATOR);
4368- if (idx == indices[0])
4369- retval = FALSE;
4370- }
4371- }
4372-
4373- gtk_tree_path_free (tree_path);
4374-
4375- return retval;
4376- }
4377-
4378-/* Creates the combo box with the save folders */
4379+/* Creates the widgets for the files/folders pane */
4380 static GtkWidget *
4381-save_folder_combo_create (GtkFileChooserDefault *impl)
4382+file_pane_create (GtkFileChooserDefault *impl)
4383 {
4384- GtkWidget *combo;
4385- GtkCellRenderer *cell;
4386+ GtkWidget *vbox;
4387+ GtkWidget *hbox;
4388+ GtkWidget *widget;
4389+ vbox = gtk_vbox_new (FALSE, DEFAULT_SPACING);
4390+ gtk_widget_show (vbox);
4391
4392- impl->shortcuts_combo_filter_model = gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->shortcuts_model), NULL);
4393- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_combo_filter_model),
4394- shortcuts_combo_filter_func,
4395- impl,
4396- NULL);
4397+ /* The volume bar and 'Create Folder' button */
4398+ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4399+ gtk_widget_show (hbox);
4400+ impl->bar = create_bar (impl);
4401+ gtk_widget_show_all (impl->bar);
4402+ gtk_box_pack_start (GTK_BOX (hbox), impl->bar, TRUE, TRUE, 0);
4403
4404- combo = g_object_new (GTK_TYPE_COMBO_BOX,
4405- "model", impl->shortcuts_combo_filter_model,
4406- "focus-on-click", FALSE,
4407- NULL);
4408- gtk_widget_show (combo);
4409+ /* Create Folder */
4410+ widget = gtk_image_new_from_icon_name ("folder-new", GTK_ICON_SIZE_BUTTON);
4411+ gtk_widget_show (widget);
4412+ impl->browse_new_folder_button = gtk_button_new ();
4413+ gtk_container_add (GTK_CONTAINER (impl->browse_new_folder_button), widget);
4414+ gtk_button_set_focus_on_click (GTK_BUTTON (impl->browse_new_folder_button),
4415+ FALSE);
4416
4417- cell = gtk_cell_renderer_pixbuf_new ();
4418- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
4419- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
4420- "pixbuf", SHORTCUTS_COL_PIXBUF,
4421- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
4422- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
4423- NULL);
4424+ g_signal_connect (impl->browse_new_folder_button, "clicked",
4425+ G_CALLBACK (new_folder_button_clicked), impl);
4426+ gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
4427
4428- cell = gtk_cell_renderer_text_new ();
4429- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
4430- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
4431- "text", SHORTCUTS_COL_NAME,
4432- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
4433- NULL);
4434+ widget = filter_create (impl);
4435+ gtk_widget_hide (widget);
4436+ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
4437
4438- gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
4439- shortcuts_row_separator_func,
4440- NULL, NULL);
4441+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4442
4443- g_signal_connect (combo, "changed",
4444- G_CALLBACK (save_folder_combo_changed_cb), impl);
4445+ /* Box for lists */
4446+ hbox = gtk_hbox_new (FALSE, LIST_HBOX_SPACING);
4447+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
4448+ gtk_widget_show (hbox);
4449
4450- return combo;
4451+ /* File list */
4452+
4453+ widget = create_file_list (impl);
4454+ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
4455+
4456+ return vbox;
4457 }
4458
4459 /* Creates the widgets specific to Save mode */
4460-static void
4461+static GtkWidget *
4462 save_widgets_create (GtkFileChooserDefault *impl)
4463 {
4464 GtkWidget *vbox;
4465- GtkWidget *table;
4466+ GtkWidget *hbox;
4467 GtkWidget *widget;
4468- GtkWidget *alignment;
4469
4470- if (impl->save_widgets != NULL)
4471- return;
4472+ vbox = gtk_vbox_new (FALSE, 0);
4473+ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4474
4475- location_switch_to_path_bar (impl);
4476-
4477- vbox = gtk_vbox_new (FALSE, 12);
4478-
4479- table = gtk_table_new (2, 2, FALSE);
4480- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
4481- gtk_widget_show (table);
4482- gtk_table_set_row_spacings (GTK_TABLE (table), 12);
4483- gtk_table_set_col_spacings (GTK_TABLE (table), 12);
4484-
4485- /* Label */
4486-
4487- widget = gtk_label_new_with_mnemonic (_("_Name:"));
4488+ widget = gtk_label_new (_("Name:"));
4489 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
4490- gtk_table_attach (GTK_TABLE (table), widget,
4491- 0, 1, 0, 1,
4492- GTK_FILL, GTK_FILL,
4493- 0, 0);
4494+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
4495 gtk_widget_show (widget);
4496
4497- /* Location entry */
4498-
4499 impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
4500 _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
4501 impl->file_system);
4502- gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
4503+/* gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45); */
4504 gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
4505- gtk_table_attach (GTK_TABLE (table), impl->location_entry,
4506- 1, 2, 0, 1,
4507- GTK_EXPAND | GTK_FILL, 0,
4508- 0, 0);
4509+ gtk_box_pack_start (GTK_BOX (hbox), impl->location_entry,
4510+ TRUE, TRUE, 0);
4511+
4512 gtk_widget_show (impl->location_entry);
4513- gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->location_entry);
4514
4515- /* Folder combo */
4516- impl->save_folder_label = gtk_label_new (NULL);
4517- gtk_misc_set_alignment (GTK_MISC (impl->save_folder_label), 0.0, 0.5);
4518- gtk_table_attach (GTK_TABLE (table), impl->save_folder_label,
4519- 0, 1, 1, 2,
4520- GTK_FILL, GTK_FILL,
4521- 0, 0);
4522- gtk_widget_show (impl->save_folder_label);
4523+ gtk_widget_show (hbox);
4524+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4525
4526- impl->save_folder_combo = save_folder_combo_create (impl);
4527- gtk_table_attach (GTK_TABLE (table), impl->save_folder_combo,
4528- 1, 2, 1, 2,
4529- GTK_EXPAND | GTK_FILL, GTK_FILL,
4530- 0, 0);
4531- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->save_folder_combo);
4532-
4533- /* Expander */
4534- alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
4535- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
4536-
4537- impl->save_expander = gtk_expander_new_with_mnemonic (_("_Browse for other folders"));
4538- gtk_container_add (GTK_CONTAINER (alignment), impl->save_expander);
4539- g_signal_connect (impl->save_expander, "notify::expanded",
4540- G_CALLBACK (expander_changed_cb),
4541- impl);
4542- gtk_widget_show_all (alignment);
4543-
4544- impl->save_widgets = vbox;
4545- gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
4546- gtk_box_reorder_child (GTK_BOX (impl), impl->save_widgets, 0);
4547- gtk_widget_show (impl->save_widgets);
4548+ return vbox;
4549 }
4550
4551 /* Destroys the widgets specific to Save mode */
4552+/* ??? */
4553 static void
4554 save_widgets_destroy (GtkFileChooserDefault *impl)
4555 {
4556@@ -4956,313 +1578,17 @@
4557 gtk_widget_destroy (impl->save_widgets);
4558 impl->save_widgets = NULL;
4559 impl->location_entry = NULL;
4560- impl->save_folder_label = NULL;
4561- impl->save_folder_combo = NULL;
4562- impl->save_expander = NULL;
4563 }
4564
4565-/* Turns on the path bar widget. Can be called even if we are already in that
4566- * mode.
4567- */
4568-static void
4569-location_switch_to_path_bar (GtkFileChooserDefault *impl)
4570-{
4571- if (impl->location_entry)
4572- {
4573- gtk_widget_destroy (impl->location_entry);
4574- impl->location_entry = NULL;
4575- }
4576-
4577- gtk_widget_hide (impl->location_entry_box);
4578-}
4579-
4580-/* Sets the full path of the current folder as the text in the location entry. */
4581-static void
4582-location_entry_set_initial_text (GtkFileChooserDefault *impl)
4583-{
4584- char *text;
4585-
4586- if (!impl->current_folder)
4587- return;
4588-
4589- if (gtk_file_system_path_is_local (impl->file_system, impl->current_folder))
4590- {
4591- char *filename;
4592-
4593- filename = gtk_file_system_path_to_filename (impl->file_system, impl->current_folder);
4594- if (filename)
4595- {
4596- text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
4597- g_free (filename);
4598- }
4599- else
4600- text = NULL;
4601- }
4602- else
4603- text = gtk_file_system_path_to_uri (impl->file_system, impl->current_folder);
4604-
4605- if (text)
4606- {
4607- gboolean need_slash;
4608- int len;
4609-
4610- len = strlen (text);
4611- need_slash = (text[len - 1] != G_DIR_SEPARATOR);
4612-
4613- if (need_slash)
4614- {
4615- char *slash_text;
4616-
4617- slash_text = g_new (char, len + 2);
4618- strcpy (slash_text, text);
4619- slash_text[len] = G_DIR_SEPARATOR;
4620- slash_text[len + 1] = 0;
4621-
4622- g_free (text);
4623- text = slash_text;
4624- }
4625-
4626- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text);
4627- g_free (text);
4628- }
4629-}
4630-
4631-/* Turns on the location entry. Can be called even if we are already in that
4632- * mode.
4633- */
4634-static void
4635-location_switch_to_filename_entry (GtkFileChooserDefault *impl)
4636-{
4637- /* when in search or recent files mode, we are not showing the
4638- * location_entry_box container, so there's no point in switching
4639- * to it.
4640- */
4641- if (impl->operation_mode == OPERATION_MODE_SEARCH ||
4642- impl->operation_mode == OPERATION_MODE_RECENT)
4643- return;
4644-
4645- if (impl->location_entry)
4646- gtk_widget_destroy (impl->location_entry);
4647-
4648- /* Box */
4649-
4650- gtk_widget_show (impl->location_entry_box);
4651-
4652- /* Entry */
4653-
4654- impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
4655- _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
4656- impl->file_system);
4657- gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
4658- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
4659-
4660- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0);
4661- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry);
4662-
4663- /* Configure the entry */
4664-
4665- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder);
4666-
4667- /* Done */
4668-
4669- gtk_widget_show (impl->location_entry);
4670- gtk_widget_grab_focus (impl->location_entry);
4671-}
4672-
4673-/* Sets a new location mode. set_buttons determines whether the toggle button
4674- * for the mode will also be changed.
4675- */
4676-static void
4677-location_mode_set (GtkFileChooserDefault *impl,
4678- LocationMode new_mode,
4679- gboolean set_button)
4680-{
4681- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
4682- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
4683- {
4684- GtkWindow *toplevel;
4685- GtkWidget *current_focus;
4686- gboolean button_active;
4687- gboolean switch_to_file_list;
4688-
4689- switch (new_mode)
4690- {
4691- case LOCATION_MODE_PATH_BAR:
4692- button_active = FALSE;
4693-
4694- /* The location_entry will disappear when we switch to path bar mode. So,
4695- * we'll focus the file list in that case, to avoid having a window with
4696- * no focused widget.
4697- */
4698- toplevel = get_toplevel (GTK_WIDGET (impl));
4699- switch_to_file_list = FALSE;
4700- if (toplevel)
4701- {
4702- current_focus = gtk_window_get_focus (toplevel);
4703- if (!current_focus || current_focus == impl->location_entry)
4704- switch_to_file_list = TRUE;
4705- }
4706-
4707- location_switch_to_path_bar (impl);
4708-
4709- if (switch_to_file_list)
4710- gtk_widget_grab_focus (impl->browse_files_tree_view);
4711-
4712- break;
4713-
4714- case LOCATION_MODE_FILENAME_ENTRY:
4715- button_active = TRUE;
4716- location_switch_to_filename_entry (impl);
4717- break;
4718-
4719- default:
4720- g_assert_not_reached ();
4721- return;
4722- }
4723-
4724- if (set_button)
4725- {
4726- g_signal_handlers_block_by_func (impl->location_button,
4727- G_CALLBACK (location_button_toggled_cb), impl);
4728-
4729- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->location_button), button_active);
4730-
4731- g_signal_handlers_unblock_by_func (impl->location_button,
4732- G_CALLBACK (location_button_toggled_cb), impl);
4733- }
4734- }
4735-
4736- impl->location_mode = new_mode;
4737-}
4738-
4739-static void
4740-location_toggle_popup_handler (GtkFileChooserDefault *impl)
4741-{
4742- /* If the file entry is not visible, show it.
4743- * If it is visible, turn it off only if it is focused. Otherwise, switch to the entry.
4744- */
4745- if (impl->location_mode == LOCATION_MODE_PATH_BAR)
4746- {
4747- location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY, TRUE);
4748- }
4749- else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
4750- {
4751- if (GTK_WIDGET_HAS_FOCUS (impl->location_entry))
4752- {
4753- location_mode_set (impl, LOCATION_MODE_PATH_BAR, TRUE);
4754- }
4755- else
4756- {
4757- gtk_widget_grab_focus (impl->location_entry);
4758- }
4759- }
4760-}
4761-
4762-/* Callback used when one of the location mode buttons is toggled */
4763-static void
4764-location_button_toggled_cb (GtkToggleButton *toggle,
4765- GtkFileChooserDefault *impl)
4766-{
4767- gboolean is_active;
4768- LocationMode new_mode;
4769-
4770- is_active = gtk_toggle_button_get_active (toggle);
4771-
4772- if (is_active)
4773- {
4774- g_assert (impl->location_mode == LOCATION_MODE_PATH_BAR);
4775- new_mode = LOCATION_MODE_FILENAME_ENTRY;
4776- }
4777- else
4778- {
4779- g_assert (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY);
4780- new_mode = LOCATION_MODE_PATH_BAR;
4781- }
4782-
4783- location_mode_set (impl, new_mode, FALSE);
4784-}
4785-
4786-/* Creates a toggle button for the location entry. */
4787-static void
4788-location_button_create (GtkFileChooserDefault *impl)
4789-{
4790- GtkWidget *image;
4791- const char *str;
4792-
4793- image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
4794- gtk_widget_show (image);
4795-
4796- impl->location_button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
4797- "image", image,
4798- NULL);
4799-
4800- g_signal_connect (impl->location_button, "toggled",
4801- G_CALLBACK (location_button_toggled_cb), impl);
4802-
4803- str = _("Type a file name");
4804-
4805- gtk_widget_set_tooltip_text (impl->location_button, str);
4806- atk_object_set_name (gtk_widget_get_accessible (impl->location_button), str);
4807-}
4808-
4809 /* Creates the main hpaned with the widgets shared by Open and Save mode */
4810 static GtkWidget *
4811 browse_widgets_create (GtkFileChooserDefault *impl)
4812 {
4813- GtkWidget *vbox;
4814- GtkWidget *hbox;
4815- GtkWidget *hpaned;
4816 GtkWidget *widget;
4817- GtkSizeGroup *size_group;
4818
4819- /* size group is used by the [+][-] buttons and the filter combo */
4820- size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4821- vbox = gtk_vbox_new (FALSE, 12);
4822+ widget = file_pane_create (impl);
4823
4824- /* Location widgets */
4825- hbox = gtk_hbox_new (FALSE, 12);
4826- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4827- gtk_widget_show (hbox);
4828- impl->browse_path_bar_hbox = hbox;
4829-
4830- location_button_create (impl);
4831- gtk_box_pack_start (GTK_BOX (hbox), impl->location_button, FALSE, FALSE, 0);
4832-
4833- /* Path bar */
4834-
4835- impl->browse_path_bar = create_path_bar (impl);
4836- g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl);
4837- gtk_widget_show_all (impl->browse_path_bar);
4838- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_path_bar, TRUE, TRUE, 0);
4839-
4840- /* Create Folder */
4841- impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder"));
4842- g_signal_connect (impl->browse_new_folder_button, "clicked",
4843- G_CALLBACK (new_folder_button_clicked), impl);
4844- gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
4845-
4846- /* Box for the location label and entry */
4847-
4848- impl->location_entry_box = gtk_hbox_new (FALSE, 12);
4849- gtk_box_pack_start (GTK_BOX (vbox), impl->location_entry_box, FALSE, FALSE, 0);
4850-
4851- impl->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
4852- gtk_widget_show (impl->location_label);
4853- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0);
4854-
4855- /* Paned widget */
4856- hpaned = gtk_hpaned_new ();
4857- gtk_widget_show (hpaned);
4858- gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
4859-
4860- widget = shortcuts_pane_create (impl, size_group);
4861- gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE);
4862- widget = file_pane_create (impl, size_group);
4863- gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE);
4864-
4865- g_object_unref (size_group);
4866-
4867- return vbox;
4868+ return widget;
4869 }
4870
4871 static GObject*
4872@@ -5284,20 +1610,14 @@
4873
4874 gtk_widget_push_composite_child ();
4875
4876- /* Recent files manager */
4877- recent_manager_update (impl);
4878+ /* Widgets for Save mode */
4879+ impl->save_widgets = save_widgets_create (impl);
4880+ gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
4881
4882- /* Shortcuts model */
4883- shortcuts_model_create (impl);
4884-
4885 /* The browse widgets */
4886 impl->browse_widgets = browse_widgets_create (impl);
4887 gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets, TRUE, TRUE, 0);
4888
4889- /* Alignment to hold extra widget */
4890- impl->extra_align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
4891- gtk_box_pack_start (GTK_BOX (impl), impl->extra_align, FALSE, FALSE, 0);
4892-
4893 gtk_widget_pop_composite_child ();
4894 update_appearance (impl);
4895
4896@@ -5306,35 +1626,7 @@
4897 return object;
4898 }
4899
4900-/* Sets the extra_widget by packing it in the appropriate place */
4901 static void
4902-set_extra_widget (GtkFileChooserDefault *impl,
4903- GtkWidget *extra_widget)
4904-{
4905- if (extra_widget)
4906- {
4907- g_object_ref (extra_widget);
4908- /* FIXME: is this right ? */
4909- gtk_widget_show (extra_widget);
4910- }
4911-
4912- if (impl->extra_widget)
4913- {
4914- gtk_container_remove (GTK_CONTAINER (impl->extra_align), impl->extra_widget);
4915- g_object_unref (impl->extra_widget);
4916- }
4917-
4918- impl->extra_widget = extra_widget;
4919- if (impl->extra_widget)
4920- {
4921- gtk_container_add (GTK_CONTAINER (impl->extra_align), impl->extra_widget);
4922- gtk_widget_show (impl->extra_align);
4923- }
4924- else
4925- gtk_widget_hide (impl->extra_align);
4926-}
4927-
4928-static void
4929 set_local_only (GtkFileChooserDefault *impl,
4930 gboolean local_only)
4931 {
4932@@ -5342,12 +1634,6 @@
4933 {
4934 impl->local_only = local_only;
4935
4936- if (impl->shortcuts_model && impl->file_system)
4937- {
4938- shortcuts_add_volumes (impl);
4939- shortcuts_add_bookmarks (impl);
4940- }
4941-
4942 if (local_only &&
4943 !gtk_file_system_path_is_local (impl->file_system, impl->current_folder))
4944 {
4945@@ -5374,21 +1660,9 @@
4946 volumes_changed_cb (GtkFileSystem *file_system,
4947 GtkFileChooserDefault *impl)
4948 {
4949- shortcuts_add_volumes (impl);
4950+ /* FIXME -- update the bar */
4951 }
4952
4953-/* Callback used when the set of bookmarks changes in the file system */
4954-static void
4955-bookmarks_changed_cb (GtkFileSystem *file_system,
4956- GtkFileChooserDefault *impl)
4957-{
4958- shortcuts_add_bookmarks (impl);
4959-
4960- bookmarks_check_add_sensitivity (impl);
4961- bookmarks_check_remove_sensitivity (impl);
4962- shortcuts_check_popup_sensitivity (impl);
4963-}
4964-
4965 /* Sets the file chooser to multiple selection mode */
4966 static void
4967 set_select_multiple (GtkFileChooserDefault *impl,
4968@@ -5408,8 +1682,6 @@
4969
4970 impl->select_multiple = select_multiple;
4971 g_object_notify (G_OBJECT (impl), "select-multiple");
4972-
4973- check_preview_change (impl);
4974 }
4975
4976 static void
4977@@ -5422,8 +1694,6 @@
4978 {
4979 g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
4980 impl->volumes_changed_id = 0;
4981- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
4982- impl->bookmarks_changed_id = 0;
4983 g_object_unref (impl->file_system);
4984 }
4985
4986@@ -5459,14 +1729,28 @@
4987 impl->volumes_changed_id = g_signal_connect (impl->file_system, "volumes-changed",
4988 G_CALLBACK (volumes_changed_cb),
4989 impl);
4990- impl->bookmarks_changed_id = g_signal_connect (impl->file_system, "bookmarks-changed",
4991- G_CALLBACK (bookmarks_changed_cb),
4992- impl);
4993 }
4994
4995 profile_end ("end", NULL);
4996 }
4997
4998+static void
4999+show_new_folder_button (GtkFileChooserDefault *impl)
5000+{
5001+ if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5002+ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) &&
5003+ impl->show_create_folder)
5004+ {
5005+ gtk_widget_show (impl->browse_new_folder_button);
5006+ gtk_misc_set_alignment (GTK_MISC (impl->location_label), 0.5, 0.5);
5007+ }
5008+ else
5009+ {
5010+ gtk_widget_hide (impl->browse_new_folder_button);
5011+ gtk_misc_set_alignment (GTK_MISC (impl->location_label), 1.0, 0.5);
5012+ }
5013+}
5014+
5015 /* This function is basically a do_all function.
5016 *
5017 * It sets the visibility on all the widgets based on the current state, and
5018@@ -5478,33 +1762,9 @@
5019 if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5020 impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5021 {
5022- const char *text;
5023+ gtk_widget_show (impl->save_widgets);
5024+ gtk_widget_show (impl->browse_widgets);
5025
5026- gtk_widget_hide (impl->location_button);
5027- save_widgets_create (impl);
5028-
5029- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
5030- text = _("Save in _folder:");
5031- else
5032- text = _("Create in _folder:");
5033-
5034- gtk_label_set_text_with_mnemonic (GTK_LABEL (impl->save_folder_label), text);
5035-
5036- if (gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)))
5037- {
5038- gtk_widget_set_sensitive (impl->save_folder_label, FALSE);
5039- gtk_widget_set_sensitive (impl->save_folder_combo, FALSE);
5040- gtk_widget_show (impl->browse_widgets);
5041- }
5042- else
5043- {
5044- gtk_widget_set_sensitive (impl->save_folder_label, TRUE);
5045- gtk_widget_set_sensitive (impl->save_folder_combo, TRUE);
5046- gtk_widget_hide (impl->browse_widgets);
5047- }
5048-
5049- gtk_widget_show (impl->browse_new_folder_button);
5050-
5051 if (impl->select_multiple)
5052 {
5053 g_warning ("Save mode cannot be set in conjunction with multiple selection mode. "
5054@@ -5515,23 +1775,12 @@
5055 else if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
5056 impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5057 {
5058- gtk_widget_show (impl->location_button);
5059- save_widgets_destroy (impl);
5060+ gtk_widget_hide (impl->save_widgets);
5061 gtk_widget_show (impl->browse_widgets);
5062- location_mode_set (impl, impl->location_mode, TRUE);
5063 }
5064
5065- if (impl->location_entry)
5066- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
5067+ show_new_folder_button (impl);
5068
5069- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
5070- gtk_widget_hide (impl->browse_new_folder_button);
5071- else
5072- gtk_widget_show (impl->browse_new_folder_button);
5073-
5074- /* This *is* needed; we need to redraw the file list because the "sensitivity"
5075- * of files may change depending whether we are in a file or folder-only mode.
5076- */
5077 gtk_widget_queue_draw (impl->browse_files_tree_view);
5078
5079 g_signal_emit_by_name (impl, "default-size-changed");
5080@@ -5556,8 +1805,7 @@
5081 {
5082 gtk_file_chooser_default_unselect_all (GTK_FILE_CHOOSER (impl));
5083
5084- if ((action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5085- action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5086+ if ((action == GTK_FILE_CHOOSER_ACTION_SAVE || action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5087 && impl->select_multiple)
5088 {
5089 g_warning ("Tried to change the file chooser action to SAVE or CREATE_FOLDER, but "
5090@@ -5584,29 +1832,10 @@
5091 set_local_only (impl, g_value_get_boolean (value));
5092 break;
5093
5094- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
5095- set_preview_widget (impl, g_value_get_object (value));
5096- break;
5097-
5098- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
5099- impl->preview_widget_active = g_value_get_boolean (value);
5100- update_preview_widget_visibility (impl);
5101- break;
5102-
5103- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
5104- impl->use_preview_label = g_value_get_boolean (value);
5105- update_preview_widget_visibility (impl);
5106- break;
5107-
5108- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
5109- set_extra_widget (impl, g_value_get_object (value));
5110- break;
5111-
5112 case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
5113 {
5114 gboolean select_multiple = g_value_get_boolean (value);
5115- if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5116- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5117+ if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5118 && select_multiple)
5119 {
5120 g_warning ("Tried to set the file chooser to multiple selection mode, but this is "
5121@@ -5639,6 +1868,51 @@
5122 }
5123 break;
5124
5125+ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER:
5126+ {
5127+ GtkFilePath * path;
5128+ gchar * new_root = g_strdup (g_value_get_string (value));
5129+
5130+ if (!new_root)
5131+ {
5132+ new_root = g_strdup ("/");
5133+ }
5134+
5135+ path = gtk_file_system_filename_to_path (impl->file_system,
5136+ new_root);
5137+ if (change_folder (impl, path, FALSE))
5138+ {
5139+ g_free (impl->root_folder);
5140+ impl->root_folder = new_root;
5141+ }
5142+ else
5143+ {
5144+ g_warning ("Unable to set [%s] as root folder", new_root);
5145+ g_free (new_root);
5146+ }
5147+
5148+ gtk_file_path_free (path);
5149+ }
5150+ break;
5151+
5152+ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER:
5153+ {
5154+ gboolean show = g_value_get_boolean (value);
5155+ if (show != impl->show_create_folder)
5156+ {
5157+ impl->show_create_folder = show;
5158+ show_new_folder_button (impl);
5159+ }
5160+ }
5161+ break;
5162+
5163+ /* These are not supported */
5164+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
5165+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
5166+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
5167+ case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
5168+ break;
5169+
5170 default:
5171 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5172 break;
5173@@ -5667,30 +1941,34 @@
5174 g_value_set_boolean (value, impl->local_only);
5175 break;
5176
5177- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
5178- g_value_set_object (value, impl->preview_widget);
5179+ case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
5180+ g_value_set_boolean (value, impl->select_multiple);
5181 break;
5182
5183- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
5184- g_value_set_boolean (value, impl->preview_widget_active);
5185+ case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
5186+ g_value_set_boolean (value, impl->show_hidden);
5187 break;
5188
5189- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
5190- g_value_set_boolean (value, impl->use_preview_label);
5191+ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER:
5192+ g_value_set_string (value, impl->root_folder);
5193 break;
5194
5195- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
5196- g_value_set_object (value, impl->extra_widget);
5197+ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER:
5198+ g_value_set_boolean (value, impl->show_create_folder);
5199 break;
5200
5201- case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
5202- g_value_set_boolean (value, impl->select_multiple);
5203+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
5204+ g_value_set_object (value, NULL);
5205 break;
5206
5207- case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
5208- g_value_set_boolean (value, impl->show_hidden);
5209+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
5210+ g_value_set_boolean (value, FALSE);
5211 break;
5212
5213+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
5214+ g_value_set_boolean (value, FALSE);
5215+ break;
5216+
5217 case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
5218 g_value_set_boolean (value, impl->do_overwrite_confirmation);
5219 break;
5220@@ -5723,24 +2001,12 @@
5221 GSList *l;
5222 GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object;
5223
5224- if (impl->extra_widget)
5225- {
5226- g_object_unref (impl->extra_widget);
5227- impl->extra_widget = NULL;
5228- }
5229-
5230 if (impl->volumes_changed_id > 0)
5231 {
5232 g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
5233 impl->volumes_changed_id = 0;
5234 }
5235
5236- if (impl->bookmarks_changed_id > 0)
5237- {
5238- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
5239- impl->bookmarks_changed_id = 0;
5240- }
5241-
5242 pending_select_paths_free (impl);
5243
5244 /* cancel all pending operations */
5245@@ -5766,23 +2032,6 @@
5246 impl->reload_icon_handles = NULL;
5247 }
5248
5249- if (impl->loading_shortcuts)
5250- {
5251- for (l = impl->loading_shortcuts; l; l = l->next)
5252- {
5253- GtkFileSystemHandle *handle =l->data;
5254- gtk_file_system_cancel_operation (handle);
5255- }
5256- g_slist_free (impl->loading_shortcuts);
5257- impl->loading_shortcuts = NULL;
5258- }
5259-
5260- if (impl->file_list_drag_data_received_handle)
5261- {
5262- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle);
5263- impl->file_list_drag_data_received_handle = NULL;
5264- }
5265-
5266 if (impl->update_current_folder_handle)
5267 {
5268 gtk_file_system_cancel_operation (impl->update_current_folder_handle);
5269@@ -5807,15 +2056,6 @@
5270 impl->update_from_entry_handle = NULL;
5271 }
5272
5273- if (impl->shortcuts_activate_iter_handle)
5274- {
5275- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle);
5276- impl->shortcuts_activate_iter_handle = NULL;
5277- }
5278-
5279- search_stop_searching (impl, TRUE);
5280- recent_stop_loading (impl);
5281-
5282 remove_settings_signal (impl, gtk_widget_get_screen (GTK_WIDGET (impl)));
5283
5284 G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->dispose (object);
5285@@ -5828,12 +2068,7 @@
5286 static void
5287 gtk_file_chooser_default_show_all (GtkWidget *widget)
5288 {
5289- GtkFileChooserDefault *impl = (GtkFileChooserDefault *) widget;
5290-
5291 gtk_widget_show (widget);
5292-
5293- if (impl->extra_widget)
5294- gtk_widget_show_all (impl->extra_widget);
5295 }
5296
5297 /* Handler for GtkWindow::set-focus; this is where we save the last-focused
5298@@ -5894,7 +2129,6 @@
5299 else
5300 impl->icon_size = FALLBACK_ICON_SIZE;
5301
5302- shortcuts_reload_icons (impl);
5303 gtk_widget_queue_resize (impl->browse_files_tree_view);
5304
5305 profile_end ("end", NULL);
5306@@ -5912,8 +2146,8 @@
5307
5308 name = g_param_spec_get_name (pspec);
5309
5310- if (strcmp (name, "gtk-icon-theme-name") == 0 ||
5311- strcmp (name, "gtk-icon-sizes") == 0)
5312+ if (strcmp (name, "gtk-icon-theme-name") == 0
5313+ || strcmp (name, "gtk-icon-sizes") == 0)
5314 change_icon_theme (impl);
5315
5316 profile_end ("end", NULL);
5317@@ -5948,24 +2182,6 @@
5318 }
5319
5320 static void
5321-recent_manager_update (GtkFileChooserDefault *impl)
5322-{
5323- GtkRecentManager *manager;
5324-
5325- profile_start ("start", NULL);
5326-
5327- if (gtk_widget_has_screen (GTK_WIDGET (impl)))
5328- manager = gtk_recent_manager_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
5329- else
5330- manager = gtk_recent_manager_get_default ();
5331-
5332- if (impl->recent_manager != manager)
5333- impl->recent_manager = manager;
5334-
5335- profile_end ("end", NULL);
5336-}
5337-
5338-static void
5339 gtk_file_chooser_default_style_set (GtkWidget *widget,
5340 GtkStyle *previous_style)
5341 {
5342@@ -6005,7 +2221,6 @@
5343
5344 remove_settings_signal (impl, previous_screen);
5345 check_icon_theme (impl);
5346- recent_manager_update (impl);
5347
5348 g_signal_emit_by_name (widget, "default-size-changed");
5349
5350@@ -6032,15 +2247,6 @@
5351
5352 impl->default_width = allocation->width;
5353 impl->default_height = allocation->height;
5354-
5355- if (impl->preview_widget_active &&
5356- impl->preview_widget &&
5357- GTK_WIDGET_DRAWABLE (impl->preview_widget))
5358- impl->default_width -= impl->preview_widget->allocation.width + PREVIEW_HBOX_SPACING;
5359-
5360- if (impl->extra_widget &&
5361- GTK_WIDGET_DRAWABLE (impl->extra_widget))
5362- impl->default_height -= GTK_BOX (widget)->spacing + impl->extra_widget->allocation.height;
5363 }
5364
5365 static gboolean
5366@@ -6094,23 +2300,18 @@
5367 settings_load (GtkFileChooserDefault *impl)
5368 {
5369 GtkFileChooserSettings *settings;
5370- LocationMode location_mode;
5371 gboolean show_hidden;
5372 gboolean expand_folders;
5373
5374 settings = _gtk_file_chooser_settings_new ();
5375
5376- location_mode = _gtk_file_chooser_settings_get_location_mode (settings);
5377 show_hidden = _gtk_file_chooser_settings_get_show_hidden (settings);
5378 expand_folders = _gtk_file_chooser_settings_get_expand_folders (settings);
5379
5380 g_object_unref (settings);
5381
5382- location_mode_set (impl, location_mode, TRUE);
5383 gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden);
5384 impl->expand_folders = expand_folders;
5385- if (impl->save_expander)
5386- gtk_expander_set_expanded (GTK_EXPANDER (impl->save_expander), expand_folders);
5387 }
5388
5389 static void
5390@@ -6120,7 +2321,6 @@
5391
5392 settings = _gtk_file_chooser_settings_new ();
5393
5394- _gtk_file_chooser_settings_set_location_mode (settings, impl->location_mode);
5395 _gtk_file_chooser_settings_set_show_hidden (settings, gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
5396 _gtk_file_chooser_settings_set_expand_folders (settings, impl->expand_folders);
5397
5398@@ -6143,44 +2343,32 @@
5399
5400 GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->map (widget);
5401
5402- if (impl->operation_mode == OPERATION_MODE_BROWSE)
5403+ switch (impl->reload_state)
5404 {
5405- switch (impl->reload_state)
5406- {
5407- case RELOAD_EMPTY:
5408- /* The user didn't explicitly give us a folder to
5409- * display, so we'll use the cwd
5410- */
5411- current_working_dir = g_get_current_dir ();
5412- gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl),
5413- current_working_dir);
5414- g_free (current_working_dir);
5415- break;
5416-
5417- case RELOAD_HAS_FOLDER:
5418- /* Nothing; we are already loading or loaded, so we
5419- * don't need to reload
5420- */
5421- break;
5422+ case RELOAD_EMPTY:
5423+ /* The user didn't explicitly give us a folder to display, so we'll use the cwd */
5424+ current_working_dir = g_get_current_dir ();
5425+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (impl), current_working_dir);
5426+ g_free (current_working_dir);
5427+ break;
5428
5429- case RELOAD_WAS_UNMAPPED:
5430- /* Just reload the current folder; else continue
5431- * the pending load.
5432- */
5433- if (impl->current_folder)
5434- {
5435- pending_select_paths_store_selection (impl);
5436- change_folder_and_display_error (impl, impl->current_folder, FALSE);
5437- }
5438- break;
5439+ case RELOAD_HAS_FOLDER:
5440+ /* Nothing; we are already loading or loaded, so we don't need to reload */
5441+ break;
5442
5443- default:
5444- g_assert_not_reached ();
5445- }
5446+ case RELOAD_WAS_UNMAPPED:
5447+ /* Just reload the current folder; else continue the pending load. */
5448+ if (impl->current_folder)
5449+ {
5450+ pending_select_paths_store_selection (impl);
5451+ change_folder_and_display_error (impl, impl->current_folder);
5452+ }
5453+ break;
5454+
5455+ default:
5456+ g_assert_not_reached ();
5457 }
5458
5459- bookmarks_changed_cb (impl->file_system, impl);
5460-
5461 settings_load (impl);
5462
5463 profile_end ("end", NULL);
5464@@ -6244,8 +2432,8 @@
5465
5466 #define COMPARE_DIRECTORIES \
5467 GtkFileChooserDefault *impl = user_data; \
5468- const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a); \
5469- const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b); \
5470+ const GtkFileInfo *info_a = _gtk_file_system_model_get_info (impl->browse_files_model, a); \
5471+ const GtkFileInfo *info_b = _gtk_file_system_model_get_info (impl->browse_files_model, b); \
5472 gboolean dir_a, dir_b; \
5473 \
5474 if (info_a) \
5475@@ -6387,6 +2575,8 @@
5476
5477 profile_start ("start", NULL);
5478
5479+ GDK_THREADS_ENTER ();
5480+
5481 impl = GTK_FILE_CHOOSER_DEFAULT (data);
5482 g_assert (impl->load_state == LOAD_PRELOAD);
5483 g_assert (impl->load_timeout_id != 0);
5484@@ -6397,6 +2587,8 @@
5485
5486 load_set_model (impl);
5487
5488+ GDK_THREADS_LEAVE ();
5489+
5490 profile_end ("end", NULL);
5491
5492 return FALSE;
5493@@ -6409,7 +2601,7 @@
5494 g_assert (impl->load_timeout_id == 0);
5495 g_assert (impl->load_state != LOAD_PRELOAD);
5496
5497- impl->load_timeout_id = gdk_threads_add_timeout (MAX_LOADING_TIME, load_timeout_cb, impl);
5498+ impl->load_timeout_id = g_timeout_add (MAX_LOADING_TIME, load_timeout_cb, impl);
5499 impl->load_state = LOAD_PRELOAD;
5500 }
5501
5502@@ -6494,12 +2686,10 @@
5503 gpointer user_data)
5504 {
5505 gboolean have_hidden;
5506- gboolean have_filtered;
5507 GSList *l;
5508 struct ShowAndSelectPathsData *data = user_data;
5509
5510 have_hidden = FALSE;
5511- have_filtered = FALSE;
5512
5513 for (l = data->paths; l; l = l->next)
5514 {
5515@@ -6515,12 +2705,9 @@
5516 if (!have_hidden)
5517 have_hidden = gtk_file_info_get_is_hidden (info);
5518
5519- if (!have_filtered)
5520- have_filtered = !gtk_file_info_get_is_folder (info) && get_is_file_filtered (data->impl, path, info);
5521-
5522 gtk_file_info_free (info);
5523
5524- if (have_hidden && have_filtered)
5525+ if (have_hidden)
5526 break; /* we now have all the information we need */
5527 }
5528 }
5529@@ -6534,9 +2721,6 @@
5530 if (have_hidden)
5531 g_object_set (data->impl, "show-hidden", TRUE, NULL);
5532
5533- if (have_filtered)
5534- set_current_filter (data->impl, NULL);
5535-
5536 for (l = data->paths; l; l = l->next)
5537 {
5538 const GtkFilePath *path;
5539@@ -6644,6 +2828,12 @@
5540 * but rather on behalf of something else like GtkFileChooserButton. In
5541 * that case, the chooser's selection should be what the caller expects,
5542 * as the user can't see that something else got selected. See bug #165264.
5543+ *
5544+ * Also, we don't select the first file if we are not in OPEN mode. Doing
5545+ * so would change the contents of the filename entry for SAVE or
5546+ * CREATE_FOLDER, which is undesired; in SELECT_FOLDER, we don't want to
5547+ * select a *different* folder from the one into which the user just
5548+ * navigated.
5549 */
5550 if (GTK_WIDGET_MAPPED (impl) && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
5551 browse_files_select_first_row (impl);
5552@@ -6690,11 +2880,17 @@
5553 profile_end ("end", NULL);
5554 }
5555
5556-static void
5557-stop_loading_and_clear_list_model (GtkFileChooserDefault *impl)
5558+/* Gets rid of the old list model and creates a new one for the current folder */
5559+static gboolean
5560+set_list_model (GtkFileChooserDefault *impl,
5561+ GError **error)
5562 {
5563+ g_assert (impl->current_folder != NULL);
5564+
5565+ profile_start ("start", NULL);
5566+
5567 load_remove_timer (impl); /* This changes the state to LOAD_EMPTY */
5568-
5569+
5570 if (impl->browse_files_model)
5571 {
5572 g_object_unref (impl->browse_files_model);
5573@@ -6706,21 +2902,7 @@
5574 g_object_unref (impl->sort_model);
5575 impl->sort_model = NULL;
5576 }
5577-
5578- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
5579-}
5580
5581-/* Gets rid of the old list model and creates a new one for the current folder */
5582-static gboolean
5583-set_list_model (GtkFileChooserDefault *impl,
5584- GError **error)
5585-{
5586- g_assert (impl->current_folder != NULL);
5587-
5588- profile_start ("start", NULL);
5589-
5590- stop_loading_and_clear_list_model (impl);
5591-
5592 set_busy_cursor (impl, TRUE);
5593 gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
5594
5595@@ -6794,17 +2976,10 @@
5596 struct update_chooser_entry_selected_foreach_closure closure;
5597 const char *file_part;
5598
5599- /* no need to update the file chooser's entry if there's no entry */
5600- if (impl->operation_mode == OPERATION_MODE_SEARCH ||
5601- impl->operation_mode == OPERATION_MODE_RECENT ||
5602- !impl->location_entry)
5603- return;
5604-
5605 if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5606 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5607- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5608- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5609- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
5610+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5611+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
5612 return;
5613
5614 g_assert (impl->location_entry != NULL);
5615@@ -6822,45 +2997,39 @@
5616 else if (closure.num_selected == 1)
5617 {
5618 GtkTreeIter child_iter;
5619-
5620- if (impl->operation_mode == OPERATION_MODE_BROWSE)
5621- {
5622- const GtkFileInfo *info;
5623- gboolean change_entry;
5624+ const GtkFileInfo *info;
5625+ gboolean change_entry;
5626
5627- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
5628- &child_iter,
5629- &closure.first_selected_iter);
5630+ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
5631+ &child_iter,
5632+ &closure.first_selected_iter);
5633
5634- info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
5635+ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
5636
5637- /* If the cursor moved to the row of the newly created folder,
5638- * retrieving info will return NULL.
5639- */
5640- if (!info)
5641- return;
5642+ /* If the cursor moved to the row of the newly created folder,
5643+ * retrieving info will return NULL.
5644+ */
5645+ if (!info)
5646+ return;
5647
5648- g_free (impl->browse_files_last_selected_name);
5649- impl->browse_files_last_selected_name =
5650- g_strdup (gtk_file_info_get_display_name (info));
5651+ g_free (impl->browse_files_last_selected_name);
5652+ impl->browse_files_last_selected_name = g_strdup (gtk_file_info_get_display_name (info));
5653
5654- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
5655- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
5656- change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */
5657- else
5658- change_entry = TRUE; /* ... unless we are in one of the folder modes */
5659+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5660+ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
5661+ change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */
5662+ else
5663+ change_entry = TRUE; /* ... unless we are in one of the folder modes */
5664
5665- if (change_entry)
5666- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
5667- impl->browse_files_last_selected_name);
5668+ if (change_entry)
5669+ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->browse_files_last_selected_name);
5670
5671- return;
5672- }
5673+ return;
5674 }
5675 else
5676 {
5677- g_assert (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5678- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
5679+ g_assert (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5680+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
5681
5682 /* Multiple selection, so just clear the entry. */
5683
5684@@ -6957,7 +3126,7 @@
5685
5686 /* get parent path and try to change the folder to that */
5687 if (gtk_file_system_get_parent (impl->file_system, data->path, &parent_path, NULL) &&
5688- parent_path != NULL)
5689+ parent_path)
5690 {
5691 gtk_file_path_free (data->path);
5692 data->path = parent_path;
5693@@ -6998,9 +3167,6 @@
5694 if (!gtk_file_info_get_is_folder (info))
5695 goto out;
5696
5697- if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), data->path, data->keep_trail, NULL))
5698- goto out;
5699-
5700 if (impl->current_folder != data->path)
5701 {
5702 if (impl->current_folder)
5703@@ -7011,17 +3177,6 @@
5704 impl->reload_state = RELOAD_HAS_FOLDER;
5705 }
5706
5707- /* Update the widgets that may trigger a folder change themselves. */
5708-
5709- if (!impl->changing_folder)
5710- {
5711- impl->changing_folder = TRUE;
5712-
5713- shortcuts_update_current_folder (impl);
5714-
5715- impl->changing_folder = FALSE;
5716- }
5717-
5718 /* Set the folder on the save entry */
5719
5720 if (impl->location_entry)
5721@@ -7041,13 +3196,7 @@
5722
5723 /* Refresh controls */
5724
5725- shortcuts_find_current_folder (impl);
5726-
5727 g_signal_emit_by_name (impl, "current-folder-changed", 0);
5728-
5729- check_preview_change (impl);
5730- bookmarks_check_add_sensitivity (impl);
5731-
5732 g_signal_emit_by_name (impl, "selection-changed", 0);
5733
5734 out:
5735@@ -7069,18 +3218,6 @@
5736
5737 profile_start ("start", (char *) path);
5738
5739- switch (impl->operation_mode)
5740- {
5741- case OPERATION_MODE_SEARCH:
5742- search_switch_to_browse_mode (impl);
5743- break;
5744- case OPERATION_MODE_RECENT:
5745- recent_switch_to_browse_mode (impl);
5746- break;
5747- case OPERATION_MODE_BROWSE:
5748- break;
5749- }
5750-
5751 g_assert (path != NULL);
5752
5753 if (impl->local_only &&
5754@@ -7123,10 +3260,6 @@
5755 {
5756 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5757
5758- if (impl->operation_mode == OPERATION_MODE_SEARCH ||
5759- impl->operation_mode == OPERATION_MODE_RECENT)
5760- return NULL;
5761-
5762 if (impl->reload_state == RELOAD_EMPTY)
5763 {
5764 char *current_working_dir;
5765@@ -7151,8 +3284,8 @@
5766 {
5767 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5768
5769- g_return_if_fail (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5770- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
5771+ g_return_if_fail (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5772+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
5773
5774 pending_select_paths_free (impl);
5775 _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name);
5776@@ -7187,14 +3320,10 @@
5777 return FALSE;
5778
5779 if (!parent_path)
5780- return _gtk_file_chooser_set_current_folder_path (chooser, path, error);
5781+ return _gtk_file_chooser_set_current_folder_path (chooser, path, error);
5782
5783- if (impl->operation_mode == OPERATION_MODE_SEARCH ||
5784- impl->operation_mode == OPERATION_MODE_RECENT ||
5785- impl->load_state == LOAD_EMPTY)
5786- {
5787- same_path = FALSE;
5788- }
5789+ if (impl->load_state == LOAD_EMPTY)
5790+ same_path = FALSE;
5791 else
5792 {
5793 g_assert (impl->current_folder != NULL);
5794@@ -7289,17 +3418,6 @@
5795 gtk_file_chooser_default_select_all (GtkFileChooser *chooser)
5796 {
5797 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5798-
5799- if (impl->operation_mode == OPERATION_MODE_SEARCH ||
5800- impl->operation_mode == OPERATION_MODE_RECENT)
5801- {
5802- GtkTreeSelection *selection;
5803-
5804- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
5805- gtk_tree_selection_select_all (selection);
5806- return;
5807- }
5808-
5809 if (impl->select_multiple)
5810 gtk_tree_model_foreach (GTK_TREE_MODEL (impl->sort_model),
5811 maybe_select, impl);
5812@@ -7340,9 +3458,8 @@
5813
5814 g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5815 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5816- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5817- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5818- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY));
5819+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5820+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5821
5822 chooser_entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry);
5823
5824@@ -7439,14 +3556,7 @@
5825 struct get_paths_closure info;
5826 GtkWindow *toplevel;
5827 GtkWidget *current_focus;
5828- gboolean file_list_seen;
5829
5830- if (impl->operation_mode == OPERATION_MODE_SEARCH)
5831- return search_get_selected_paths (impl);
5832-
5833- if (impl->operation_mode == OPERATION_MODE_RECENT)
5834- return recent_get_selected_paths (impl);
5835-
5836 info.impl = impl;
5837 info.result = NULL;
5838 info.path_from_entry = NULL;
5839@@ -7457,14 +3567,12 @@
5840 else
5841 current_focus = NULL;
5842
5843- file_list_seen = FALSE;
5844 if (current_focus == impl->browse_files_tree_view)
5845 {
5846 GtkTreeSelection *selection;
5847
5848 file_list:
5849
5850- file_list_seen = TRUE;
5851 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
5852 gtk_tree_selection_selected_foreach (selection, get_paths_foreach, &info);
5853
5854@@ -7499,12 +3607,8 @@
5855 return NULL;
5856 }
5857
5858- if (info.path_from_entry)
5859- info.result = g_slist_prepend (info.result, info.path_from_entry);
5860- else if (!file_list_seen)
5861- goto file_list;
5862- else
5863- return NULL;
5864+ g_assert (info.path_from_entry != NULL);
5865+ info.result = g_slist_prepend (info.result, info.path_from_entry);
5866 }
5867 else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
5868 goto file_list;
5869@@ -7512,9 +3616,9 @@
5870 goto file_entry;
5871 else
5872 {
5873- /* The focus is on a dialog's action area button or something else */
5874- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
5875- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5876+ /* The focus is on a dialog's action area button or something else */
5877+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5878+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5879 goto file_entry;
5880 else
5881 goto file_list;
5882@@ -7533,17 +3637,6 @@
5883 return g_slist_reverse (info.result);
5884 }
5885
5886-static GtkFilePath *
5887-gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser)
5888-{
5889- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5890-
5891- if (impl->preview_path)
5892- return gtk_file_path_copy (impl->preview_path);
5893- else
5894- return NULL;
5895-}
5896-
5897 static GtkFileSystem *
5898 gtk_file_chooser_default_get_file_system (GtkFileChooser *chooser)
5899 {
5900@@ -7558,9 +3651,9 @@
5901 gboolean show)
5902 {
5903 if (show)
5904- gtk_widget_show (impl->filter_combo_hbox);
5905+ gtk_widget_show (impl->filter_combo);
5906 else
5907- gtk_widget_hide (impl->filter_combo_hbox);
5908+ gtk_widget_hide (impl->filter_combo);
5909 }
5910
5911 static void
5912@@ -7588,7 +3683,7 @@
5913 if (!g_slist_find (impl->filters, impl->current_filter))
5914 set_current_filter (impl, filter);
5915
5916- show_filters (impl, TRUE);
5917+ show_filters (impl, g_slist_length (impl->filters) > 1);
5918 }
5919
5920 static void
5921@@ -7627,8 +3722,7 @@
5922
5923 g_object_unref (filter);
5924
5925- if (!impl->filters)
5926- show_filters (impl, FALSE);
5927+ show_filters (impl, g_slist_length (impl->filters) > 1);
5928 }
5929
5930 static GSList *
5931@@ -7639,234 +3733,6 @@
5932 return g_slist_copy (impl->filters);
5933 }
5934
5935-/* Returns the position in the shortcuts tree where the nth specified shortcut would appear */
5936-static int
5937-shortcuts_get_pos_for_shortcut_folder (GtkFileChooserDefault *impl,
5938- int pos)
5939-{
5940- return pos + shortcuts_get_index (impl, SHORTCUTS_SHORTCUTS);
5941-}
5942-
5943-struct AddShortcutData
5944-{
5945- GtkFileChooserDefault *impl;
5946- GtkFilePath *path;
5947-};
5948-
5949-static void
5950-add_shortcut_get_info_cb (GtkFileSystemHandle *handle,
5951- const GtkFileInfo *info,
5952- const GError *error,
5953- gpointer user_data)
5954-{
5955- int pos;
5956- gboolean cancelled = handle->cancelled;
5957- struct AddShortcutData *data = user_data;
5958-
5959- if (!g_slist_find (data->impl->loading_shortcuts, handle))
5960- goto out;
5961-
5962- data->impl->loading_shortcuts = g_slist_remove (data->impl->loading_shortcuts, handle);
5963-
5964- if (cancelled || error || !gtk_file_info_get_is_folder (info))
5965- goto out;
5966-
5967- pos = shortcuts_get_pos_for_shortcut_folder (data->impl, data->impl->num_shortcuts);
5968-
5969- shortcuts_insert_path (data->impl, pos, SHORTCUT_TYPE_PATH, NULL, data->path, NULL, FALSE, SHORTCUTS_SHORTCUTS);
5970-
5971-out:
5972- g_object_unref (data->impl);
5973- gtk_file_path_free (data->path);
5974- g_free (data);
5975-
5976- g_object_unref (handle);
5977-}
5978-
5979-static gboolean
5980-gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
5981- const GtkFilePath *path,
5982- GError **error)
5983-{
5984- GtkFileSystemHandle *handle;
5985- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5986- struct AddShortcutData *data;
5987- GSList *l;
5988- int pos;
5989-
5990- /* Avoid adding duplicates */
5991- pos = shortcut_find_position (impl, path);
5992- if (pos >= 0 && pos < shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR))
5993- {
5994- gchar *uri;
5995-
5996- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5997- /* translators, "Shortcut" means "Bookmark" here */
5998- g_set_error (error,
5999- GTK_FILE_CHOOSER_ERROR,
6000- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
6001- _("Shortcut %s already exists"),
6002- uri);
6003- g_free (uri);
6004-
6005- return FALSE;
6006- }
6007-
6008- for (l = impl->loading_shortcuts; l; l = l->next)
6009- {
6010- GtkFileSystemHandle *h = l->data;
6011- GtkFilePath *p;
6012-
6013- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key");
6014- if (p && !gtk_file_path_compare (path, p))
6015- {
6016- gchar *uri;
6017-
6018- uri = gtk_file_system_path_to_uri (impl->file_system, path);
6019- g_set_error (error,
6020- GTK_FILE_CHOOSER_ERROR,
6021- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
6022- _("Shortcut %s already exists"),
6023- uri);
6024- g_free (uri);
6025-
6026- return FALSE;
6027- }
6028- }
6029-
6030- data = g_new0 (struct AddShortcutData, 1);
6031- data->impl = g_object_ref (impl);
6032- data->path = gtk_file_path_copy (path);
6033-
6034- handle = gtk_file_system_get_info (impl->file_system, path,
6035- GTK_FILE_INFO_IS_FOLDER,
6036- add_shortcut_get_info_cb, data);
6037-
6038- if (!handle)
6039- return FALSE;
6040-
6041- impl->loading_shortcuts = g_slist_append (impl->loading_shortcuts, handle);
6042- g_object_set_data (G_OBJECT (handle), "add-shortcut-path-key", data->path);
6043-
6044- return TRUE;
6045-}
6046-
6047-static gboolean
6048-gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
6049- const GtkFilePath *path,
6050- GError **error)
6051-{
6052- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
6053- int pos;
6054- GtkTreeIter iter;
6055- GSList *l;
6056- char *uri;
6057- int i;
6058-
6059- for (l = impl->loading_shortcuts; l; l = l->next)
6060- {
6061- GtkFileSystemHandle *h = l->data;
6062- GtkFilePath *p;
6063-
6064- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key");
6065- if (p && !gtk_file_path_compare (path, p))
6066- {
6067- impl->loading_shortcuts = g_slist_remove (impl->loading_shortcuts, h);
6068- gtk_file_system_cancel_operation (h);
6069- return TRUE;
6070- }
6071- }
6072-
6073- if (impl->num_shortcuts == 0)
6074- goto out;
6075-
6076- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
6077- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
6078- g_assert_not_reached ();
6079-
6080- for (i = 0; i < impl->num_shortcuts; i++)
6081- {
6082- gpointer col_data;
6083- ShortcutType shortcut_type;
6084- GtkFilePath *shortcut;
6085-
6086- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
6087- SHORTCUTS_COL_DATA, &col_data,
6088- SHORTCUTS_COL_TYPE, &shortcut_type,
6089- -1);
6090- g_assert (col_data != NULL);
6091- g_assert (shortcut_type == SHORTCUT_TYPE_PATH);
6092-
6093- shortcut = col_data;
6094- if (gtk_file_path_compare (shortcut, path) == 0)
6095- {
6096- shortcuts_remove_rows (impl, pos + i, 1);
6097- impl->num_shortcuts--;
6098- return TRUE;
6099- }
6100-
6101- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
6102- g_assert_not_reached ();
6103- }
6104-
6105- out:
6106-
6107- uri = gtk_file_system_path_to_uri (impl->file_system, path);
6108- /* translators, "Shortcut" means "Bookmark" here */
6109- g_set_error (error,
6110- GTK_FILE_CHOOSER_ERROR,
6111- GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
6112- _("Shortcut %s does not exist"),
6113- uri);
6114- g_free (uri);
6115-
6116- return FALSE;
6117-}
6118-
6119-static GSList *
6120-gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
6121-{
6122- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
6123- int pos;
6124- GtkTreeIter iter;
6125- int i;
6126- GSList *list;
6127-
6128- if (impl->num_shortcuts == 0)
6129- return NULL;
6130-
6131- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
6132- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
6133- g_assert_not_reached ();
6134-
6135- list = NULL;
6136-
6137- for (i = 0; i < impl->num_shortcuts; i++)
6138- {
6139- gpointer col_data;
6140- ShortcutType shortcut_type;
6141- GtkFilePath *shortcut;
6142-
6143- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
6144- SHORTCUTS_COL_DATA, &col_data,
6145- SHORTCUTS_COL_TYPE, &shortcut_type,
6146- -1);
6147- g_assert (col_data != NULL);
6148- g_assert (shortcut_type == SHORTCUT_TYPE_PATH);
6149-
6150- shortcut = col_data;
6151- list = g_slist_prepend (list, gtk_file_path_copy (shortcut));
6152-
6153- if (i != impl->num_shortcuts - 1)
6154- {
6155- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
6156- g_assert_not_reached ();
6157- }
6158- }
6159-
6160- return g_slist_reverse (list);
6161-}
6162-
6163 /* Guesses a size based upon font sizes */
6164 static void
6165 find_good_size_from_style (GtkWidget *widget,
6166@@ -7911,25 +3777,9 @@
6167 gint *default_height)
6168 {
6169 GtkFileChooserDefault *impl;
6170- GtkRequisition req;
6171
6172 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
6173 find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height);
6174-
6175- if (impl->preview_widget_active &&
6176- impl->preview_widget &&
6177- GTK_WIDGET_VISIBLE (impl->preview_widget))
6178- {
6179- gtk_widget_size_request (impl->preview_box, &req);
6180- *default_width += PREVIEW_HBOX_SPACING + req.width;
6181- }
6182-
6183- if (impl->extra_widget &&
6184- GTK_WIDGET_VISIBLE (impl->extra_widget))
6185- {
6186- gtk_widget_size_request (impl->extra_align, &req);
6187- *default_height += GTK_BOX (chooser_embed)->spacing + req.height;
6188- }
6189 }
6190
6191 static gboolean
6192@@ -7940,8 +3790,7 @@
6193 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
6194
6195 return (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
6196- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
6197- gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)));
6198+ impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
6199 }
6200
6201 struct switch_folder_closure {
6202@@ -7988,7 +3837,7 @@
6203
6204 g_assert (closure.path && closure.num_selected == 1);
6205
6206- change_folder_and_display_error (impl, closure.path, FALSE);
6207+ change_folder_and_display_error (impl, closure.path);
6208 }
6209
6210 /* Gets the GtkFileInfo for the selected row in the file list; assumes single
6211@@ -8187,24 +4036,7 @@
6212 }
6213 }
6214
6215-/* Gives the focus to the browse tree view only if it is visible */
6216 static void
6217-focus_browse_tree_view_if_possible (GtkFileChooserDefault *impl)
6218-{
6219- gboolean do_focus;
6220-
6221- if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
6222- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6223- && !gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)))
6224- do_focus = FALSE;
6225- else
6226- do_focus = TRUE;
6227-
6228- if (do_focus)
6229- gtk_widget_grab_focus (impl->browse_files_tree_view);
6230-}
6231-
6232-static void
6233 action_create_folder_cb (GtkFileSystemHandle *handle,
6234 const GtkFilePath *path,
6235 const GError *error,
6236@@ -8300,7 +4132,7 @@
6237 else
6238 {
6239 /* This will display an error, which is what we want */
6240- change_folder_and_display_error (data->impl, data->parent_path, FALSE);
6241+ change_folder_and_display_error (data->impl, data->parent_path);
6242 }
6243
6244 out:
6245@@ -8378,51 +4210,7 @@
6246 g_object_unref (handle);
6247 }
6248
6249-static void
6250-paste_text_received (GtkClipboard *clipboard,
6251- const gchar *text,
6252- GtkFileChooserDefault *impl)
6253-{
6254- GtkFilePath *path;
6255
6256- if (!text)
6257- return;
6258-
6259- path = gtk_file_system_uri_to_path (impl->file_system, text);
6260- if (!path)
6261- {
6262- if (!g_path_is_absolute (text))
6263- {
6264- location_popup_handler (impl, text);
6265- return;
6266- }
6267-
6268- path = gtk_file_system_filename_to_path (impl->file_system, text);
6269- if (!path)
6270- {
6271- location_popup_handler (impl, text);
6272- return;
6273- }
6274- }
6275-
6276- if (!gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (impl), path, NULL))
6277- location_popup_handler (impl, text);
6278-
6279- gtk_file_path_free (path);
6280-}
6281-
6282-/* Handler for the "location-popup-on-paste" keybinding signal */
6283-static void
6284-location_popup_on_paste_handler (GtkFileChooserDefault *impl)
6285-{
6286- GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl),
6287- GDK_SELECTION_CLIPBOARD);
6288- gtk_clipboard_request_text (clipboard,
6289- (GtkClipboardTextReceivedFunc) paste_text_received,
6290- impl);
6291-}
6292-
6293-
6294 /* Implementation for GtkFileChooserEmbed::should_respond() */
6295 static gboolean
6296 gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
6297@@ -8469,12 +4257,6 @@
6298
6299 g_assert (impl->action >= GTK_FILE_CHOOSER_ACTION_OPEN && impl->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
6300
6301- if (impl->operation_mode == OPERATION_MODE_SEARCH)
6302- return search_should_respond (impl);
6303-
6304- if (impl->operation_mode == OPERATION_MODE_RECENT)
6305- return recent_should_respond (impl);
6306-
6307 selection_check (impl, &num_selected, &all_files, &all_folders);
6308
6309 if (num_selected > 2)
6310@@ -8533,9 +4315,8 @@
6311
6312 g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6313 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
6314- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6315- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6316- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY));
6317+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6318+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
6319
6320 entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry);
6321 check_save_entry (impl, &path, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
6322@@ -8548,14 +4329,14 @@
6323 error = NULL;
6324 if (is_folder)
6325 {
6326- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
6327- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
6328+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6329+ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
6330 {
6331- change_folder_and_display_error (impl, path, TRUE);
6332+ change_folder_and_display_error (impl, path);
6333 retval = FALSE;
6334 }
6335- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
6336- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6337+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
6338+ || GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6339 {
6340 /* The folder already exists, so we do not need to create it.
6341 * Just respond to terminate the dialog.
6342@@ -8598,37 +4379,13 @@
6343 gtk_file_path_free (path);
6344 return retval;
6345 }
6346- else if (impl->toplevel_last_focus_widget == impl->browse_shortcuts_tree_view)
6347- {
6348- /* The focus is on a dialog's action area button, *and* the widget that
6349- * was focused immediately before it is the shortcuts list. Switch to the
6350- * selected shortcut and tell the caller not to respond.
6351- */
6352- GtkTreeIter iter;
6353-
6354- if (shortcuts_get_selected (impl, &iter))
6355- {
6356- shortcuts_activate_iter (impl, &iter);
6357-
6358- focus_browse_tree_view_if_possible (impl);
6359- }
6360- else
6361- goto file_list;
6362-
6363- return FALSE;
6364- }
6365 else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
6366 {
6367 /* The focus is on a dialog's action area button, *and* the widget that
6368- * was focused immediately before it is the file list.
6369+ * was focused immediately before it is the file list.
6370 */
6371 goto file_list;
6372 }
6373- else if (impl->operation_mode == OPERATION_MODE_SEARCH && impl->toplevel_last_focus_widget == impl->search_entry)
6374- {
6375- search_entry_activate_cb (GTK_ENTRY (impl->search_entry), impl);
6376- return FALSE;
6377- }
6378 else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry)
6379 {
6380 /* The focus is on a dialog's action area button, *and* the widget that
6381@@ -8657,17 +4414,16 @@
6382
6383 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
6384
6385- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
6386- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6387+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6388+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6389 {
6390- if (impl->location_mode == LOCATION_MODE_PATH_BAR)
6391 widget = impl->browse_files_tree_view;
6392- else
6393- widget = impl->location_entry;
6394 }
6395- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
6396- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6397- widget = impl->location_entry;
6398+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6399+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6400+ {
6401+ widget = impl->location_entry;
6402+ }
6403 else
6404 {
6405 g_assert_not_reached ();
6406@@ -8678,1475 +4434,7 @@
6407 gtk_widget_grab_focus (widget);
6408 }
6409
6410-/* Callback used from gtk_tree_selection_selected_foreach(); gets the selected GtkFilePaths */
6411 static void
6412-search_selected_foreach_get_path_cb (GtkTreeModel *model,
6413- GtkTreePath *path,
6414- GtkTreeIter *iter,
6415- gpointer data)
6416-{
6417- GSList **list;
6418- const GtkFilePath *file_path;
6419- GtkFilePath *file_path_copy;
6420-
6421- list = data;
6422-
6423- gtk_tree_model_get (model, iter, SEARCH_MODEL_COL_PATH, &file_path, -1);
6424- file_path_copy = gtk_file_path_copy (file_path);
6425- *list = g_slist_prepend (*list, file_path_copy);
6426-}
6427-
6428-/* Constructs a list of the selected paths in search mode */
6429-static GSList *
6430-search_get_selected_paths (GtkFileChooserDefault *impl)
6431-{
6432- GSList *result;
6433- GtkTreeSelection *selection;
6434-
6435- result = NULL;
6436-
6437- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
6438- gtk_tree_selection_selected_foreach (selection, search_selected_foreach_get_path_cb, &result);
6439- result = g_slist_reverse (result);
6440-
6441- return result;
6442-}
6443-
6444-/* Called from ::should_respond(). We return whether there are selected files
6445- * in the search list.
6446- */
6447-static gboolean
6448-search_should_respond (GtkFileChooserDefault *impl)
6449-{
6450- GtkTreeSelection *selection;
6451-
6452- g_assert (impl->operation_mode == OPERATION_MODE_SEARCH);
6453-
6454- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
6455- return (gtk_tree_selection_count_selected_rows (selection) != 0);
6456-}
6457-
6458-struct SearchHitInsertRequest
6459-{
6460- GtkFileChooserDefault *impl;
6461- GtkFilePath *path;
6462- GtkTreeRowReference *row_ref;
6463-};
6464-
6465-static void
6466-search_hit_get_info_cb (GtkFileSystemHandle *handle,
6467- const GtkFileInfo *info,
6468- const GError *error,
6469- gpointer data)
6470-{
6471- gboolean cancelled = handle->cancelled;
6472- GdkPixbuf *pixbuf = NULL;
6473- GtkTreePath *path;
6474- GtkTreeIter iter;
6475- GtkFileSystemHandle *model_handle;
6476- gboolean is_folder = FALSE;
6477- char *mime_type;
6478- char *display_name;
6479- struct SearchHitInsertRequest *request = data;
6480-
6481- if (!request->impl->search_model)
6482- goto out;
6483-
6484- path = gtk_tree_row_reference_get_path (request->row_ref);
6485- if (!path)
6486- goto out;
6487-
6488- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->search_model),
6489- &iter, path);
6490- gtk_tree_path_free (path);
6491-
6492- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->search_model), &iter,
6493- SEARCH_MODEL_COL_HANDLE, &model_handle,
6494- -1);
6495- if (handle != model_handle)
6496- goto out;
6497-
6498- /* set the handle to NULL in the model */
6499- gtk_list_store_set (request->impl->search_model, &iter,
6500- SEARCH_MODEL_COL_HANDLE, NULL,
6501- -1);
6502-
6503- if (cancelled)
6504- goto out;
6505-
6506- if (!info)
6507- {
6508- gtk_list_store_remove (request->impl->search_model, &iter);
6509- goto out;
6510- }
6511-
6512- display_name = g_strdup (gtk_file_info_get_display_name (info));
6513- mime_type = g_strdup (gtk_file_info_get_mime_type (info));
6514- is_folder = gtk_file_info_get_is_folder (info);
6515- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
6516- request->impl->icon_size, NULL);
6517-
6518- gtk_list_store_set (request->impl->search_model, &iter,
6519- SEARCH_MODEL_COL_PIXBUF, pixbuf,
6520- SEARCH_MODEL_COL_DISPLAY_NAME, display_name,
6521- SEARCH_MODEL_COL_MIME_TYPE, mime_type,
6522- SEARCH_MODEL_COL_IS_FOLDER, is_folder,
6523- -1);
6524-
6525- if (pixbuf)
6526- g_object_unref (pixbuf);
6527-
6528-out:
6529- g_object_unref (request->impl);
6530- gtk_file_path_free (request->path);
6531- gtk_tree_row_reference_free (request->row_ref);
6532- g_free (request);
6533-
6534- g_object_unref (handle);
6535-}
6536-
6537-/* Adds one hit from the search engine to the search_model */
6538-static void
6539-search_add_hit (GtkFileChooserDefault *impl,
6540- gchar *uri)
6541-{
6542- GtkFilePath *path;
6543- char *filename;
6544- char *tmp;
6545- char *collation_key;
6546- struct stat statbuf;
6547- struct stat *statbuf_copy;
6548- GtkTreeIter iter;
6549- GtkTreePath *p;
6550- GtkFileSystemHandle *handle;
6551- struct SearchHitInsertRequest *request;
6552-
6553- path = gtk_file_system_uri_to_path (impl->file_system, uri);
6554- if (!path)
6555- return;
6556-
6557- filename = gtk_file_system_path_to_filename (impl->file_system, path);
6558- if (!filename)
6559- {
6560- gtk_file_path_free (path);
6561- return;
6562- }
6563-
6564- if (stat (filename, &statbuf) != 0)
6565- {
6566- gtk_file_path_free (path);
6567- g_free (filename);
6568- return;
6569- }
6570-
6571- statbuf_copy = g_new (struct stat, 1);
6572- *statbuf_copy = statbuf;
6573-
6574- tmp = g_filename_display_name (filename);
6575- collation_key = g_utf8_collate_key_for_filename (tmp, -1);
6576- g_free (tmp);
6577-
6578- request = g_new0 (struct SearchHitInsertRequest, 1);
6579- request->impl = g_object_ref (impl);
6580- request->path = gtk_file_path_copy (path);
6581-
6582- gtk_list_store_append (impl->search_model, &iter);
6583- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->search_model), &iter);
6584-
6585- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->search_model), p);
6586- gtk_tree_path_free (p);
6587-
6588- handle = gtk_file_system_get_info (impl->file_system, path,
6589- GTK_FILE_INFO_IS_FOLDER | GTK_FILE_INFO_ICON | GTK_FILE_INFO_MIME_TYPE | GTK_FILE_INFO_DISPLAY_NAME,
6590- search_hit_get_info_cb,
6591- request);
6592-
6593- gtk_list_store_set (impl->search_model, &iter,
6594- SEARCH_MODEL_COL_PATH, path,
6595- SEARCH_MODEL_COL_COLLATION_KEY, collation_key,
6596- SEARCH_MODEL_COL_STAT, statbuf_copy,
6597- SEARCH_MODEL_COL_HANDLE, handle,
6598- -1);
6599-}
6600-
6601-/* Callback used from GtkSearchEngine when we get new hits */
6602-static void
6603-search_engine_hits_added_cb (GtkSearchEngine *engine,
6604- GList *hits,
6605- gpointer data)
6606-{
6607- GtkFileChooserDefault *impl;
6608- GList *l;
6609-
6610- impl = GTK_FILE_CHOOSER_DEFAULT (data);
6611-
6612- for (l = hits; l; l = l->next)
6613- search_add_hit (impl, (gchar*)l->data);
6614-}
6615-
6616-/* Callback used from GtkSearchEngine when the query is done running */
6617-static void
6618-search_engine_finished_cb (GtkSearchEngine *engine,
6619- gpointer data)
6620-{
6621- GtkFileChooserDefault *impl;
6622-
6623- impl = GTK_FILE_CHOOSER_DEFAULT (data);
6624-
6625-#if 0
6626- /* EB: setting the model here will avoid loads of row events,
6627- * but it'll make the search look like blocked.
6628- */
6629- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
6630- GTK_TREE_MODEL (impl->search_model_filter));
6631-#endif
6632-
6633- /* FMQ: if search was empty, say that we got no hits */
6634- set_busy_cursor (impl, FALSE);
6635-}
6636-
6637-/* Displays a generic error when we cannot create a GtkSearchEngine.
6638- * It would be better if _gtk_search_engine_new() gave us a GError
6639- * with a better message, but it doesn't do that right now.
6640- */
6641-static void
6642-search_error_could_not_create_client (GtkFileChooserDefault *impl)
6643-{
6644- error_message (impl,
6645- _("Could not start the search process"),
6646- _("The program was not able to create a connection to the indexer "
6647- "daemon. Please make sure it is running."));
6648-}
6649-
6650-static void
6651-search_engine_error_cb (GtkSearchEngine *engine,
6652- const gchar *message,
6653- gpointer data)
6654-{
6655- GtkFileChooserDefault *impl;
6656-
6657- impl = GTK_FILE_CHOOSER_DEFAULT (data);
6658-
6659- search_stop_searching (impl, TRUE);
6660- error_message (impl, _("Could not send the search request"), message);
6661-
6662- set_busy_cursor (impl, FALSE);
6663-}
6664-
6665-/* Frees the data in the search_model */
6666-static void
6667-search_clear_model (GtkFileChooserDefault *impl,
6668- gboolean remove_from_treeview)
6669-{
6670- GtkTreeModel *model;
6671- GtkTreeIter iter;
6672-
6673- if (!impl->search_model)
6674- return;
6675-
6676- model = GTK_TREE_MODEL (impl->search_model);
6677-
6678- if (gtk_tree_model_get_iter_first (model, &iter))
6679- do
6680- {
6681- GtkFilePath *path;
6682- gchar *display_name;
6683- gchar *collation_key;
6684- struct stat *statbuf;
6685- GtkFileSystemHandle *handle;
6686-
6687- gtk_tree_model_get (model, &iter,
6688- SEARCH_MODEL_COL_PATH, &path,
6689- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
6690- SEARCH_MODEL_COL_COLLATION_KEY, &collation_key,
6691- SEARCH_MODEL_COL_STAT, &statbuf,
6692- SEARCH_MODEL_COL_HANDLE, &handle,
6693- -1);
6694-
6695- if (handle)
6696- gtk_file_system_cancel_operation (handle);
6697-
6698- gtk_file_path_free (path);
6699- g_free (display_name);
6700- g_free (collation_key);
6701- g_free (statbuf);
6702- }
6703- while (gtk_tree_model_iter_next (model, &iter));
6704-
6705- g_object_unref (impl->search_model);
6706- impl->search_model = NULL;
6707-
6708- g_object_unref (impl->search_model_filter);
6709- impl->search_model_filter = NULL;
6710-
6711- g_object_unref (impl->search_model_sort);
6712- impl->search_model_sort = NULL;
6713-
6714- if (remove_from_treeview)
6715- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
6716-}
6717-
6718-/* Stops any ongoing searches; does not touch the search_model */
6719-static void
6720-search_stop_searching (GtkFileChooserDefault *impl,
6721- gboolean remove_query)
6722-{
6723- if (remove_query && impl->search_query)
6724- {
6725- g_object_unref (impl->search_query);
6726- impl->search_query = NULL;
6727- }
6728-
6729- if (impl->search_engine)
6730- {
6731- _gtk_search_engine_stop (impl->search_engine);
6732-
6733- g_object_unref (impl->search_engine);
6734- impl->search_engine = NULL;
6735- }
6736-}
6737-
6738-/* Stops any pending searches, clears the file list, and switches back to OPERATION_MODE_BROWSE */
6739-static void
6740-search_switch_to_browse_mode (GtkFileChooserDefault *impl)
6741-{
6742- g_assert (impl->operation_mode != OPERATION_MODE_BROWSE);
6743-
6744- search_stop_searching (impl, FALSE);
6745- search_clear_model (impl, TRUE);
6746-
6747- gtk_widget_destroy (impl->search_hbox);
6748- impl->search_hbox = NULL;
6749- impl->search_entry = NULL;
6750-
6751- gtk_widget_show (impl->browse_path_bar);
6752- gtk_widget_show (impl->browse_new_folder_button);
6753-
6754- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
6755- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6756- {
6757- gtk_widget_show (impl->location_button);
6758-
6759- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
6760- gtk_widget_show (impl->location_entry_box);
6761- }
6762-
6763- impl->operation_mode = OPERATION_MODE_BROWSE;
6764-
6765- file_list_set_sort_column_ids (impl);
6766-}
6767-
6768-/* Sort callback from the path column */
6769-static gint
6770-search_column_path_sort_func (GtkTreeModel *model,
6771- GtkTreeIter *a,
6772- GtkTreeIter *b,
6773- gpointer user_data)
6774-{
6775- GtkFileChooserDefault *impl = user_data;
6776- GtkTreeIter child_a, child_b;
6777- const char *collation_key_a, *collation_key_b;
6778- gboolean is_folder_a, is_folder_b;
6779-
6780- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
6781- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
6782-
6783- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a,
6784- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a,
6785- SEARCH_MODEL_COL_COLLATION_KEY, &collation_key_a,
6786- -1);
6787- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b,
6788- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b,
6789- SEARCH_MODEL_COL_COLLATION_KEY, &collation_key_b,
6790- -1);
6791-
6792- if (!collation_key_a)
6793- return 1;
6794-
6795- if (!collation_key_b)
6796- return -1;
6797-
6798- /* always show folders first */
6799- if (is_folder_a != is_folder_b)
6800- return is_folder_a ? 1 : -1;
6801-
6802- return strcmp (collation_key_a, collation_key_b);
6803-}
6804-
6805-/* Sort callback from the modification time column */
6806-static gint
6807-search_column_mtime_sort_func (GtkTreeModel *model,
6808- GtkTreeIter *a,
6809- GtkTreeIter *b,
6810- gpointer user_data)
6811-{
6812- GtkFileChooserDefault *impl = user_data;
6813- GtkTreeIter child_a, child_b;
6814- const struct stat *statbuf_a, *statbuf_b;
6815- gboolean is_folder_a, is_folder_b;
6816-
6817- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
6818- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
6819-
6820- /* Note that although we store a whole struct stat in the model, we only
6821- * compare the mtime here. If we add another column relative to a struct stat
6822- * (e.g. a file size column), we'll want another sort callback similar to this
6823- * one as well.
6824- */
6825- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_a,
6826- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_a,
6827- SEARCH_MODEL_COL_STAT, &statbuf_a,
6828- -1);
6829- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_b,
6830- SEARCH_MODEL_COL_IS_FOLDER, &is_folder_b,
6831- SEARCH_MODEL_COL_STAT, &statbuf_b,
6832- -1);
6833-
6834- if (!statbuf_a)
6835- return 1;
6836-
6837- if (!statbuf_b)
6838- return -1;
6839-
6840- if (is_folder_a != is_folder_b)
6841- return is_folder_a ? 1 : -1;
6842-
6843- if (statbuf_a->st_mtime < statbuf_b->st_mtime)
6844- return -1;
6845- else if (statbuf_a->st_mtime > statbuf_b->st_mtime)
6846- return 1;
6847- else
6848- return 0;
6849-}
6850-
6851-static gboolean
6852-search_get_is_filtered (GtkFileChooserDefault *impl,
6853- const GtkFilePath *path,
6854- const gchar *display_name,
6855- const gchar *mime_type)
6856-{
6857- GtkFileFilterInfo filter_info;
6858- GtkFileFilterFlags needed;
6859- gboolean result;
6860-
6861- if (!impl->current_filter)
6862- return FALSE;
6863-
6864- filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
6865- needed = gtk_file_filter_get_needed (impl->current_filter);
6866-
6867- filter_info.display_name = display_name;
6868- filter_info.mime_type = mime_type;
6869-
6870- if (needed & GTK_FILE_FILTER_FILENAME)
6871- {
6872- filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path);
6873- if (filter_info.filename)
6874- filter_info.contains |= GTK_FILE_FILTER_FILENAME;
6875- }
6876- else
6877- filter_info.filename = NULL;
6878-
6879- if (needed & GTK_FILE_FILTER_URI)
6880- {
6881- filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path);
6882- if (filter_info.uri)
6883- filter_info.contains |= GTK_FILE_FILTER_URI;
6884- }
6885- else
6886- filter_info.uri = NULL;
6887-
6888- result = gtk_file_filter_filter (impl->current_filter, &filter_info);
6889-
6890- if (filter_info.filename)
6891- g_free ((gchar *) filter_info.filename);
6892- if (filter_info.uri)
6893- g_free ((gchar *) filter_info.uri);
6894-
6895- return !result;
6896-
6897-}
6898-
6899-/* Visibility function for the recent filter model */
6900-static gboolean
6901-search_model_visible_func (GtkTreeModel *model,
6902- GtkTreeIter *iter,
6903- gpointer user_data)
6904-{
6905- GtkFileChooserDefault *impl = user_data;
6906- GtkFilePath *file_path;
6907- gchar *display_name, *mime_type;
6908- gboolean is_folder;
6909-
6910- if (!impl->current_filter)
6911- return TRUE;
6912-
6913- gtk_tree_model_get (model, iter,
6914- SEARCH_MODEL_COL_PATH, &file_path,
6915- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
6916- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
6917- SEARCH_MODEL_COL_MIME_TYPE, &mime_type,
6918- -1);
6919-
6920- if (!display_name)
6921- return TRUE;
6922-
6923- if (is_folder)
6924- return TRUE;
6925-
6926- return !search_get_is_filtered (impl, file_path, display_name, mime_type);
6927-}
6928-
6929-/* Creates the search_model and puts it in the tree view */
6930-static void
6931-search_setup_model (GtkFileChooserDefault *impl)
6932-{
6933- g_assert (impl->search_model == NULL);
6934- g_assert (impl->search_model_filter == NULL);
6935- g_assert (impl->search_model_sort == NULL);
6936-
6937- /* We store these columns in the search model:
6938- *
6939- * SEARCH_MODEL_COL_PATH - a GtkFilePath for the hit's URI, stored as a
6940- * pointer not as a GTK_TYPE_FILE_PATH
6941- * SEARCH_MODEL_COL_DISPLAY_NAME - a string with the display name, stored
6942- * as a pointer not as a G_TYPE_STRING
6943- * SEARCH_MODEL_COL_COLLATION_KEY - collation key for the filename, stored
6944- * as a pointer not as a G_TYPE_STRING
6945- * SEARCH_MODEL_COL_STAT - pointer to a struct stat
6946- * SEARCH_MODEL_COL_HANDLE - handle used when getting the hit's info
6947- * SEARCH_MODEL_COL_PIXBUF - GdkPixbuf for the hit's icon
6948- * SEARCH_MODEL_COL_MIME_TYPE - a string with the hit's MIME type
6949- * SEARCH_MODEL_COL_IS_FOLDER - a boolean flag for folders
6950- *
6951- * Keep this in sync with the enumeration defined near the beginning
6952- * of this file.
6953- */
6954- impl->search_model = gtk_list_store_new (SEARCH_MODEL_COL_NUM_COLUMNS,
6955- G_TYPE_POINTER,
6956- G_TYPE_POINTER,
6957- G_TYPE_POINTER,
6958- G_TYPE_POINTER,
6959- G_TYPE_POINTER,
6960- GDK_TYPE_PIXBUF,
6961- G_TYPE_POINTER,
6962- G_TYPE_BOOLEAN);
6963-
6964- impl->search_model_filter =
6965- GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->search_model), NULL));
6966- gtk_tree_model_filter_set_visible_func (impl->search_model_filter,
6967- search_model_visible_func,
6968- impl, NULL);
6969-
6970- impl->search_model_sort =
6971- GTK_TREE_MODEL_SORT (search_model_sort_new (impl, GTK_TREE_MODEL (impl->search_model_filter)));
6972- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort),
6973- SEARCH_MODEL_COL_PATH,
6974- search_column_path_sort_func,
6975- impl, NULL);
6976- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->search_model_sort),
6977- SEARCH_MODEL_COL_STAT,
6978- search_column_mtime_sort_func,
6979- impl, NULL);
6980- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->search_model_sort),
6981- SEARCH_MODEL_COL_STAT,
6982- GTK_SORT_DESCENDING);
6983-
6984- /* EB: setting the model here will make the hits list update feel
6985- * more "alive" than setting the model at the end of the search
6986- * run
6987- */
6988- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
6989- GTK_TREE_MODEL (impl->search_model_sort));
6990-}
6991-
6992-static void
6993-search_get_valid_child_iter (GtkFileChooserDefault *impl,
6994- GtkTreeIter *child_iter,
6995- GtkTreeIter *iter)
6996-{
6997- GtkTreeIter middle;
6998-
6999- if (!impl->search_model)
7000- return;
7001-
7002- if (!impl->search_model_filter || !impl->search_model_sort)
7003- return;
7004-
7005- /* pass 1: get the iterator in the filter model */
7006- gtk_tree_model_sort_convert_iter_to_child_iter (impl->search_model_sort,
7007- &middle, iter);
7008-
7009- /* pass 2: get the iterator in the real model */
7010- gtk_tree_model_filter_convert_iter_to_child_iter (impl->search_model_filter,
7011- child_iter, &middle);
7012-}
7013-
7014-/* Creates a new query with the specified text and launches it */
7015-static void
7016-search_start_query (GtkFileChooserDefault *impl,
7017- const gchar *query_text)
7018-{
7019- search_stop_searching (impl, FALSE);
7020- search_clear_model (impl, TRUE);
7021- search_setup_model (impl);
7022- set_busy_cursor (impl, TRUE);
7023-
7024- if (impl->search_engine == NULL)
7025- impl->search_engine = _gtk_search_engine_new ();
7026-
7027- if (!impl->search_engine)
7028- {
7029- set_busy_cursor (impl, FALSE);
7030- search_error_could_not_create_client (impl); /* lame; we don't get an error code or anything */
7031- return;
7032- }
7033-
7034- if (!impl->search_query)
7035- {
7036- impl->search_query = _gtk_query_new ();
7037- _gtk_query_set_text (impl->search_query, query_text);
7038- }
7039-
7040- _gtk_search_engine_set_query (impl->search_engine, impl->search_query);
7041-
7042- g_signal_connect (impl->search_engine, "hits-added",
7043- G_CALLBACK (search_engine_hits_added_cb), impl);
7044- g_signal_connect (impl->search_engine, "finished",
7045- G_CALLBACK (search_engine_finished_cb), impl);
7046- g_signal_connect (impl->search_engine, "error",
7047- G_CALLBACK (search_engine_error_cb), impl);
7048-
7049- _gtk_search_engine_start (impl->search_engine);
7050-}
7051-
7052-/* Callback used when the user presses Enter while typing on the search
7053- * entry; starts the query
7054- */
7055-static void
7056-search_entry_activate_cb (GtkEntry *entry,
7057- gpointer data)
7058-{
7059- GtkFileChooserDefault *impl;
7060- const char *text;
7061-
7062- impl = GTK_FILE_CHOOSER_DEFAULT (data);
7063-
7064- text = gtk_entry_get_text (GTK_ENTRY (impl->search_entry));
7065- if (strlen (text) == 0)
7066- return;
7067-
7068- /* reset any existing query object */
7069- if (impl->search_query)
7070- {
7071- g_object_unref (impl->search_query);
7072- impl->search_query = NULL;
7073- }
7074-
7075- search_start_query (impl, text);
7076-}
7077-
7078-/* Hides the path bar and creates the search entry */
7079-static void
7080-search_setup_widgets (GtkFileChooserDefault *impl)
7081-{
7082- GtkWidget *label;
7083-
7084- impl->search_hbox = gtk_hbox_new (FALSE, 12);
7085-
7086- /* Label */
7087-
7088- label = gtk_label_new_with_mnemonic (_("_Search:"));
7089- gtk_box_pack_start (GTK_BOX (impl->search_hbox), label, FALSE, FALSE, 0);
7090-
7091- /* Entry */
7092-
7093- impl->search_entry = gtk_entry_new ();
7094- gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->search_entry);
7095- g_signal_connect (impl->search_entry, "activate",
7096- G_CALLBACK (search_entry_activate_cb),
7097- impl);
7098- gtk_box_pack_start (GTK_BOX (impl->search_hbox), impl->search_entry, TRUE, TRUE, 0);
7099-
7100- /* if there already is a query, restart it */
7101- if (impl->search_query)
7102- {
7103- gchar *query = _gtk_query_get_text (impl->search_query);
7104-
7105- if (query)
7106- {
7107- gtk_entry_set_text (GTK_ENTRY (impl->search_entry), query);
7108- search_start_query (impl, query);
7109-
7110- g_free (query);
7111- }
7112- else
7113- {
7114- g_object_unref (impl->search_query);
7115- impl->search_query = NULL;
7116- }
7117- }
7118-
7119- gtk_widget_hide (impl->browse_path_bar);
7120- gtk_widget_hide (impl->browse_new_folder_button);
7121-
7122- /* Box for search widgets */
7123- gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->search_hbox, TRUE, TRUE, 0);
7124- gtk_widget_show_all (impl->search_hbox);
7125-
7126- /* Hide the location widgets temporarily */
7127-
7128- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
7129- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
7130- {
7131- gtk_widget_hide (impl->location_button);
7132- gtk_widget_hide (impl->location_entry_box);
7133- }
7134-
7135- gtk_widget_grab_focus (impl->search_entry);
7136-
7137- /* FMQ: hide the filter combo? */
7138-}
7139-
7140-/* Main entry point to the searching functions; this gets called when the user
7141- * activates the Search shortcut.
7142- */
7143-static void
7144-search_activate (GtkFileChooserDefault *impl)
7145-{
7146- OperationMode previous_mode;
7147-
7148- if (impl->operation_mode == OPERATION_MODE_SEARCH)
7149- {
7150- gtk_widget_grab_focus (impl->search_entry);
7151- return;
7152- }
7153-
7154- previous_mode = impl->operation_mode;
7155- impl->operation_mode = OPERATION_MODE_SEARCH;
7156-
7157- switch (previous_mode)
7158- {
7159- case OPERATION_MODE_RECENT:
7160- recent_stop_loading (impl);
7161- recent_clear_model (impl, TRUE);
7162- break;
7163-
7164- case OPERATION_MODE_BROWSE:
7165- stop_loading_and_clear_list_model (impl);
7166- break;
7167-
7168- case OPERATION_MODE_SEARCH:
7169- g_assert_not_reached ();
7170- break;
7171- }
7172-
7173- g_assert (impl->search_hbox == NULL);
7174- g_assert (impl->search_entry == NULL);
7175- g_assert (impl->search_model == NULL);
7176- g_assert (impl->search_model_filter == NULL);
7177-
7178- search_setup_widgets (impl);
7179- file_list_set_sort_column_ids (impl);
7180-}
7181-
7182-/*
7183- * Recent files support
7184- */
7185-
7186-/* Frees the data in the recent_model */
7187-static void
7188-recent_clear_model (GtkFileChooserDefault *impl,
7189- gboolean remove_from_treeview)
7190-{
7191- GtkTreeModel *model;
7192- GtkTreeIter iter;
7193-
7194- if (!impl->recent_model)
7195- return;
7196-
7197- model = GTK_TREE_MODEL (impl->recent_model);
7198-
7199- if (remove_from_treeview)
7200- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view), NULL);
7201-
7202- if (gtk_tree_model_get_iter_first (model, &iter))
7203- {
7204- do
7205- {
7206- GtkFilePath *file_path;
7207- GtkFileSystemHandle *handle;
7208- GtkRecentInfo *recent_info;
7209- gchar *display_name;
7210-
7211- gtk_tree_model_get (model, &iter,
7212- RECENT_MODEL_COL_DISPLAY_NAME, &display_name,
7213- RECENT_MODEL_COL_PATH, &file_path,
7214- RECENT_MODEL_COL_HANDLE, &handle,
7215- RECENT_MODEL_COL_INFO, &recent_info,
7216- -1);
7217-
7218- if (handle)
7219- gtk_file_system_cancel_operation (handle);
7220-
7221- gtk_file_path_free (file_path);
7222- gtk_recent_info_unref (recent_info);
7223- g_free (display_name);
7224- }
7225- while (gtk_tree_model_iter_next (model, &iter));
7226- }
7227-
7228- g_object_unref (impl->recent_model);
7229- impl->recent_model = NULL;
7230-
7231- g_object_unref (impl->recent_model_filter);
7232- impl->recent_model_filter = NULL;
7233-
7234- g_object_unref (impl->recent_model_sort);
7235- impl->recent_model_sort = NULL;
7236-}
7237-
7238-/* Stops any ongoing loading of the recent files list; does
7239- * not touch the recent_model
7240- */
7241-static void
7242-recent_stop_loading (GtkFileChooserDefault *impl)
7243-{
7244- if (impl->load_recent_id)
7245- {
7246- g_source_remove (impl->load_recent_id);
7247- impl->load_recent_id = 0;
7248- }
7249-}
7250-
7251-/* Stops any pending load, clears the file list, and switches
7252- * back to OPERATION_MODE_BROWSE
7253- */
7254-static void
7255-recent_switch_to_browse_mode (GtkFileChooserDefault *impl)
7256-{
7257- g_assert (impl->operation_mode != OPERATION_MODE_BROWSE);
7258-
7259- recent_stop_loading (impl);
7260- recent_clear_model (impl, TRUE);
7261-
7262- gtk_widget_show (impl->browse_path_bar);
7263- gtk_widget_show (impl->browse_new_folder_button);
7264-
7265- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
7266- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
7267- {
7268- gtk_widget_show (impl->location_button);
7269-
7270- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
7271- gtk_widget_show (impl->location_entry_box);
7272- }
7273-
7274- impl->operation_mode = OPERATION_MODE_BROWSE;
7275-
7276- file_list_set_sort_column_ids (impl);
7277-}
7278-
7279-/* Sort callback from the modification time column */
7280-static gint
7281-recent_column_mtime_sort_func (GtkTreeModel *model,
7282- GtkTreeIter *a,
7283- GtkTreeIter *b,
7284- gpointer user_data)
7285-{
7286- GtkFileChooserDefault *impl = user_data;
7287- GtkTreeIter child_a, child_b;
7288- GtkRecentInfo *info_a, *info_b;
7289- gboolean is_folder_a, is_folder_b;
7290-
7291- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
7292- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
7293-
7294- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_a,
7295- RECENT_MODEL_COL_IS_FOLDER, &is_folder_a,
7296- RECENT_MODEL_COL_INFO, &info_a,
7297- -1);
7298- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_b,
7299- RECENT_MODEL_COL_IS_FOLDER, &is_folder_b,
7300- RECENT_MODEL_COL_INFO, &info_b,
7301- -1);
7302-
7303- if (!info_a)
7304- return 1;
7305-
7306- if (!info_b)
7307- return -1;
7308-
7309- /* folders always go first */
7310- if (is_folder_a != is_folder_b)
7311- return is_folder_a ? 1 : -1;
7312-
7313- if (gtk_recent_info_get_modified (info_a) < gtk_recent_info_get_modified (info_b))
7314- return -1;
7315- else if (gtk_recent_info_get_modified (info_a) > gtk_recent_info_get_modified (info_b))
7316- return 1;
7317- else
7318- return 0;
7319-}
7320-
7321-static gint
7322-recent_column_path_sort_func (GtkTreeModel *model,
7323- GtkTreeIter *a,
7324- GtkTreeIter *b,
7325- gpointer user_data)
7326-{
7327- GtkFileChooserDefault *impl = user_data;
7328- GtkTreeIter child_a, child_b;
7329- gboolean is_folder_a, is_folder_b;
7330- gchar *name_a, *name_b;
7331-
7332- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_a, a);
7333- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_b, b);
7334-
7335- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_a,
7336- RECENT_MODEL_COL_IS_FOLDER, &is_folder_a,
7337- RECENT_MODEL_COL_DISPLAY_NAME, &name_a,
7338- -1);
7339- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_b,
7340- RECENT_MODEL_COL_IS_FOLDER, &is_folder_b,
7341- RECENT_MODEL_COL_DISPLAY_NAME, &name_b,
7342- -1);
7343-
7344- if (!name_a)
7345- return 1;
7346-
7347- if (!name_b)
7348- return -1;
7349-
7350- if (is_folder_a != is_folder_b)
7351- return is_folder_a ? 1 : -1;
7352-
7353- return strcmp (name_a, name_b);
7354-}
7355-
7356-static gboolean
7357-recent_get_is_filtered (GtkFileChooserDefault *impl,
7358- const GtkFilePath *path,
7359- GtkRecentInfo *recent_info)
7360-{
7361- GtkFileFilterInfo filter_info;
7362- GtkFileFilterFlags needed;
7363- gboolean result;
7364-
7365- if (!impl->current_filter)
7366- return FALSE;
7367-
7368- filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
7369- needed = gtk_file_filter_get_needed (impl->current_filter);
7370-
7371- filter_info.display_name = gtk_recent_info_get_display_name (recent_info);
7372- filter_info.mime_type = gtk_recent_info_get_mime_type (recent_info);
7373-
7374- if (needed & GTK_FILE_FILTER_FILENAME)
7375- {
7376- filter_info.filename = gtk_file_system_path_to_filename (impl->file_system, path);
7377- if (filter_info.filename)
7378- filter_info.contains |= GTK_FILE_FILTER_FILENAME;
7379- }
7380- else
7381- filter_info.filename = NULL;
7382-
7383- if (needed & GTK_FILE_FILTER_URI)
7384- {
7385- filter_info.uri = gtk_file_system_path_to_uri (impl->file_system, path);
7386- if (filter_info.uri)
7387- filter_info.contains |= GTK_FILE_FILTER_URI;
7388- }
7389- else
7390- filter_info.uri = NULL;
7391-
7392- result = gtk_file_filter_filter (impl->current_filter, &filter_info);
7393-
7394- if (filter_info.filename)
7395- g_free ((gchar *) filter_info.filename);
7396- if (filter_info.uri)
7397- g_free ((gchar *) filter_info.uri);
7398-
7399- return !result;
7400-}
7401-
7402-/* Visibility function for the recent filter model */
7403-static gboolean
7404-recent_model_visible_func (GtkTreeModel *model,
7405- GtkTreeIter *iter,
7406- gpointer user_data)
7407-{
7408- GtkFileChooserDefault *impl = user_data;
7409- GtkFilePath *file_path;
7410- GtkRecentInfo *recent_info;
7411- gboolean is_folder;
7412-
7413- if (!impl->current_filter)
7414- return TRUE;
7415-
7416- gtk_tree_model_get (model, iter,
7417- RECENT_MODEL_COL_INFO, &recent_info,
7418- RECENT_MODEL_COL_PATH, &file_path,
7419- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
7420- -1);
7421-
7422- if (!recent_info)
7423- return TRUE;
7424-
7425- if (is_folder)
7426- return TRUE;
7427-
7428- return !recent_get_is_filtered (impl, file_path, recent_info);
7429-}
7430-
7431-static void
7432-recent_setup_model (GtkFileChooserDefault *impl)
7433-{
7434- g_assert (impl->recent_model == NULL);
7435- g_assert (impl->recent_model_filter == NULL);
7436- g_assert (impl->recent_model_sort == NULL);
7437-
7438- /* We store these columns in the search model:
7439- *
7440- * RECENT_MODEL_COL_PATH - a pointer to GtkFilePath for the hit's URI,
7441- * stored as a pointer and not as a GTK_TYPE_FILE_PATH;
7442- * RECENT_MODEL_COL_DISPLAY_NAME - a string with the display name,
7443- * stored as a pointer and not as a G_TYPE_STRING;
7444- * RECENT_MODEL_COL_INFO - GtkRecentInfo, stored as a pointer and not
7445- * as a GTK_TYPE_RECENT_INFO;
7446- * RECENT_MODEL_COL_IS_FOLDER - boolean flag;
7447- * RECENT_MODEL_COL_HANDLE - GtkFileSystemHandle, stored as a pointer
7448- * and not as a GTK_TYPE_FILE_SYSTEM_HANDLE;
7449- *
7450- * Keep this in sync with the enumeration defined near the beginning of
7451- * this file.
7452- */
7453- impl->recent_model = gtk_list_store_new (RECENT_MODEL_COL_NUM_COLUMNS,
7454- G_TYPE_POINTER,
7455- G_TYPE_POINTER,
7456- G_TYPE_POINTER,
7457- G_TYPE_BOOLEAN,
7458- G_TYPE_POINTER);
7459-
7460- impl->recent_model_filter =
7461- GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (impl->recent_model), NULL));
7462- gtk_tree_model_filter_set_visible_func (impl->recent_model_filter,
7463- recent_model_visible_func,
7464- impl,
7465- NULL);
7466-
7467- /* this is the model that will actually be added to
7468- * the browse_files_tree_view widget; remember: we are
7469- * stuffing the real model into a filter model and then
7470- * into a sort model; this means we'll have to translate
7471- * the child iterator *twice* to get from a path or an
7472- * iterator coming from the tree view widget to the
7473- * real data inside the model.
7474- */
7475- impl->recent_model_sort =
7476- GTK_TREE_MODEL_SORT (recent_model_sort_new (impl, GTK_TREE_MODEL (impl->recent_model_filter)));
7477- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort),
7478- RECENT_MODEL_COL_PATH,
7479- recent_column_path_sort_func,
7480- impl, NULL);
7481- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (impl->recent_model_sort),
7482- RECENT_MODEL_COL_INFO,
7483- recent_column_mtime_sort_func,
7484- impl, NULL);
7485- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model_sort),
7486- RECENT_MODEL_COL_INFO,
7487- GTK_SORT_DESCENDING);
7488-}
7489-
7490-typedef struct
7491-{
7492- GtkFileChooserDefault *impl;
7493- GList *items;
7494- gint n_items;
7495- gint n_loaded_items;
7496- guint needs_sorting : 1;
7497-} RecentLoadData;
7498-
7499-static void
7500-recent_idle_cleanup (gpointer data)
7501-{
7502- RecentLoadData *load_data = data;
7503- GtkFileChooserDefault *impl = load_data->impl;
7504-
7505- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
7506- GTK_TREE_MODEL (impl->recent_model_sort));
7507-
7508- set_busy_cursor (impl, FALSE);
7509-
7510- impl->load_recent_id = 0;
7511-
7512- if (load_data->items)
7513- {
7514- g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
7515- g_list_free (load_data->items);
7516- }
7517-
7518- g_free (load_data);
7519-}
7520-
7521-struct RecentItemInsertRequest
7522-{
7523- GtkFileChooserDefault *impl;
7524- GtkFilePath *path;
7525- GtkTreeRowReference *row_ref;
7526-};
7527-
7528-static void
7529-recent_item_get_info_cb (GtkFileSystemHandle *handle,
7530- const GtkFileInfo *info,
7531- const GError *error,
7532- gpointer data)
7533-{
7534- gboolean cancelled = handle->cancelled;
7535- GtkTreePath *path;
7536- GtkTreeIter iter;
7537- GtkFileSystemHandle *model_handle;
7538- gboolean is_folder = FALSE;
7539- struct RecentItemInsertRequest *request = data;
7540-
7541- if (!request->impl->recent_model)
7542- goto out;
7543-
7544- path = gtk_tree_row_reference_get_path (request->row_ref);
7545- if (!path)
7546- goto out;
7547-
7548- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->recent_model),
7549- &iter, path);
7550- gtk_tree_path_free (path);
7551-
7552- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->recent_model), &iter,
7553- RECENT_MODEL_COL_HANDLE, &model_handle,
7554- -1);
7555- if (handle != model_handle)
7556- goto out;
7557-
7558- gtk_list_store_set (request->impl->recent_model, &iter,
7559- RECENT_MODEL_COL_HANDLE, NULL,
7560- -1);
7561-
7562- if (cancelled)
7563- goto out;
7564-
7565- if (!info)
7566- {
7567- gtk_list_store_remove (request->impl->recent_model, &iter);
7568- goto out;
7569- }
7570-
7571- is_folder = gtk_file_info_get_is_folder (info);
7572-
7573- gtk_list_store_set (request->impl->recent_model, &iter,
7574- RECENT_MODEL_COL_IS_FOLDER, is_folder,
7575- -1);
7576-
7577-out:
7578- g_object_unref (request->impl);
7579- gtk_file_path_free (request->path);
7580- gtk_tree_row_reference_free (request->row_ref);
7581- g_free (request);
7582-
7583- g_object_unref (handle);
7584-}
7585-
7586-static gint
7587-recent_sort_mru (gconstpointer a,
7588- gconstpointer b)
7589-{
7590- GtkRecentInfo *info_a = (GtkRecentInfo *) a;
7591- GtkRecentInfo *info_b = (GtkRecentInfo *) b;
7592-
7593- return (gtk_recent_info_get_modified (info_b) - gtk_recent_info_get_modified (info_a));
7594-}
7595-
7596-static gint
7597-get_recent_files_limit (GtkWidget *widget)
7598-{
7599- GtkSettings *settings;
7600- gint limit;
7601-
7602- if (gtk_widget_has_screen (widget))
7603- settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget));
7604- else
7605- settings = gtk_settings_get_default ();
7606-
7607- g_object_get (G_OBJECT (settings), "gtk-recent-files-limit", &limit, NULL);
7608-
7609- return limit;
7610-}
7611-
7612-static gboolean
7613-recent_idle_load (gpointer data)
7614-{
7615- RecentLoadData *load_data = data;
7616- GtkFileChooserDefault *impl = load_data->impl;
7617- GtkTreeIter iter;
7618- GtkTreePath *p;
7619- GtkRecentInfo *info;
7620- const gchar *uri, *display_name;
7621- GtkFilePath *path;
7622- GtkFileSystemHandle *handle;
7623- struct RecentItemInsertRequest *request;
7624-
7625- if (!impl->recent_manager)
7626- return FALSE;
7627-
7628- /* first iteration: load all the items */
7629- if (!load_data->items)
7630- {
7631- load_data->items = gtk_recent_manager_get_items (impl->recent_manager);
7632- if (!load_data->items)
7633- return FALSE;
7634-
7635- load_data->needs_sorting = TRUE;
7636-
7637- return TRUE;
7638- }
7639-
7640- /* second iteration: preliminary MRU sorting and clamping */
7641- if (load_data->needs_sorting)
7642- {
7643- gint limit;
7644-
7645- load_data->items = g_list_sort (load_data->items, recent_sort_mru);
7646- load_data->n_items = g_list_length (load_data->items);
7647-
7648- limit = get_recent_files_limit (GTK_WIDGET (impl));
7649-
7650- if (limit != -1 && (load_data->n_items > limit))
7651- {
7652- GList *clamp, *l;
7653-
7654- clamp = g_list_nth (load_data->items, limit - 1);
7655- if (G_LIKELY (clamp))
7656- {
7657- l = clamp->next;
7658- clamp->next = NULL;
7659-
7660- g_list_foreach (l, (GFunc) gtk_recent_info_unref, NULL);
7661- g_list_free (l);
7662-
7663- load_data->n_items = limit;
7664- }
7665- }
7666-
7667- load_data->n_loaded_items = 0;
7668- load_data->needs_sorting = FALSE;
7669-
7670- return TRUE;
7671- }
7672-
7673- info = g_list_nth_data (load_data->items, load_data->n_loaded_items);
7674- g_assert (info != NULL);
7675-
7676- uri = gtk_recent_info_get_uri (info);
7677- display_name = gtk_recent_info_get_display_name (info);
7678- path = gtk_file_system_uri_to_path (impl->file_system, uri);
7679- if (!path)
7680- goto load_next;
7681-
7682- gtk_list_store_append (impl->recent_model, &iter);
7683- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->recent_model), &iter);
7684-
7685- request = g_new0 (struct RecentItemInsertRequest, 1);
7686- request->impl = g_object_ref (impl);
7687- request->path = gtk_file_path_copy (path);
7688- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->recent_model), p);
7689- gtk_tree_path_free (p);
7690-
7691- handle = gtk_file_system_get_info (impl->file_system, path,
7692- GTK_FILE_INFO_IS_FOLDER,
7693- recent_item_get_info_cb,
7694- request);
7695-
7696- gtk_list_store_set (impl->recent_model, &iter,
7697- RECENT_MODEL_COL_PATH, path,
7698- RECENT_MODEL_COL_DISPLAY_NAME, g_strdup (display_name),
7699- RECENT_MODEL_COL_INFO, gtk_recent_info_ref (info),
7700- RECENT_MODEL_COL_HANDLE, handle,
7701- -1);
7702-
7703-load_next:
7704-
7705- load_data->n_loaded_items += 1;
7706-
7707- /* finished loading items */
7708- if (load_data->n_loaded_items == load_data->n_items)
7709- {
7710- g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
7711- g_list_free (load_data->items);
7712- load_data->items = NULL;
7713-
7714- return FALSE;
7715- }
7716-
7717- return TRUE;
7718-}
7719-
7720-static void
7721-recent_start_loading (GtkFileChooserDefault *impl)
7722-{
7723- RecentLoadData *load_data;
7724-
7725- recent_stop_loading (impl);
7726- recent_clear_model (impl, TRUE);
7727- recent_setup_model (impl);
7728- set_busy_cursor (impl, TRUE);
7729-
7730- if (!impl->recent_manager)
7731- recent_manager_update (impl);
7732-
7733- g_assert (impl->load_recent_id == 0);
7734-
7735- load_data = g_new (RecentLoadData, 1);
7736- load_data->impl = impl;
7737- load_data->items = NULL;
7738- load_data->n_items = 0;
7739- load_data->n_loaded_items = 0;
7740- load_data->needs_sorting = TRUE;
7741-
7742- /* begin lazy loading the recent files into the model */
7743- impl->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
7744- recent_idle_load,
7745- load_data,
7746- recent_idle_cleanup);
7747-}
7748-
7749-static void
7750-recent_selected_foreach_get_path_cb (GtkTreeModel *model,
7751- GtkTreePath *path,
7752- GtkTreeIter *iter,
7753- gpointer data)
7754-{
7755- GSList **list;
7756- const GtkFilePath *file_path;
7757- GtkFilePath *file_path_copy;
7758-
7759- list = data;
7760-
7761- gtk_tree_model_get (model, iter, RECENT_MODEL_COL_PATH, &file_path, -1);
7762- file_path_copy = gtk_file_path_copy (file_path);
7763- *list = g_slist_prepend (*list, file_path_copy);
7764-}
7765-
7766-/* Constructs a list of the selected paths in recent files mode */
7767-static GSList *
7768-recent_get_selected_paths (GtkFileChooserDefault *impl)
7769-{
7770- GSList *result;
7771- GtkTreeSelection *selection;
7772-
7773- result = NULL;
7774-
7775- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
7776- gtk_tree_selection_selected_foreach (selection, recent_selected_foreach_get_path_cb, &result);
7777- result = g_slist_reverse (result);
7778-
7779- return result;
7780-}
7781-
7782-/* Called from ::should_respond(). We return whether there are selected
7783- * files in the recent files list.
7784- */
7785-static gboolean
7786-recent_should_respond (GtkFileChooserDefault *impl)
7787-{
7788- GtkTreeSelection *selection;
7789-
7790- g_assert (impl->operation_mode == OPERATION_MODE_RECENT);
7791-
7792- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
7793- return (gtk_tree_selection_count_selected_rows (selection) != 0);
7794-}
7795-
7796-/* Hide the location widgets temporarily */
7797-static void
7798-recent_hide_entry (GtkFileChooserDefault *impl)
7799-{
7800- gtk_widget_hide (impl->browse_path_bar);
7801- gtk_widget_hide (impl->browse_new_folder_button);
7802-
7803- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
7804- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
7805- {
7806- gtk_widget_hide (impl->location_button);
7807- gtk_widget_hide (impl->location_entry_box);
7808- }
7809-}
7810-
7811-/* Main entry point to the recent files functions; this gets called when
7812- * the user activates the Recently Used shortcut.
7813- */
7814-static void
7815-recent_activate (GtkFileChooserDefault *impl)
7816-{
7817- OperationMode previous_mode;
7818-
7819- if (impl->operation_mode == OPERATION_MODE_RECENT)
7820- return;
7821-
7822- previous_mode = impl->operation_mode;
7823- impl->operation_mode = OPERATION_MODE_RECENT;
7824-
7825- switch (previous_mode)
7826- {
7827- case OPERATION_MODE_SEARCH:
7828- search_stop_searching (impl, FALSE);
7829- search_clear_model (impl, TRUE);
7830-
7831- gtk_widget_destroy (impl->search_hbox);
7832- impl->search_hbox = NULL;
7833- impl->search_entry = NULL;
7834- break;
7835-
7836- case OPERATION_MODE_BROWSE:
7837- stop_loading_and_clear_list_model (impl);
7838- break;
7839-
7840- case OPERATION_MODE_RECENT:
7841- g_assert_not_reached ();
7842- break;
7843- }
7844-
7845- recent_hide_entry (impl);
7846- file_list_set_sort_column_ids (impl);
7847- recent_start_loading (impl);
7848-}
7849-
7850-/* convert an iterator coming from the model bound to
7851- * browse_files_tree_view to an interator inside the
7852- * real recent_model
7853- */
7854-static void
7855-recent_get_valid_child_iter (GtkFileChooserDefault *impl,
7856- GtkTreeIter *child_iter,
7857- GtkTreeIter *iter)
7858-{
7859- GtkTreeIter middle;
7860-
7861- if (!impl->recent_model)
7862- return;
7863-
7864- if (!impl->recent_model_filter || !impl->recent_model_sort)
7865- return;
7866-
7867- /* pass 1: get the iterator in the filter model */
7868- gtk_tree_model_sort_convert_iter_to_child_iter (impl->recent_model_sort,
7869- &middle, iter);
7870-
7871- /* pass 2: get the iterator in the real model */
7872- gtk_tree_model_filter_convert_iter_to_child_iter (impl->recent_model_filter,
7873- child_iter,
7874- &middle);
7875-}
7876-
7877-
7878-static void
7879 set_current_filter (GtkFileChooserDefault *impl,
7880 GtkFileFilter *filter)
7881 {
7882@@ -10175,12 +4463,6 @@
7883 if (impl->browse_files_model)
7884 install_list_model_filter (impl);
7885
7886- if (impl->search_model_filter)
7887- gtk_tree_model_filter_refilter (impl->search_model_filter);
7888-
7889- if (impl->recent_model_filter)
7890- gtk_tree_model_filter_refilter (impl->recent_model_filter);
7891-
7892 g_object_notify (G_OBJECT (impl), "filter");
7893 }
7894 }
7895@@ -10195,355 +4477,7 @@
7896 set_current_filter (impl, new_filter);
7897 }
7898
7899-static void
7900-check_preview_change (GtkFileChooserDefault *impl)
7901-{
7902- GtkTreePath *cursor_path;
7903- const GtkFilePath *new_path;
7904- const char *new_display_name;
7905-
7906- gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL);
7907- new_path = NULL;
7908- new_display_name = NULL;
7909- if (cursor_path)
7910- {
7911- GtkTreeIter child_iter;
7912-
7913- if (impl->operation_mode == OPERATION_MODE_BROWSE)
7914- {
7915- if (impl->sort_model)
7916- {
7917- GtkTreeIter iter;
7918- const GtkFileInfo *new_info;
7919-
7920- gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, cursor_path);
7921- gtk_tree_path_free (cursor_path);
7922-
7923- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
7924-
7925- new_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
7926- new_info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
7927- if (new_info)
7928- new_display_name = gtk_file_info_get_display_name (new_info);
7929- }
7930- }
7931- else if (impl->operation_mode == OPERATION_MODE_SEARCH)
7932- {
7933- GtkTreeIter iter;
7934-
7935- gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort),
7936- &iter, cursor_path);
7937- gtk_tree_path_free (cursor_path);
7938-
7939- search_get_valid_child_iter (impl, &child_iter, &iter);
7940- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
7941- SEARCH_MODEL_COL_PATH, &new_path,
7942- SEARCH_MODEL_COL_DISPLAY_NAME, &new_display_name,
7943- -1);
7944- }
7945- else if (impl->operation_mode == OPERATION_MODE_RECENT)
7946- {
7947- GtkTreeIter iter;
7948-
7949- gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort),
7950- &iter, cursor_path);
7951- gtk_tree_path_free (cursor_path);
7952-
7953- recent_get_valid_child_iter (impl, &child_iter, &iter);
7954- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
7955- RECENT_MODEL_COL_PATH, &new_path,
7956- RECENT_MODEL_COL_DISPLAY_NAME, &new_display_name,
7957- -1);
7958- }
7959- }
7960-
7961- if (new_path != impl->preview_path &&
7962- !(new_path && impl->preview_path &&
7963- gtk_file_path_compare (new_path, impl->preview_path) == 0))
7964- {
7965- if (impl->preview_path)
7966- {
7967- gtk_file_path_free (impl->preview_path);
7968- g_free (impl->preview_display_name);
7969- }
7970-
7971- if (new_path)
7972- {
7973- impl->preview_path = gtk_file_path_copy (new_path);
7974- impl->preview_display_name = g_strdup (new_display_name);
7975- }
7976- else
7977- {
7978- impl->preview_path = NULL;
7979- impl->preview_display_name = NULL;
7980- }
7981-
7982- if (impl->use_preview_label && impl->preview_label)
7983- gtk_label_set_text (GTK_LABEL (impl->preview_label), impl->preview_display_name);
7984-
7985- g_signal_emit_by_name (impl, "update-preview");
7986- }
7987-}
7988-
7989-static void
7990-shortcuts_activate_volume_mount_cb (GtkFileSystemHandle *handle,
7991- GtkFileSystemVolume *volume,
7992- const GError *error,
7993- gpointer data)
7994-{
7995- GtkFilePath *path;
7996- gboolean cancelled = handle->cancelled;
7997- GtkFileChooserDefault *impl = data;
7998-
7999- if (handle != impl->shortcuts_activate_iter_handle)
8000- goto out;
8001-
8002- impl->shortcuts_activate_iter_handle = NULL;
8003-
8004- set_busy_cursor (impl, FALSE);
8005-
8006- if (cancelled)
8007- goto out;
8008-
8009- if (error)
8010- {
8011- char *msg;
8012-
8013- msg = g_strdup_printf (_("Could not mount %s"),
8014- gtk_file_system_volume_get_display_name (impl->file_system, volume));
8015- error_message (impl, msg, error->message);
8016- g_free (msg);
8017-
8018- goto out;
8019- }
8020-
8021- path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
8022- if (path != NULL)
8023- {
8024- change_folder_and_display_error (impl, path, FALSE);
8025- focus_browse_tree_view_if_possible (impl);
8026-
8027- gtk_file_path_free (path);
8028- }
8029-
8030-out:
8031- g_object_unref (impl);
8032- g_object_unref (handle);
8033-}
8034-
8035-
8036-/* Activates a volume by mounting it if necessary and then switching to its
8037- * base path.
8038- */
8039-static void
8040-shortcuts_activate_volume (GtkFileChooserDefault *impl,
8041- GtkFileSystemVolume *volume)
8042-{
8043- GtkFilePath *path;
8044-
8045- switch (impl->operation_mode)
8046- {
8047- case OPERATION_MODE_BROWSE:
8048- break;
8049- case OPERATION_MODE_SEARCH:
8050- search_switch_to_browse_mode (impl);
8051- break;
8052- case OPERATION_MODE_RECENT:
8053- recent_switch_to_browse_mode (impl);
8054- break;
8055- }
8056-
8057- /* We ref the file chooser since volume_mount() may run a main loop, and the
8058- * user could close the file chooser window in the meantime.
8059- */
8060- g_object_ref (impl);
8061-
8062- if (!gtk_file_system_volume_get_is_mounted (impl->file_system, volume))
8063- {
8064- set_busy_cursor (impl, TRUE);
8065-
8066- impl->shortcuts_activate_iter_handle =
8067- gtk_file_system_volume_mount (impl->file_system, volume,
8068- shortcuts_activate_volume_mount_cb,
8069- g_object_ref (impl));
8070- }
8071- else
8072- {
8073- path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
8074- if (path != NULL)
8075- {
8076- change_folder_and_display_error (impl, path, FALSE);
8077- gtk_file_path_free (path);
8078- }
8079- }
8080-
8081- g_object_unref (impl);
8082-}
8083-
8084-/* Opens the folder or volume at the specified iter in the shortcuts model */
8085-struct ShortcutsActivateData
8086-{
8087- GtkFileChooserDefault *impl;
8088- GtkFilePath *path;
8089-};
8090-
8091-static void
8092-shortcuts_activate_get_info_cb (GtkFileSystemHandle *handle,
8093- const GtkFileInfo *info,
8094- const GError *error,
8095- gpointer user_data)
8096-{
8097- gboolean cancelled = handle->cancelled;
8098- struct ShortcutsActivateData *data = user_data;
8099-
8100- if (handle != data->impl->shortcuts_activate_iter_handle)
8101- goto out;
8102-
8103- data->impl->shortcuts_activate_iter_handle = NULL;
8104-
8105- if (cancelled)
8106- goto out;
8107-
8108- if (!error && gtk_file_info_get_is_folder (info))
8109- {
8110- change_folder_and_display_error (data->impl, data->path, FALSE);
8111- focus_browse_tree_view_if_possible (data->impl);
8112- }
8113- else
8114- gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (data->impl),
8115- data->path,
8116- NULL);
8117-
8118-out:
8119- g_object_unref (data->impl);
8120- gtk_file_path_free (data->path);
8121- g_free (data);
8122-
8123- g_object_unref (handle);
8124-}
8125-
8126-static void
8127-shortcuts_activate_iter (GtkFileChooserDefault *impl,
8128- GtkTreeIter *iter)
8129-{
8130- gpointer col_data;
8131- ShortcutType shortcut_type;
8132-
8133- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY && impl->action != GTK_FILE_CHOOSER_ACTION_SAVE)
8134- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
8135-
8136- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
8137- SHORTCUTS_COL_DATA, &col_data,
8138- SHORTCUTS_COL_TYPE, &shortcut_type,
8139- -1);
8140-
8141- if (impl->shortcuts_activate_iter_handle)
8142- {
8143- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle);
8144- impl->shortcuts_activate_iter_handle = NULL;
8145- }
8146-
8147- if (shortcut_type == SHORTCUT_TYPE_SEPARATOR)
8148- return;
8149- else if (shortcut_type == SHORTCUT_TYPE_VOLUME)
8150- {
8151- GtkFileSystemVolume *volume;
8152-
8153- volume = col_data;
8154-
8155- shortcuts_activate_volume (impl, volume);
8156- }
8157- else if (shortcut_type == SHORTCUT_TYPE_PATH)
8158- {
8159- struct ShortcutsActivateData *data;
8160-
8161- data = g_new0 (struct ShortcutsActivateData, 1);
8162- data->impl = g_object_ref (impl);
8163- data->path = gtk_file_path_copy (col_data);
8164-
8165- impl->shortcuts_activate_iter_handle =
8166- gtk_file_system_get_info (impl->file_system, data->path,
8167- GTK_FILE_INFO_IS_FOLDER,
8168- shortcuts_activate_get_info_cb, data);
8169- }
8170- else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
8171- {
8172- search_activate (impl);
8173- }
8174- else if (shortcut_type == SHORTCUT_TYPE_RECENT)
8175- {
8176- recent_activate (impl);
8177- }
8178-}
8179-
8180-/* Callback used when a row in the shortcuts list is activated */
8181-static void
8182-shortcuts_row_activated_cb (GtkTreeView *tree_view,
8183- GtkTreePath *path,
8184- GtkTreeViewColumn *column,
8185- GtkFileChooserDefault *impl)
8186-{
8187- GtkTreeIter iter;
8188- GtkTreeIter child_iter;
8189-
8190- if (!gtk_tree_model_get_iter (impl->shortcuts_pane_filter_model, &iter, path))
8191- return;
8192-
8193- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_pane_filter_model),
8194- &child_iter,
8195- &iter);
8196- shortcuts_activate_iter (impl, &child_iter);
8197-}
8198-
8199-/* Handler for GtkWidget::key-press-event on the shortcuts list */
8200 static gboolean
8201-shortcuts_key_press_event_cb (GtkWidget *widget,
8202- GdkEventKey *event,
8203- GtkFileChooserDefault *impl)
8204-{
8205- guint modifiers;
8206-
8207- modifiers = gtk_accelerator_get_default_mod_mask ();
8208-
8209- if ((event->keyval == GDK_BackSpace
8210- || event->keyval == GDK_Delete
8211- || event->keyval == GDK_KP_Delete)
8212- && (event->state & modifiers) == 0)
8213- {
8214- remove_selected_bookmarks (impl);
8215- return TRUE;
8216- }
8217-
8218- if ((event->keyval == GDK_F2)
8219- && (event->state & modifiers) == 0)
8220- {
8221- rename_selected_bookmark (impl);
8222- return TRUE;
8223- }
8224-
8225- return FALSE;
8226-}
8227-
8228-static gboolean
8229-shortcuts_select_func (GtkTreeSelection *selection,
8230- GtkTreeModel *model,
8231- GtkTreePath *path,
8232- gboolean path_currently_selected,
8233- gpointer data)
8234-{
8235- GtkFileChooserDefault *impl = data;
8236- GtkTreeIter filter_iter;
8237- ShortcutType shortcut_type;
8238-
8239- if (!gtk_tree_model_get_iter (impl->shortcuts_pane_filter_model, &filter_iter, path))
8240- g_assert_not_reached ();
8241-
8242- gtk_tree_model_get (impl->shortcuts_pane_filter_model, &filter_iter, SHORTCUTS_COL_TYPE, &shortcut_type, -1);
8243-
8244- return shortcut_type != SHORTCUT_TYPE_SEPARATOR;
8245-}
8246-
8247-static gboolean
8248 list_select_func (GtkTreeSelection *selection,
8249 GtkTreeModel *model,
8250 GtkTreePath *path,
8251@@ -10556,55 +4490,17 @@
8252 impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8253 {
8254 GtkTreeIter iter, child_iter;
8255+ const GtkFileInfo *info;
8256
8257- switch (impl->operation_mode)
8258- {
8259- case OPERATION_MODE_SEARCH:
8260- {
8261- gboolean is_folder;
8262+ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path))
8263+ return FALSE;
8264+
8265+ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
8266
8267- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path))
8268- return FALSE;
8269+ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
8270
8271- search_get_valid_child_iter (impl, &child_iter, &iter);
8272- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
8273- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
8274- -1);
8275- if (!is_folder)
8276- return FALSE;
8277- }
8278- break;
8279-
8280- case OPERATION_MODE_RECENT:
8281- {
8282- gboolean is_folder;
8283-
8284- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path))
8285- return FALSE;
8286-
8287- recent_get_valid_child_iter (impl, &child_iter, &iter);
8288- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
8289- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
8290- -1);
8291- if (!is_folder)
8292- return FALSE;
8293- }
8294- break;
8295-
8296- case OPERATION_MODE_BROWSE:
8297- {
8298- const GtkFileInfo *info;
8299-
8300- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path))
8301- return FALSE;
8302-
8303- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
8304- info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
8305- if (info && !gtk_file_info_get_is_folder (info))
8306- return FALSE;
8307- }
8308- break;
8309- }
8310+ if (info && !gtk_file_info_get_is_folder (info))
8311+ return FALSE;
8312 }
8313
8314 return TRUE;
8315@@ -10615,8 +4511,7 @@
8316 GtkFileChooserDefault *impl)
8317 {
8318 /* See if we are in the new folder editable row for Save mode */
8319- if (impl->operation_mode == OPERATION_MODE_BROWSE &&
8320- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
8321+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
8322 {
8323 const GtkFileInfo *info;
8324 gboolean had_selection;
8325@@ -10634,9 +4529,6 @@
8326 if (impl->location_entry)
8327 update_chooser_entry (impl);
8328
8329- check_preview_change (impl);
8330- bookmarks_check_add_sensitivity (impl);
8331-
8332 g_signal_emit_by_name (impl, "selection-changed", 0);
8333 }
8334
8335@@ -10647,107 +4539,30 @@
8336 GtkTreeViewColumn *column,
8337 GtkFileChooserDefault *impl)
8338 {
8339- GtkTreeIter iter;
8340- GtkTreeIter child_iter;
8341+ GtkTreeIter iter, child_iter;
8342+ const GtkFileInfo *info;
8343
8344- switch (impl->operation_mode)
8345- {
8346- case OPERATION_MODE_SEARCH:
8347- {
8348- GtkFilePath *file_path;
8349- gboolean is_folder;
8350+ if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path))
8351+ return;
8352
8353- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->search_model_sort), &iter, path))
8354- return;
8355+ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
8356
8357- search_get_valid_child_iter (impl, &child_iter, &iter);
8358- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
8359- SEARCH_MODEL_COL_PATH, &file_path,
8360- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
8361- -1);
8362-
8363- if (is_folder)
8364- {
8365- change_folder_and_display_error (impl, file_path, FALSE);
8366- return;
8367- }
8368+ info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
8369
8370- g_signal_emit_by_name (impl, "file-activated");
8371- }
8372- break;
8373+ if (gtk_file_info_get_is_folder (info))
8374+ {
8375+ const GtkFilePath *file_path;
8376
8377- case OPERATION_MODE_RECENT:
8378- {
8379- GtkFilePath *file_path;
8380- gboolean is_folder;
8381+ file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
8382
8383- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->recent_model_sort), &iter, path))
8384- return;
8385-
8386- recent_get_valid_child_iter (impl, &child_iter, &iter);
8387- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
8388- RECENT_MODEL_COL_PATH, &file_path,
8389- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
8390- -1);
8391+ change_folder_and_display_error (impl, file_path);
8392
8393- if (is_folder)
8394- {
8395- change_folder_and_display_error (impl, file_path, FALSE);
8396- return;
8397- }
8398-
8399- g_signal_emit_by_name (impl, "file-activated");
8400- }
8401- break;
8402-
8403- case OPERATION_MODE_BROWSE:
8404- {
8405- const GtkFileInfo *info;
8406-
8407- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, path))
8408- return;
8409-
8410- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
8411- &child_iter, &iter);
8412- info = _gtk_file_system_model_get_info (impl->browse_files_model,
8413- &child_iter);
8414-
8415- if (gtk_file_info_get_is_folder (info))
8416- {
8417- const GtkFilePath *file_path;
8418-
8419- file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
8420- change_folder_and_display_error (impl, file_path, FALSE);
8421- return;
8422- }
8423-
8424- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
8425- impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
8426- g_signal_emit_by_name (impl, "file-activated");
8427- }
8428- break;
8429+ return;
8430 }
8431-}
8432
8433-static void
8434-path_bar_clicked (GtkPathBar *path_bar,
8435- GtkFilePath *file_path,
8436- GtkFilePath *child_path,
8437- gboolean child_is_hidden,
8438- GtkFileChooserDefault *impl)
8439-{
8440- if (child_path)
8441- pending_select_paths_add (impl, child_path);
8442-
8443- if (!change_folder_and_display_error (impl, file_path, FALSE))
8444- return;
8445-
8446- /* Say we have "/foo/bar/[.baz]" and the user clicks on "bar". We should then
8447- * show hidden files so that ".baz" appears in the file list, as it will still
8448- * be shown in the path bar: "/foo/[bar]/.baz"
8449- */
8450- if (child_is_hidden)
8451- g_object_set (impl, "show-hidden", TRUE, NULL);
8452+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
8453+ impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
8454+ g_signal_emit_by_name (impl, "file-activated");
8455 }
8456
8457 static const GtkFileInfo *
8458@@ -10772,83 +4587,40 @@
8459 {
8460 GtkFileChooserDefault *impl = data;
8461 GtkTreeIter child_iter;
8462- GdkPixbuf *pixbuf = NULL;
8463+ const GtkFilePath *path;
8464+ GdkPixbuf *pixbuf;
8465+ const GtkFileInfo *info;
8466 gboolean sensitive = TRUE;
8467
8468 profile_start ("start", NULL);
8469
8470- switch (impl->operation_mode)
8471- {
8472- case OPERATION_MODE_SEARCH:
8473- {
8474- GtkTreeIter child_iter;
8475- gboolean is_folder;
8476+ info = get_list_file_info (impl, iter);
8477
8478- search_get_valid_child_iter (impl, &child_iter, iter);
8479- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
8480- SEARCH_MODEL_COL_PIXBUF, &pixbuf,
8481- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
8482- -1);
8483-
8484- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8485- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8486- sensitive = is_folder;
8487- }
8488- break;
8489+ gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
8490+ &child_iter,
8491+ iter);
8492+ path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
8493
8494- case OPERATION_MODE_RECENT:
8495- {
8496- GtkTreeIter child_iter;
8497- GtkRecentInfo *info;
8498- gboolean is_folder;
8499+ if (path)
8500+ {
8501+ pixbuf = NULL;
8502
8503- recent_get_valid_child_iter (impl, &child_iter, iter);
8504- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
8505- RECENT_MODEL_COL_INFO, &info,
8506- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
8507- -1);
8508-
8509- pixbuf = gtk_recent_info_get_icon (info, impl->icon_size);
8510-
8511- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8512- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8513- sensitive = is_folder;
8514- }
8515- break;
8516-
8517- case OPERATION_MODE_BROWSE:
8518- {
8519- const GtkFileInfo *info;
8520- const GtkFilePath *path;
8521-
8522- info = get_list_file_info (impl, iter);
8523-
8524- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model,
8525- &child_iter,
8526- iter);
8527- path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
8528- if (path)
8529- {
8530- if (info)
8531- {
8532- /* FIXME: NULL GError */
8533- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (impl),
8534- impl->icon_size, NULL);
8535- }
8536- }
8537- else
8538- {
8539- /* We are on the editable row */
8540- pixbuf = NULL;
8541- }
8542-
8543- if (info &&
8544- (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8545- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
8546- sensitive = gtk_file_info_get_is_folder (info);
8547- }
8548- break;
8549+ if (info)
8550+ {
8551+ /* FIXME: NULL GError */
8552+ pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (impl),
8553+ impl->icon_size, NULL);
8554+ }
8555 }
8556+ else
8557+ {
8558+ /* We are on the editable row */
8559+ pixbuf = NULL;
8560+ }
8561+
8562+ if (info && (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8563+ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
8564+ sensitive = gtk_file_info_get_is_folder (info);
8565
8566 g_object_set (cell,
8567 "pixbuf", pixbuf,
8568@@ -10869,85 +4641,21 @@
8569 gpointer data)
8570 {
8571 GtkFileChooserDefault *impl = data;
8572- const GtkFileInfo *info;
8573+ const GtkFileInfo *info = get_list_file_info (impl, iter);
8574 gboolean sensitive = TRUE;
8575
8576- if (impl->operation_mode == OPERATION_MODE_SEARCH)
8577- {
8578- GtkTreeIter child_iter;
8579- gchar *display_name;
8580- gboolean is_folder;
8581-
8582- search_get_valid_child_iter (impl, &child_iter, iter);
8583- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
8584- SEARCH_MODEL_COL_DISPLAY_NAME, &display_name,
8585- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
8586- -1);
8587-
8588- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8589- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8590- {
8591- sensitive = is_folder;
8592- }
8593-
8594- g_object_set (cell,
8595- "text", display_name,
8596- "sensitive", sensitive,
8597- "ellipsize", PANGO_ELLIPSIZE_END,
8598- NULL);
8599-
8600- return;
8601- }
8602-
8603- if (impl->operation_mode == OPERATION_MODE_RECENT)
8604- {
8605- GtkTreeIter child_iter;
8606- GtkRecentInfo *recent_info;
8607- gchar *display_name;
8608- gboolean is_folder;
8609-
8610- recent_get_valid_child_iter (impl, &child_iter, iter);
8611- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
8612- RECENT_MODEL_COL_INFO, &recent_info,
8613- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
8614- -1);
8615-
8616- display_name = gtk_recent_info_get_short_name (recent_info);
8617-
8618- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8619- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8620- {
8621- sensitive = is_folder;
8622- }
8623-
8624- g_object_set (cell,
8625- "text", display_name,
8626- "sensitive", sensitive,
8627- "ellipsize", PANGO_ELLIPSIZE_END,
8628- NULL);
8629-
8630- g_free (display_name);
8631-
8632- return;
8633- }
8634-
8635- info = get_list_file_info (impl, iter);
8636- sensitive = TRUE;
8637-
8638 if (!info)
8639 {
8640 g_object_set (cell,
8641 "text", _("Type name of new folder"),
8642- "sensitive", TRUE,
8643- "ellipsize", PANGO_ELLIPSIZE_NONE,
8644 NULL);
8645
8646 return;
8647 }
8648
8649
8650- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8651- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8652+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
8653+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8654 {
8655 sensitive = gtk_file_info_get_is_folder (info);
8656 }
8657@@ -10955,7 +4663,6 @@
8658 g_object_set (cell,
8659 "text", gtk_file_info_get_display_name (info),
8660 "sensitive", sensitive,
8661- "ellipsize", PANGO_ELLIPSIZE_END,
8662 NULL);
8663 }
8664
8665@@ -11017,142 +4724,64 @@
8666 gpointer data)
8667 {
8668 GtkFileChooserDefault *impl;
8669- time_t time_mtime;
8670- gchar *date_str = NULL;
8671+ const GtkFileInfo *info;
8672+ GtkFileTime time_mtime;
8673+ GDate mtime, now;
8674+ int days_diff;
8675+ char buf[256];
8676 gboolean sensitive = TRUE;
8677
8678 impl = data;
8679
8680- if (impl->operation_mode == OPERATION_MODE_SEARCH)
8681+ info = get_list_file_info (impl, iter);
8682+ if (!info)
8683 {
8684- GtkTreeIter child_iter;
8685- struct stat *statbuf;
8686- gboolean is_folder;
8687-
8688- search_get_valid_child_iter (impl, &child_iter, iter);
8689- gtk_tree_model_get (GTK_TREE_MODEL (impl->search_model), &child_iter,
8690- SEARCH_MODEL_COL_STAT, &statbuf,
8691- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
8692- -1);
8693- if (statbuf)
8694- time_mtime = statbuf->st_mtime;
8695- else
8696- time_mtime = 0;
8697-
8698-
8699- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8700- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8701- sensitive = is_folder;
8702+ g_object_set (cell,
8703+ "text", "",
8704+ "sensitive", TRUE,
8705+ NULL);
8706+ return;
8707 }
8708- else if (impl->operation_mode == OPERATION_MODE_RECENT)
8709- {
8710- GtkTreeIter child_iter;
8711- GtkRecentInfo *info;
8712- gboolean is_folder;
8713
8714- recent_get_valid_child_iter (impl, &child_iter, iter);
8715- gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &child_iter,
8716- RECENT_MODEL_COL_INFO, &info,
8717- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
8718- -1);
8719+ time_mtime = gtk_file_info_get_modification_time (info);
8720
8721- if (info)
8722- time_mtime = gtk_recent_info_get_modified (info);
8723- else
8724- time_mtime = 0;
8725-
8726- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8727- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8728- sensitive = is_folder;
8729- }
8730+ if (time_mtime == 0)
8731+ strcpy (buf, _("Unknown"));
8732 else
8733 {
8734- const GtkFileInfo *info;
8735-
8736- info = get_list_file_info (impl, iter);
8737- if (!info)
8738- {
8739- g_object_set (cell,
8740- "text", "",
8741- "sensitive", TRUE,
8742- NULL);
8743- return;
8744- }
8745-
8746- time_mtime = (time_t) gtk_file_info_get_modification_time (info);
8747-
8748- if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8749- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8750- sensitive = gtk_file_info_get_is_folder (info);
8751- }
8752-
8753- if (G_UNLIKELY (time_mtime == 0))
8754- date_str = g_strdup (_("Unknown"));
8755- else
8756- {
8757- GDate mtime, now;
8758- gint days_diff;
8759- struct tm tm_mtime;
8760 time_t time_now;
8761- const gchar *format;
8762- gchar *locale_format = NULL;
8763- gchar buf[256];
8764-
8765-#ifdef HAVE_LOCALTIME_R
8766- localtime_r ((time_t *) &time_mtime, &tm_mtime);
8767-#else
8768- {
8769- struct tm *ptm = localtime ((time_t *) &time_mtime);
8770-
8771- if (!ptm)
8772- {
8773- g_warning ("ptm != NULL failed");
8774-
8775- g_object_set (cell,
8776- "text", _("Unknown"),
8777- "sensitive", sensitive,
8778- NULL);
8779- return;
8780- }
8781- else
8782- memcpy ((void *) &tm_mtime, (void *) ptm, sizeof (struct tm));
8783- }
8784-#endif /* HAVE_LOCALTIME_R */
8785-
8786 g_date_set_time_t (&mtime, time_mtime);
8787 time_now = time (NULL);
8788 g_date_set_time_t (&now, time_now);
8789
8790 days_diff = g_date_get_julian (&now) - g_date_get_julian (&mtime);
8791
8792- /* Translators: %H means "hours" and %M means "minutes" */
8793 if (days_diff == 0)
8794- format = _("Today at %H:%M");
8795+ strcpy (buf, _("Today"));
8796 else if (days_diff == 1)
8797- format = _("Yesterday at %H:%M");
8798+ strcpy (buf, _("Yesterday"));
8799 else
8800 {
8801+ char *format;
8802+
8803 if (days_diff > 1 && days_diff < 7)
8804 format = "%A"; /* Days from last week */
8805 else
8806 format = "%x"; /* Any other date */
8807- }
8808
8809- locale_format = g_locale_from_utf8 (format, -1, NULL, NULL, NULL);
8810-
8811- if (strftime (buf, sizeof (buf), locale_format, &tm_mtime) != 0)
8812- date_str = g_locale_to_utf8 (buf, -1, NULL, NULL, NULL);
8813- else
8814- date_str = g_strdup (_("Unknown"));
8815-
8816- g_free (locale_format);
8817+ if (g_date_strftime (buf, sizeof (buf), format, &mtime) == 0)
8818+ strcpy (buf, _("Unknown"));
8819+ }
8820 }
8821
8822+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
8823+ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8824+ sensitive = gtk_file_info_get_is_folder (info);
8825+
8826 g_object_set (cell,
8827- "text", date_str,
8828+ "text", buf,
8829 "sensitive", sensitive,
8830 NULL);
8831- g_free (date_str);
8832 }
8833
8834 GtkWidget *
8835@@ -11163,437 +4792,73 @@
8836 NULL);
8837 }
8838
8839+/* Handler for the "up-folder" keybinding signal */
8840 static void
8841-location_set_user_text (GtkFileChooserDefault *impl,
8842- const gchar *path)
8843+up_folder_handler (GtkFileChooserDefault *impl)
8844 {
8845- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), path);
8846- gtk_editable_set_position (GTK_EDITABLE (impl->location_entry), -1);
8847-}
8848+ GtkFilePath * parent;
8849+ pending_select_paths_add (impl, impl->current_folder);
8850
8851-static void
8852-location_popup_handler (GtkFileChooserDefault *impl,
8853- const gchar *path)
8854-{
8855- if (impl->operation_mode != OPERATION_MODE_BROWSE)
8856- {
8857- GtkWidget *widget_to_focus;
8858-
8859- /* This will give us the location widgets back */
8860- switch (impl->operation_mode)
8861- {
8862- case OPERATION_MODE_SEARCH:
8863- search_switch_to_browse_mode (impl);
8864- break;
8865- case OPERATION_MODE_RECENT:
8866- recent_switch_to_browse_mode (impl);
8867- break;
8868- case OPERATION_MODE_BROWSE:
8869- g_assert_not_reached ();
8870- break;
8871- }
8872+ if (gtk_file_system_get_parent (impl->file_system, impl->current_folder,
8873+ &parent, NULL) && parent)
8874+ {
8875+ impl->path_history = g_slist_prepend (impl->path_history,
8876+ gtk_file_path_copy (impl->current_folder));
8877
8878- if (impl->current_folder)
8879- change_folder_and_display_error (impl, impl->current_folder, FALSE);
8880-
8881- if (impl->location_mode == LOCATION_MODE_PATH_BAR)
8882- widget_to_focus = impl->browse_files_tree_view;
8883- else
8884- widget_to_focus = impl->location_entry;
8885-
8886- gtk_widget_grab_focus (widget_to_focus);
8887- return;
8888- }
8889-
8890- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
8891- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
8892- {
8893- LocationMode new_mode;
8894-
8895- if (path != NULL)
8896- {
8897- /* since the user typed something, we unconditionally want to turn on the entry */
8898- new_mode = LOCATION_MODE_FILENAME_ENTRY;
8899- }
8900- else if (impl->location_mode == LOCATION_MODE_PATH_BAR)
8901- new_mode = LOCATION_MODE_FILENAME_ENTRY;
8902- else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
8903- new_mode = LOCATION_MODE_PATH_BAR;
8904- else
8905- {
8906- g_assert_not_reached ();
8907- return;
8908- }
8909-
8910- location_mode_set (impl, new_mode, TRUE);
8911- if (new_mode == LOCATION_MODE_FILENAME_ENTRY)
8912- {
8913- if (path != NULL)
8914- location_set_user_text (impl, path);
8915- else
8916- {
8917- location_entry_set_initial_text (impl);
8918- gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1);
8919- }
8920- }
8921- }
8922- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
8923- impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
8924- {
8925- gtk_widget_grab_focus (impl->location_entry);
8926- if (path != NULL)
8927- location_set_user_text (impl, path);
8928- }
8929- else
8930- g_assert_not_reached ();
8931+ change_folder_and_display_error (impl, parent);
8932+ gtk_file_path_free (parent);
8933+ }
8934 }
8935
8936-/* Handler for the "up-folder" keybinding signal */
8937-static void
8938-up_folder_handler (GtkFileChooserDefault *impl)
8939-{
8940- _gtk_path_bar_up (GTK_PATH_BAR (impl->browse_path_bar));
8941-}
8942-
8943 /* Handler for the "down-folder" keybinding signal */
8944 static void
8945 down_folder_handler (GtkFileChooserDefault *impl)
8946 {
8947- _gtk_path_bar_down (GTK_PATH_BAR (impl->browse_path_bar));
8948-}
8949+ if (impl->path_history)
8950+ {
8951+ GtkFilePath * path = impl->path_history->data;
8952
8953-/* Switches to the shortcut in the specified index */
8954-static void
8955-switch_to_shortcut (GtkFileChooserDefault *impl,
8956- int pos)
8957-{
8958- GtkTreeIter iter;
8959-
8960- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
8961- g_assert_not_reached ();
8962-
8963- shortcuts_activate_iter (impl, &iter);
8964- focus_browse_tree_view_if_possible (impl);
8965+ change_folder_and_display_error (impl, path);
8966+ impl->path_history = g_slist_remove (impl->path_history, path);
8967+ gtk_file_path_free (path);
8968+ }
8969 }
8970
8971 /* Handler for the "home-folder" keybinding signal */
8972 static void
8973 home_folder_handler (GtkFileChooserDefault *impl)
8974 {
8975- if (impl->has_home)
8976- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_HOME));
8977 }
8978
8979-/* Handler for the "desktop-folder" keybinding signal */
8980 static void
8981-desktop_folder_handler (GtkFileChooserDefault *impl)
8982-{
8983- if (impl->has_desktop)
8984- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_DESKTOP));
8985-}
8986-
8987-/* Handler for the "search-shortcut" keybinding signal */
8988-static void
8989-search_shortcut_handler (GtkFileChooserDefault *impl)
8990-{
8991- if (impl->has_search)
8992- {
8993- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_SEARCH));
8994-
8995- /* we want the entry widget to grab the focus the first
8996- * time, not the browse_files_tree_view widget.
8997- */
8998- if (impl->search_entry)
8999- gtk_widget_grab_focus (impl->search_entry);
9000- }
9001-}
9002-
9003-/* Handler for the "recent-shortcut" keybinding signal */
9004-static void
9005-recent_shortcut_handler (GtkFileChooserDefault *impl)
9006-{
9007- if (impl->has_recent)
9008- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_RECENT));
9009-}
9010-
9011-static void
9012-quick_bookmark_handler (GtkFileChooserDefault *impl,
9013- gint bookmark_index)
9014-{
9015- int bookmark_pos;
9016- GtkTreePath *path;
9017-
9018- if (bookmark_index < 0 || bookmark_index >= impl->num_bookmarks)
9019- return;
9020-
9021- bookmark_pos = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS) + bookmark_index;
9022-
9023- path = gtk_tree_path_new_from_indices (bookmark_pos, -1);
9024- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
9025- path, NULL,
9026- FALSE, 0.0, 0.0);
9027- gtk_tree_path_free (path);
9028-
9029- switch_to_shortcut (impl, bookmark_pos);
9030-}
9031-
9032-static void
9033 show_hidden_handler (GtkFileChooserDefault *impl)
9034 {
9035- g_object_set (impl,
9036- "show-hidden", !impl->show_hidden,
9037- NULL);
9038 }
9039
9040-
9041-/* Drag and drop interfaces */
9042-
9043-static void
9044-_shortcuts_pane_model_filter_class_init (ShortcutsPaneModelFilterClass *class)
9045+static GtkFilePath *
9046+gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser)
9047 {
9048+ return NULL;
9049 }
9050
9051-static void
9052-_shortcuts_pane_model_filter_init (ShortcutsPaneModelFilter *model)
9053-{
9054- model->impl = NULL;
9055-}
9056-
9057-/* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
9058 static gboolean
9059-shortcuts_pane_model_filter_row_draggable (GtkTreeDragSource *drag_source,
9060- GtkTreePath *path)
9061+gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
9062+ const GtkFilePath *path,
9063+ GError **error)
9064 {
9065- ShortcutsPaneModelFilter *model;
9066- int pos;
9067- int bookmarks_pos;
9068-
9069- model = SHORTCUTS_PANE_MODEL_FILTER (drag_source);
9070-
9071- pos = *gtk_tree_path_get_indices (path);
9072- bookmarks_pos = shortcuts_get_index (model->impl, SHORTCUTS_BOOKMARKS);
9073-
9074- return (pos >= bookmarks_pos && pos < bookmarks_pos + model->impl->num_bookmarks);
9075-}
9076-
9077-/* GtkTreeDragSource::drag_data_get implementation for the shortcuts filter model */
9078-static gboolean
9079-shortcuts_pane_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
9080- GtkTreePath *path,
9081- GtkSelectionData *selection_data)
9082-{
9083- ShortcutsPaneModelFilter *model;
9084-
9085- model = SHORTCUTS_PANE_MODEL_FILTER (drag_source);
9086-
9087- /* FIXME */
9088-
9089- return FALSE;
9090-}
9091-
9092-/* Fill the GtkTreeDragSourceIface vtable */
9093-static void
9094-shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface)
9095-{
9096- iface->row_draggable = shortcuts_pane_model_filter_row_draggable;
9097- iface->drag_data_get = shortcuts_pane_model_filter_drag_data_get;
9098-}
9099-
9100-#if 0
9101-/* Fill the GtkTreeDragDestIface vtable */
9102-static void
9103-shortcuts_pane_model_filter_drag_dest_iface_init (GtkTreeDragDestIface *iface)
9104-{
9105- iface->drag_data_received = shortcuts_pane_model_filter_drag_data_received;
9106- iface->row_drop_possible = shortcuts_pane_model_filter_row_drop_possible;
9107-}
9108-#endif
9109-
9110-static GtkTreeModel *
9111-shortcuts_pane_model_filter_new (GtkFileChooserDefault *impl,
9112- GtkTreeModel *child_model,
9113- GtkTreePath *root)
9114-{
9115- ShortcutsPaneModelFilter *model;
9116-
9117- model = g_object_new (SHORTCUTS_PANE_MODEL_FILTER_TYPE,
9118- "child-model", child_model,
9119- "virtual-root", root,
9120- NULL);
9121-
9122- model->impl = impl;
9123-
9124- return GTK_TREE_MODEL (model);
9125-}
9126-
9127-
9128-
9129-static gboolean
9130-recent_model_sort_row_draggable (GtkTreeDragSource *drag_source,
9131- GtkTreePath *path)
9132-{
9133- RecentModelSort *model;
9134- GtkTreeIter iter, child_iter;
9135- gboolean is_folder;
9136-
9137- model = RECENT_MODEL_SORT (drag_source);
9138- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
9139 return FALSE;
9140-
9141- recent_get_valid_child_iter (model->impl, &child_iter, &iter);
9142- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter,
9143- RECENT_MODEL_COL_IS_FOLDER, &is_folder,
9144- -1);
9145-
9146- return is_folder;
9147 }
9148
9149 static gboolean
9150-recent_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
9151- GtkTreePath *path,
9152- GtkSelectionData *selection_data)
9153+gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
9154+ const GtkFilePath *path,
9155+ GError **error)
9156 {
9157- RecentModelSort *model;
9158- GtkTreeIter iter, child_iter;
9159- GtkFilePath *file_path;
9160- gchar **uris;
9161-
9162- model = RECENT_MODEL_SORT (drag_source);
9163- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
9164- return FALSE;
9165-
9166- recent_get_valid_child_iter (model->impl, &child_iter, &iter);
9167- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->recent_model), &child_iter,
9168- RECENT_MODEL_COL_PATH, &file_path,
9169- -1);
9170- g_assert (file_path != NULL);
9171-
9172- uris = g_new (gchar *, 2);
9173- uris[0] = gtk_file_system_path_to_uri (model->impl->file_system, file_path);
9174- uris[1] = NULL;
9175-
9176- gtk_selection_data_set_uris (selection_data, uris);
9177-
9178- g_strfreev (uris);
9179-
9180- return TRUE;
9181+ return TRUE;
9182 }
9183
9184-static void
9185-recent_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface)
9186+static GSList *
9187+gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
9188 {
9189- iface->row_draggable = recent_model_sort_row_draggable;
9190- iface->drag_data_get = recent_model_sort_drag_data_get;
9191+ return NULL;
9192 }
9193-
9194-static void
9195-_recent_model_sort_class_init (RecentModelSortClass *klass)
9196-{
9197-
9198-}
9199-
9200-static void
9201-_recent_model_sort_init (RecentModelSort *model)
9202-{
9203- model->impl = NULL;
9204-}
9205-
9206-static GtkTreeModel *
9207-recent_model_sort_new (GtkFileChooserDefault *impl,
9208- GtkTreeModel *child_model)
9209-{
9210- RecentModelSort *model;
9211-
9212- model = g_object_new (RECENT_MODEL_SORT_TYPE,
9213- "model", child_model,
9214- NULL);
9215- model->impl = impl;
9216-
9217- return GTK_TREE_MODEL (model);
9218-}
9219-
9220-
9221-
9222-static gboolean
9223-search_model_sort_row_draggable (GtkTreeDragSource *drag_source,
9224- GtkTreePath *path)
9225-{
9226- SearchModelSort *model;
9227- GtkTreeIter iter, child_iter;
9228- gboolean is_folder;
9229-
9230- model = SEARCH_MODEL_SORT (drag_source);
9231- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
9232- return FALSE;
9233-
9234- search_get_valid_child_iter (model->impl, &child_iter, &iter);
9235- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter,
9236- SEARCH_MODEL_COL_IS_FOLDER, &is_folder,
9237- -1);
9238-
9239- return is_folder;
9240-}
9241-
9242-static gboolean
9243-search_model_sort_drag_data_get (GtkTreeDragSource *drag_source,
9244- GtkTreePath *path,
9245- GtkSelectionData *selection_data)
9246-{
9247- SearchModelSort *model;
9248- GtkTreeIter iter, child_iter;
9249- GtkFilePath *file_path;
9250- gchar **uris;
9251-
9252- model = SEARCH_MODEL_SORT (drag_source);
9253- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
9254- return FALSE;
9255-
9256- search_get_valid_child_iter (model->impl, &child_iter, &iter);
9257- gtk_tree_model_get (GTK_TREE_MODEL (model->impl->search_model), &child_iter,
9258- RECENT_MODEL_COL_PATH, &file_path,
9259- -1);
9260- g_assert (file_path != NULL);
9261-
9262- uris = g_new (gchar *, 2);
9263- uris[0] = gtk_file_system_path_to_uri (model->impl->file_system, file_path);
9264- uris[1] = NULL;
9265-
9266- gtk_selection_data_set_uris (selection_data, uris);
9267-
9268- g_strfreev (uris);
9269-
9270- return TRUE;
9271-}
9272-
9273-static void
9274-search_model_sort_drag_source_iface_init (GtkTreeDragSourceIface *iface)
9275-{
9276- iface->row_draggable = search_model_sort_row_draggable;
9277- iface->drag_data_get = search_model_sort_drag_data_get;
9278-}
9279-
9280-static void
9281-_search_model_sort_class_init (SearchModelSortClass *klass)
9282-{
9283-
9284-}
9285-
9286-static void
9287-_search_model_sort_init (SearchModelSort *model)
9288-{
9289- model->impl = NULL;
9290-}
9291-
9292-static GtkTreeModel *
9293-search_model_sort_new (GtkFileChooserDefault *impl,
9294- GtkTreeModel *child_model)
9295-{
9296- SearchModelSort *model;
9297-
9298- model = g_object_new (SEARCH_MODEL_SORT_TYPE,
9299- "model", child_model,
9300- NULL);
9301- model->impl = impl;
9302-
9303- return GTK_TREE_MODEL (model);
9304-}
9305Index: gtk+-2.12.5/gtk/gtkfilechooserprivate.h
9306===================================================================
9307--- gtk+-2.12.5/gtk/gtkfilechooserprivate.h (revision 19337)
9308+++ gtk+-2.12.5/gtk/gtkfilechooserprivate.h (working copy)
9309@@ -25,9 +25,6 @@
9310 #include "gtkfilesystem.h"
9311 #include "gtkfilesystemmodel.h"
9312 #include "gtkliststore.h"
9313-#include "gtkrecentmanager.h"
9314-#include "gtksearchengine.h"
9315-#include "gtkquery.h"
9316 #include "gtktooltips.h"
9317 #include "gtktreemodelsort.h"
9318 #include "gtktreestore.h"
9319@@ -146,12 +143,6 @@
9320 LOCATION_MODE_FILENAME_ENTRY
9321 } LocationMode;
9322
9323-typedef enum {
9324- OPERATION_MODE_BROWSE,
9325- OPERATION_MODE_SEARCH,
9326- OPERATION_MODE_RECENT
9327-} OperationMode;
9328-
9329 struct _GtkFileChooserDefault
9330 {
9331 GtkVBox parent_instance;
9332@@ -162,53 +153,19 @@
9333
9334 /* Save mode widgets */
9335 GtkWidget *save_widgets;
9336+ GtkWidget *save_file_name_entry;
9337
9338- GtkWidget *save_folder_label;
9339- GtkWidget *save_folder_combo;
9340- GtkWidget *save_expander;
9341-
9342 /* The file browsing widgets */
9343 GtkWidget *browse_widgets;
9344- GtkWidget *browse_shortcuts_tree_view;
9345- GtkWidget *browse_shortcuts_add_button;
9346- GtkWidget *browse_shortcuts_remove_button;
9347- GtkWidget *browse_shortcuts_popup_menu;
9348- GtkWidget *browse_shortcuts_popup_menu_remove_item;
9349- GtkWidget *browse_shortcuts_popup_menu_rename_item;
9350 GtkWidget *browse_files_tree_view;
9351- GtkWidget *browse_files_popup_menu;
9352- GtkWidget *browse_files_popup_menu_add_shortcut_item;
9353- GtkWidget *browse_files_popup_menu_hidden_files_item;
9354 GtkWidget *browse_new_folder_button;
9355- GtkWidget *browse_path_bar_hbox;
9356- GtkWidget *browse_path_bar;
9357+ GtkWidget *bar;
9358+ GtkWidget *up_button;
9359
9360 GtkFileSystemModel *browse_files_model;
9361- char *browse_files_last_selected_name;
9362+ char *browse_files_last_selected_name; /* ??? */
9363
9364- /* OPERATION_MODE_SEARCH */
9365- GtkWidget *search_hbox;
9366- GtkWidget *search_entry;
9367- GtkSearchEngine *search_engine;
9368- GtkQuery *search_query;
9369- GtkListStore *search_model;
9370- GtkTreeModelFilter *search_model_filter;
9371- GtkTreeModelSort *search_model_sort;
9372-
9373- /* OPERATION_MODE_RECENT */
9374- GtkRecentManager *recent_manager;
9375- GtkListStore *recent_model;
9376- guint load_recent_id;
9377- GtkTreeModelFilter *recent_model_filter;
9378- GtkTreeModelSort *recent_model_sort;
9379-
9380- GtkWidget *filter_combo_hbox;
9381 GtkWidget *filter_combo;
9382- GtkWidget *preview_box;
9383- GtkWidget *preview_label;
9384- GtkWidget *preview_widget;
9385- GtkWidget *extra_align;
9386- GtkWidget *extra_widget;
9387
9388 GtkWidget *location_button;
9389 GtkWidget *location_entry_box;
9390@@ -217,23 +174,13 @@
9391 LocationMode location_mode;
9392
9393 GtkListStore *shortcuts_model;
9394+ GtkTreeModel *shortcuts_filter_model;
9395
9396- /* Filter for the shortcuts pane. We filter out the "current folder" row and
9397- * the separator that we use for the "Save in folder" combo.
9398- */
9399- GtkTreeModel *shortcuts_pane_filter_model;
9400-
9401- /* Filter for the "Save in folder" combo. We filter out the Search row and
9402- * its separator.
9403- */
9404- GtkTreeModel *shortcuts_combo_filter_model;
9405-
9406 GtkTreeModelSort *sort_model;
9407
9408 /* Handles */
9409 GSList *loading_shortcuts;
9410 GSList *reload_icon_handles;
9411- GtkFileSystemHandle *file_list_drag_data_received_handle;
9412 GtkFileSystemHandle *update_current_folder_handle;
9413 GtkFileSystemHandle *show_and_select_paths_handle;
9414 GtkFileSystemHandle *should_respond_get_info_handle;
9415@@ -246,9 +193,8 @@
9416 ReloadState reload_state;
9417 guint load_timeout_id;
9418
9419- OperationMode operation_mode;
9420-
9421 GSList *pending_select_paths;
9422+ GSList *path_history;
9423
9424 GtkFileFilter *current_filter;
9425 GSList *filters;
9426@@ -256,20 +202,16 @@
9427 GtkTooltips *tooltips;
9428
9429 int num_volumes;
9430- int num_shortcuts;
9431- int num_bookmarks;
9432
9433 gulong volumes_changed_id;
9434- gulong bookmarks_changed_id;
9435
9436 GtkFilePath *current_volume_path;
9437 GtkFilePath *current_folder;
9438- GtkFilePath *preview_path;
9439- char *preview_display_name;
9440
9441 GtkTreeViewColumn *list_name_column;
9442 GtkCellRenderer *list_name_renderer;
9443- GtkTreeViewColumn *list_mtime_column;
9444+ guint32 list_press_time;
9445+ GtkTreePath *list_press_path;
9446
9447 GSource *edited_idle;
9448 char *edited_new_text;
9449@@ -280,10 +222,7 @@
9450 gulong toplevel_set_focus_id;
9451 GtkWidget *toplevel_last_focus_widget;
9452
9453-#if 0
9454- GdkDragContext *shortcuts_drag_context;
9455- GSource *shortcuts_drag_outside_idle;
9456-#endif
9457+ gchar * root_folder;
9458
9459 gint default_width;
9460 gint default_height;
9461@@ -291,23 +230,13 @@
9462 /* Flags */
9463
9464 guint local_only : 1;
9465- guint preview_widget_active : 1;
9466- guint use_preview_label : 1;
9467 guint select_multiple : 1;
9468 guint show_hidden : 1;
9469+ guint show_create_folder : 1;
9470 guint do_overwrite_confirmation : 1;
9471 guint list_sort_ascending : 1;
9472 guint changing_folder : 1;
9473- guint shortcuts_current_folder_active : 1;
9474 guint expand_folders : 1;
9475- guint has_home : 1;
9476- guint has_desktop : 1;
9477- guint has_search : 1;
9478- guint has_recent : 1;
9479-
9480-#if 0
9481- guint shortcuts_drag_outside : 1;
9482-#endif
9483 };
9484
9485
9486Index: gtk+-2.12.5/tests/autotestfilechooser.c
9487===================================================================
9488--- gtk+-2.12.5/tests/autotestfilechooser.c (revision 19337)
9489+++ gtk+-2.12.5/tests/autotestfilechooser.c (working copy)
9490@@ -510,9 +510,6 @@
9491 && (impl->location_mode == LOCATION_MODE_PATH_BAR
9492 ? impl->location_entry == NULL
9493 : impl->location_entry != NULL)
9494- && impl->save_folder_label == NULL
9495- && impl->save_folder_combo == NULL
9496- && impl->save_expander == NULL
9497 && GTK_IS_CONTAINER (impl->browse_widgets) && GTK_WIDGET_DRAWABLE (impl->browse_widgets));
9498 }
9499 else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action))
9500@@ -523,9 +520,6 @@
9501 */
9502 passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && GTK_WIDGET_DRAWABLE (impl->save_widgets)
9503 && impl->location_entry != NULL && GTK_WIDGET_DRAWABLE (impl->location_entry)
9504- && GTK_IS_LABEL (impl->save_folder_label) && GTK_WIDGET_DRAWABLE (impl->save_folder_label)
9505- && GTK_IS_COMBO_BOX (impl->save_folder_combo) && GTK_WIDGET_DRAWABLE (impl->save_folder_combo)
9506- && GTK_IS_EXPANDER (impl->save_expander) && GTK_WIDGET_DRAWABLE (impl->save_expander)
9507 && GTK_IS_CONTAINER (impl->browse_widgets));
9508
9509 /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of
9510@@ -1026,11 +1020,6 @@
9511 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
9512 sleep_in_main_loop (500);
9513
9514- g_signal_emit_by_name (impl->browse_path_bar, "path-clicked",
9515- (GtkFilePath *) cwd_path,
9516- (GtkFilePath *) base_dir_path,
9517- FALSE);
9518- sleep_in_main_loop (500);
9519 passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
9520
9521 log_test (passed, "test_folder_switch_and_filters(): filter after changing folder");
diff --git a/meta/packages/gtk+/gtk+-2.13.2/filechooser-props.patch b/meta/packages/gtk+/gtk+-2.13.2/filechooser-props.patch
new file mode 100644
index 0000000000..7d55f3cbb9
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/filechooser-props.patch
@@ -0,0 +1,57 @@
1Index: gtk+-2.12.3/gtk/gtkfilechooser.c
2===================================================================
3--- gtk+-2.12.3.orig/gtk/gtkfilechooser.c 2007-12-04 16:52:08.000000000 +0000
4+++ gtk+-2.12.3/gtk/gtkfilechooser.c 2008-01-02 13:15:38.000000000 +0000
5@@ -272,6 +272,20 @@
6 "if necessary."),
7 FALSE,
8 GTK_PARAM_READWRITE));
9+
10+ g_object_interface_install_property (g_iface,
11+ g_param_spec_string ("root-folder",
12+ P_("File System Root"),
13+ P_("Root folder for the file system below which the user should not be able to switch"),
14+ NULL,
15+ G_PARAM_WRITABLE));
16+
17+ g_object_interface_install_property (g_iface,
18+ g_param_spec_boolean ("show-create-folder",
19+ P_("Show Create Folder button"),
20+ P_("Whether the Create Folder button should be visible on the bar"),
21+ TRUE,
22+ G_PARAM_READWRITE));
23 }
24
25 /**
26Index: gtk+-2.12.3/gtk/gtkfilechooserutils.h
27===================================================================
28--- gtk+-2.12.3.orig/gtk/gtkfilechooserutils.h 2007-12-04 16:52:08.000000000 +0000
29+++ gtk+-2.12.3/gtk/gtkfilechooserutils.h 2008-01-02 13:15:17.000000000 +0000
30@@ -41,7 +41,9 @@
31 GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
32 GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN,
33 GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION,
34- GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION
35+ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
36+ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER,
37+ GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER
38 } GtkFileChooserProp;
39
40 void _gtk_file_chooser_install_properties (GObjectClass *klass);
41Index: gtk+-2.12.3/gtk/gtkfilechooserutils.c
42===================================================================
43--- gtk+-2.12.3.orig/gtk/gtkfilechooserutils.c 2007-12-04 16:52:08.000000000 +0000
44+++ gtk+-2.12.3/gtk/gtkfilechooserutils.c 2008-01-02 13:15:17.000000000 +0000
45@@ -117,6 +117,12 @@
46 g_object_class_override_property (klass,
47 GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION,
48 "do-overwrite-confirmation");
49+ g_object_class_override_property (klass,
50+ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
51+ "root-folder");
52+ g_object_class_override_property (klass,
53+ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER,
54+ "show-create-folder");
55 }
56
57 /**
diff --git a/meta/packages/gtk+/gtk+-2.13.2/filechooser-sizefix.patch b/meta/packages/gtk+/gtk+-2.13.2/filechooser-sizefix.patch
new file mode 100644
index 0000000000..694b059b9a
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/filechooser-sizefix.patch
@@ -0,0 +1,35 @@
1--- gtk+-2.12.7.orig/gtk/gtkfilechooserdialog.c
2+++ gtk+-2.12.7/gtk/gtkfilechooserdialog.c
3@@ -165,10 +165,10 @@
4 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
5
6 if (width)
7- *width = MIN (*width, (monitor.width * 3) / 4);
8+ *width = MIN (*width, monitor.width);
9
10 if (height)
11- *height = MIN (*height, (monitor.height * 3) / 4);
12+ *height = MIN (*height, monitor.height);
13 }
14
15 static void
16@@ -183,6 +183,7 @@
17
18 priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
19
20+#if 0
21 /* Unset any previously set size */
22 gtk_widget_set_size_request (GTK_WIDGET (dialog), -1, -1);
23
24@@ -209,6 +210,11 @@
25 /* Ideal target size plus any extra size */
26 width = default_width + width + (2 * GTK_CONTAINER (dialog)->border_width);
27 height = default_height + height + (2 * GTK_CONTAINER (dialog)->border_width);
28+#endif
29+
30+ /* for small screens we just hard code a sensible value */
31+ width = 350;
32+ height = 350;
33
34 if (GTK_WIDGET_REALIZED (dialog))
35 clamp_to_screen (GTK_WIDGET (dialog), &width, &height);
diff --git a/meta/packages/gtk+/gtk+-2.13.2/filesystem-volumes.patch b/meta/packages/gtk+/gtk+-2.13.2/filesystem-volumes.patch
new file mode 100644
index 0000000000..826fd6bee0
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/filesystem-volumes.patch
@@ -0,0 +1,198 @@
1Index: gtk+-2.12.3/gtk/gtkfilesystemunix.c
2===================================================================
3--- gtk+-2.12.3.orig/gtk/gtkfilesystemunix.c 2007-12-04 16:52:08.000000000 +0000
4+++ gtk+-2.12.3/gtk/gtkfilesystemunix.c 2008-01-02 13:15:02.000000000 +0000
5@@ -38,6 +38,7 @@
6 #include <errno.h>
7 #include <string.h>
8 #include <sys/stat.h>
9+#include <sys/statvfs.h>
10 #include <sys/types.h>
11 #include <pwd.h>
12 #ifdef HAVE_UNISTD_H
13@@ -474,7 +475,55 @@
14 static GSList *
15 gtk_file_system_unix_list_volumes (GtkFileSystem *file_system)
16 {
17- return g_slist_append (NULL, get_root_volume ());
18+ struct statvfs stv;
19+ struct stat st;
20+ GSList * l = g_slist_append (NULL, get_root_volume ());
21+
22+ if (!statvfs ("/.", &stv))
23+ {
24+ fsblkcnt_t root_blocks = stv.f_blocks;
25+ fsfilcnt_t root_files = stv.f_files;
26+
27+ GDir * dir;
28+ if ((dir = g_dir_open ("/media", 0, NULL)) != NULL)
29+ {
30+ const gchar * name;
31+ while ((name = g_dir_read_name (dir)) != NULL)
32+ {
33+ gchar * abs_name;
34+
35+ /* Skip ram disks */
36+ if (!strcmp (name, "ram"))
37+ continue;
38+
39+ abs_name = g_strconcat ("/media/", name, NULL);
40+
41+ if (!stat (abs_name, &st) && S_ISDIR (st.st_mode))
42+ {
43+ gchar * dot = g_strconcat (abs_name, "/.", NULL);
44+ if (!statvfs (dot, &stv) &&
45+ (stv.f_blocks != root_blocks ||
46+ stv.f_files != root_files))
47+ {
48+ GtkFilePath * path =
49+ gtk_file_system_filename_to_path (file_system,
50+ abs_name);
51+
52+ if (path)
53+ l = g_slist_append (l, path);
54+ }
55+
56+ g_free (dot);
57+ }
58+
59+ g_free (abs_name);
60+ }
61+
62+ g_dir_close (dir);
63+ }
64+ }
65+
66+ return l;
67 }
68
69 static GtkFileSystemVolume *
70@@ -488,13 +537,18 @@
71 remove_trailing_slash (const char *filename)
72 {
73 int len;
74-
75+
76 len = strlen (filename);
77
78- if (len > 1 && filename[len - 1] == '/')
79- return g_strndup (filename, len - 1);
80- else
81- return g_memdup (filename, len + 1);
82+ if (len > 1)
83+ {
84+ gchar *c = g_utf8_prev_char (filename + len);
85+
86+ if (c && *c == '/')
87+ return g_strndup (filename, len - 1);
88+ }
89+
90+ return g_memdup (filename, len + 1);
91 }
92
93 /* Delay callback dispatching
94@@ -1128,7 +1182,7 @@
95 gtk_file_system_unix_volume_get_base_path (GtkFileSystem *file_system,
96 GtkFileSystemVolume *volume)
97 {
98- return gtk_file_path_new_dup ("/");
99+ return gtk_file_path_copy ((GtkFilePath*)volume);
100 }
101
102 static gboolean
103@@ -1162,7 +1216,32 @@
104 gtk_file_system_unix_volume_get_display_name (GtkFileSystem *file_system,
105 GtkFileSystemVolume *volume)
106 {
107- return g_strdup (_("File System")); /* Same as Nautilus */
108+ gchar * slash;
109+ gchar * path;
110+ gchar * c;
111+
112+ g_return_val_if_fail (file_system && volume, NULL);
113+
114+ path = gtk_file_system_path_to_filename (file_system, (GtkFilePath*) volume);
115+
116+ g_return_val_if_fail (path && *path, NULL);
117+
118+ if (path[0] == '/' && !path[1])
119+ return g_strdup (_("Filesystem")); /* Same as Nautilus */
120+
121+ /* Now the media volumes */
122+ /* strip trailing / if any */
123+ c = g_utf8_prev_char (path + strlen(path));
124+
125+ if (*c == '/')
126+ *c = 0;
127+
128+ slash = g_utf8_strrchr (path, -1, '/');
129+
130+ if (!slash)
131+ return g_strdup (path);
132+
133+ return g_strdup (slash + 1);
134 }
135
136 static IconType
137@@ -1250,10 +1329,57 @@
138 GtkFileSystemVolume *volume,
139 GError **error)
140 {
141- /* FIXME: maybe we just always want to return GTK_STOCK_HARDDISK here?
142- * or the new tango icon name?
143- */
144- return g_strdup ("gnome-dev-harddisk");
145+ gchar * c;
146+ gchar * slash;
147+ gchar * path = NULL;
148+ GtkFilePath * fpath;
149+ const gchar * id = NULL;
150+
151+ g_return_val_if_fail (file_system && volume, NULL);
152+
153+ fpath = gtk_file_system_volume_get_base_path (file_system, volume);
154+
155+ if (!fpath)
156+ goto out;
157+
158+ path = gtk_file_system_path_to_filename (file_system, fpath);
159+ gtk_file_path_free (fpath);
160+
161+ if (!path || !*path || (*path == '/' && !path[1]))
162+ goto out;
163+
164+ /* Now the media volumes */
165+ /* strip trailing / if any */
166+ c = g_utf8_prev_char (path + strlen(path));
167+
168+ if (*c == '/')
169+ *c = 0;
170+
171+ slash = g_utf8_strrchr (path, -1, '/');
172+
173+ if (slash)
174+ {
175+ slash++;
176+
177+ if (!strcmp (slash, "card"))
178+ id = "gnome-dev-media-sdmmc";
179+ else if (!strcmp (slash, "cf"))
180+ id = "gnome-dev-media-cf";
181+ else if (!strncmp (slash, "mmc", 3))
182+ id = "gnome-dev-media-sdmmc";
183+ else if (!strcmp (slash, "usbhdd"))
184+ id = "gnome-dev-removable-usb";
185+ else
186+ id = "gnome-dev-removable";
187+ }
188+
189+ out:
190+ g_free (path);
191+
192+ if (!id)
193+ id = "gnome-fs-blockdev";
194+
195+ return g_strdup (id);
196 }
197
198 static char *
diff --git a/meta/packages/gtk+/gtk+-2.13.2/gtklabel-resize-patch b/meta/packages/gtk+/gtk+-2.13.2/gtklabel-resize-patch
new file mode 100644
index 0000000000..df29656343
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/gtklabel-resize-patch
@@ -0,0 +1,10 @@
1--- gtk+-2.4.3/gtk/gtklabel.c~ 2004-06-11 13:50:34.000000000 +0100
2+++ gtk+-2.4.3/gtk/gtklabel.c 2004-07-05 13:33:57.000000000 +0100
3@@ -1623,6 +1623,7 @@
4
5 /* We have to clear the layout, fonts etc. may have changed */
6 gtk_label_clear_layout (label);
7+ gtk_widget_queue_resize (GTK_WIDGET (label));
8 }
9
10 static void
diff --git a/meta/packages/gtk+/gtk+-2.13.2/hardcoded_libtool.patch b/meta/packages/gtk+/gtk+-2.13.2/hardcoded_libtool.patch
new file mode 100644
index 0000000000..1c2cd0576d
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/hardcoded_libtool.patch
@@ -0,0 +1,29 @@
1--- /tmp/configure.in 2007-01-08 17:50:49.000000000 +0100
2+++ gtk+-2.10.7/configure.in 2007-01-08 17:52:33.495251000 +0100
3@@ -371,7 +371,7 @@
4 case $enable_explicit_deps in
5 auto)
6 export SED
7- deplibs_check_method=`(./libtool --config; echo 'eval echo $deplibs_check_method') | sh`
8+ deplibs_check_method=`($host_alias-libtool --config; echo 'eval echo $deplibs_check_method') | sh`
9 if test "x$deplibs_check_method" '!=' xpass_all || test "x$enable_static" = xyes ; then
10 enable_explicit_deps=yes
11 else
12@@ -773,7 +773,7 @@
13 dnl Now we check to see if our libtool supports shared lib deps
14 dnl (in a rather ugly way even)
15 if $dynworks; then
16- pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} ./libtool --config"
17+ pixbuf_libtool_config="${CONFIG_SHELL-/bin/sh} $host_alias-libtool --config"
18 pixbuf_deplibs_check=`$pixbuf_libtool_config | \
19 grep '^[[a-z_]]*check[[a-z_]]*_method=[['\''"]]' | \
20 sed 's/.*[['\''"]]\(.*\)[['\''"]]$/\1/'`
21@@ -1611,7 +1611,7 @@
22 # We are using gmodule-no-export now, but I'm leaving the stripping
23 # code in place for now, since pango and atk still require gmodule.
24 export SED
25-export_dynamic=`(./libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh`
26+export_dynamic=`($host_alias-libtool --config; echo eval echo \\$export_dynamic_flag_spec) | sh`
27 if test -n "$export_dynamic"; then
28 GDK_PIXBUF_DEP_LIBS=`echo $GDK_PIXBUF_DEP_LIBS | sed -e "s/$export_dynamic//"`
29 GDK_PIXBUF_XLIB_DEP_LIBS=`echo $GDK_PIXBUF_XLIB_DEP_LIBS | sed -e "s/$export_dynamic//"`
diff --git a/meta/packages/gtk+/gtk+-2.13.2/menu-deactivate.patch b/meta/packages/gtk+/gtk+-2.13.2/menu-deactivate.patch
new file mode 100644
index 0000000000..cfb8849e9f
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/menu-deactivate.patch
@@ -0,0 +1,51 @@
1--- gtk+-2.10.0/gtk/gtkmenushell.c.orig 2006-07-05 17:17:34.000000000 +0200
2+++ gtk+-2.10.0/gtk/gtkmenushell.c 2006-07-05 17:19:01.000000000 +0200
3@@ -42,7 +42,7 @@
4 #include "gtkintl.h"
5 #include "gtkalias.h"
6
7-#define MENU_SHELL_TIMEOUT 500
8+#define MENU_SHELL_TIMEOUT 2000
9
10 #define PACK_DIRECTION(m) \
11 (GTK_IS_MENU_BAR (m) \
12@@ -203,6 +203,8 @@
13
14 G_DEFINE_TYPE (GtkMenuShell, gtk_menu_shell, GTK_TYPE_CONTAINER)
15
16+static int last_crossing_time;
17+
18 static void
19 gtk_menu_shell_class_init (GtkMenuShellClass *klass)
20 {
21@@ -517,6 +519,7 @@
22 gtk_grab_add (GTK_WIDGET (menu_shell));
23 menu_shell->have_grab = TRUE;
24 menu_shell->active = TRUE;
25+ last_crossing_time = 0;
26 }
27 }
28
29@@ -669,6 +672,13 @@
30 menu_shell->activate_time = 0;
31 deactivate = FALSE;
32 }
33+
34+ if (last_crossing_time != 0
35+ && ((event->time - last_crossing_time) < 500))
36+ {
37+ last_crossing_time = 0;
38+ deactivate = FALSE;
39+ }
40
41 if (deactivate)
42 {
43@@ -716,6 +726,8 @@
44 {
45 menu_item = gtk_get_event_widget ((GdkEvent*) event);
46
47+ last_crossing_time = event->time;
48+
49 if (!menu_item ||
50 (GTK_IS_MENU_ITEM (menu_item) &&
51 !_gtk_menu_item_is_selectable (menu_item)))
diff --git a/meta/packages/gtk+/gtk+-2.13.2/no-demos.patch b/meta/packages/gtk+/gtk+-2.13.2/no-demos.patch
new file mode 100644
index 0000000000..0fc4c48d1a
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/no-demos.patch
@@ -0,0 +1,10 @@
1--- gtk+-2.10.1/Makefile.am.orig 2006-08-08 12:37:30.000000000 +0100
2+++ gtk+-2.10.1/Makefile.am 2006-08-08 12:37:48.000000000 +0100
3@@ -1,6 +1,6 @@
4 ## Makefile.am for GTK+
5
6-SRC_SUBDIRS = gdk-pixbuf gdk gtk modules demos tests perf contrib
7+SRC_SUBDIRS = gdk-pixbuf gdk gtk modules tests perf contrib
8 SUBDIRS = po po-properties $(SRC_SUBDIRS) docs m4macros
9
10 # require automake 1.4
diff --git a/meta/packages/gtk+/gtk+-2.13.2/pangoxft2.10.6.diff b/meta/packages/gtk+/gtk+-2.13.2/pangoxft2.10.6.diff
new file mode 100644
index 0000000000..63828cec63
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/pangoxft2.10.6.diff
@@ -0,0 +1,2456 @@
1http://mail.gnome.org/archives/performance-list/2006-October/msg00063.html
2
3From: Xan Lópe
4To: ext Matt Hoosier
5Cc: performance-list gnome org
6Subject: Re: [patch] Remove pangocairo from Gtk+ 2.8.20
7Date: Mon, 30 Oct 2006 14:31:56 +0200
8Hi,
9
10I've upgraded your patch against GTK+ 2.10.6, and we are getting great
11performance figures compared to GTK+ 2.10.6 with pangocairo too
12(basically at the level of GTK+ 2.6.10 again). Right now I'm working on
13a python/cairo script to get some nice graphics from a torture test
14session with several GTK+s, hope to get it ready soon.
15
16Index: gtk+-2.10.6/configure.in
17===================================================================
18--- gtk+-2.10.6.orig/configure.in 2006-10-30 12:59:28.000000000 +0000
19+++ gtk+-2.10.6/configure.in 2006-10-30 12:59:30.000000000 +0000
20@@ -1435,7 +1435,7 @@
21 if test "x$gdktarget" = "xwin32"; then
22 PANGO_PACKAGES="pangowin32 pangocairo"
23 else
24- PANGO_PACKAGES="pango pangocairo"
25+ PANGO_PACKAGES="pango pangocairo pangoxft"
26 fi
27
28 AC_MSG_CHECKING(Pango flags)
29Index: gtk+-2.10.6/gdk/gdkaliasdef.c
30===================================================================
31--- gtk+-2.10.6.orig/gdk/gdkaliasdef.c 2006-10-30 12:58:29.000000000 +0000
32+++ gtk+-2.10.6/gdk/gdkaliasdef.c 2006-10-30 12:59:30.000000000 +0000
33@@ -1799,9 +1799,6 @@
34 #undef gdk_pango_context_get
35 extern __typeof (gdk_pango_context_get) gdk_pango_context_get __attribute((alias("IA__gdk_pango_context_get"), visibility("default")));
36
37-#undef gdk_pango_context_get_for_screen
38-extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default")));
39-
40 #ifndef GDK_DISABLE_DEPRECATED
41 #undef gdk_pango_context_set_colormap
42 extern __typeof (gdk_pango_context_set_colormap) gdk_pango_context_set_colormap __attribute((alias("IA__gdk_pango_context_set_colormap"), visibility("default")));
43@@ -1836,6 +1833,13 @@
44
45 #endif
46 #endif
47+#if IN_HEADER(__GDK_PANGO_H__)
48+#if IN_FILE(__GDK_PANGO_X11_C__)
49+#undef gdk_pango_context_get_for_screen
50+extern __typeof (gdk_pango_context_get_for_screen) gdk_pango_context_get_for_screen __attribute((alias("IA__gdk_pango_context_get_for_screen"), visibility("default")));
51+
52+#endif
53+#endif
54 #if IN_HEADER(__GDK_PIXBUF_H__)
55 #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__)
56 #undef gdk_pixbuf_get_from_drawable
57Index: gtk+-2.10.6/gdk/gdkalias.h
58===================================================================
59--- gtk+-2.10.6.orig/gdk/gdkalias.h 2006-10-30 12:58:29.000000000 +0000
60+++ gtk+-2.10.6/gdk/gdkalias.h 2006-10-30 12:59:30.000000000 +0000
61@@ -1796,9 +1796,6 @@
62 extern __typeof (gdk_pango_context_get) IA__gdk_pango_context_get __attribute((visibility("hidden")));
63 #define gdk_pango_context_get IA__gdk_pango_context_get
64
65-extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden")));
66-#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen
67-
68 #ifndef GDK_DISABLE_DEPRECATED
69 extern __typeof (gdk_pango_context_set_colormap) IA__gdk_pango_context_set_colormap __attribute((visibility("hidden")));
70 #define gdk_pango_context_set_colormap IA__gdk_pango_context_set_colormap
71@@ -1833,6 +1830,13 @@
72
73 #endif
74 #endif
75+#if IN_HEADER(__GDK_PANGO_H__)
76+#if IN_FILE(__GDK_PANGO_X11_C__)
77+extern __typeof (gdk_pango_context_get_for_screen) IA__gdk_pango_context_get_for_screen __attribute((visibility("hidden")));
78+#define gdk_pango_context_get_for_screen IA__gdk_pango_context_get_for_screen
79+
80+#endif
81+#endif
82 #if IN_HEADER(__GDK_PIXBUF_H__)
83 #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__)
84 extern __typeof (gdk_pixbuf_get_from_drawable) IA__gdk_pixbuf_get_from_drawable __attribute((visibility("hidden")));
85Index: gtk+-2.10.6/gdk/gdkdraw.c
86===================================================================
87--- gtk+-2.10.6.orig/gdk/gdkdraw.c 2006-10-30 12:58:29.000000000 +0000
88+++ gtk+-2.10.6/gdk/gdkdraw.c 2006-10-30 12:59:30.000000000 +0000
89@@ -909,9 +909,9 @@
90 {
91 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
92 g_return_if_fail (GDK_IS_GC (gc));
93-
94- real_draw_glyphs (drawable, gc, NULL, font,
95- x, y, glyphs);
96+
97+
98+ GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs);
99 }
100
101 /**
102@@ -949,8 +949,9 @@
103 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
104 g_return_if_fail (GDK_IS_GC (gc));
105
106- real_draw_glyphs (drawable, gc, matrix, font,
107- x / PANGO_SCALE, y / PANGO_SCALE, glyphs);
108+ if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed)
109+ GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed (drawable, gc, matrix,
110+ font, x, y, glyphs);
111 }
112
113 /**
114@@ -974,28 +975,12 @@
115 GdkTrapezoid *trapezoids,
116 gint n_trapezoids)
117 {
118- cairo_t *cr;
119- int i;
120-
121 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
122 g_return_if_fail (GDK_IS_GC (gc));
123 g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
124
125- cr = gdk_cairo_create (drawable);
126- _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
127-
128- for (i = 0; i < n_trapezoids; i++)
129- {
130- cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1);
131- cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1);
132- cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2);
133- cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y2);
134- cairo_close_path (cr);
135- }
136-
137- cairo_fill (cr);
138-
139- cairo_destroy (cr);
140+ GDK_DRAWABLE_GET_CLASS (drawable)->draw_trapezoids (drawable, gc,
141+ trapezoids, n_trapezoids);
142 }
143
144 /**
145Index: gtk+-2.10.6/gdk/gdkpango.c
146===================================================================
147--- gtk+-2.10.6.orig/gdk/gdkpango.c 2006-10-30 12:58:29.000000000 +0000
148+++ gtk+-2.10.6/gdk/gdkpango.c 2006-10-30 12:59:30.000000000 +0000
149@@ -50,19 +50,34 @@
150 GdkBitmap *stipple[MAX_RENDER_PART + 1];
151 gboolean embossed;
152
153- cairo_t *cr;
154- PangoRenderPart last_part;
155+ /* When switching between the normal and shadow copies when
156+ * drawing shadows we can get unexpected recursion into the
157+ * drawing functions; the 'in_emboss' flag guards against that.
158+ */
159+ gboolean in_emboss;
160
161 /* Current target */
162 GdkDrawable *drawable;
163 GdkGC *base_gc;
164
165 gboolean gc_changed;
166+
167+ /* Cached GC, derived from base_gc */
168+ GdkGC *gc;
169+ PangoColor gc_color;
170+ gboolean gc_color_set;
171+ GdkBitmap *gc_stipple;
172+
173+ /* we accumulate trapezoids for the same PangoRenderPart */
174+ GArray *trapezoids;
175+ PangoRenderPart trapezoid_part;
176 };
177
178 static PangoAttrType gdk_pango_attr_stipple_type;
179 static PangoAttrType gdk_pango_attr_embossed_type;
180
181+static void flush_trapezoids (GdkPangoRenderer *gdk_renderer);
182+
183 enum {
184 PROP_0,
185 PROP_SCREEN
186@@ -77,6 +92,10 @@
187 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
188 int i;
189
190+ if (priv->gc)
191+ g_object_unref (priv->gc);
192+ if (priv->gc_stipple)
193+ g_object_unref (priv->gc_stipple);
194 if (priv->base_gc)
195 g_object_unref (priv->base_gc);
196 if (priv->drawable)
197@@ -86,6 +105,8 @@
198 if (priv->stipple[i])
199 g_object_unref (priv->stipple[i]);
200
201+ g_array_free (priv->trapezoids, TRUE);
202+
203 G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object);
204 }
205
206@@ -112,25 +133,6 @@
207 return object;
208 }
209
210-/* Adjusts matrix and color for the renderer to draw the secondary
211- * "shadow" copy for embossed text */
212-static void
213-emboss_context (cairo_t *cr)
214-{
215- cairo_matrix_t tmp_matrix;
216-
217- /* The gymnastics here to adjust the matrix are because we want
218- * to offset by +1,+1 in device-space, not in user-space,
219- * so we can't just draw the layout at x + 1, y + 1
220- */
221- cairo_get_matrix (cr, &tmp_matrix);
222- tmp_matrix.x0 += 1.0;
223- tmp_matrix.y0 += 1.0;
224- cairo_set_matrix (cr, &tmp_matrix);
225-
226- cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
227-}
228-
229 static inline gboolean
230 color_equal (PangoColor *c1, PangoColor *c2)
231 {
232@@ -146,74 +148,154 @@
233 return FALSE;
234 }
235
236-static cairo_t *
237-get_cairo_context (GdkPangoRenderer *gdk_renderer,
238- PangoRenderPart part)
239+/* Adjusts matrix and color for the renderer to draw the secondar
240+ * "shadow" copy for embossed text */
241+static void
242+emboss_renderer (PangoRenderer *renderer,
243+ PangoRenderPart part,
244+ PangoMatrix **save_matrix,
245+ PangoColor **save_color)
246+{
247+ GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv;
248+ static const PangoColor white = { 0xffff, 0xffff, 0xffff };
249+ PangoMatrix tmp_matrix = PANGO_MATRIX_INIT;
250+
251+ priv->in_emboss = TRUE;
252+
253+ *save_color = pango_renderer_get_color (renderer, part);
254+ if (*save_color)
255+ *save_color = pango_color_copy (*save_color);
256+
257+ *save_matrix = renderer->matrix;
258+ if (*save_matrix)
259+ {
260+ *save_matrix = pango_matrix_copy (*save_matrix);
261+ tmp_matrix = **save_matrix;
262+ }
263+
264+ /* The gymnastics here to adjust the matrix are because we want
265+ * to offset by +1,+1 in device-space, not in user-space,
266+ * so we can't just draw the layout at x + 1, y + 1
267+ */
268+ tmp_matrix.x0 += 1;
269+ tmp_matrix.y0 += 1;
270+
271+ pango_renderer_set_matrix (renderer, &tmp_matrix);
272+ pango_renderer_set_color (renderer, part, &white);
273+}
274+
275+/* Restores from emboss_renderer() */
276+static void
277+unemboss_renderer (PangoRenderer *renderer,
278+ PangoRenderPart part,
279+ PangoMatrix **save_matrix,
280+ PangoColor **save_color)
281+{
282+ GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv;
283+ pango_renderer_set_matrix (renderer, *save_matrix);
284+ pango_renderer_set_color (renderer, part, *save_color);
285+
286+ if (*save_matrix)
287+ pango_matrix_free (*save_matrix);
288+ if (*save_color)
289+ pango_color_free (*save_color);
290+
291+ priv->in_emboss = FALSE;
292+}
293+
294+/* Gets the GC for drawing @part. This make involve copying the base GC
295+ * for the renderer, in which case we keep a one-GC cache. */
296+static GdkGC *
297+get_gc (GdkPangoRenderer *gdk_renderer,
298+ PangoRenderPart part)
299 {
300 PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer);
301+ PangoColor *color;
302+ GdkBitmap *stipple;
303 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
304
305- if (!priv->cr)
306+ color = pango_renderer_get_color (renderer, part);
307+
308+ if (part <= MAX_RENDER_PART)
309+ stipple = priv->stipple[part];
310+ else
311+ stipple = NULL;
312+
313+ if (!color && !stipple) /* nothing override, use base_gc */
314+ return priv->base_gc;
315+ else
316 {
317- const PangoMatrix *matrix;
318+ gboolean new_stipple = FALSE;
319+ gboolean new_color = FALSE;
320
321- priv->cr = gdk_cairo_create (priv->drawable);
322+ if (stipple != priv->gc_stipple)
323+ new_stipple = TRUE;
324
325- matrix = pango_renderer_get_matrix (renderer);
326- if (matrix)
327+ if ((priv->gc_color_set && !color) ||
328+ (!priv->gc_color_set && color) ||
329+ priv->gc_color.red != color->red ||
330+ priv->gc_color.green != color->green ||
331+ priv->gc_color.blue != color->blue)
332+ new_color = TRUE;
333+
334+ if (!priv->gc)
335 {
336- cairo_matrix_t cairo_matrix;
337-
338- cairo_matrix_init (&cairo_matrix,
339- matrix->xx, matrix->yx,
340- matrix->xy, matrix->yy,
341- matrix->x0, matrix->y0);
342- cairo_set_matrix (priv->cr, &cairo_matrix);
343+ priv->gc = gdk_gc_new (priv->drawable);
344+ gdk_gc_copy (priv->gc, priv->base_gc);
345+ }
346+ else if (new_color && priv->gc_color_set && !color)
347+ {
348+ /* We have to recopy the original GC onto the cached GC
349+ * to get the default color */
350+ new_stipple = TRUE;
351+ gdk_gc_copy (priv->gc, priv->base_gc);
352+ }
353+ else if (new_stipple && priv->gc_stipple && !stipple)
354+ {
355+ /* Similarly, we need to make a new copy to restore to the
356+ * default stipple state (the caller may have set a stipple
357+ * on the GC, and even if not, gdk_gc_set_stipple (gc, NULL)
358+ * doesn't work currently to restore to the default X stipple) */
359+ new_color = TRUE;
360+ gdk_gc_copy (priv->gc, priv->base_gc);
361 }
362- }
363-
364- if (part != priv->last_part)
365- {
366- PangoColor *pango_color;
367- GdkColor *color;
368- GdkColor tmp_color;
369- gboolean changed;
370
371- pango_color = pango_renderer_get_color (renderer, part);
372-
373- if (priv->last_part != -1)
374- changed = priv->gc_changed ||
375- priv->stipple[priv->last_part] != priv->stipple[part] ||
376- !color_equal (pango_color,
377- pango_renderer_get_color (renderer, priv->last_part));
378- else
379- changed = TRUE;
380-
381- if (changed)
382+ if (new_color)
383 {
384- if (pango_color)
385+ if (color)
386 {
387- tmp_color.red = pango_color->red;
388- tmp_color.green = pango_color->green;
389- tmp_color.blue = pango_color->blue;
390+ GdkColor gdk_color;
391+
392+ gdk_color.red = color->red;
393+ gdk_color.green = color->green;
394+ gdk_color.blue = color->blue;
395
396- color = &tmp_color;
397+ gdk_gc_set_rgb_fg_color (priv->gc, &gdk_color);
398+
399+ priv->gc_color = *color;
400+ priv->gc_color_set = TRUE;
401 }
402 else
403- color = NULL;
404+ priv->gc_color_set = FALSE;
405+ }
406
407- _gdk_gc_update_context (priv->base_gc,
408- priv->cr,
409- color,
410- priv->stipple[part],
411- priv->gc_changed);
412+ if (new_stipple)
413+ {
414+ if (priv->gc_stipple)
415+ g_object_unref (priv->gc_stipple);
416+
417+ if (stipple)
418+ {
419+ gdk_gc_set_stipple (priv->gc, stipple);
420+ gdk_gc_set_fill (priv->gc, GDK_STIPPLED);
421+ priv->gc_stipple = g_object_ref (stipple);
422+ }
423+ else
424+ priv->gc_stipple = NULL;
425 }
426
427- priv->last_part = part;
428- priv->gc_changed = FALSE;
429+ return priv->gc;
430 }
431-
432- return priv->cr;
433 }
434
435 static void
436@@ -225,133 +307,78 @@
437 {
438 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
439 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
440- cairo_t *cr;
441
442- cr = get_cairo_context (gdk_renderer,
443- PANGO_RENDER_PART_FOREGROUND);
444+ flush_trapezoids (gdk_renderer);
445
446- if (priv->embossed)
447+ if (!priv->in_emboss && priv->embossed)
448 {
449- cairo_save (cr);
450- emboss_context (cr);
451- cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
452- pango_cairo_show_glyph_string (cr, font, glyphs);
453- cairo_restore (cr);
454- }
455-
456- cairo_move_to (cr, (double)x / PANGO_SCALE, (double)y / PANGO_SCALE);
457- pango_cairo_show_glyph_string (cr, font, glyphs);
458-}
459-
460-/* Draws an error underline that looks like one of:
461- * H E H
462- * /\ /\ /\ /\ /\ -
463- * A/ \ / \ / \ A/ \ / \ |
464- * \ \ / \ / /D \ \ / \ |
465- * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square
466- * \ /\ F / \ F /\ \ |
467- * \ / \ / \ / \ \G |
468- * \ / \ / \ / \ / |
469- * \/ \/ \/ \/ -
470- * B B
471- * |----|
472- * unit_width = (HEIGHT_SQUARES - 1) * square
473- *
474- * The x, y, width, height passed in give the desired bounding box;
475- * x/width are adjusted to make the underline a integer number of units
476- * wide.
477- */
478-#define HEIGHT_SQUARES 2.5
479+ PangoMatrix *save_matrix;
480+ PangoColor *save_color;
481
482-/* Cut-and-pasted between here and pango/pango/pangocairo-render.c */
483+ emboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color);
484+ gdk_draw_glyphs_transformed (priv->drawable,
485+ get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND),
486+ renderer->matrix, font, x, y, glyphs);
487+ unemboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color);
488+ }
489+
490+ gdk_draw_glyphs_transformed (priv->drawable,
491+ get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND),
492+ renderer->matrix, font, x, y, glyphs);
493+}
494+
495+/* Outputs any pending trapezoids, we do this when the part or
496+ * part color changes, when we are about to draw text, etc. */
497 static void
498-draw_error_underline (cairo_t *cr,
499- double x,
500- double y,
501- double width,
502- double height)
503-{
504- double square = height / HEIGHT_SQUARES;
505- double unit_width = (HEIGHT_SQUARES - 1) * square;
506- int width_units = (width + unit_width / 2) / unit_width;
507- double y_top, y_bottom;
508- int i;
509+flush_trapezoids (GdkPangoRenderer *gdk_renderer)
510+{
511+ GdkPangoRendererPrivate *priv = gdk_renderer->priv;
512
513- x += (width - width_units * unit_width) / 2;
514- width = width_units * unit_width;
515+ if (!priv->trapezoids || priv->trapezoids->len == 0)
516+ return;
517
518- y_top = y;
519- y_bottom = y + height;
520-
521- /* Bottom of squiggle */
522- cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */
523- for (i = 0; i < width_units; i += 2)
524- {
525- double x_middle = x + (i + 1) * unit_width;
526- double x_right = x + (i + 2) * unit_width;
527-
528- cairo_line_to (cr, x_middle, y_bottom); /* B */
529-
530- if (i + 1 == width_units)
531- /* Nothing */;
532- else if (i + 2 == width_units)
533- cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */
534- else
535- cairo_line_to (cr, x_right, y_top + square); /* C */
536- }
537-
538- /* Top of squiggle */
539- for (i -= 2; i >= 0; i -= 2)
540- {
541- double x_left = x + i * unit_width;
542- double x_middle = x + (i + 1) * unit_width;
543- double x_right = x + (i + 2) * unit_width;
544-
545- if (i + 1 == width_units)
546- cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */
547- else {
548- if (i + 2 == width_units)
549- cairo_line_to (cr, x_right, y_top); /* E */
550- cairo_line_to (cr, x_middle, y_bottom - square); /* F */
551- }
552-
553- cairo_line_to (cr, x_left, y_top); /* H */
554- }
555+ gdk_draw_trapezoids (priv->drawable,
556+ get_gc (gdk_renderer, priv->trapezoid_part),
557+ (GdkTrapezoid *)priv->trapezoids->data,
558+ priv->trapezoids->len);
559
560- cairo_close_path (cr);
561- cairo_fill (cr);
562+ g_array_set_size (priv->trapezoids, 0);
563 }
564
565+/* Draws a single trapezoid ... we don't draw it immediately, but rather
566+ * cache it to join together with other trapezoids that form part of the
567+ * same logical shape */
568 static void
569-gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
570- PangoRenderPart part,
571- int x,
572- int y,
573- int width,
574- int height)
575+gdk_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
576+ PangoRenderPart part,
577+ double y1,
578+ double x11,
579+ double x21,
580+ double y2,
581+ double x12,
582+ double x22)
583 {
584 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
585- GdkPangoRendererPrivate *priv = gdk_renderer->priv;
586- cairo_t *cr;
587-
588- cr = get_cairo_context (gdk_renderer, part);
589-
590- if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
591- {
592- cairo_save (cr);
593- emboss_context (cr);
594- cairo_rectangle (cr,
595- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
596- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
597+ GdkTrapezoid trap;
598
599- cairo_fill (cr);
600- cairo_restore (cr);
601- }
602+ if (!gdk_renderer->priv->trapezoids)
603+ gdk_renderer->priv->trapezoids = g_array_new (FALSE, FALSE,
604+ sizeof (GdkTrapezoid));
605+
606+ if (gdk_renderer->priv->trapezoids->len > 0 &&
607+ gdk_renderer->priv->trapezoid_part != part)
608+ flush_trapezoids (gdk_renderer);
609+
610+ gdk_renderer->priv->trapezoid_part = part;
611+
612+ trap.y1 = y1;
613+ trap.x11 = x11 / 2;
614+ trap.x21 = x21;
615+ trap.y2 = y2;
616+ trap.x12 = x12;
617+ trap.x22 = x22;
618
619- cairo_rectangle (cr,
620- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
621- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
622- cairo_fill (cr);
623+ g_array_append_val (gdk_renderer->priv->trapezoids, trap);
624 }
625
626 static void
627@@ -363,23 +390,51 @@
628 {
629 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
630 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
631- cairo_t *cr;
632-
633- cr = get_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE);
634-
635- if (priv->embossed)
636+
637+ if (!priv->in_emboss && priv->embossed)
638 {
639- cairo_save (cr);
640- emboss_context (cr);
641- draw_error_underline (cr,
642- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
643- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
644- cairo_restore (cr);
645+ PangoMatrix *save_matrix;
646+ PangoColor *save_color;
647+
648+ emboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color);
649+ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer,
650+ x, y, width, height);
651+ unemboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color);
652 }
653
654- draw_error_underline (cr,
655- (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
656- (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
657+ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer,
658+ x, y, width, height);
659+}
660+
661+/* We can't handle embossing at the level of trapezoids, because when an
662+ * underline is split into multiple trapezoids, the normal and shadow
663+ * trapezoids will be drawn mixed together. Instead, we have to emboss
664+ * and entire rectangle or error underline
665+ */
666+static void
667+gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer,
668+ PangoRenderPart part,
669+ int x,
670+ int y,
671+ int width,
672+ int height)
673+{
674+ GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
675+ GdkPangoRendererPrivate *priv = gdk_renderer->priv;
676+
677+ if (!priv->in_emboss && priv->embossed && part != PANGO_RENDER_PART_BACKGROUND)
678+ {
679+ PangoMatrix *save_matrix;
680+ PangoColor *save_color;
681+
682+ emboss_renderer (renderer, part, &save_matrix, &save_color);
683+ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part,
684+ x, y, width, height);
685+ unemboss_renderer (renderer, part, &save_matrix, &save_color);
686+ }
687+
688+ PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part,
689+ x, y, width, height);
690 }
691
692 static void
693@@ -388,8 +443,8 @@
694 {
695 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
696
697- if (gdk_renderer->priv->last_part == part)
698- gdk_renderer->priv->last_part = (PangoRenderPart)-1;
699+ if (part == gdk_renderer->priv->trapezoid_part)
700+ flush_trapezoids (gdk_renderer);
701 }
702
703 static void
704@@ -410,13 +465,8 @@
705 {
706 GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer);
707 GdkPangoRendererPrivate *priv = gdk_renderer->priv;
708-
709- if (priv->cr)
710- {
711- cairo_destroy (priv->cr);
712- priv->cr = NULL;
713- }
714- priv->last_part = (PangoRenderPart)-1;
715+
716+ flush_trapezoids (gdk_renderer);
717 }
718
719 static void
720@@ -515,7 +565,6 @@
721 GDK_TYPE_PANGO_RENDERER,
722 GdkPangoRendererPrivate);
723
724- renderer->priv->last_part = (PangoRenderPart)-1;
725 renderer->priv->gc_changed = TRUE;
726 }
727
728@@ -527,6 +576,7 @@
729 PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
730
731 renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs;
732+ renderer_class->draw_trapezoid = gdk_pango_renderer_draw_trapezoid;
733 renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle;
734 renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline;
735 renderer_class->part_changed = gdk_pango_renderer_part_changed;
736@@ -647,6 +697,8 @@
737
738 priv = gdk_renderer->priv;
739
740+ flush_trapezoids (gdk_renderer);
741+
742 if (priv->drawable != drawable)
743 {
744 if (priv->drawable)
745@@ -681,6 +733,8 @@
746
747 priv = gdk_renderer->priv;
748
749+ flush_trapezoids (gdk_renderer);
750+
751 if (priv->base_gc != gc)
752 {
753 if (priv->base_gc)
754@@ -689,6 +743,20 @@
755 if (priv->base_gc)
756 g_object_ref (priv->base_gc);
757
758+ if (priv->gc)
759+ {
760+ g_object_unref (priv->gc);
761+ priv->gc = NULL;
762+ }
763+
764+ priv->gc_color_set = FALSE;
765+
766+ if (priv->gc_stipple)
767+ {
768+ g_object_unref (priv->gc_stipple);
769+ priv->gc_stipple = NULL;
770+ }
771+
772 priv->gc_changed = TRUE;
773 }
774 }
775@@ -1414,50 +1482,5 @@
776 return gdk_pango_context_get_for_screen (gdk_screen_get_default ());
777 }
778
779-/**
780- * gdk_pango_context_get_for_screen:
781- * @screen: the #GdkScreen for which the context is to be created.
782- *
783- * Creates a #PangoContext for @screen.
784- *
785- * The context must be freed when you're finished with it.
786- *
787- * When using GTK+, normally you should use gtk_widget_get_pango_context()
788- * instead of this function, to get the appropriate context for
789- * the widget you intend to render text onto.
790- *
791- * The newly created context will have the default font options
792- * (see #cairo_font_options_t) for the screen; if these options
793- * change it will not be updated. Using gtk_widget_get_pango_context()
794- * is more convenient if you want to keep a context around and track
795- * changes to the screen's font rendering settings.
796- *
797- * Return value: a new #PangoContext for @screen
798- *
799- * Since: 2.2
800- **/
801-PangoContext *
802-gdk_pango_context_get_for_screen (GdkScreen *screen)
803-{
804- PangoFontMap *fontmap;
805- PangoContext *context;
806- const cairo_font_options_t *options;
807- double dpi;
808-
809- g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
810-
811- fontmap = pango_cairo_font_map_get_default ();
812-
813- context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
814-
815- options = gdk_screen_get_font_options (screen);
816- pango_cairo_context_set_font_options (context, options);
817-
818- dpi = gdk_screen_get_resolution (screen);
819- pango_cairo_context_set_resolution (context, dpi);
820-
821- return context;
822-}
823-
824 #define __GDK_PANGO_C__
825 #include "gdkaliasdef.c"
826Index: gtk+-2.10.6/gdk/gdk.symbols
827===================================================================
828--- gtk+-2.10.6.orig/gdk/gdk.symbols 2006-10-30 12:58:29.000000000 +0000
829+++ gtk+-2.10.6/gdk/gdk.symbols 2006-10-30 12:59:30.000000000 +0000
830@@ -861,7 +861,6 @@
831 gdk_pango_attr_embossed_new
832 gdk_pango_attr_stipple_new
833 gdk_pango_context_get
834-gdk_pango_context_get_for_screen
835 #ifndef GDK_DISABLE_DEPRECATED
836 gdk_pango_context_set_colormap
837 #endif
838@@ -877,6 +876,12 @@
839 #endif
840 #endif
841
842+#if IN_HEADER(__GDK_PANGO_H__)
843+#if IN_FILE(__GDK_PANGO_X11_C__)
844+gdk_pango_context_get_for_screen
845+#endif
846+#endif
847+
848 #if IN_HEADER(__GDK_PIXBUF_H__)
849 #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__)
850 gdk_pixbuf_get_from_drawable
851Index: gtk+-2.10.6/gdk/gdkwindow.c
852===================================================================
853--- gtk+-2.10.6.orig/gdk/gdkwindow.c 2006-10-30 12:58:29.000000000 +0000
854+++ gtk+-2.10.6/gdk/gdkwindow.c 2006-10-30 12:59:30.000000000 +0000
855@@ -1834,9 +1834,14 @@
856 }
857 else
858 {
859- method->cr = cairo_create (paint->surface);
860+ /*method->cr = cairo_create (paint->surface);
861
862- gdk_cairo_set_source_color (method->cr, &private->bg_color);
863+ gdk_cairo_set_source_color (method->cr, &private->bg_color);*/
864+ GdkGC *gc = _gdk_drawable_get_scratch_gc (paint->pixmap, FALSE);
865+
866+ gdk_gc_set_foreground (gc, &(private->bg_color));
867+
868+ method->gc = g_object_ref (gc);
869 }
870 }
871
872Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c
873===================================================================
874--- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.c 2006-10-30 12:58:29.000000000 +0000
875+++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.c 2006-10-30 12:59:30.000000000 +0000
876@@ -190,7 +190,8 @@
877 display_x11->leader_window_title_set = FALSE;
878
879 display_x11->have_render = GDK_UNKNOWN;
880-
881+ display_x11->have_render_with_trapezoids = GDK_UNKNOWN;
882+
883 #ifdef HAVE_XFIXES
884 if (XFixesQueryExtension (display_x11->xdisplay,
885 &display_x11->xfixes_event_base,
886Index: gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h
887===================================================================
888--- gtk+-2.10.6.orig/gdk/x11/gdkdisplay-x11.h 2006-10-30 12:58:29.000000000 +0000
889+++ gtk+-2.10.6/gdk/x11/gdkdisplay-x11.h 2006-10-30 12:59:30.000000000 +0000
890@@ -78,6 +78,7 @@
891 gboolean use_xshm;
892 gboolean have_shm_pixmaps;
893 GdkTristate have_render;
894+ GdkTristate have_render_with_trapezoids;
895 gboolean have_xfixes;
896 gint xfixes_event_base;
897
898Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c
899===================================================================
900--- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.c 2006-10-30 12:58:30.000000000 +0000
901+++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.c 2006-10-30 12:59:30.000000000 +0000
902@@ -26,6 +26,8 @@
903
904 #include <config.h>
905
906+#include <pango/pangoxft.h>
907+
908 #include "gdkx.h"
909 #include "gdkregion-generic.h"
910
911@@ -106,7 +108,21 @@
912 GdkGC *gc,
913 GdkPoint *points,
914 gint npoints);
915-
916+
917+static void gdk_x11_draw_glyphs (GdkDrawable *drawable,
918+ GdkGC *gc,
919+ PangoFont *font,
920+ gint x,
921+ gint y,
922+ PangoGlyphString *glyphs);
923+static void gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable,
924+ GdkGC *gc,
925+ PangoMatrix *matrix,
926+ PangoFont *font,
927+ gint x,
928+ gint y,
929+ PangoGlyphString *glyphs);
930+
931 static void gdk_x11_draw_image (GdkDrawable *drawable,
932 GdkGC *gc,
933 GdkImage *image,
934@@ -129,6 +145,11 @@
935 gint x_dither,
936 gint y_dither);
937
938+static void gdk_x11_draw_trapezoids (GdkDrawable *drawable,
939+ GdkGC *gc,
940+ GdkTrapezoid *trapezoids,
941+ gint n_trapezoids);
942+
943 static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
944
945 static void gdk_x11_set_colormap (GdkDrawable *drawable,
946@@ -163,8 +184,11 @@
947 drawable_class->draw_points = gdk_x11_draw_points;
948 drawable_class->draw_segments = gdk_x11_draw_segments;
949 drawable_class->draw_lines = gdk_x11_draw_lines;
950+ drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
951+ drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed;
952 drawable_class->draw_image = gdk_x11_draw_image;
953 drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
954+ drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids;
955
956 drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
957
958@@ -327,6 +351,72 @@
959 return x11display->have_render == GDK_YES;
960 }
961
962+gboolean
963+_gdk_x11_have_render_with_trapezoids (GdkDisplay *display)
964+{
965+ Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
966+ GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
967+
968+ if (x11display->have_render_with_trapezoids == GDK_UNKNOWN)
969+ {
970+ x11display->have_render_with_trapezoids = GDK_NO;
971+ if (_gdk_x11_have_render (display))
972+ {
973+ /*
974+ * Require protocol >= 0.4 for CompositeTrapezoids support.
975+ */
976+ int major_version, minor_version;
977+
978+#define XRENDER_TETRAPEZOIDS_MAJOR 0
979+#define XRENDER_TETRAPEZOIDS_MINOR 4
980+
981+ if (XRenderQueryVersion (xdisplay, &major_version,
982+ &minor_version))
983+ if ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) &&
984+ (minor_version >= XRENDER_TETRAPEZOIDS_MINOR))
985+ x11display->have_render_with_trapezoids = GDK_YES;
986+ }
987+ }
988+
989+ return x11display->have_render_with_trapezoids == GDK_YES;
990+}
991+
992+static XftDraw *
993+gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
994+{
995+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
996+
997+ if (impl->xft_draw == NULL)
998+ {
999+ GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
1000+
1001+ if (colormap)
1002+ {
1003+ GdkVisual *visual;
1004+
1005+ visual = gdk_colormap_get_visual (colormap);
1006+
1007+ impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
1008+ GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
1009+ }
1010+ else if (gdk_drawable_get_depth (drawable) == 1)
1011+ {
1012+ impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid);
1013+ }
1014+ else
1015+ {
1016+ g_warning ("Using Xft rendering requires the drawable argument to\n"
1017+ "have a specified colormap. All windows have a colormap,\n"
1018+ "however, pixmaps only have colormap by default if they\n"
1019+ "were created with a non-NULL window argument. Otherwise\n"
1020+ "a colormap must be set on them with gdk_drawable_set_colormap");
1021+ return NULL;
1022+ }
1023+ }
1024+
1025+ return impl->xft_draw;
1026+}
1027+
1028 static Picture
1029 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
1030 {
1031@@ -393,6 +483,57 @@
1032 }
1033 }
1034
1035+static void
1036+gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable,
1037+ GdkGC *gc)
1038+{
1039+ XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
1040+ GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
1041+
1042+ if (gc && clip_region)
1043+ {
1044+ GdkRegionBox *boxes = clip_region->rects;
1045+ gint n_boxes = clip_region->numRects;
1046+#if 0 /* Until XftDrawSetClipRectangles is there */
1047+ XRectangle *rects = g_new (XRectangle, n_boxes);
1048+ int i;
1049+
1050+ for (i=0; i < n_boxes; i++)
1051+ {
1052+ rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
1053+ rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
1054+ rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
1055+ rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
1056+ }
1057+ XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes);
1058+
1059+ g_free (rects);
1060+#else
1061+ Region xregion = XCreateRegion ();
1062+ int i;
1063+
1064+ for (i=0; i < n_boxes; i++)
1065+ {
1066+ XRectangle rect;
1067+
1068+ rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
1069+ rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
1070+ rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
1071+ rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
1072+
1073+ XUnionRectWithRegion (&rect, xregion, xregion);
1074+ }
1075+
1076+ XftDrawSetClip (xft_draw, xregion);
1077+ XDestroyRegion (xregion);
1078+#endif
1079+ }
1080+ else
1081+ {
1082+ XftDrawSetClip (xft_draw, NULL);
1083+ }
1084+}
1085+
1086 /*****************************************************
1087 * X11 specific implementations of generic functions *
1088 *****************************************************/
1089@@ -780,6 +921,45 @@
1090 }
1091
1092 static void
1093+gdk_x11_draw_glyphs (GdkDrawable *drawable,
1094+ GdkGC *gc,
1095+ PangoFont *font,
1096+ gint x,
1097+ gint y,
1098+ PangoGlyphString *glyphs)
1099+{
1100+ gdk_x11_draw_glyphs_transformed (drawable, gc, NULL,
1101+ font,
1102+ x * PANGO_SCALE,
1103+ y * PANGO_SCALE,
1104+ glyphs);
1105+}
1106+
1107+static void
1108+gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable,
1109+ GdkGC *gc,
1110+ PangoMatrix *matrix,
1111+ PangoFont *font,
1112+ gint x,
1113+ gint y,
1114+ PangoGlyphString *glyphs)
1115+{
1116+ GdkDrawableImplX11 *impl;
1117+ PangoRenderer *renderer;
1118+
1119+ impl = GDK_DRAWABLE_IMPL_X11 (drawable);
1120+
1121+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
1122+
1123+ renderer = _gdk_x11_renderer_get (drawable, gc);
1124+ if (matrix)
1125+ pango_renderer_set_matrix (renderer, matrix);
1126+ pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
1127+ if (matrix)
1128+ pango_renderer_set_matrix (renderer, NULL);
1129+}
1130+
1131+static void
1132 gdk_x11_draw_image (GdkDrawable *drawable,
1133 GdkGC *gc,
1134 GdkImage *image,
1135@@ -1444,6 +1624,47 @@
1136 }
1137
1138 static void
1139+gdk_x11_draw_trapezoids (GdkDrawable *drawable,
1140+ GdkGC *gc,
1141+ GdkTrapezoid *trapezoids,
1142+ gint n_trapezoids)
1143+{
1144+ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1145+ GdkDisplay *display = gdk_screen_get_display (screen);
1146+ XTrapezoid *xtrapezoids;
1147+ gint i;
1148+
1149+ if (!_gdk_x11_have_render_with_trapezoids (display))
1150+ {
1151+ GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1152+ GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_trapezoids (wrapper, gc,
1153+ trapezoids, n_trapezoids);
1154+ return;
1155+ }
1156+
1157+ xtrapezoids = g_new (XTrapezoid, n_trapezoids);
1158+
1159+ for (i = 0; i < n_trapezoids; i++)
1160+ {
1161+ xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1);
1162+ xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2);
1163+ xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11);
1164+ xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1);
1165+ xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12);
1166+ xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2);
1167+ xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21);
1168+ xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1);
1169+ xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22);
1170+ xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2);
1171+ }
1172+
1173+ _gdk_x11_drawable_draw_xtrapezoids (drawable, gc,
1174+ xtrapezoids, n_trapezoids);
1175+
1176+ g_free (xtrapezoids);
1177+}
1178+
1179+static void
1180 gdk_x11_cairo_surface_destroy (void *data)
1181 {
1182 GdkDrawableImplX11 *impl = data;
1183@@ -1498,5 +1719,89 @@
1184 return impl->cairo_surface;
1185 }
1186
1187+void
1188+_gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable,
1189+ GdkGC *gc,
1190+ XTrapezoid *xtrapezoids,
1191+ int n_trapezoids)
1192+{
1193+ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1194+ GdkDisplay *display = gdk_screen_get_display (screen);
1195+ GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
1196+
1197+ XftDraw *draw;
1198+
1199+ if (!_gdk_x11_have_render_with_trapezoids (display))
1200+ {
1201+ /* This is the case of drawing the borders of the unknown glyph box
1202+ * without render on the display, we need to feed it back to
1203+ * fallback code. Not efficient, but doesn't matter.
1204+ */
1205+ GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids);
1206+ int i;
1207+
1208+ for (i = 0; i < n_trapezoids; i++)
1209+ {
1210+ trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top);
1211+ trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom);
1212+ trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x);
1213+ trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x);
1214+ trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x);
1215+ trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x);
1216+ }
1217+
1218+ gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids);
1219+ g_free (trapezoids);
1220+
1221+ return;
1222+ }
1223+
1224+ gdk_x11_drawable_update_xft_clip (drawable, gc);
1225+ draw = gdk_x11_drawable_get_xft_draw (drawable);
1226+
1227+ if (!x11display->mask_format)
1228+ x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay,
1229+ PictStandardA8);
1230+
1231+ XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver,
1232+ _gdk_x11_gc_get_fg_picture (gc),
1233+ XftDrawPicture (draw),
1234+ x11display->mask_format,
1235+ - gc->ts_x_origin, - gc->ts_y_origin,
1236+ xtrapezoids, n_trapezoids);
1237+}
1238+
1239+void
1240+_gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable,
1241+ GdkGC *gc,
1242+ XftFont *xft_font,
1243+ XftGlyphSpec *glyphs,
1244+ gint n_glyphs)
1245+{
1246+ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1247+ GdkDisplay *display = gdk_screen_get_display (screen);
1248+ GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
1249+ XftDraw *draw;
1250+
1251+ gdk_x11_drawable_update_xft_clip (drawable, gc);
1252+ draw = gdk_x11_drawable_get_xft_draw (drawable);
1253+
1254+ if (_gdk_x11_have_render (display))
1255+ {
1256+ XftGlyphSpecRender (x11display->xdisplay, PictOpOver,
1257+ _gdk_x11_gc_get_fg_picture (gc),
1258+ xft_font,
1259+ XftDrawPicture (draw),
1260+ - gc->ts_x_origin, - gc->ts_y_origin,
1261+ glyphs, n_glyphs);
1262+ }
1263+ else
1264+ {
1265+ XftColor color;
1266+
1267+ _gdk_gc_x11_get_fg_xft_color (gc, &color);
1268+ XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs);
1269+ }
1270+}
1271 #define __GDK_DRAWABLE_X11_C__
1272 #include "gdkaliasdef.c"
1273Index: gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h
1274===================================================================
1275--- gtk+-2.10.6.orig/gdk/x11/gdkdrawable-x11.h 2006-10-30 12:58:30.000000000 +0000
1276+++ gtk+-2.10.6/gdk/x11/gdkdrawable-x11.h 2006-10-30 12:59:30.000000000 +0000
1277@@ -33,6 +33,7 @@
1278
1279 #include <X11/Xlib.h>
1280 #include <X11/extensions/Xrender.h>
1281+#include <X11/Xft/Xft.h>
1282
1283 G_BEGIN_DECLS
1284
1285@@ -68,6 +69,8 @@
1286 Window xid;
1287 GdkScreen *screen;
1288
1289+ XftDraw *xft_draw;
1290+
1291 Picture picture;
1292 cairo_surface_t *cairo_surface;
1293 };
1294@@ -92,7 +95,15 @@
1295 /* Note that the following take GdkDrawableImplX11, not the wrapper drawable */
1296 void _gdk_x11_drawable_finish (GdkDrawable *drawable);
1297 void _gdk_x11_drawable_update_size (GdkDrawable *drawable);
1298-
1299+void _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable,
1300+ GdkGC *gc,
1301+ XTrapezoid *xtrapezoids,
1302+ int n_trapezoids);
1303+void _gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable,
1304+ GdkGC *gc,
1305+ XftFont *xft_font,
1306+ XftGlyphSpec *glyphs,
1307+ gint n_glyphs);
1308 G_END_DECLS
1309
1310 #endif /* __GDK_DRAWABLE_X11_H__ */
1311Index: gtk+-2.10.6/gdk/x11/gdkgc-x11.c
1312===================================================================
1313--- gtk+-2.10.6.orig/gdk/x11/gdkgc-x11.c 2006-10-30 12:58:30.000000000 +0000
1314+++ gtk+-2.10.6/gdk/x11/gdkgc-x11.c 2006-10-30 12:59:30.000000000 +0000
1315@@ -80,7 +80,10 @@
1316 gdk_gc_x11_finalize (GObject *object)
1317 {
1318 GdkGCX11 *x11_gc = GDK_GC_X11 (object);
1319-
1320+
1321+ if (x11_gc->fg_picture != None)
1322+ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
1323+
1324 XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
1325
1326 G_OBJECT_CLASS (_gdk_gc_x11_parent_class)->finalize (object);
1327@@ -110,7 +113,7 @@
1328
1329 private->dirty_mask = 0;
1330 private->have_clip_mask = FALSE;
1331-
1332+
1333 private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1334
1335 private->depth = gdk_drawable_get_depth (drawable);
1336@@ -339,6 +342,18 @@
1337 }
1338
1339 static void
1340+clear_fg_picture (GdkGC *gc)
1341+{
1342+ GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1343+
1344+ if (x11_gc->fg_picture != None)
1345+ {
1346+ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
1347+ x11_gc->fg_picture = None;
1348+ }
1349+}
1350+
1351+static void
1352 gdk_x11_gc_set_values (GdkGC *gc,
1353 GdkGCValues *values,
1354 GdkGCValuesMask values_mask)
1355@@ -367,6 +382,29 @@
1356 x11_gc->have_clip_mask = values->clip_mask != NULL;
1357 }
1358
1359+ if (values_mask & GDK_GC_BACKGROUND)
1360+ {
1361+ if (_gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED)
1362+ clear_fg_picture (gc);
1363+ }
1364+
1365+ if (values_mask & GDK_GC_FILL)
1366+ {
1367+ clear_fg_picture (gc);
1368+ }
1369+
1370+ if (values_mask & GDK_GC_STIPPLE)
1371+ {
1372+ if (_gdk_gc_get_fill (gc) == GDK_STIPPLED || _gdk_gc_get_fill (gc) == GDK_OPAQUE_STIPPLED)
1373+ clear_fg_picture (gc);
1374+ }
1375+
1376+ if (values_mask & GDK_GC_TILE)
1377+ {
1378+ if (_gdk_gc_get_fill (gc) == GDK_TILED)
1379+ clear_fg_picture (gc);
1380+ }
1381+
1382 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
1383
1384 XChangeGC (GDK_GC_XDISPLAY (gc),
1385@@ -642,6 +680,8 @@
1386 x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask;
1387 x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region;
1388 x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask;
1389+
1390+ clear_fg_picture (dst_gc);
1391 }
1392
1393 /**
1394@@ -701,5 +741,359 @@
1395 return gc_x11->xgc;
1396 }
1397
1398+/* Various bits of the below are roughly cribbed from XFree86
1399+ * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard
1400+ */
1401+
1402+static XRenderPictFormat *
1403+foreground_format (GdkGC *gc)
1404+{
1405+ XRenderPictFormat pf;
1406+
1407+ pf.type = PictTypeDirect;
1408+ pf.depth = 32;
1409+ pf.direct.redMask = 0xff;
1410+ pf.direct.greenMask = 0xff;
1411+ pf.direct.blueMask = 0xff;
1412+ pf.direct.alphaMask = 0xff;
1413+
1414+ return XRenderFindFormat (GDK_GC_XDISPLAY (gc),
1415+ (PictFormatType |
1416+ PictFormatDepth |
1417+ PictFormatRedMask |
1418+ PictFormatGreenMask |
1419+ PictFormatBlueMask |
1420+ PictFormatAlphaMask),
1421+ &pf,
1422+ 0);
1423+}
1424+
1425+static Picture
1426+make_fg_tile_picture (GdkGC *gc)
1427+{
1428+ GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1429+ GdkVisual *visual = gdk_drawable_get_visual (_gdk_gc_get_tile (gc));
1430+ XRenderPictFormat *format = NULL;
1431+
1432+ if (visual)
1433+ {
1434+ format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc),
1435+ GDK_VISUAL_XVISUAL (visual));
1436+ }
1437+ else if (x11_gc->depth == 1)
1438+ {
1439+ format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
1440+ PictStandardA1);
1441+ }
1442+
1443+ if (format)
1444+ {
1445+ XRenderPictureAttributes pa;
1446+ pa.repeat = True;
1447+
1448+ return XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1449+ GDK_PIXMAP_XID (_gdk_gc_get_tile (gc)),
1450+ format,
1451+ CPRepeat, &pa);
1452+ }
1453+
1454+ return None;
1455+}
1456+
1457+static Picture
1458+make_stipple_picture (GdkGC *gc)
1459+{
1460+ XRenderPictFormat *format = NULL;
1461+ XRenderPictureAttributes pa;
1462+
1463+ format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
1464+ PictStandardA1);
1465+
1466+ pa.repeat = True;
1467+ return XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1468+ GDK_PIXMAP_XID (_gdk_gc_get_stipple (gc)),
1469+ format,
1470+ CPRepeat, &pa);
1471+}
1472+
1473+static Picture
1474+make_color_picture (GdkGC *gc,
1475+ XRenderColor *color)
1476+{
1477+ GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1478+ XRenderPictureAttributes pa;
1479+ XRenderPictFormat *pix_format = foreground_format (gc);
1480+ Pixmap pix;
1481+ Picture picture;
1482+
1483+ if (!pix_format)
1484+ return None;
1485+
1486+ pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
1487+ GDK_SCREEN_XROOTWIN (x11_gc->screen),
1488+ 1, 1, pix_format->depth);
1489+ pa.repeat = True;
1490+ picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1491+ pix,
1492+ pix_format,
1493+ CPRepeat, &pa);
1494+ XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
1495+
1496+ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1497+ picture, color,
1498+ 0, 0, 1, 1);
1499+
1500+ return picture;
1501+}
1502+
1503+static void
1504+get_bg_color (GdkGC *gc,
1505+ XRenderColor *render_color)
1506+{
1507+ GdkColormap *cmap;
1508+
1509+ cmap = gdk_gc_get_colormap (gc);
1510+
1511+ if (cmap)
1512+ {
1513+ GdkColor color;
1514+
1515+ gdk_colormap_query_color (cmap, _gdk_gc_get_bg_pixel (gc), &color);
1516+
1517+ render_color->alpha = 0xffff;
1518+ render_color->red = color.red;
1519+ render_color->green = color.green;
1520+ render_color->blue = color.blue;
1521+ }
1522+ else /* Not worth warning, just use black */
1523+ {
1524+ render_color->alpha = 0xffff;
1525+ render_color->red = 0;
1526+ render_color->green = 0;
1527+ render_color->blue = 0;
1528+ }
1529+}
1530+
1531+/**
1532+ * _gdk_x11_gc_get_fg_picture:
1533+ * @gc: a #GdkGC
1534+ *
1535+ * Gets a Xrender Picture object suitable for being the source
1536+ * drawable for drawing with the foreground the graphics context.
1537+ *
1538+ * Return value: a Picture, owned by the GC; this cannot be
1539+ * used over subsequent modification of the GC.
1540+ **/
1541+Picture
1542+_gdk_x11_gc_get_fg_picture (GdkGC *gc)
1543+{
1544+ GdkGCX11 *x11_gc;
1545+ gboolean new = FALSE;
1546+ XftColor xftcolor;
1547+ GdkFill fill;
1548+ int width, height;
1549+
1550+ g_return_val_if_fail (GDK_IS_GC_X11 (gc), None);
1551+
1552+ if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc)))
1553+ return None;
1554+
1555+ x11_gc = GDK_GC_X11 (gc);
1556+
1557+ fill = GDK_SOLID;
1558+ width = 1;
1559+ height = 1;
1560+
1561+ switch (_gdk_gc_get_fill (gc))
1562+ {
1563+ case GDK_SOLID:
1564+ break;
1565+ case GDK_TILED:
1566+ if (_gdk_gc_get_tile (gc))
1567+ {
1568+ if (!x11_gc->fg_picture)
1569+ x11_gc->fg_picture = make_fg_tile_picture (gc);
1570+
1571+ if (x11_gc->fg_picture != None)
1572+ return x11_gc->fg_picture;
1573+ }
1574+ break;
1575+ case GDK_STIPPLED:
1576+ case GDK_OPAQUE_STIPPLED:
1577+ if (_gdk_gc_get_stipple (gc))
1578+ {
1579+ gdk_drawable_get_size (_gdk_gc_get_stipple (gc), &width, &height);
1580+ fill = _gdk_gc_get_fill (gc);
1581+ }
1582+ break;
1583+ }
1584+
1585+ if (x11_gc->fg_picture == None)
1586+ {
1587+ XRenderPictureAttributes pa;
1588+ XRenderPictFormat *pix_format = foreground_format (gc);
1589+ Pixmap pix;
1590+
1591+ if (!pix_format)
1592+ return None;
1593+
1594+ pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
1595+ GDK_SCREEN_XROOTWIN (x11_gc->screen),
1596+ width, height, pix_format->depth);
1597+ pa.repeat = True;
1598+ x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1599+ pix,
1600+ pix_format,
1601+ CPRepeat, &pa);
1602+ XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
1603+
1604+ new = TRUE;
1605+ }
1606+
1607+ _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor);
1608+
1609+ if (x11_gc->fg_picture_color.alpha != 0xffff ||
1610+ x11_gc->fg_picture_color.red != xftcolor.color.red ||
1611+ x11_gc->fg_picture_color.green != xftcolor.color.green ||
1612+ x11_gc->fg_picture_color.blue != xftcolor.color.blue)
1613+ {
1614+ x11_gc->fg_picture_color.alpha = 0xffff;
1615+ x11_gc->fg_picture_color.red = xftcolor.color.red;
1616+ x11_gc->fg_picture_color.green = xftcolor.color.green;
1617+ x11_gc->fg_picture_color.blue = xftcolor.color.blue;
1618+
1619+ new = TRUE;
1620+ }
1621+
1622+ switch (fill)
1623+ {
1624+ case GDK_SOLID:
1625+ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1626+ x11_gc->fg_picture, &x11_gc->fg_picture_color,
1627+ 0, 0, width, height);
1628+ break;
1629+ case GDK_STIPPLED:
1630+ {
1631+ Picture stipple_picture = make_stipple_picture (gc);
1632+
1633+ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1634+ x11_gc->fg_picture, &x11_gc->fg_picture_color,
1635+ 0, 0, width, height);
1636+ XRenderComposite (GDK_GC_XDISPLAY (gc),
1637+ PictOpInReverse,
1638+ stipple_picture, None, x11_gc->fg_picture,
1639+ 0, 0, 0, 0, 0, 0, width, height);
1640+
1641+ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
1642+ }
1643+ break;
1644+ case GDK_OPAQUE_STIPPLED:
1645+ {
1646+ XRenderColor bg_color;
1647+
1648+ Picture stipple_picture = make_stipple_picture (gc);
1649+ Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color);
1650+
1651+ get_bg_color (gc, &bg_color);
1652+
1653+ XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1654+ x11_gc->fg_picture, &bg_color,
1655+ 0, 0, width, height);
1656+ XRenderComposite (GDK_GC_XDISPLAY (gc),
1657+ PictOpOver,
1658+ fg_picture, stipple_picture, x11_gc->fg_picture,
1659+ 0, 0, 0, 0, 0, 0, width, height);
1660+
1661+ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
1662+ XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture);
1663+ }
1664+ break;
1665+ case GDK_TILED:
1666+ g_assert_not_reached (); /* handled above */
1667+ break;
1668+ }
1669+
1670+ return x11_gc->fg_picture;
1671+}
1672+
1673+/**
1674+ * _gdk_gc_x11_get_fg_xft_color:
1675+ * @gc: a #GdkGC
1676+ * @xftcolor: location to store the color
1677+ *
1678+ * Gets the foreground color of the GC as a XftColor.
1679+ **/
1680+void
1681+_gdk_gc_x11_get_fg_xft_color (GdkGC *gc,
1682+ XftColor *xftcolor)
1683+{
1684+ GdkGCX11 *x11_gc;
1685+ GdkColormap *cmap;
1686+ GdkColor color;
1687+
1688+ g_return_if_fail (GDK_IS_GC_X11 (gc));
1689+
1690+ x11_gc = GDK_GC_X11 (gc);
1691+
1692+ cmap = gdk_gc_get_colormap (gc);
1693+
1694+ xftcolor->pixel = _gdk_gc_get_fg_pixel (gc);
1695+
1696+ if (cmap)
1697+ {
1698+ gdk_colormap_query_color (cmap, xftcolor->pixel, &color);
1699+ xftcolor->color.alpha = 0xffff;
1700+ xftcolor->color.red = color.red;
1701+ xftcolor->color.green = color.green;
1702+ xftcolor->color.blue = color.blue;
1703+ }
1704+ else if (x11_gc->depth == 1)
1705+ {
1706+ /* Drawing with Xft on a bitmap is a bit bizzare; it
1707+ * takes alpha >= 0x8000 to mean 'set to 1' and
1708+ * alpha < 0x8000 to mean 'set to 0'.
1709+ */
1710+ if (xftcolor->pixel)
1711+ {
1712+ xftcolor->color.red = 0xffff;
1713+ xftcolor->color.green = 0xffff;
1714+ xftcolor->color.blue = 0xffff;
1715+ xftcolor->color.alpha = 0xffff;
1716+ }
1717+ else
1718+ {
1719+ xftcolor->color.red = 0;
1720+ xftcolor->color.green = 0;
1721+ xftcolor->color.blue = 0;
1722+ xftcolor->color.alpha = 0;
1723+ }
1724+ }
1725+ else
1726+ {
1727+ g_warning ("Using Xft rendering requires the GC argument to have a\n"
1728+ "specified colormap. If the GC was created for a drawable\n"
1729+ "with a colormap, the colormap will be set on the GC\n"
1730+ "automatically. Otherwise, a colormap must be set on it with"
1731+ "gdk_gc_set_colormap");
1732+ }
1733+}
1734+
1735+void
1736+_gdk_windowing_gc_get_foreground (GdkGC *gc,
1737+ GdkColor *color)
1738+{
1739+ GdkColormap *cmap;
1740+
1741+ g_return_if_fail (GDK_IS_GC_X11 (gc));
1742+
1743+ color->pixel = _gdk_gc_get_fg_pixel (gc);
1744+
1745+ cmap = gdk_gc_get_colormap (gc);
1746+
1747+ if (cmap)
1748+ gdk_colormap_query_color (cmap, _gdk_gc_get_fg_pixel (gc), color);
1749+ else
1750+ g_warning ("No colormap in _gdk_windowing_gc_get_foreground");
1751+}
1752 #define __GDK_GC_X11_C__
1753 #include "gdkaliasdef.c"
1754Index: gtk+-2.10.6/gdk/x11/gdkprivate-x11.h
1755===================================================================
1756--- gtk+-2.10.6.orig/gdk/x11/gdkprivate-x11.h 2006-10-30 12:58:30.000000000 +0000
1757+++ gtk+-2.10.6/gdk/x11/gdkprivate-x11.h 2006-10-30 12:59:30.000000000 +0000
1758@@ -63,6 +63,9 @@
1759 guint have_clip_region : 1;
1760 guint have_clip_mask : 1;
1761 guint depth : 8;
1762+
1763+ Picture fg_picture;
1764+ XRenderColor fg_picture_color;
1765 };
1766
1767 struct _GdkGCX11Class
1768@@ -102,6 +105,11 @@
1769 GType _gdk_gc_x11_get_type (void);
1770
1771 gboolean _gdk_x11_have_render (GdkDisplay *display);
1772+gboolean _gdk_x11_have_render_with_trapezoids (GdkDisplay *display);
1773+
1774+Picture _gdk_x11_gc_get_fg_picture (GdkGC *gc);
1775+void _gdk_gc_x11_get_fg_xft_color (GdkGC *gc,
1776+ XftColor *xftcolor);
1777
1778 GdkGC *_gdk_x11_gc_new (GdkDrawable *drawable,
1779 GdkGCValues *values,
1780Index: gtk+-2.10.6/gdk/x11/gdkwindow-x11.c
1781===================================================================
1782--- gtk+-2.10.6.orig/gdk/x11/gdkwindow-x11.c 2006-10-30 12:58:30.000000000 +0000
1783+++ gtk+-2.10.6/gdk/x11/gdkwindow-x11.c 2006-10-30 12:59:30.000000000 +0000
1784@@ -1114,7 +1114,8 @@
1785 {
1786 GdkWindowObject *private = (GdkWindowObject *)window;
1787 GdkToplevelX11 *toplevel;
1788-
1789+ GdkDrawableImplX11 *draw_impl;
1790+
1791 g_return_if_fail (GDK_IS_WINDOW (window));
1792
1793 _gdk_selection_window_destroyed (window);
1794@@ -1126,6 +1127,11 @@
1795 if (toplevel)
1796 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1797
1798+ draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
1799+
1800+ if (draw_impl->xft_draw)
1801+ XftDrawDestroy (draw_impl->xft_draw);
1802+
1803 _gdk_x11_drawable_finish (private->impl);
1804
1805 if (!recursing && !foreign_destroy)
1806Index: gtk+-2.10.6/gdk/x11/Makefile.am
1807===================================================================
1808--- gtk+-2.10.6.orig/gdk/x11/Makefile.am 2006-10-30 12:58:30.000000000 +0000
1809+++ gtk+-2.10.6/gdk/x11/Makefile.am 2006-10-30 12:59:30.000000000 +0000
1810@@ -37,6 +37,7 @@
1811 gdkinput.c \
1812 gdkkeys-x11.c \
1813 gdkmain-x11.c \
1814+ gdkpango-x11.c \
1815 gdkpixmap-x11.c \
1816 gdkpixmap-x11.h \
1817 gdkproperty-x11.c \
1818Index: gtk+-2.10.6/gtk/gtkcalendar.c
1819===================================================================
1820--- gtk+-2.10.6.orig/gtk/gtkcalendar.c 2006-10-30 12:58:30.000000000 +0000
1821+++ gtk+-2.10.6/gtk/gtkcalendar.c 2006-10-30 12:59:30.000000000 +0000
1822@@ -1821,7 +1821,7 @@
1823 }
1824 }
1825
1826-
1827+
1828 /****************************************
1829 * Repainting *
1830 ****************************************/
1831@@ -1831,7 +1831,7 @@
1832 {
1833 GtkWidget *widget = GTK_WIDGET (calendar);
1834 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1835- cairo_t *cr;
1836+ GdkGC *gc;
1837 char buffer[255];
1838 int x, y;
1839 gint header_width;
1840@@ -1849,7 +1849,7 @@
1841 else
1842 year_left = !priv->year_before;
1843
1844- cr = gdk_cairo_create (priv->header_win);
1845+ gc = calendar->gc;
1846
1847 header_width = widget->allocation.width - 2 * widget->style->xthickness;
1848
1849@@ -1902,9 +1902,9 @@
1850 - (max_year_width - logical_rect.width)/2);
1851
1852
1853- gdk_cairo_set_source_color (cr, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1854- cairo_move_to (cr, x, y);
1855- pango_cairo_show_layout (cr, layout);
1856+ gdk_gc_set_foreground (gc, HEADER_FG_COLOR (GTK_WIDGET (calendar)));
1857+ gdk_draw_layout (priv->header_win, gc, x, y, layout);
1858+
1859
1860 /* Draw month */
1861 g_snprintf (buffer, sizeof (buffer), "%s", default_monthname[calendar->month]);
1862@@ -1924,19 +1924,19 @@
1863 else
1864 x = 3 + priv->arrow_width + (max_month_width - logical_rect.width)/2;
1865
1866- cairo_move_to (cr, x, y);
1867- pango_cairo_show_layout (cr, layout);
1868-
1869+ gdk_draw_layout (priv->header_win, gc, x, y, layout);
1870+
1871+ gdk_gc_set_foreground (gc, BACKGROUND_COLOR (GTK_WIDGET (calendar)));
1872+
1873 g_object_unref (layout);
1874- cairo_destroy (cr);
1875 }
1876
1877 static void
1878 calendar_paint_day_names (GtkCalendar *calendar)
1879 {
1880 GtkWidget *widget = GTK_WIDGET (calendar);
1881+ GdkGC *gc;
1882 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1883- cairo_t *cr;
1884 char buffer[255];
1885 int day,i;
1886 int day_width, cal_width;
1887@@ -1946,8 +1946,7 @@
1888 gint focus_padding;
1889 gint focus_width;
1890
1891- cr = gdk_cairo_create (priv->day_name_win);
1892-
1893+ gc = calendar->gc;
1894 gtk_widget_style_get (GTK_WIDGET (widget),
1895 "focus-line-width", &focus_width,
1896 "focus-padding", &focus_padding,
1897@@ -1961,22 +1960,19 @@
1898 * Draw rectangles as inverted background for the labels.
1899 */
1900
1901- gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
1902- cairo_rectangle (cr,
1903- CALENDAR_MARGIN, CALENDAR_MARGIN,
1904- cal_width-CALENDAR_MARGIN * 2,
1905- priv->day_name_h - CALENDAR_MARGIN);
1906- cairo_fill (cr);
1907-
1908+ gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget));
1909+ gdk_draw_rectangle (priv->day_name_win, gc, TRUE,
1910+ CALENDAR_MARGIN, CALENDAR_MARGIN,
1911+ cal_width-CALENDAR_MARGIN * 2,
1912+ priv->day_name_h - CALENDAR_MARGIN);
1913+
1914 if (calendar->display_flags & GTK_CALENDAR_SHOW_WEEK_NUMBERS)
1915- {
1916- cairo_rectangle (cr,
1917- CALENDAR_MARGIN,
1918- priv->day_name_h - CALENDAR_YSEP,
1919- priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1920- CALENDAR_YSEP);
1921- cairo_fill (cr);
1922- }
1923+ gdk_draw_rectangle (priv->day_name_win, gc, TRUE,
1924+ CALENDAR_MARGIN,
1925+ priv->day_name_h - CALENDAR_YSEP,
1926+ priv->week_width - CALENDAR_YSEP - CALENDAR_MARGIN,
1927+ CALENDAR_YSEP);
1928+
1929
1930 /*
1931 * Write the labels
1932@@ -1984,7 +1980,7 @@
1933
1934 layout = gtk_widget_create_pango_layout (widget, NULL);
1935
1936- gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
1937+ gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget));
1938 for (i = 0; i < 7; i++)
1939 {
1940 if (gtk_widget_get_direction (GTK_WIDGET (calendar)) == GTK_TEXT_DIR_RTL)
1941@@ -1997,19 +1993,18 @@
1942 pango_layout_set_text (layout, buffer, -1);
1943 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
1944
1945- cairo_move_to (cr,
1946- (CALENDAR_MARGIN +
1947- + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
1948- (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0))
1949- : 0)
1950- + day_wid_sep * i
1951- + (day_width - logical_rect.width)/2),
1952- CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y);
1953- pango_cairo_show_layout (cr, layout);
1954+ gdk_draw_layout (priv->day_name_win, gc,
1955+ (CALENDAR_MARGIN +
1956+ + (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
1957+ (priv->week_width + (priv->week_width ? CALENDAR_XSEP : 0))
1958+ : 0)
1959+ + day_wid_sep * i
1960+ + (day_width - logical_rect.width)/2),
1961+ CALENDAR_MARGIN + focus_width + focus_padding + logical_rect.y,
1962+ layout);
1963 }
1964
1965 g_object_unref (layout);
1966- cairo_destroy (cr);
1967 }
1968
1969 static void
1970@@ -2017,7 +2012,7 @@
1971 {
1972 GtkWidget *widget = GTK_WIDGET (calendar);
1973 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
1974- cairo_t *cr;
1975+ GdkGC *gc;
1976 gint row, week = 0, year;
1977 gint x_loc;
1978 char buffer[32];
1979@@ -2027,7 +2022,7 @@
1980 gint focus_padding;
1981 gint focus_width;
1982
1983- cr = gdk_cairo_create (priv->week_win);
1984+ gc = calendar->gc;
1985
1986 gtk_widget_style_get (GTK_WIDGET (widget),
1987 "focus-line-width", &focus_width,
1988@@ -2038,20 +2033,20 @@
1989 * Draw a rectangle as inverted background for the labels.
1990 */
1991
1992- gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
1993+ gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (widget));
1994 if (priv->day_name_win)
1995- cairo_rectangle (cr,
1996- CALENDAR_MARGIN,
1997- 0,
1998- priv->week_width - CALENDAR_MARGIN,
1999- priv->main_h - CALENDAR_MARGIN);
2000+ gdk_draw_rectangle (priv->week_win, gc, TRUE,
2001+ CALENDAR_MARGIN,
2002+ 0,
2003+ priv->week_width - CALENDAR_MARGIN,
2004+ priv->main_h - CALENDAR_MARGIN);
2005 else
2006- cairo_rectangle (cr,
2007- CALENDAR_MARGIN,
2008- CALENDAR_MARGIN,
2009- priv->week_width - CALENDAR_MARGIN,
2010- priv->main_h - 2 * CALENDAR_MARGIN);
2011- cairo_fill (cr);
2012+ gdk_draw_rectangle (priv->week_win, gc, TRUE,
2013+ CALENDAR_MARGIN,
2014+ CALENDAR_MARGIN,
2015+ priv->week_width - CALENDAR_MARGIN,
2016+ priv->main_h - 2 * CALENDAR_MARGIN);
2017+
2018
2019 /*
2020 * Write the labels
2021@@ -2059,7 +2054,7 @@
2022
2023 layout = gtk_widget_create_pango_layout (widget, NULL);
2024
2025- gdk_cairo_set_source_color (cr, SELECTED_FG_COLOR (widget));
2026+ gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (widget));
2027 day_height = calendar_row_height (calendar);
2028 for (row = 0; row < 6; row++)
2029 {
2030@@ -2095,12 +2090,10 @@
2031 - logical_rect.width
2032 - CALENDAR_XSEP - focus_padding - focus_width);
2033
2034- cairo_move_to (cr, x_loc, y_loc);
2035- pango_cairo_show_layout (cr, layout);
2036+ gdk_draw_layout (priv->week_win, gc, x_loc, y_loc, layout);
2037 }
2038
2039 g_object_unref (layout);
2040- cairo_destroy (cr);
2041 }
2042
2043 static void
2044@@ -2149,7 +2142,7 @@
2045 {
2046 GtkWidget *widget = GTK_WIDGET (calendar);
2047 GtkCalendarPrivate *priv = GTK_CALENDAR_GET_PRIVATE (calendar);
2048- cairo_t *cr;
2049+ GdkGC *gc;
2050 GdkColor *text_color;
2051 gchar buffer[32];
2052 gint day;
2053@@ -2162,7 +2155,7 @@
2054 g_return_if_fail (row < 6);
2055 g_return_if_fail (col < 7);
2056
2057- cr = gdk_cairo_create (priv->main_win);
2058+ gc = calendar->gc;
2059
2060 day = calendar->day[row][col];
2061
2062@@ -2170,11 +2163,11 @@
2063
2064 if (calendar->day_month[row][col] == MONTH_PREV)
2065 {
2066- text_color = PREV_MONTH_COLOR (widget);
2067+ gdk_gc_set_foreground (gc, PREV_MONTH_COLOR (GTK_WIDGET (calendar)));
2068 }
2069 else if (calendar->day_month[row][col] == MONTH_NEXT)
2070 {
2071- text_color = NEXT_MONTH_COLOR (widget);
2072+ gdk_gc_set_foreground (gc, NEXT_MONTH_COLOR (GTK_WIDGET (calendar)));
2073 }
2074 else
2075 {
2076@@ -2188,16 +2181,16 @@
2077 #endif
2078 if (calendar->selected_day == day)
2079 {
2080- gdk_cairo_set_source_color (cr, SELECTED_BG_COLOR (widget));
2081- gdk_cairo_rectangle (cr, &day_rect);
2082- cairo_fill (cr);
2083+ gdk_gc_set_foreground (gc, SELECTED_BG_COLOR (GTK_WIDGET (calendar)));
2084+ gdk_draw_rectangle (priv->main_win, gc, TRUE, day_rect.x, day_rect.y,
2085+ day_rect.width, day_rect.height);
2086 }
2087 if (calendar->selected_day == day)
2088- text_color = SELECTED_FG_COLOR (widget);
2089+ gdk_gc_set_foreground (gc, SELECTED_FG_COLOR (GTK_WIDGET (calendar)));
2090 else if (calendar->marked_date[day-1])
2091- text_color = MARKED_COLOR (widget);
2092+ gdk_gc_set_foreground (gc, MARKED_COLOR (GTK_WIDGET (calendar)));
2093 else
2094- text_color = NORMAL_DAY_COLOR (widget);
2095+ gdk_gc_set_foreground (gc, NORMAL_DAY_COLOR (GTK_WIDGET (calendar)));
2096 }
2097
2098 /* Translators: this defines whether the day numbers should use
2099@@ -2219,16 +2212,13 @@
2100 x_loc -= logical_rect.width;
2101 y_loc = day_rect.y + (day_rect.height - logical_rect.height) / 2;
2102
2103- gdk_cairo_set_source_color (cr, text_color);
2104- cairo_move_to (cr, x_loc, y_loc);
2105- pango_cairo_show_layout (cr, layout);
2106+ gdk_draw_layout (priv->main_win, gc,
2107+ x_loc, y_loc, layout);
2108
2109 if (calendar->marked_date[day-1]
2110 && calendar->day_month[row][col] == MONTH_CURRENT)
2111- {
2112- cairo_move_to (cr, x_loc - 1, y_loc);
2113- pango_cairo_show_layout (cr, layout);
2114- }
2115+ gdk_draw_layout (priv->main_win, gc,
2116+ x_loc-1, y_loc, layout);
2117
2118 if (GTK_WIDGET_HAS_FOCUS (calendar)
2119 && calendar->focus_row == row && calendar->focus_col == col)
2120@@ -2253,7 +2243,6 @@
2121 }
2122
2123 g_object_unref (layout);
2124- cairo_destroy (cr);
2125 }
2126
2127 static void
2128Index: gtk+-2.10.6/gtk/gtkentry.c
2129===================================================================
2130--- gtk+-2.10.6.orig/gtk/gtkentry.c 2006-10-30 12:58:30.000000000 +0000
2131+++ gtk+-2.10.6/gtk/gtkentry.c 2006-10-30 12:59:30.000000000 +0000
2132@@ -3333,7 +3333,6 @@
2133 if (GTK_WIDGET_DRAWABLE (entry))
2134 {
2135 PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
2136- cairo_t *cr;
2137 gint x, y;
2138 gint start_pos, end_pos;
2139
2140@@ -3341,56 +3340,60 @@
2141
2142 get_layout_position (entry, &x, &y);
2143
2144- cr = gdk_cairo_create (entry->text_area);
2145-
2146- cairo_move_to (cr, x, y);
2147- gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
2148- pango_cairo_show_layout (cr, layout);
2149-
2150+ gdk_draw_layout (entry->text_area, widget->style->text_gc [widget->state],
2151+ x, y,
2152+ layout);
2153+
2154 if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos))
2155 {
2156 gint *ranges;
2157 gint n_ranges, i;
2158 PangoRectangle logical_rect;
2159- GdkColor *selection_color, *text_color;
2160+ GdkGC *selection_gc, *text_gc;
2161 GtkBorder inner_border;
2162-
2163+ GdkRegion *clip_region;
2164+
2165 pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
2166 gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
2167
2168 if (GTK_WIDGET_HAS_FOCUS (entry))
2169 {
2170- selection_color = &widget->style->base [GTK_STATE_SELECTED];
2171- text_color = &widget->style->text [GTK_STATE_SELECTED];
2172+ selection_gc = widget->style->base_gc [GTK_STATE_SELECTED];
2173+ text_gc = widget->style->text_gc [GTK_STATE_SELECTED];
2174 }
2175 else
2176 {
2177- selection_color = &widget->style->base [GTK_STATE_ACTIVE];
2178- text_color = &widget->style->text [GTK_STATE_ACTIVE];
2179+ selection_gc = widget->style->base_gc [GTK_STATE_ACTIVE];
2180+ text_gc = widget->style->text_gc [GTK_STATE_ACTIVE];
2181 }
2182-
2183+
2184+ clip_region = gdk_region_new ();
2185 _gtk_entry_effective_inner_border (entry, &inner_border);
2186
2187 for (i = 0; i < n_ranges; ++i)
2188- cairo_rectangle (cr,
2189- inner_border.left - entry->scroll_offset + ranges[2 * i],
2190- y,
2191- ranges[2 * i + 1],
2192- logical_rect.height);
2193+ {
2194+ GdkRectangle rect;
2195
2196- cairo_clip (cr);
2197-
2198- gdk_cairo_set_source_color (cr, selection_color);
2199- cairo_paint (cr);
2200+ rect.x = inner_border.left - entry->scroll_offset + ranges[2 * i];
2201+ rect.y = y;
2202+ rect.width = ranges[2 * i + 1];
2203+ rect.height = logical_rect.height;
2204+
2205+ gdk_draw_rectangle (entry->text_area, selection_gc, TRUE,
2206+ rect.x, rect.y, rect.width, rect.height);
2207
2208- cairo_move_to (cr, x, y);
2209- gdk_cairo_set_source_color (cr, text_color);
2210- pango_cairo_show_layout (cr, layout);
2211+ gdk_region_union_with_rect (clip_region, &rect);
2212+ }
2213
2214+ gdk_gc_set_clip_region (text_gc, clip_region);
2215+ gdk_draw_layout (entry->text_area, text_gc,
2216+ x, y,
2217+ layout);
2218+ gdk_gc_set_clip_region (text_gc, NULL);
2219+
2220+ gdk_region_destroy (clip_region);
2221 g_free (ranges);
2222 }
2223-
2224- cairo_destroy (cr);
2225 }
2226 }
2227
2228Index: gtk+-2.10.6/gtk/gtkwidget.c
2229===================================================================
2230--- gtk+-2.10.6.orig/gtk/gtkwidget.c 2006-10-30 12:58:30.000000000 +0000
2231+++ gtk+-2.10.6/gtk/gtkwidget.c 2006-10-30 12:59:30.000000000 +0000
2232@@ -5445,7 +5445,8 @@
2233 GdkScreen *screen;
2234
2235 update_pango_context (widget, context);
2236-
2237+/* TODO: Figure out the proper way to handle this in a pangoxft setting
2238+
2239 screen = gtk_widget_get_screen_unchecked (widget);
2240 if (screen)
2241 {
2242@@ -5453,7 +5454,7 @@
2243 gdk_screen_get_resolution (screen));
2244 pango_cairo_context_set_font_options (context,
2245 gdk_screen_get_font_options (screen));
2246- }
2247+ }*/
2248 }
2249 }
2250
2251Index: gtk+-2.10.6/gdk/x11/gdkpango-x11.c
2252===================================================================
2253--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2254+++ gtk+-2.10.6/gdk/x11/gdkpango-x11.c 2006-10-30 12:59:30.000000000 +0000
2255@@ -0,0 +1,174 @@
2256+/* GDK - The GIMP Drawing Kit
2257+ * Copyright (C) 2000 Red Hat, Inc.
2258+ *
2259+ * This library is free software; you can redistribute it and/or
2260+ * modify it under the terms of the GNU Lesser General Public
2261+ * License as published by the Free Software Foundation; either
2262+ * version 2 of the License, or (at your option) any later version.
2263+ *
2264+ * This library is distributed in the hope that it will be useful,
2265+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2266+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2267+ * Lesser General Public License for more details.
2268+ *
2269+ * You should have received a copy of the GNU Lesser General Public
2270+ * License along with this library; if not, write to the
2271+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
2272+ * Boston, MA 02111-1307, USA.
2273+ */
2274+
2275+#include <config.h>
2276+#include <stdlib.h>
2277+
2278+#include "gdkx.h"
2279+#include "gdkdisplay-x11.h"
2280+#include "gdkpango.h"
2281+#include <pango/pangoxft.h>
2282+#include <pango/pangoxft-render.h>
2283+#include "gdkalias.h"
2284+
2285+#include <math.h>
2286+
2287+typedef struct _GdkX11Renderer GdkX11Renderer;
2288+typedef struct _GdkX11RendererClass GdkX11RendererClass;
2289+
2290+#define GDK_TYPE_X11_RENDERER (_gdk_x11_renderer_get_type())
2291+#define GDK_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_RENDERER, GdkX11Renderer))
2292+#define GDK_IS_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_RENDERER))
2293+#define GDK_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_RENDERER, GdkX11RendererClass))
2294+#define GDK_IS_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_RENDERER))
2295+#define GDK_X11_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_RENDERER, GdkX11RendererClass))
2296+
2297+#define MAX_RENDER_PART PANGO_RENDER_PART_STRIKETHROUGH
2298+
2299+struct _GdkX11Renderer
2300+{
2301+ PangoXftRenderer parent_instance;
2302+
2303+ XRenderPictFormat *mask_format;
2304+
2305+ GdkDrawable *drawable;
2306+ GdkGC *gc;
2307+};
2308+
2309+struct _GdkX11RendererClass
2310+{
2311+ PangoXftRendererClass parent_class;
2312+};
2313+
2314+G_DEFINE_TYPE (GdkX11Renderer, _gdk_x11_renderer, PANGO_TYPE_XFT_RENDERER)
2315+
2316+static void
2317+gdk_x11_renderer_finalize (GObject *object)
2318+{
2319+ G_OBJECT_CLASS (_gdk_x11_renderer_parent_class)->finalize (object);
2320+}
2321+
2322+static void
2323+gdk_x11_renderer_composite_trapezoids (PangoXftRenderer *xftrenderer,
2324+ PangoRenderPart part,
2325+ XTrapezoid *trapezoids,
2326+ int n_trapezoids)
2327+{
2328+ /* Because we only use this renderer for "draw_glyphs()" calls, we
2329+ * won't hit this code path much. However, it is hit for drawing
2330+ * the "unknown glyph" hex squares. We can safely ignore the part,
2331+ */
2332+ GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer);
2333+
2334+ _gdk_x11_drawable_draw_xtrapezoids (x11_renderer->drawable,
2335+ x11_renderer->gc,
2336+ trapezoids, n_trapezoids);
2337+
2338+}
2339+
2340+static void
2341+gdk_x11_renderer_composite_glyphs (PangoXftRenderer *xftrenderer,
2342+ XftFont *xft_font,
2343+ XftGlyphSpec *glyphs,
2344+ gint n_glyphs)
2345+{
2346+ GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer);
2347+
2348+ _gdk_x11_drawable_draw_xft_glyphs (x11_renderer->drawable,
2349+ x11_renderer->gc,
2350+ xft_font, glyphs, n_glyphs);
2351+}
2352+
2353+static void
2354+_gdk_x11_renderer_init (GdkX11Renderer *renderer)
2355+{
2356+}
2357+
2358+static void
2359+_gdk_x11_renderer_class_init (GdkX11RendererClass *klass)
2360+{
2361+ PangoXftRendererClass *xftrenderer_class = PANGO_XFT_RENDERER_CLASS (klass);
2362+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
2363+
2364+ xftrenderer_class->composite_glyphs = gdk_x11_renderer_composite_glyphs;
2365+ xftrenderer_class->composite_trapezoids = gdk_x11_renderer_composite_trapezoids;
2366+
2367+ object_class->finalize = gdk_x11_renderer_finalize;
2368+}
2369+
2370+PangoRenderer *
2371+_gdk_x11_renderer_get (GdkDrawable *drawable,
2372+ GdkGC *gc)
2373+{
2374+ GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
2375+ GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
2376+ GdkX11Renderer *x11_renderer;
2377+
2378+ if (!screen_x11->renderer)
2379+ {
2380+ screen_x11->renderer = g_object_new (GDK_TYPE_X11_RENDERER,
2381+ "display", GDK_SCREEN_XDISPLAY (screen),
2382+ "screen", GDK_SCREEN_XNUMBER (screen),
2383+ NULL);
2384+ }
2385+
2386+ x11_renderer = GDK_X11_RENDERER (screen_x11->renderer);
2387+
2388+ x11_renderer->drawable = drawable;
2389+ x11_renderer->gc = gc;
2390+
2391+ return screen_x11->renderer;
2392+}
2393+
2394+/**
2395+ * gdk_pango_context_get_for_screen:
2396+ * @screen: the #GdkScreen for which the context is to be created.
2397+ *
2398+ * Creates a #PangoContext for @screen.
2399+ *
2400+ * The context must be freed when you're finished with it.
2401+ *
2402+ * When using GTK+, normally you should use gtk_widget_get_pango_context()
2403+ * instead of this function, to get the appropriate context for
2404+ * the widget you intend to render text onto.
2405+ *
2406+ * Return value: a new #PangoContext for @screen
2407+ *
2408+ * Since: 2.2
2409+ **/
2410+PangoContext *
2411+gdk_pango_context_get_for_screen (GdkScreen *screen)
2412+{
2413+ PangoContext *context;
2414+
2415+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2416+
2417+ if (screen->closed)
2418+ return NULL;
2419+
2420+ context = pango_xft_get_context (GDK_SCREEN_XDISPLAY (screen),
2421+ GDK_SCREEN_X11 (screen)->screen_num);
2422+
2423+ g_object_set_data (G_OBJECT (context), "gdk-pango-screen", screen);
2424+
2425+ return context;
2426+}
2427+
2428+#define __GDK_PANGO_X11_C__
2429+#include "gdkaliasdef.c"
2430Index: gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c
2431===================================================================
2432--- gtk+-2.10.6.orig/gdk/x11/gdkpixmap-x11.c 2006-10-30 12:58:30.000000000 +0000
2433+++ gtk+-2.10.6/gdk/x11/gdkpixmap-x11.c 2006-10-30 12:59:30.000000000 +0000
2434@@ -119,6 +119,9 @@
2435 {
2436 GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
2437
2438+ if (draw_impl->xft_draw)
2439+ XftDrawDestroy (draw_impl->xft_draw);
2440+
2441 _gdk_x11_drawable_finish (GDK_DRAWABLE (draw_impl));
2442 }
2443
2444--- gtk+-2.10.6.orig/gtk/gtkcalendar.c.orig 2006-11-14 14:39:34.000000000 -0800
2445+++ gtk+-2.10.6/gtk/gtkcalendar.c 2006-11-14 14:37:34.000000000 -0800
2446@@ -1495,6 +1495,10 @@ gtk_calendar_realize (GtkWidget *widget)
2447 BACKGROUND_COLOR ( GTK_WIDGET ( calendar)));
2448 gdk_window_show (priv->main_win);
2449 gdk_window_set_user_data (priv->main_win, widget);
2450+
2451+ /* Set widgets gc */
2452+ calendar->gc = gdk_gc_new (widget->window);
2453+
2454 gdk_window_set_background (widget->window, BACKGROUND_COLOR (widget));
2455 gdk_window_show (widget->window);
2456 gdk_window_set_user_data (widget->window, widget);
diff --git a/meta/packages/gtk+/gtk+-2.13.2/range-no-redraw.patch b/meta/packages/gtk+/gtk+-2.13.2/range-no-redraw.patch
new file mode 100644
index 0000000000..14387b8a2e
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/range-no-redraw.patch
@@ -0,0 +1,127 @@
15f084ea0849d5967a3c22821542ecaaa8accb398
2diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
3index bd95351..64e0e59 100644
4--- gtk/gtkrange.c
5+++ gtk/gtkrange.c
6@@ -109,6 +109,8 @@ struct _GtkRangeLayout
7 GtkSensitivityType upper_sensitivity;
8
9 gdouble fill_level;
10+
11+ guint motion_idle_id;
12 };
13
14
15@@ -205,6 +207,8 @@ static gboolean gtk_range_real_change_value (GtkRange *range,
16 static void gtk_range_update_value (GtkRange *range);
17 static gboolean gtk_range_key_press (GtkWidget *range,
18 GdkEventKey *event);
19+static void gtk_range_add_motion_idle (GtkRange *range);
20+static void gtk_range_remove_motion_idle (GtkRange *range);
21
22
23 static guint signals[LAST_SIGNAL];
24@@ -1167,6 +1171,7 @@ gtk_range_destroy (GtkObject *object)
25
26 gtk_range_remove_step_timer (range);
27 gtk_range_remove_update_timer (range);
28+ gtk_range_remove_motion_idle (range);
29
30 if (range->adjustment)
31 {
32@@ -1276,6 +1281,7 @@ gtk_range_unrealize (GtkWidget *widget)
33
34 gtk_range_remove_step_timer (range);
35 gtk_range_remove_update_timer (range);
36+ gtk_range_remove_motion_idle (range);
37
38 gdk_window_set_user_data (range->event_window, NULL);
39 gdk_window_destroy (range->event_window);
40@@ -2165,7 +2171,7 @@ gtk_range_motion_notify (GtkWidget *widget,
41 gtk_widget_queue_draw (widget);
42
43 if (range->layout->grab_location == MOUSE_SLIDER)
44- update_slider_position (range, x, y);
45+ gtk_range_add_motion_idle (range);
46
47 /* We handled the event if the mouse was in the range_rect */
48 return range->layout->mouse_location != MOUSE_OUTSIDE;
49@@ -3335,9 +3341,10 @@ initial_timeout (gpointer data)
50 g_object_get (settings, "gtk-timeout-repeat", &timeout, NULL);
51
52 range = GTK_RANGE (data);
53- range->timer->timeout_id = gdk_threads_add_timeout (timeout * SCROLL_DELAY_FACTOR,
54- second_timeout,
55- range);
56+ range->timer->timeout_id =
57+ gdk_threads_add_timeout (timeout * SCROLL_DELAY_FACTOR,
58+ second_timeout,
59+ range);
60 /* remove self */
61 return FALSE;
62 }
63@@ -3357,9 +3364,8 @@ gtk_range_add_step_timer (GtkRange *range,
64
65 range->timer = g_new (GtkRangeStepTimer, 1);
66
67- range->timer->timeout_id = gdk_threads_add_timeout (timeout,
68- initial_timeout,
69- range);
70+ range->timer->timeout_id =
71+ gdk_threads_add_timeout (timeout, initial_timeout, range);
72 range->timer->step = step;
73
74 gtk_range_scroll (range, range->timer->step);
75@@ -3397,9 +3403,8 @@ gtk_range_reset_update_timer (GtkRange *range)
76 {
77 gtk_range_remove_update_timer (range);
78
79- range->update_timeout_id = gdk_threads_add_timeout (UPDATE_DELAY,
80- update_timeout,
81- range);
82+ range->update_timeout_id =
83+ gdk_threads_add_timeout (UPDATE_DELAY, update_timeout, range);
84 }
85
86 static void
87@@ -3412,5 +3417,40 @@ gtk_range_remove_update_timer (GtkRange *range)
88 }
89 }
90
91+static gboolean
92+motion_idle (gpointer data)
93+{
94+ GtkRange *range = data;
95+ GtkRangeLayout *layout = range->layout;
96+
97+ update_slider_position (range, layout->mouse_x, layout->mouse_y);
98+
99+ layout->motion_idle_id = 0;
100+
101+ return FALSE;
102+}
103+
104+static void
105+gtk_range_add_motion_idle (GtkRange *range)
106+{
107+ if (!range->layout->motion_idle_id)
108+ {
109+ range->layout->motion_idle_id =
110+ gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
111+ motion_idle, range,
112+ NULL);
113+ }
114+}
115+
116+static void
117+gtk_range_remove_motion_idle (GtkRange *range)
118+{
119+ if (range->layout->motion_idle_id != 0)
120+ {
121+ g_source_remove (range->layout->motion_idle_id);
122+ range->layout->motion_idle_id = 0;
123+ }
124+}
125+
126 #define __GTK_RANGE_C__
127 #include "gtkaliasdef.c"
diff --git a/meta/packages/gtk+/gtk+-2.13.2/run-iconcache.patch b/meta/packages/gtk+/gtk+-2.13.2/run-iconcache.patch
new file mode 100644
index 0000000000..ac15e9ab24
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/run-iconcache.patch
@@ -0,0 +1,19 @@
1--- /tmp/Makefile.am 2007-01-08 17:44:47.000000000 +0100
2+++ gtk+-2.10.7/gtk/Makefile.am 2007-01-08 17:45:17.025251000 +0100
3@@ -1128,11 +1128,11 @@
4 ./gtk-update-icon-cache
5 endif
6
7-gtkbuiltincache.h: @REBUILD@ stamp-icons
8- $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT)
9- $(gtk_update_icon_cache_program) --force --ignore-theme-index \
10- --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \
11- mv gtkbuiltincache.h.tmp gtkbuiltincache.h
12+#gtkbuiltincache.h: @REBUILD@ stamp-icons
13+# $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT)
14+# $(gtk_update_icon_cache_program) --force --ignore-theme-index \
15+# --source builtin_icons stock-icons > gtkbuiltincache.h.tmp && \
16+# mv gtkbuiltincache.h.tmp gtkbuiltincache.h
17
18 EXTRA_DIST += \
19 $(STOCK_ICONS) \
diff --git a/meta/packages/gtk+/gtk+-2.13.2/toggle-font.diff b/meta/packages/gtk+/gtk+-2.13.2/toggle-font.diff
new file mode 100644
index 0000000000..59ad150b2f
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/toggle-font.diff
@@ -0,0 +1,100 @@
1Index: gtk/gtkcellrenderertoggle.c
2===================================================================
3--- gtk/gtkcellrenderertoggle.c (revision 18523)
4+++ gtk/gtkcellrenderertoggle.c (working copy)
5@@ -71,6 +71,8 @@
6 PROP_INDICATOR_SIZE
7 };
8
9+/* This is a hard-coded default which promptly gets overridden by a size
10+ calculated from the font size. */
11 #define TOGGLE_WIDTH 13
12
13 static guint toggle_cell_signals[LAST_SIGNAL] = { 0 };
14@@ -80,8 +82,9 @@
15 typedef struct _GtkCellRendererTogglePrivate GtkCellRendererTogglePrivate;
16 struct _GtkCellRendererTogglePrivate
17 {
18- gint indicator_size;
19-
20+ gint indicator_size; /* This is the real size */
21+ gint override_size; /* This is the size set from the indicator-size property */
22+ GtkWidget *cached_widget;
23 guint inconsistent : 1;
24 };
25
26@@ -104,6 +107,7 @@
27 GTK_CELL_RENDERER (celltoggle)->ypad = 2;
28
29 priv->indicator_size = TOGGLE_WIDTH;
30+ priv->override_size = 0;
31 priv->inconsistent = FALSE;
32 }
33
34@@ -210,7 +214,7 @@
35 g_value_set_boolean (value, celltoggle->radio);
36 break;
37 case PROP_INDICATOR_SIZE:
38- g_value_set_int (value, priv->indicator_size);
39+ g_value_set_int (value, priv->override_size ? priv->override_size : priv->indicator_size);
40 break;
41 default:
42 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
43@@ -245,7 +249,7 @@
44 celltoggle->radio = g_value_get_boolean (value);
45 break;
46 case PROP_INDICATOR_SIZE:
47- priv->indicator_size = g_value_get_int (value);
48+ priv->override_size = g_value_get_int (value);
49 break;
50 default:
51 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
52@@ -273,6 +277,27 @@
53 }
54
55 static void
56+on_widget_style_set (GtkWidget *widget, GtkStyle *previous, gpointer user_data)
57+{
58+ GtkCellRendererTogglePrivate *priv = user_data;
59+ PangoContext *context;
60+ PangoFontMetrics *metrics;
61+ int height;
62+
63+ context = gtk_widget_get_pango_context (widget);
64+ metrics = pango_context_get_metrics (context,
65+ widget->style->font_desc,
66+ pango_context_get_language (context));
67+
68+ height = pango_font_metrics_get_ascent (metrics) +
69+ pango_font_metrics_get_descent (metrics);
70+
71+ pango_font_metrics_unref (metrics);
72+
73+ priv->indicator_size = PANGO_PIXELS (height * 0.85);
74+}
75+
76+static void
77 gtk_cell_renderer_toggle_get_size (GtkCellRenderer *cell,
78 GtkWidget *widget,
79 GdkRectangle *cell_area,
80@@ -287,6 +312,20 @@
81
82 priv = GTK_CELL_RENDERER_TOGGLE_GET_PRIVATE (cell);
83
84+ if (priv->override_size) {
85+ priv->indicator_size = priv->override_size;
86+ } else if (priv->cached_widget != widget) {
87+ if (priv->cached_widget) {
88+ g_object_remove_weak_pointer (widget, &priv->cached_widget);
89+ g_signal_handlers_disconnect_by_func (priv->cached_widget, on_widget_style_set, priv);
90+ }
91+ priv->cached_widget = widget;
92+ g_object_add_weak_pointer (widget, &priv->cached_widget);
93+ g_signal_connect (widget, "style-set", on_widget_style_set, priv);
94+
95+ on_widget_style_set (widget, NULL, priv);
96+ }
97+
98 calc_width = (gint) cell->xpad * 2 + priv->indicator_size;
99 calc_height = (gint) cell->ypad * 2 + priv->indicator_size;
100
diff --git a/meta/packages/gtk+/gtk+-2.13.2/xsettings.patch b/meta/packages/gtk+/gtk+-2.13.2/xsettings.patch
new file mode 100644
index 0000000000..b63e262d34
--- /dev/null
+++ b/meta/packages/gtk+/gtk+-2.13.2/xsettings.patch
@@ -0,0 +1,16 @@
1--- gtk+-2.4.4/gdk/x11/gdkevents-x11.c.old Sun Aug 22 17:14:00 2004
2+++ gtk+-2.4.4/gdk/x11/gdkevents-x11.c Sun Aug 22 17:14:00 2004
3@@ -2827,10 +2827,9 @@
4 {
5 GdkScreenX11 *screen = data;
6
7- if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
8- return GDK_FILTER_REMOVE;
9- else
10- return GDK_FILTER_CONTINUE;
11+ xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent);
12+
13+ return GDK_FILTER_CONTINUE;
14 }
15
16 static void
diff --git a/meta/packages/gtk+/gtk+_2.13.2.bb b/meta/packages/gtk+/gtk+_2.13.2.bb
new file mode 100644
index 0000000000..8d0994fd1d
--- /dev/null
+++ b/meta/packages/gtk+/gtk+_2.13.2.bb
@@ -0,0 +1,47 @@
1require gtk+.inc
2
3DEPENDS += "cairo"
4
5SRC_URI = "http://download.gnome.org/sources/gtk+/2.13/gtk+-${PV}.tar.bz2 \
6 file://xsettings.patch;patch=1 \
7 file://run-iconcache.patch;patch=1 \
8 file://hardcoded_libtool.patch;patch=1 \
9 file://no-demos.patch;patch=1 \
10 file://cellrenderer-cairo.patch;patch=1;pnum=0 \
11 file://entry-cairo.patch;patch=1;pnum=0 \
12 file://toggle-font.diff;patch=1;pnum=0 \
13 file://filesystem-volumes.patch;patch=1 \
14# TO MERGE
15# file://filechooser-props.patch;patch=1 \
16# file://filechooser-default.patch;patch=1 \
17# file://filechooser-sizefix.patch;patch=1 \
18# temporary
19# file://gtklabel-resize-patch;patch=1 \
20# file://menu-deactivate.patch;patch=1 \
21# file://combo-arrow-size.patch;patch=1;pnum=0 \
22 "
23
24EXTRA_OECONF = "--without-libtiff --without-libjasper --disable-xkb --disable-glibtest --disable-cups"
25
26LIBV = "2.10.0"
27
28PACKAGES_DYNAMIC = "gdk-pixbuf-loader-* gtk-immodule-* gtk-printbackend-*"
29
30python populate_packages_prepend () {
31 import os.path
32
33 prologue = bb.data.getVar("postinst_prologue", d, 1)
34 postinst_pixbufloader = bb.data.getVar("postinst_pixbufloader", d, 1)
35
36 gtk_libdir = bb.data.expand('${libdir}/gtk-2.0/${LIBV}', d)
37 loaders_root = os.path.join(gtk_libdir, 'loaders')
38 immodules_root = os.path.join(gtk_libdir, 'immodules')
39 printmodules_root = os.path.join(gtk_libdir, 'printbackends');
40
41 do_split_packages(d, loaders_root, '^libpixbufloader-(.*)\.so$', 'gdk-pixbuf-loader-%s', 'GDK pixbuf loader for %s', postinst_pixbufloader)
42 do_split_packages(d, immodules_root, '^im-(.*)\.so$', 'gtk-immodule-%s', 'GTK input module for %s', prologue + 'gtk-query-immodules-2.0 > /etc/gtk-2.0/gtk.immodules')
43 do_split_packages(d, printmodules_root, '^libprintbackend-(.*)\.so$', 'gtk-printbackend-%s', 'GTK printbackend module for %s')
44
45 if (bb.data.getVar('DEBIAN_NAMES', d, 1)):
46 bb.data.setVar('PKG_${PN}', 'libgtk-2.0', d)
47}
diff --git a/meta/packages/pango/pango-1.21.2/no-tests.patch b/meta/packages/pango/pango-1.21.2/no-tests.patch
new file mode 100644
index 0000000000..dafcb20c3b
--- /dev/null
+++ b/meta/packages/pango/pango-1.21.2/no-tests.patch
@@ -0,0 +1,10 @@
1--- /tmp/Makefile.am 2007-03-01 13:29:37.000000000 +0100
2+++ pango-1.16.0/Makefile.am 2007-03-01 13:29:52.545251000 +0100
3@@ -1,6 +1,6 @@
4 ## Process this file with automake to create Makefile.in.
5
6-SUBDIRS= pango modules pango-view examples docs tools tests
7+SUBDIRS= pango modules pango-view examples docs tools
8
9 EXTRA_DIST = \
10 autogen.sh \
diff --git a/meta/packages/pango/pango_1.10.2.bb b/meta/packages/pango/pango_1.10.2.bb
deleted file mode 100644
index 6b8d912d40..0000000000
--- a/meta/packages/pango/pango_1.10.2.bb
+++ /dev/null
@@ -1,49 +0,0 @@
1LICENSE = "LGPL"
2SECTION = "x11/libs"
3DEPENDS = "glib-2.0 fontconfig freetype zlib virtual/libx11 libxft gtk-doc-native cairo"
4DESCRIPTION = "The goal of the Pango project is to provide an \
5Open Source framework for the layout and rendering of \
6internationalized text."
7PR = "r0"
8
9RRECOMMENDS_${PN} = "pango-module-basic-x pango-module-basic-fc"
10
11# seems to go wrong with default cflags
12FULL_OPTIMIZATION_arm = "-O2"
13
14SRC_URI = "ftp://ftp.gtk.org/pub/gtk/v2.8/pango-${PV}.tar.bz2 \
15 file://no-tests.patch;patch=1"
16
17inherit autotools pkgconfig
18
19EXTRA_OECONF = "--disable-glibtest \
20 --enable-explicit-deps=no \
21 --disable-debug"
22
23LEAD_SONAME = "libpango-1.0*"
24LIBV = "1.4.0"
25
26FILES_${PN} = "/etc ${bindir}/* ${libdir}/libpango*.so.*"
27FILES_${PN}-dbg += "${libdir}/pango/${LIBV}/modules/.debug"
28FILES_${PN}-dev += "${libdir}/pango/${LIBV}/modules/*.la"
29
30do_stage () {
31autotools_stage_all
32}
33
34postinst_prologue() {
35if [ "x$D" != "x" ]; then
36 exit 1
37fi
38
39}
40
41PACKAGES_DYNAMIC = "pango-module-*"
42
43python populate_packages_prepend () {
44 prologue = bb.data.getVar("postinst_prologue", d, 1)
45
46 modules_root = bb.data.expand('${libdir}/pango/${LIBV}/modules', d)
47
48 do_split_packages(d, modules_root, '^pango-(.*)\.so$', 'pango-module-%s', 'Pango module %s', prologue + 'pango-querymodules > /etc/pango/pango.modules')
49}
diff --git a/meta/packages/pango/pango_1.21.2.bb b/meta/packages/pango/pango_1.21.2.bb
new file mode 100644
index 0000000000..be37e8f76b
--- /dev/null
+++ b/meta/packages/pango/pango_1.21.2.bb
@@ -0,0 +1,3 @@
1require pango.inc
2
3SRC_URI += "file://no-tests.patch;patch=1"