summaryrefslogtreecommitdiffstats
path: root/meta/packages/gtk+
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@linux.intel.com>2009-01-02 17:03:34 +0000
committerRichard Purdie <rpurdie@linux.intel.com>2009-01-02 17:03:34 +0000
commit23486c1532e7653a1b4ef405e28a014f0223fd11 (patch)
tree7fcc106fd926fc1dd9e60528a6cf4daf94c3dd2d /meta/packages/gtk+
parentcf093fa0f307a4614585f711bf501885cf1fccf6 (diff)
downloadpoky-23486c1532e7653a1b4ef405e28a014f0223fd11.tar.gz
gtk+: Drop old 2.10.* and 2.13* versions
Diffstat (limited to 'meta/packages/gtk+')
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/cellrenderer-cairo.patch32
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/combo-arrow-size.patch66
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/disable-print.patch50
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/entry-cairo.patch103
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch6651
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch77
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch32
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filechooser.patch25
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch198
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/gtklabel-resize-patch10
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/hardcoded_libtool.patch29
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/menu-deactivate.patch51
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/no-demos.patch10
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/pangoxft2.10.6.diff2456
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/range-no-redraw.patch41
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/run-iconcache.patch19
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/scrolled-placement.patch35
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/toggle-font.diff100
-rw-r--r--meta/packages/gtk+/gtk+-2.10.14/xsettings.patch16
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/cellrenderer-cairo.patch32
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/combo-arrow-size.patch67
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/entry-cairo.patch103
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/filechooser-default.patch9521
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/filechooser-props.patch57
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/filechooser-sizefix.patch35
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/filesystem-volumes.patch198
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/gtklabel-resize-patch10
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/hardcoded_libtool.patch29
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/menu-deactivate.patch51
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/no-demos.patch10
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/pangoxft2.10.6.diff2456
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/range-no-redraw.patch127
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/run-iconcache.patch19
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/toggle-font.diff100
-rw-r--r--meta/packages/gtk+/gtk+-2.13.3/xsettings.patch16
-rw-r--r--meta/packages/gtk+/gtk+_2.10.14.bb50
-rw-r--r--meta/packages/gtk+/gtk+_2.13.3.bb47
37 files changed, 0 insertions, 22929 deletions
diff --git a/meta/packages/gtk+/gtk+-2.10.14/cellrenderer-cairo.patch b/meta/packages/gtk+/gtk+-2.10.14/cellrenderer-cairo.patch
deleted file mode 100644
index 4439e69fb6..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/cellrenderer-cairo.patch
+++ /dev/null
@@ -1,32 +0,0 @@
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.10.14/combo-arrow-size.patch b/meta/packages/gtk+/gtk+-2.10.14/combo-arrow-size.patch
deleted file mode 100644
index ec408a5f28..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/combo-arrow-size.patch
+++ /dev/null
@@ -1,66 +0,0 @@
1Index: gtk/gtkcombobox.c
2===================================================================
3--- gtk/gtkcombobox.c.orig 2007-08-21 11:10:15.000000000 +0000
4+++ gtk/gtkcombobox.c 2007-08-21 11:13:00.000000000 +0000
5@@ -692,6 +692,25 @@
6 FALSE,
7 GTK_PARAM_READABLE));
8
9+ /**
10+ * GtkComboBox:arrow-size:
11+ *
12+ * Sets the minimum size of the arrow in the combo box. Note
13+ * that the arrow size is coupled to the font size, so in case
14+ * a larger font is used, the arrow will be larger than set
15+ * by arrow size.
16+ *
17+ * Since: 2.12
18+ */
19+ gtk_widget_class_install_style_property (widget_class,
20+ g_param_spec_int ("arrow-size",
21+ P_("Arrow Size"),
22+ P_("The minimum size of the arrow in the combo box"),
23+ 0,
24+ G_MAXINT,
25+ 15,
26+ GTK_PARAM_READABLE));
27+
28 g_type_class_add_private (object_class, sizeof (GtkComboBoxPrivate));
29 }
30
31@@ -1926,8 +1945,13 @@
32 {
33 GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
34 gint focus_width, focus_pad;
35+ gint font_size;
36+ gint arrow_size;
37 GtkAllocation child;
38 GtkRequisition req;
39+ PangoContext *context;
40+ PangoFontMetrics *metrics;
41+ PangoFontDescription *font_desc;
42 gboolean is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
43
44 widget->allocation = *allocation;
45@@ -1935,8 +1959,21 @@
46 gtk_widget_style_get (GTK_WIDGET (widget),
47 "focus-line-width", &focus_width,
48 "focus-padding", &focus_pad,
49+ "arrow-size", &arrow_size,
50 NULL);
51
52+ font_desc = GTK_BIN (widget)->child->style->font_desc;
53+ context = gtk_widget_get_pango_context (widget);
54+ metrics = pango_context_get_metrics (context, font_desc,
55+ pango_context_get_language (context));
56+ font_size = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
57+ pango_font_metrics_get_descent (metrics));
58+ pango_font_metrics_unref (metrics);
59+
60+ arrow_size = MAX (arrow_size, font_size);
61+
62+ gtk_widget_set_size_request (combo_box->priv->arrow, arrow_size, arrow_size);
63+
64 if (!combo_box->priv->tree_view)
65 {
66 if (combo_box->priv->cell_view)
diff --git a/meta/packages/gtk+/gtk+-2.10.14/disable-print.patch b/meta/packages/gtk+/gtk+-2.10.14/disable-print.patch
deleted file mode 100644
index 1067773f12..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/disable-print.patch
+++ /dev/null
@@ -1,50 +0,0 @@
1--- gtk+-2.10.0/configure.in~ 2006-07-05 18:11:44.000000000 +0200
2+++ gtk+-2.10.0/configure.in 2006-07-05 18:11:44.000000000 +0200
3@@ -1539,26 +1539,27 @@
4 # Printing system checks
5 ################################################################
6
7-AC_PATH_PROG(CUPS_CONFIG, cups-config, no)
8-if test "x$CUPS_CONFIG" != "xno"; then
9- CUPS_CFLAGS=`cups-config --cflags | sed 's/-O[0-9]*//' | sed 's/-m[^\t]*//g'`
10- CUPS_LIBS=`cups-config --libs`
11-
12- CUPS_API_VERSION=`cups-config --api-version`
13- CUPS_API_MAJOR=`echo -n $CUPS_API_VERSION | awk -F. '{print $1}'`
14- CUPS_API_MINOR=`echo -n $CUPS_API_VERSION | awk -F. '{print $2}'`
15-
16- if test $CUPS_API_MAJOR -gt 1 -o \
17- $CUPS_API_MAJOR -eq 1 -a $CUPS_API_MINOR -ge 2; then
18- AC_DEFINE(HAVE_CUPS_API_1_2)
19- fi
20-
21- AC_SUBST(CUPS_API_MAJOR)
22- AC_SUBST(CUPS_API_MINOR)
23- AC_SUBST(CUPS_CFLAGS)
24- AC_SUBST(CUPS_LIBS)
25-fi
26-AM_CONDITIONAL(HAVE_CUPS, test "x$CUPS_CONFIG" != "xno")
27+#AC_PATH_PROG(CUPS_CONFIG, cups-config, no)
28+#if test "x$CUPS_CONFIG" != "xno"; then
29+# CUPS_CFLAGS=`cups-config --cflags | sed 's/-O[0-9]*//' | sed 's/-m[^\t]*//g'`
30+# CUPS_LIBS=`cups-config --libs`
31+#
32+# CUPS_API_VERSION=`cups-config --api-version`
33+# CUPS_API_MAJOR=`echo -n $CUPS_API_VERSION | awk -F. '{print $1}'`
34+# CUPS_API_MINOR=`echo -n $CUPS_API_VERSION | awk -F. '{print $2}'`
35+#
36+# if test $CUPS_API_MAJOR -gt 1 -o \
37+# $CUPS_API_MAJOR -eq 1 -a $CUPS_API_MINOR -ge 2; then
38+# AC_DEFINE(HAVE_CUPS_API_1_2)
39+# fi
40+#
41+# AC_SUBST(CUPS_API_MAJOR)
42+# AC_SUBST(CUPS_API_MINOR)
43+# AC_SUBST(CUPS_CFLAGS)
44+# AC_SUBST(CUPS_LIBS)
45+#fi
46+#AM_CONDITIONAL(HAVE_CUPS, test "x$CUPS_CONFIG" != "xno")
47+AM_CONDITIONAL(HAVE_CUPS,false)
48
49 gtk_save_cppflags="$CPPFLAGS"
50 CPPFLAGS="$CPPFLAGS $GTK_DEP_CFLAGS"
diff --git a/meta/packages/gtk+/gtk+-2.10.14/entry-cairo.patch b/meta/packages/gtk+/gtk+-2.10.14/entry-cairo.patch
deleted file mode 100644
index 3313e7f132..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/entry-cairo.patch
+++ /dev/null
@@ -1,103 +0,0 @@
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.10.14/filechooser-default.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch
deleted file mode 100644
index 5e68c48739..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/filechooser-default.patch
+++ /dev/null
@@ -1,6651 +0,0 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooserdefault.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooserdefault.c 2007-07-16 20:44:17.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooserdefault.c 2007-08-30 15:23:54.000000000 +0100
5@@ -33,7 +33,6 @@
6 #include "gtkcombobox.h"
7 #include "gtkentry.h"
8 #include "gtkeventbox.h"
9-#include "gtkexpander.h"
10 #include "gtkfilechooserprivate.h"
11 #include "gtkfilechooserdefault.h"
12 #include "gtkfilechooserembed.h"
13@@ -54,7 +53,6 @@
14 #include "gtkmarshalers.h"
15 #include "gtkmenuitem.h"
16 #include "gtkmessagedialog.h"
17-#include "gtkpathbar.h"
18 #include "gtkprivate.h"
19 #include "gtkradiobutton.h"
20 #include "gtkscrolledwindow.h"
21@@ -88,6 +86,8 @@
22 #include <io.h>
23 #endif
24
25+#define DEFAULT_SPACING 5
26+
27 /* Profiling stuff */
28 #undef PROFILE_FILE_CHOOSER
29 #ifdef PROFILE_FILE_CHOOSER
30@@ -98,6 +98,7 @@
31 #endif
32
33 #define PROFILE_INDENT 4
34+
35 static int profile_indent;
36
37 static void
38@@ -137,8 +138,6 @@
39 #define profile_msg(x, y)
40 #endif
41
42-
43-
44 typedef struct _GtkFileChooserDefaultClass GtkFileChooserDefaultClass;
45
46 #define GTK_FILE_CHOOSER_DEFAULT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
47@@ -146,6 +145,7 @@
48 #define GTK_FILE_CHOOSER_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_CHOOSER_DEFAULT, GtkFileChooserDefaultClass))
49
50 #define MAX_LOADING_TIME 500
51+#define LONG_CLICK_LENGTH 500
52
53 struct _GtkFileChooserDefaultClass
54 {
55@@ -159,27 +159,12 @@
56 UP_FOLDER,
57 DOWN_FOLDER,
58 HOME_FOLDER,
59- DESKTOP_FOLDER,
60- QUICK_BOOKMARK,
61- LOCATION_TOGGLE_POPUP,
62 SHOW_HIDDEN,
63 LAST_SIGNAL
64 };
65
66 static guint signals[LAST_SIGNAL] = { 0 };
67
68-/* Column numbers for the shortcuts tree. Keep these in sync with shortcuts_model_create() */
69-enum {
70- SHORTCUTS_COL_PIXBUF,
71- SHORTCUTS_COL_NAME,
72- SHORTCUTS_COL_DATA,
73- SHORTCUTS_COL_IS_VOLUME,
74- SHORTCUTS_COL_REMOVABLE,
75- SHORTCUTS_COL_PIXBUF_VISIBLE,
76- SHORTCUTS_COL_HANDLE,
77- SHORTCUTS_COL_NUM_COLUMNS
78-};
79-
80 /* Column numbers for the file list */
81 enum {
82 FILE_LIST_COL_NAME,
83@@ -188,62 +173,10 @@
84 FILE_LIST_COL_NUM_COLUMNS
85 };
86
87-/* Identifiers for target types */
88-enum {
89- GTK_TREE_MODEL_ROW,
90- TEXT_URI_LIST
91-};
92-
93-/* Target types for dragging from the shortcuts list */
94-static const GtkTargetEntry shortcuts_source_targets[] = {
95- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW }
96-};
97-
98-static const int num_shortcuts_source_targets = (sizeof (shortcuts_source_targets)
99- / sizeof (shortcuts_source_targets[0]));
100-
101-/* Target types for dropping into the shortcuts list */
102-static const GtkTargetEntry shortcuts_dest_targets[] = {
103- { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, GTK_TREE_MODEL_ROW },
104- { "text/uri-list", 0, TEXT_URI_LIST }
105-};
106-
107-static const int num_shortcuts_dest_targets = (sizeof (shortcuts_dest_targets)
108- / sizeof (shortcuts_dest_targets[0]));
109-
110-/* Target types for DnD from the file list */
111-static const GtkTargetEntry file_list_source_targets[] = {
112- { "text/uri-list", 0, TEXT_URI_LIST }
113-};
114-
115-static const int num_file_list_source_targets = (sizeof (file_list_source_targets)
116- / sizeof (file_list_source_targets[0]));
117-
118-/* Target types for dropping into the file list */
119-static const GtkTargetEntry file_list_dest_targets[] = {
120- { "text/uri-list", 0, TEXT_URI_LIST }
121-};
122-
123-static const int num_file_list_dest_targets = (sizeof (file_list_dest_targets)
124- / sizeof (file_list_dest_targets[0]));
125-
126-
127-/* Interesting places in the shortcuts bar */
128-typedef enum {
129- SHORTCUTS_HOME,
130- SHORTCUTS_DESKTOP,
131- SHORTCUTS_VOLUMES,
132- SHORTCUTS_SHORTCUTS,
133- SHORTCUTS_BOOKMARKS_SEPARATOR,
134- SHORTCUTS_BOOKMARKS,
135- SHORTCUTS_CURRENT_FOLDER_SEPARATOR,
136- SHORTCUTS_CURRENT_FOLDER
137-} ShortcutsIndex;
138-
139 /* Icon size for if we can't get it from the theme */
140-#define FALLBACK_ICON_SIZE 16
141+#define FALLBACK_ICON_SIZE 24
142
143-#define PREVIEW_HBOX_SPACING 12
144+#define LIST_HBOX_SPACING DEFAULT_SPACING
145 #define NUM_LINES 45
146 #define NUM_CHARS 60
147
148@@ -308,7 +241,6 @@
149 const GtkFilePath *path,
150 GError **error);
151 static GSList * gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser);
152-
153 static void gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
154 gint *default_width,
155 gint *default_height);
156@@ -316,50 +248,17 @@
157 static gboolean gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed);
158 static void gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed);
159
160-static void location_popup_handler (GtkFileChooserDefault *impl,
161- const gchar *path);
162-static void location_popup_on_paste_handler (GtkFileChooserDefault *impl);
163-static void location_toggle_popup_handler (GtkFileChooserDefault *impl);
164 static void up_folder_handler (GtkFileChooserDefault *impl);
165 static void down_folder_handler (GtkFileChooserDefault *impl);
166 static void home_folder_handler (GtkFileChooserDefault *impl);
167-static void desktop_folder_handler (GtkFileChooserDefault *impl);
168-static void quick_bookmark_handler (GtkFileChooserDefault *impl,
169- gint bookmark_index);
170 static void show_hidden_handler (GtkFileChooserDefault *impl);
171 static void update_appearance (GtkFileChooserDefault *impl);
172
173-static void set_current_filter (GtkFileChooserDefault *impl,
174- GtkFileFilter *filter);
175-static void check_preview_change (GtkFileChooserDefault *impl);
176-
177 static void filter_combo_changed (GtkComboBox *combo_box,
178 GtkFileChooserDefault *impl);
179-static void shortcuts_row_activated_cb (GtkTreeView *tree_view,
180- GtkTreePath *path,
181- GtkTreeViewColumn *column,
182- GtkFileChooserDefault *impl);
183-
184-static gboolean shortcuts_key_press_event_cb (GtkWidget *widget,
185- GdkEventKey *event,
186- GtkFileChooserDefault *impl);
187-
188-static gboolean shortcuts_select_func (GtkTreeSelection *selection,
189- GtkTreeModel *model,
190- GtkTreePath *path,
191- gboolean path_currently_selected,
192- gpointer data);
193-static gboolean shortcuts_get_selected (GtkFileChooserDefault *impl,
194- GtkTreeIter *iter);
195-static void shortcuts_activate_iter (GtkFileChooserDefault *impl,
196- GtkTreeIter *iter);
197-static int shortcuts_get_index (GtkFileChooserDefault *impl,
198- ShortcutsIndex where);
199-static int shortcut_find_position (GtkFileChooserDefault *impl,
200- const GtkFilePath *path);
201-
202-static void bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl);
203
204+static void set_current_filter (GtkFileChooserDefault *impl,
205+ GtkFileFilter *filter);
206 static gboolean list_select_func (GtkTreeSelection *selection,
207 GtkTreeModel *model,
208 GtkTreePath *path,
209@@ -378,19 +277,6 @@
210 GtkTreeIter *iter,
211 gpointer user_data);
212
213-static void path_bar_clicked (GtkPathBar *path_bar,
214- GtkFilePath *file_path,
215- GtkFilePath *child_path,
216- gboolean child_is_hidden,
217- GtkFileChooserDefault *impl);
218-
219-static void add_bookmark_button_clicked_cb (GtkButton *button,
220- GtkFileChooserDefault *impl);
221-static void remove_bookmark_button_clicked_cb (GtkButton *button,
222- GtkFileChooserDefault *impl);
223-static void save_folder_combo_changed_cb (GtkComboBox *combo,
224- GtkFileChooserDefault *impl);
225-
226 static void list_icon_data_func (GtkTreeViewColumn *tree_column,
227 GtkCellRenderer *cell,
228 GtkTreeModel *tree_model,
229@@ -422,40 +308,8 @@
230
231 static void location_button_toggled_cb (GtkToggleButton *toggle,
232 GtkFileChooserDefault *impl);
233-static void location_switch_to_path_bar (GtkFileChooserDefault *impl);
234 static void settings_load (GtkFileChooserDefault *impl);
235
236-
237-
238-/* Drag and drop interface declarations */
239-
240-typedef struct {
241- GtkTreeModelFilter parent;
242-
243- GtkFileChooserDefault *impl;
244-} ShortcutsModelFilter;
245-
246-typedef struct {
247- GtkTreeModelFilterClass parent_class;
248-} ShortcutsModelFilterClass;
249-
250-#define SHORTCUTS_MODEL_FILTER_TYPE (_shortcuts_model_filter_get_type ())
251-#define SHORTCUTS_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHORTCUTS_MODEL_FILTER_TYPE, ShortcutsModelFilter))
252-
253-static void shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
254-
255-G_DEFINE_TYPE_WITH_CODE (ShortcutsModelFilter,
256- _shortcuts_model_filter,
257- GTK_TYPE_TREE_MODEL_FILTER,
258- G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
259- shortcuts_model_filter_drag_source_iface_init))
260-
261-static GtkTreeModel *shortcuts_model_filter_new (GtkFileChooserDefault *impl,
262- GtkTreeModel *child_model,
263- GtkTreePath *root);
264-
265-
266-
267 G_DEFINE_TYPE_WITH_CODE (GtkFileChooserDefault, _gtk_file_chooser_default, GTK_TYPE_VBOX,
268 G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
269 gtk_file_chooser_default_iface_init)
270@@ -465,13 +319,9 @@
271 static void
272 _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
273 {
274- static const guint quick_bookmark_keyvals[10] = {
275- GDK_1, GDK_2, GDK_3, GDK_4, GDK_5, GDK_6, GDK_7, GDK_8, GDK_9, GDK_0
276- };
277 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
278 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
279 GtkBindingSet *binding_set;
280- int i;
281
282 gobject_class->finalize = gtk_file_chooser_default_finalize;
283 gobject_class->constructor = gtk_file_chooser_default_constructor;
284@@ -491,7 +341,7 @@
285 _gtk_binding_signal_new (I_("location-popup"),
286 G_OBJECT_CLASS_TYPE (class),
287 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
288- G_CALLBACK (location_popup_handler),
289+ NULL,
290 NULL, NULL,
291 _gtk_marshal_VOID__STRING,
292 G_TYPE_NONE, 1, G_TYPE_STRING);
293@@ -499,15 +349,7 @@
294 _gtk_binding_signal_new ("location-popup-on-paste",
295 G_OBJECT_CLASS_TYPE (class),
296 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
297- G_CALLBACK (location_popup_on_paste_handler),
298- NULL, NULL,
299- _gtk_marshal_VOID__VOID,
300- G_TYPE_NONE, 0);
301- signals[LOCATION_TOGGLE_POPUP] =
302- _gtk_binding_signal_new (I_("location-toggle-popup"),
303- G_OBJECT_CLASS_TYPE (class),
304- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
305- G_CALLBACK (location_toggle_popup_handler),
306+ NULL,
307 NULL, NULL,
308 _gtk_marshal_VOID__VOID,
309 G_TYPE_NONE, 0);
310@@ -535,22 +377,6 @@
311 NULL, NULL,
312 _gtk_marshal_VOID__VOID,
313 G_TYPE_NONE, 0);
314- signals[DESKTOP_FOLDER] =
315- _gtk_binding_signal_new (I_("desktop-folder"),
316- G_OBJECT_CLASS_TYPE (class),
317- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
318- G_CALLBACK (desktop_folder_handler),
319- NULL, NULL,
320- _gtk_marshal_VOID__VOID,
321- G_TYPE_NONE, 0);
322- signals[QUICK_BOOKMARK] =
323- _gtk_binding_signal_new (I_("quick-bookmark"),
324- G_OBJECT_CLASS_TYPE (class),
325- G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
326- G_CALLBACK (quick_bookmark_handler),
327- NULL, NULL,
328- _gtk_marshal_VOID__INT,
329- G_TYPE_NONE, 1, G_TYPE_INT);
330 signals[SHOW_HIDDEN] =
331 _gtk_binding_signal_new ("show-hidden",
332 G_OBJECT_CLASS_TYPE (class),
333@@ -618,20 +444,10 @@
334 "home-folder",
335 0);
336 gtk_binding_entry_add_signal (binding_set,
337- GDK_d, GDK_MOD1_MASK,
338- "desktop-folder",
339- 0);
340- gtk_binding_entry_add_signal (binding_set,
341 GDK_h, GDK_CONTROL_MASK,
342 "show-hidden",
343 0);
344
345- for (i = 0; i < 10; i++)
346- gtk_binding_entry_add_signal (binding_set,
347- quick_bookmark_keyvals[i], GDK_MOD1_MASK,
348- "quick-bookmark",
349- 1, G_TYPE_INT, i);
350-
351 _gtk_file_chooser_install_properties (gobject_class);
352
353 gtk_settings_install_property (g_param_spec_string ("gtk-file-chooser-backend",
354@@ -649,7 +465,6 @@
355 iface->select_all = gtk_file_chooser_default_select_all;
356 iface->unselect_all = gtk_file_chooser_default_unselect_all;
357 iface->get_paths = gtk_file_chooser_default_get_paths;
358- iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
359 iface->get_file_system = gtk_file_chooser_default_get_file_system;
360 iface->set_current_folder = gtk_file_chooser_default_set_current_folder;
361 iface->get_current_folder = gtk_file_chooser_default_get_current_folder;
362@@ -657,9 +472,12 @@
363 iface->add_filter = gtk_file_chooser_default_add_filter;
364 iface->remove_filter = gtk_file_chooser_default_remove_filter;
365 iface->list_filters = gtk_file_chooser_default_list_filters;
366+
367+ /* these are only stubs */
368+ iface->get_preview_path = gtk_file_chooser_default_get_preview_path;
369 iface->add_shortcut_folder = gtk_file_chooser_default_add_shortcut_folder;
370 iface->remove_shortcut_folder = gtk_file_chooser_default_remove_shortcut_folder;
371- iface->list_shortcut_folders = gtk_file_chooser_default_list_shortcut_folders;
372+
373 }
374
375 static void
376@@ -679,80 +497,27 @@
377 access ("MARK: *** CREATE FILE CHOOSER", F_OK);
378 #endif
379 impl->local_only = TRUE;
380- impl->preview_widget_active = TRUE;
381- impl->use_preview_label = TRUE;
382 impl->select_multiple = FALSE;
383 impl->show_hidden = FALSE;
384+ impl->show_create_folder = TRUE;
385 impl->icon_size = FALLBACK_ICON_SIZE;
386 impl->load_state = LOAD_EMPTY;
387 impl->reload_state = RELOAD_EMPTY;
388 impl->pending_select_paths = NULL;
389- impl->location_mode = LOCATION_MODE_PATH_BAR;
390+ impl->location_mode = LOCATION_MODE_FILENAME_ENTRY;
391+ impl->path_history = NULL;
392
393- gtk_box_set_spacing (GTK_BOX (impl), 12);
394+ gtk_box_set_spacing (GTK_BOX (impl), DEFAULT_SPACING);
395
396 impl->tooltips = gtk_tooltips_new ();
397 g_object_ref_sink (impl->tooltips);
398
399- profile_end ("end", NULL);
400-}
401-
402-/* Frees the data columns for the specified iter in the shortcuts model*/
403-static void
404-shortcuts_free_row_data (GtkFileChooserDefault *impl,
405- GtkTreeIter *iter)
406-{
407- gpointer col_data;
408- gboolean is_volume;
409- GtkFileSystemHandle *handle;
410-
411- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
412- SHORTCUTS_COL_DATA, &col_data,
413- SHORTCUTS_COL_IS_VOLUME, &is_volume,
414- SHORTCUTS_COL_HANDLE, &handle,
415- -1);
416-
417- if (handle)
418- gtk_file_system_cancel_operation (handle);
419-
420- if (!col_data)
421- return;
422-
423- if (is_volume)
424- {
425- GtkFileSystemVolume *volume;
426-
427- volume = col_data;
428- gtk_file_system_volume_free (impl->file_system, volume);
429- }
430- else
431- {
432- GtkFilePath *path;
433+ if (!impl->root_folder)
434+ impl->root_folder = g_strdup ("/");
435
436- path = col_data;
437- gtk_file_path_free (path);
438- }
439+ profile_end ("end", NULL);
440 }
441
442-/* Frees all the data columns in the shortcuts model */
443-static void
444-shortcuts_free (GtkFileChooserDefault *impl)
445-{
446- GtkTreeIter iter;
447-
448- if (!impl->shortcuts_model)
449- return;
450-
451- if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
452- do
453- {
454- shortcuts_free_row_data (impl, &iter);
455- }
456- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter));
457-
458- g_object_unref (impl->shortcuts_model);
459- impl->shortcuts_model = NULL;
460-}
461
462 static void
463 pending_select_paths_free (GtkFileChooserDefault *impl)
464@@ -771,6 +536,7 @@
465 impl->pending_select_paths = NULL;
466 }
467
468+
469 static void
470 pending_select_paths_add (GtkFileChooserDefault *impl,
471 const GtkFilePath *path)
472@@ -810,15 +576,27 @@
473 }
474
475 static void
476-gtk_file_chooser_default_finalize (GObject *object)
477+path_history_free (GtkFileChooserDefault *impl)
478 {
479- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
480 GSList *l;
481
482- if (impl->shortcuts_filter_model)
483- g_object_unref (impl->shortcuts_filter_model);
484+ for (l = impl->path_history; l; l = l->next)
485+ {
486+ GtkFilePath *path;
487+
488+ path = l->data;
489+ gtk_file_path_free (path);
490+ }
491+
492+ g_slist_free (impl->path_history);
493+ impl->path_history = NULL;
494+}
495
496- shortcuts_free (impl);
497+static void
498+gtk_file_chooser_default_finalize (GObject *object)
499+{
500+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (object);
501+ GSList *l;
502
503 g_object_unref (impl->file_system);
504
505@@ -842,8 +620,7 @@
506 if (impl->current_folder)
507 gtk_file_path_free (impl->current_folder);
508
509- if (impl->preview_path)
510- gtk_file_path_free (impl->preview_path);
511+ path_history_free (impl);
512
513 load_remove_timer (impl);
514
515@@ -854,12 +631,18 @@
516 if (impl->sort_model)
517 g_object_unref (impl->sort_model);
518
519- g_free (impl->preview_display_name);
520+ if (impl->list_press_path)
521+ {
522+ gtk_tree_path_free (impl->list_press_path);
523+ impl->list_press_path = NULL;
524+ }
525
526 g_free (impl->edited_new_text);
527
528 g_object_unref (impl->tooltips);
529
530+ g_free (impl->root_folder);
531+
532 G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->finalize (object);
533 }
534
535@@ -944,28 +727,6 @@
536 path, error);
537 }
538
539-/* Shows an error dialog about not being able to add a bookmark */
540-static void
541-error_adding_bookmark_dialog (GtkFileChooserDefault *impl,
542- const GtkFilePath *path,
543- GError *error)
544-{
545- error_dialog (impl,
546- _("Could not add a bookmark"),
547- path, error);
548-}
549-
550-/* Shows an error dialog about not being able to remove a bookmark */
551-static void
552-error_removing_bookmark_dialog (GtkFileChooserDefault *impl,
553- const GtkFilePath *path,
554- GError *error)
555-{
556- error_dialog (impl,
557- _("Could not remove bookmark"),
558- path, error);
559-}
560-
561 /* Shows an error dialog about not being able to create a folder */
562 static void
563 error_creating_folder_dialog (GtkFileChooserDefault *impl,
564@@ -1015,2637 +776,389 @@
565
566 /* Changes folders, displaying an error dialog if this fails */
567 static gboolean
568-change_folder_and_display_error (GtkFileChooserDefault *impl,
569- const GtkFilePath *path,
570- gboolean clear_entry)
571+change_folder (GtkFileChooserDefault *impl, const GtkFilePath *path,
572+ gboolean errormsg)
573 {
574 GError *error;
575 gboolean result;
576 GtkFilePath *path_copy;
577+ gchar * file_name;
578
579 g_return_val_if_fail (path != NULL, FALSE);
580
581- profile_start ("start", (char *) path);
582+ path_copy = gtk_file_path_copy (path);
583+ file_name = gtk_file_system_path_to_filename (impl->file_system, path_copy);
584
585- /* We copy the path because of this case:
586- *
587- * list_row_activated()
588- * fetches path from model; path belongs to the model (*)
589- * calls change_folder_and_display_error()
590- * calls _gtk_file_chooser_set_current_folder_path()
591- * changing folders fails, sets model to NULL, thus freeing the path in (*)
592- */
593+ if (!file_name)
594+ {
595+ gtk_file_path_free (path_copy);
596+ return 0;
597+ }
598+
599+ if (impl->root_folder && file_name[0] == '/' && file_name[1] == 0)
600+ {
601+ /* If changing to / and we have root_folder, change into it instead */
602+ gtk_file_path_free (path_copy);
603+ path_copy = gtk_file_system_filename_to_path (impl->file_system,
604+ impl->root_folder);
605+
606+ gtk_widget_set_sensitive (impl->up_button, FALSE);
607+ }
608+ else if (impl->root_folder &&
609+ strcmp (file_name, impl->root_folder) &&
610+ !strncmp (file_name, impl->root_folder, strlen (file_name)))
611+ {
612+ /* refuse to change below the root */
613+ gtk_file_path_free (path_copy);
614+ g_free (file_name);
615+ return 0;
616+ }
617+ else if (!strcmp (file_name, impl->root_folder))
618+ {
619+ gtk_widget_set_sensitive (impl->up_button, FALSE);
620+ }
621+ else if (impl->current_folder && !strcmp (file_name, "/media"))
622+ {
623+ /* Asked to changed into /media -- if we are already in a media
624+ * child folder, we refuse, but if we are in the root, we permit this
625+ */
626+ gchar *name =
627+ gtk_file_system_path_to_filename (impl->file_system,
628+ impl->current_folder);
629+
630+ if (name && !strncmp (name, "/media", 6))
631+ {
632+ g_free (name);
633+ gtk_file_path_free (path_copy);
634+ g_free (file_name);
635+ return 0;
636+ }
637+
638+ gtk_widget_set_sensitive (impl->up_button, TRUE);
639+ }
640+ else if (!strncmp (file_name, "/media/", 7))
641+ {
642+ /* Changing into a media child -- if it is an immediate child, disable
643+ * the Up button
644+ */
645+ gchar * p = file_name + 7;
646+ gchar * q = strchr (p, '/');
647+ if (!q)
648+ gtk_widget_set_sensitive (impl->up_button, FALSE);
649+ else
650+ gtk_widget_set_sensitive (impl->up_button, TRUE);
651+ }
652+ else
653+ {
654+ gtk_widget_set_sensitive (impl->up_button, TRUE);
655+ }
656
657- path_copy = gtk_file_path_copy (path);
658
659 error = NULL;
660- result = gtk_file_chooser_default_update_current_folder (GTK_FILE_CHOOSER (impl), path_copy, TRUE, clear_entry, &error);
661+ result = _gtk_file_chooser_set_current_folder_path (GTK_FILE_CHOOSER (impl), path_copy, &error);
662
663- if (!result)
664+ if (errormsg && !result)
665 error_changing_folder_dialog (impl, path_copy, error);
666
667- gtk_file_path_free (path_copy);
668+ gtk_label_set_text (GTK_LABEL (impl->location_label), file_name);
669
670- profile_end ("end", (char *) path);
671+ gtk_file_path_free (path_copy);
672+ g_free (file_name);
673
674 return result;
675 }
676
677-static void
678-update_preview_widget_visibility (GtkFileChooserDefault *impl)
679+static gboolean
680+change_folder_and_display_error (GtkFileChooserDefault *impl,
681+ const GtkFilePath *path)
682 {
683- if (impl->use_preview_label)
684- {
685- if (!impl->preview_label)
686- {
687- impl->preview_label = gtk_label_new (impl->preview_display_name);
688- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_label, FALSE, FALSE, 0);
689- gtk_box_reorder_child (GTK_BOX (impl->preview_box), impl->preview_label, 0);
690- gtk_label_set_ellipsize (GTK_LABEL (impl->preview_label), PANGO_ELLIPSIZE_MIDDLE);
691- gtk_widget_show (impl->preview_label);
692- }
693- }
694+ return change_folder (impl, path, TRUE);
695+}
696+
697+
698+/* FIXME: GtkFileSystem needs a function to split a remote path
699+ * into hostname and path components, or maybe just have a
700+ * gtk_file_system_path_get_display_name().
701+ *
702+ * This function is also used in gtkfilechooserbutton.c
703+ */
704+gchar *
705+_gtk_file_chooser_label_for_uri (const gchar *uri)
706+{
707+ const gchar *path, *start, *end, *p;
708+ gchar *host, *label;
709+
710+ start = strstr (uri, "://");
711+ start += 3;
712+ path = strchr (start, '/');
713+
714+ if (path)
715+ end = path;
716 else
717 {
718- if (impl->preview_label)
719- {
720- gtk_widget_destroy (impl->preview_label);
721- impl->preview_label = NULL;
722- }
723+ end = uri + strlen (uri);
724+ path = "/";
725 }
726
727- if (impl->preview_widget_active && impl->preview_widget)
728- gtk_widget_show (impl->preview_box);
729- else
730- gtk_widget_hide (impl->preview_box);
731+ /* strip username */
732+ p = strchr (start, '@');
733+ if (p && p < end)
734+ {
735+ start = p + 1;
736+ }
737
738- g_signal_emit_by_name (impl, "default-size-changed");
739-}
740+ p = strchr (start, ':');
741+ if (p && p < end)
742+ end = p;
743
744-static void
745-set_preview_widget (GtkFileChooserDefault *impl,
746- GtkWidget *preview_widget)
747-{
748- if (preview_widget == impl->preview_widget)
749- return;
750+ host = g_strndup (start, end - start);
751
752- if (impl->preview_widget)
753- gtk_container_remove (GTK_CONTAINER (impl->preview_box),
754- impl->preview_widget);
755+ /* Translators: the first string is a path and the second string
756+ * is a hostname. Nautilus and the panel contain the same string
757+ * to translate.
758+ */
759+ label = g_strdup_printf (_("%1$s on %2$s"), path, host);
760
761- impl->preview_widget = preview_widget;
762- if (impl->preview_widget)
763- {
764- gtk_widget_show (impl->preview_widget);
765- gtk_box_pack_start (GTK_BOX (impl->preview_box), impl->preview_widget, TRUE, TRUE, 0);
766- gtk_box_reorder_child (GTK_BOX (impl->preview_box),
767- impl->preview_widget,
768- (impl->use_preview_label && impl->preview_label) ? 1 : 0);
769- }
770+ g_free (host);
771
772- update_preview_widget_visibility (impl);
773+ return label;
774 }
775
776-/* Re-reads all the icons for the shortcuts, used when the theme changes */
777-struct ReloadIconsData
778-{
779- GtkFileChooserDefault *impl;
780- GtkTreeRowReference *row_ref;
781-};
782
783+/* Callback used when the "New Folder" button is clicked */
784 static void
785-shortcuts_reload_icons_get_info_cb (GtkFileSystemHandle *handle,
786- const GtkFileInfo *info,
787- const GError *error,
788- gpointer user_data)
789+new_folder_button_clicked (GtkButton *button,
790+ GtkFileChooserDefault *impl)
791 {
792- GdkPixbuf *pixbuf;
793 GtkTreeIter iter;
794 GtkTreePath *path;
795- gboolean cancelled = handle->cancelled;
796- struct ReloadIconsData *data = user_data;
797-
798- if (!g_slist_find (data->impl->reload_icon_handles, handle))
799- goto out;
800
801- data->impl->reload_icon_handles = g_slist_remove (data->impl->reload_icon_handles, handle);
802-
803- if (cancelled || error)
804- goto out;
805+ if (!impl->browse_files_model)
806+ return; /* FIXME: this sucks. Disable the New Folder button or something. */
807
808- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (data->impl),
809- data->impl->icon_size, NULL);
810+ /* Prevent button from being clicked twice */
811+ gtk_widget_set_sensitive (impl->browse_new_folder_button, FALSE);
812
813- path = gtk_tree_row_reference_get_path (data->row_ref);
814- gtk_tree_model_get_iter (GTK_TREE_MODEL (data->impl->shortcuts_model), &iter, path);
815- gtk_list_store_set (data->impl->shortcuts_model, &iter,
816- SHORTCUTS_COL_PIXBUF, pixbuf,
817- -1);
818- gtk_tree_path_free (path);
819+ _gtk_file_system_model_add_editable (impl->browse_files_model, &iter);
820
821- if (pixbuf)
822- g_object_unref (pixbuf);
823+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->browse_files_model), &iter);
824+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
825+ path, impl->list_name_column,
826+ FALSE, 0.0, 0.0);
827
828-out:
829- gtk_tree_row_reference_free (data->row_ref);
830- g_object_unref (data->impl);
831- g_free (data);
832+ g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
833+ gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
834+ path,
835+ impl->list_name_column,
836+ TRUE);
837
838- g_object_unref (handle);
839+ gtk_tree_path_free (path);
840 }
841
842 static void
843-shortcuts_reload_icons (GtkFileChooserDefault *impl)
844+edited_idle_create_folder_cb (GtkFileSystemHandle *handle,
845+ const GtkFilePath *path,
846+ const GError *error,
847+ gpointer data)
848 {
849- GSList *l;
850- GtkTreeIter iter;
851-
852- profile_start ("start", NULL);
853+ gboolean cancelled = handle->cancelled;
854+ GtkFileChooserDefault *impl = data;
855
856- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
857+ if (!g_slist_find (impl->pending_handles, handle))
858 goto out;
859
860- for (l = impl->reload_icon_handles; l; l = l->next)
861- {
862- GtkFileSystemHandle *handle = GTK_FILE_SYSTEM_HANDLE (l->data);
863- gtk_file_system_cancel_operation (handle);
864- }
865- g_slist_free (impl->reload_icon_handles);
866- impl->reload_icon_handles = NULL;
867+ impl->pending_handles = g_slist_remove (impl->pending_handles, handle);
868
869- do
870- {
871- gpointer data;
872- gboolean is_volume;
873- gboolean pixbuf_visible;
874- GdkPixbuf *pixbuf;
875+ if (cancelled)
876+ goto out;
877
878- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
879- SHORTCUTS_COL_DATA, &data,
880- SHORTCUTS_COL_IS_VOLUME, &is_volume,
881- SHORTCUTS_COL_PIXBUF_VISIBLE, &pixbuf_visible,
882- -1);
883+ if (!error)
884+ change_folder_and_display_error (impl, path);
885+ else
886+ error_creating_folder_dialog (impl, path, g_error_copy (error));
887
888- if (pixbuf_visible && data)
889- {
890- if (is_volume)
891- {
892- GtkFileSystemVolume *volume;
893+ out:
894+ g_object_unref (impl);
895+ g_object_unref (handle);
896+}
897
898- volume = data;
899- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
900- impl->icon_size, NULL);
901-
902- gtk_list_store_set (impl->shortcuts_model, &iter,
903- SHORTCUTS_COL_PIXBUF, pixbuf,
904- -1);
905-
906- if (pixbuf)
907- g_object_unref (pixbuf);
908- }
909- else if (gtk_file_system_path_is_local (impl->file_system, (GtkFilePath *)data))
910- {
911- const GtkFilePath *path;
912- struct ReloadIconsData *info;
913- GtkTreePath *tree_path;
914- GtkFileSystemHandle *handle;
915-
916- path = data;
917-
918- info = g_new0 (struct ReloadIconsData, 1);
919- info->impl = g_object_ref (impl);
920- tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
921- info->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), tree_path);
922- gtk_tree_path_free (tree_path);
923-
924- handle = gtk_file_system_get_info (impl->file_system, path,
925- GTK_FILE_INFO_ICON,
926- shortcuts_reload_icons_get_info_cb,
927- info);
928- impl->reload_icon_handles = g_slist_append (impl->reload_icon_handles, handle);
929- }
930- else
931- {
932- GtkIconTheme *icon_theme;
933-
934- /* Don't call get_info for remote paths to avoid latency and
935- * auth dialogs.
936- * If we switch to a better bookmarks file format (XBEL), we
937- * should use mime info to get a better icon.
938- */
939- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
940- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory",
941- impl->icon_size, 0, NULL);
942-
943- gtk_list_store_set (impl->shortcuts_model, &iter,
944- SHORTCUTS_COL_PIXBUF, pixbuf,
945- -1);
946-
947- if (pixbuf)
948- g_object_unref (pixbuf);
949- }
950- }
951- }
952- while (gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model),&iter));
953-
954- out:
955-
956- profile_end ("end", NULL);
957-}
958-
959-static void
960-shortcuts_find_folder (GtkFileChooserDefault *impl,
961- GtkFilePath *folder)
962-{
963- GtkTreeSelection *selection;
964- int pos;
965- GtkTreePath *path;
966-
967- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
968-
969- g_assert (folder != NULL);
970- pos = shortcut_find_position (impl, folder);
971- if (pos == -1)
972- {
973- gtk_tree_selection_unselect_all (selection);
974- return;
975- }
976-
977- path = gtk_tree_path_new_from_indices (pos, -1);
978- gtk_tree_selection_select_path (selection, path);
979- gtk_tree_path_free (path);
980-}
981-
982-/* If a shortcut corresponds to the current folder, selects it */
983-static void
984-shortcuts_find_current_folder (GtkFileChooserDefault *impl)
985-{
986- shortcuts_find_folder (impl, impl->current_folder);
987-}
988-
989-/* Removes the specified number of rows from the shortcuts list */
990-static void
991-shortcuts_remove_rows (GtkFileChooserDefault *impl,
992- int start_row,
993- int n_rows)
994-{
995- GtkTreePath *path;
996-
997- path = gtk_tree_path_new_from_indices (start_row, -1);
998-
999- for (; n_rows; n_rows--)
1000- {
1001- GtkTreeIter iter;
1002-
1003- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path))
1004- g_assert_not_reached ();
1005-
1006- shortcuts_free_row_data (impl, &iter);
1007- gtk_list_store_remove (impl->shortcuts_model, &iter);
1008- }
1009-
1010- gtk_tree_path_free (path);
1011-}
1012-
1013-static void
1014-shortcuts_update_count (GtkFileChooserDefault *impl,
1015- ShortcutsIndex type,
1016- gint value)
1017-{
1018- switch (type)
1019- {
1020- case SHORTCUTS_HOME:
1021- if (value < 0)
1022- impl->has_home = FALSE;
1023- else
1024- impl->has_home = TRUE;
1025- break;
1026-
1027- case SHORTCUTS_DESKTOP:
1028- if (value < 0)
1029- impl->has_desktop = FALSE;
1030- else
1031- impl->has_desktop = TRUE;
1032- break;
1033-
1034- case SHORTCUTS_VOLUMES:
1035- impl->num_volumes += value;
1036- break;
1037-
1038- case SHORTCUTS_SHORTCUTS:
1039- impl->num_shortcuts += value;
1040- break;
1041-
1042- case SHORTCUTS_BOOKMARKS:
1043- impl->num_bookmarks += value;
1044- break;
1045-
1046- case SHORTCUTS_CURRENT_FOLDER:
1047- if (value < 0)
1048- impl->shortcuts_current_folder_active = FALSE;
1049- else
1050- impl->shortcuts_current_folder_active = TRUE;
1051- break;
1052-
1053- default:
1054- /* nothing */
1055- break;
1056- }
1057-}
1058-
1059-struct ShortcutsInsertRequest
1060-{
1061- GtkFileChooserDefault *impl;
1062- GtkFilePath *parent_path;
1063- GtkFilePath *path;
1064- int pos;
1065- char *label_copy;
1066- GtkTreeRowReference *row_ref;
1067- ShortcutsIndex type;
1068- gboolean name_only;
1069- gboolean removable;
1070-};
1071-
1072-static void
1073-get_file_info_finished (GtkFileSystemHandle *handle,
1074- const GtkFileInfo *info,
1075- const GError *error,
1076- gpointer data)
1077-{
1078- gint pos = -1;
1079- gboolean cancelled = handle->cancelled;
1080- gboolean is_volume = FALSE;
1081- GdkPixbuf *pixbuf;
1082- GtkTreePath *path;
1083- GtkTreeIter iter;
1084- GtkFileSystemHandle *model_handle;
1085- struct ShortcutsInsertRequest *request = data;
1086-
1087- path = gtk_tree_row_reference_get_path (request->row_ref);
1088- if (!path)
1089- /* Handle doesn't exist anymore in the model */
1090- goto out;
1091-
1092- pos = gtk_tree_path_get_indices (path)[0];
1093- gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->shortcuts_model),
1094- &iter, path);
1095- gtk_tree_path_free (path);
1096-
1097- /* validate handle, else goto out */
1098- gtk_tree_model_get (GTK_TREE_MODEL (request->impl->shortcuts_model), &iter,
1099- SHORTCUTS_COL_HANDLE, &model_handle,
1100- -1);
1101- if (handle != model_handle)
1102- goto out;
1103-
1104- /* set the handle to NULL in the model (we unref later on) */
1105- gtk_list_store_set (request->impl->shortcuts_model, &iter,
1106- SHORTCUTS_COL_HANDLE, NULL,
1107- -1);
1108-
1109- if (cancelled)
1110- goto out;
1111-
1112- if (!info)
1113- {
1114- gtk_list_store_remove (request->impl->shortcuts_model, &iter);
1115- shortcuts_update_count (request->impl, request->type, -1);
1116-
1117- if (request->type == SHORTCUTS_HOME)
1118- {
1119- const char *home = g_get_home_dir ();
1120- GtkFilePath *home_path;
1121-
1122- home_path = gtk_file_system_filename_to_path (request->impl->file_system, home);
1123- error_getting_info_dialog (request->impl, home_path, g_error_copy (error));
1124- gtk_file_path_free (home_path);
1125- }
1126- else if (request->type == SHORTCUTS_CURRENT_FOLDER)
1127- {
1128- /* Remove the current folder separator */
1129- gint separator_pos = shortcuts_get_index (request->impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1130- shortcuts_remove_rows (request->impl, separator_pos, 1);
1131- }
1132-
1133- goto out;
1134- }
1135-
1136- if (!request->label_copy)
1137- request->label_copy = g_strdup (gtk_file_info_get_display_name (info));
1138- pixbuf = gtk_file_info_render_icon (info, GTK_WIDGET (request->impl),
1139- request->impl->icon_size, NULL);
1140-
1141- gtk_list_store_set (request->impl->shortcuts_model, &iter,
1142- SHORTCUTS_COL_PIXBUF, pixbuf,
1143- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1144- SHORTCUTS_COL_NAME, request->label_copy,
1145- SHORTCUTS_COL_IS_VOLUME, is_volume,
1146- SHORTCUTS_COL_REMOVABLE, request->removable,
1147- -1);
1148-
1149- if (request->impl->shortcuts_filter_model)
1150- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (request->impl->shortcuts_filter_model));
1151-
1152- if (request->type == SHORTCUTS_CURRENT_FOLDER
1153- && request->impl->save_folder_combo != NULL)
1154- {
1155- /* The current folder is updated via _activate_iter(), don't
1156- * have save_folder_combo_changed_cb() call _activate_iter()
1157- * again.
1158- */
1159- g_signal_handlers_block_by_func (request->impl->save_folder_combo,
1160- G_CALLBACK (save_folder_combo_changed_cb),
1161- request->impl);
1162- gtk_combo_box_set_active (GTK_COMBO_BOX (request->impl->save_folder_combo), pos);
1163- g_signal_handlers_unblock_by_func (request->impl->save_folder_combo,
1164- G_CALLBACK (save_folder_combo_changed_cb),
1165- request->impl);
1166- }
1167-
1168- if (pixbuf)
1169- g_object_unref (pixbuf);
1170-
1171-out:
1172- g_object_unref (request->impl);
1173- gtk_file_path_free (request->parent_path);
1174- gtk_file_path_free (request->path);
1175- gtk_tree_row_reference_free (request->row_ref);
1176- g_free (request->label_copy);
1177- g_free (request);
1178-
1179- g_object_unref (handle);
1180-}
1181-
1182-/* FIXME: GtkFileSystem needs a function to split a remote path
1183- * into hostname and path components, or maybe just have a
1184- * gtk_file_system_path_get_display_name().
1185- *
1186- * This function is also used in gtkfilechooserbutton.c
1187- */
1188-gchar *
1189-_gtk_file_chooser_label_for_uri (const gchar *uri)
1190-{
1191- const gchar *path, *start, *end, *p;
1192- gchar *host, *label;
1193-
1194- start = strstr (uri, "://");
1195- start += 3;
1196- path = strchr (start, '/');
1197-
1198- if (path)
1199- end = path;
1200- else
1201- {
1202- end = uri + strlen (uri);
1203- path = "/";
1204- }
1205-
1206- /* strip username */
1207- p = strchr (start, '@');
1208- if (p && p < end)
1209- {
1210- start = p + 1;
1211- }
1212-
1213- p = strchr (start, ':');
1214- if (p && p < end)
1215- end = p;
1216-
1217- host = g_strndup (start, end - start);
1218-
1219- /* Translators: the first string is a path and the second string
1220- * is a hostname. Nautilus and the panel contain the same string
1221- * to translate.
1222- */
1223- label = g_strdup_printf (_("%1$s on %2$s"), path, host);
1224-
1225- g_free (host);
1226-
1227- return label;
1228-}
1229-
1230-/* Inserts a path in the shortcuts tree, making a copy of it; alternatively,
1231- * inserts a volume. A position of -1 indicates the end of the tree.
1232- */
1233-static void
1234-shortcuts_insert_path (GtkFileChooserDefault *impl,
1235- int pos,
1236- gboolean is_volume,
1237- GtkFileSystemVolume *volume,
1238- const GtkFilePath *path,
1239- const char *label,
1240- gboolean removable,
1241- ShortcutsIndex type)
1242-{
1243- char *label_copy;
1244- GdkPixbuf *pixbuf = NULL;
1245- gpointer data = NULL;
1246- GtkTreeIter iter;
1247- GtkIconTheme *icon_theme;
1248-
1249- profile_start ("start", is_volume ? "volume" : (char *) path);
1250-
1251- if (is_volume)
1252- {
1253- data = volume;
1254- label_copy = gtk_file_system_volume_get_display_name (impl->file_system, volume);
1255- pixbuf = gtk_file_system_volume_render_icon (impl->file_system, volume, GTK_WIDGET (impl),
1256- impl->icon_size, NULL);
1257- }
1258- else if (gtk_file_system_path_is_local (impl->file_system, path))
1259- {
1260- struct ShortcutsInsertRequest *request;
1261- GtkFileSystemHandle *handle;
1262- GtkTreePath *p;
1263-
1264- request = g_new0 (struct ShortcutsInsertRequest, 1);
1265- request->impl = g_object_ref (impl);
1266- request->path = gtk_file_path_copy (path);
1267- request->name_only = TRUE;
1268- request->removable = removable;
1269- request->pos = pos;
1270- request->type = type;
1271- if (label)
1272- request->label_copy = g_strdup (label);
1273-
1274- if (pos == -1)
1275- gtk_list_store_append (impl->shortcuts_model, &iter);
1276- else
1277- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
1278-
1279- p = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
1280- request->row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (impl->shortcuts_model), p);
1281- gtk_tree_path_free (p);
1282-
1283- handle = gtk_file_system_get_info (request->impl->file_system, request->path,
1284- GTK_FILE_INFO_DISPLAY_NAME | GTK_FILE_INFO_IS_HIDDEN | GTK_FILE_INFO_ICON,
1285- get_file_info_finished, request);
1286-
1287- gtk_list_store_set (impl->shortcuts_model, &iter,
1288- SHORTCUTS_COL_DATA, gtk_file_path_copy (path),
1289- SHORTCUTS_COL_IS_VOLUME, is_volume,
1290- SHORTCUTS_COL_HANDLE, handle,
1291- -1);
1292-
1293- shortcuts_update_count (impl, type, 1);
1294-
1295- return;
1296- }
1297- else
1298- {
1299- /* Don't call get_info for remote paths to avoid latency and
1300- * auth dialogs.
1301- */
1302- data = gtk_file_path_copy (path);
1303- if (label)
1304- label_copy = g_strdup (label);
1305- else
1306- {
1307- gchar *uri;
1308-
1309- uri = gtk_file_system_path_to_uri (impl->file_system, path);
1310-
1311- label_copy = _gtk_file_chooser_label_for_uri (uri);
1312-
1313- g_free (uri);
1314- }
1315-
1316- /* If we switch to a better bookmarks file format (XBEL), we
1317- * should use mime info to get a better icon.
1318- */
1319- icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (impl)));
1320- pixbuf = gtk_icon_theme_load_icon (icon_theme, "gnome-fs-directory",
1321- impl->icon_size, 0, NULL);
1322- }
1323-
1324- if (pos == -1)
1325- gtk_list_store_append (impl->shortcuts_model, &iter);
1326- else
1327- gtk_list_store_insert (impl->shortcuts_model, &iter, pos);
1328-
1329- shortcuts_update_count (impl, type, 1);
1330-
1331- gtk_list_store_set (impl->shortcuts_model, &iter,
1332- SHORTCUTS_COL_PIXBUF, pixbuf,
1333- SHORTCUTS_COL_PIXBUF_VISIBLE, TRUE,
1334- SHORTCUTS_COL_NAME, label_copy,
1335- SHORTCUTS_COL_DATA, data,
1336- SHORTCUTS_COL_IS_VOLUME, is_volume,
1337- SHORTCUTS_COL_REMOVABLE, removable,
1338- SHORTCUTS_COL_HANDLE, NULL,
1339- -1);
1340-
1341- if (impl->shortcuts_filter_model)
1342- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
1343-
1344- if (type == SHORTCUTS_CURRENT_FOLDER && impl->save_folder_combo != NULL)
1345- {
1346- /* The current folder is updated via _activate_iter(), don't
1347- * have save_folder_combo_changed_cb() call _activate_iter()
1348- * again.
1349- */
1350- gint combo_pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
1351- g_signal_handlers_block_by_func (impl->save_folder_combo,
1352- G_CALLBACK (save_folder_combo_changed_cb),
1353- impl);
1354- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), combo_pos);
1355- g_signal_handlers_unblock_by_func (impl->save_folder_combo,
1356- G_CALLBACK (save_folder_combo_changed_cb),
1357- impl);
1358- }
1359-
1360- g_free (label_copy);
1361-
1362- if (pixbuf)
1363- g_object_unref (pixbuf);
1364-
1365- profile_end ("end", NULL);
1366-}
1367-
1368-/* Appends an item for the user's home directory to the shortcuts model */
1369-static void
1370-shortcuts_append_home (GtkFileChooserDefault *impl)
1371-{
1372- const char *home;
1373- GtkFilePath *home_path;
1374-
1375- profile_start ("start", NULL);
1376-
1377- home = g_get_home_dir ();
1378- if (home == NULL)
1379- {
1380- profile_end ("end - no home directory!?", NULL);
1381- return;
1382- }
1383-
1384- home_path = gtk_file_system_filename_to_path (impl->file_system, home);
1385-
1386- shortcuts_insert_path (impl, -1, FALSE, NULL, home_path, NULL, FALSE, SHORTCUTS_HOME);
1387-
1388- gtk_file_path_free (home_path);
1389-
1390- profile_end ("end", NULL);
1391-}
1392-
1393-/* Appends the ~/Desktop directory to the shortcuts model */
1394-static void
1395-shortcuts_append_desktop (GtkFileChooserDefault *impl)
1396-{
1397- char *name;
1398- const char *home;
1399- GtkFilePath *path;
1400-
1401- profile_start ("start", NULL);
1402-
1403-#ifdef G_OS_WIN32
1404- name = _gtk_file_system_win32_get_desktop ();
1405-#else
1406- home = g_get_home_dir ();
1407- if (home == NULL)
1408- {
1409- profile_end ("end - no home directory!?", NULL);
1410- return;
1411- }
1412-
1413- name = g_build_filename (home, "Desktop", NULL);
1414-#endif
1415-
1416- path = gtk_file_system_filename_to_path (impl->file_system, name);
1417- g_free (name);
1418-
1419- shortcuts_insert_path (impl, -1, FALSE, NULL, path, _("Desktop"), FALSE, SHORTCUTS_DESKTOP);
1420- /* We do not actually pop up an error dialog if there is no desktop directory
1421- * because some people may really not want to have one.
1422- */
1423-
1424- gtk_file_path_free (path);
1425-
1426- profile_end ("end", NULL);
1427-}
1428-
1429-/* Appends a list of GtkFilePath to the shortcuts model; returns how many were inserted */
1430-static int
1431-shortcuts_append_paths (GtkFileChooserDefault *impl,
1432- GSList *paths)
1433-{
1434- int start_row;
1435- int num_inserted;
1436- gchar *label;
1437-
1438- profile_start ("start", NULL);
1439-
1440- /* As there is no separator now, we want to start there.
1441- */
1442- start_row = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
1443- num_inserted = 0;
1444-
1445- for (; paths; paths = paths->next)
1446- {
1447- GtkFilePath *path;
1448-
1449- path = paths->data;
1450-
1451- if (impl->local_only &&
1452- !gtk_file_system_path_is_local (impl->file_system, path))
1453- continue;
1454-
1455- label = gtk_file_system_get_bookmark_label (impl->file_system, path);
1456-
1457- /* NULL GError, but we don't really want to show error boxes here */
1458- shortcuts_insert_path (impl, start_row + num_inserted, FALSE, NULL, path, label, TRUE, SHORTCUTS_BOOKMARKS);
1459- num_inserted++;
1460-
1461- g_free (label);
1462- }
1463-
1464- profile_end ("end", NULL);
1465-
1466- return num_inserted;
1467-}
1468-
1469-/* Returns the index for the corresponding item in the shortcuts bar */
1470-static int
1471-shortcuts_get_index (GtkFileChooserDefault *impl,
1472- ShortcutsIndex where)
1473-{
1474- int n;
1475-
1476- n = 0;
1477-
1478- if (where == SHORTCUTS_HOME)
1479- goto out;
1480-
1481- n += impl->has_home ? 1 : 0;
1482-
1483- if (where == SHORTCUTS_DESKTOP)
1484- goto out;
1485-
1486- n += impl->has_desktop ? 1 : 0;
1487-
1488- if (where == SHORTCUTS_VOLUMES)
1489- goto out;
1490-
1491- n += impl->num_volumes;
1492-
1493- if (where == SHORTCUTS_SHORTCUTS)
1494- goto out;
1495-
1496- n += impl->num_shortcuts;
1497-
1498- if (where == SHORTCUTS_BOOKMARKS_SEPARATOR)
1499- goto out;
1500-
1501- /* If there are no bookmarks there won't be a separator */
1502- n += (impl->num_bookmarks > 0) ? 1 : 0;
1503-
1504- if (where == SHORTCUTS_BOOKMARKS)
1505- goto out;
1506-
1507- n += impl->num_bookmarks;
1508-
1509- if (where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR)
1510- goto out;
1511-
1512- n += 1;
1513-
1514- if (where == SHORTCUTS_CURRENT_FOLDER)
1515- goto out;
1516-
1517- g_assert_not_reached ();
1518-
1519- out:
1520-
1521- return n;
1522-}
1523-
1524-/* Adds all the file system volumes to the shortcuts model */
1525-static void
1526-shortcuts_add_volumes (GtkFileChooserDefault *impl)
1527-{
1528- int start_row;
1529- GSList *list, *l;
1530- int n;
1531- gboolean old_changing_folders;
1532-
1533- profile_start ("start", NULL);
1534-
1535-
1536- old_changing_folders = impl->changing_folder;
1537- impl->changing_folder = TRUE;
1538-
1539- start_row = shortcuts_get_index (impl, SHORTCUTS_VOLUMES);
1540- shortcuts_remove_rows (impl, start_row, impl->num_volumes);
1541- impl->num_volumes = 0;
1542-
1543- list = gtk_file_system_list_volumes (impl->file_system);
1544-
1545- n = 0;
1546-
1547- for (l = list; l; l = l->next)
1548- {
1549- GtkFileSystemVolume *volume;
1550-
1551- volume = l->data;
1552-
1553- if (impl->local_only)
1554- {
1555- if (gtk_file_system_volume_get_is_mounted (impl->file_system, volume))
1556- {
1557- GtkFilePath *base_path;
1558-
1559- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
1560- if (base_path != NULL)
1561- {
1562- gboolean is_local = gtk_file_system_path_is_local (impl->file_system, base_path);
1563- gtk_file_path_free (base_path);
1564-
1565- if (!is_local)
1566- {
1567- gtk_file_system_volume_free (impl->file_system, volume);
1568- continue;
1569- }
1570- }
1571- }
1572- }
1573-
1574- shortcuts_insert_path (impl, start_row + n, TRUE, volume, NULL, NULL, FALSE, SHORTCUTS_VOLUMES);
1575- n++;
1576- }
1577-
1578- impl->num_volumes = n;
1579- g_slist_free (list);
1580-
1581- if (impl->shortcuts_filter_model)
1582- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
1583-
1584- impl->changing_folder = old_changing_folders;
1585-
1586- profile_end ("end", NULL);
1587-}
1588-
1589-/* Inserts a separator node in the shortcuts list */
1590-static void
1591-shortcuts_insert_separator (GtkFileChooserDefault *impl,
1592- ShortcutsIndex where)
1593-{
1594- GtkTreeIter iter;
1595-
1596- g_assert (where == SHORTCUTS_BOOKMARKS_SEPARATOR || where == SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1597-
1598- gtk_list_store_insert (impl->shortcuts_model, &iter,
1599- shortcuts_get_index (impl, where));
1600- gtk_list_store_set (impl->shortcuts_model, &iter,
1601- SHORTCUTS_COL_PIXBUF, NULL,
1602- SHORTCUTS_COL_PIXBUF_VISIBLE, FALSE,
1603- SHORTCUTS_COL_NAME, NULL,
1604- SHORTCUTS_COL_DATA, NULL,
1605- -1);
1606-}
1607-
1608-/* Updates the list of bookmarks */
1609-static void
1610-shortcuts_add_bookmarks (GtkFileChooserDefault *impl)
1611-{
1612- GSList *bookmarks;
1613- gboolean old_changing_folders;
1614- GtkTreeIter iter;
1615- GtkFilePath *list_selected = NULL;
1616- GtkFilePath *combo_selected = NULL;
1617- gboolean is_volume;
1618- gpointer col_data;
1619-
1620- profile_start ("start", NULL);
1621-
1622- old_changing_folders = impl->changing_folder;
1623- impl->changing_folder = TRUE;
1624-
1625- if (shortcuts_get_selected (impl, &iter))
1626- {
1627- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model),
1628- &iter,
1629- SHORTCUTS_COL_DATA, &col_data,
1630- SHORTCUTS_COL_IS_VOLUME, &is_volume,
1631- -1);
1632-
1633- if (col_data && !is_volume)
1634- list_selected = gtk_file_path_copy (col_data);
1635- }
1636-
1637- if (impl->save_folder_combo &&
1638- gtk_combo_box_get_active_iter (GTK_COMBO_BOX (impl->save_folder_combo),
1639- &iter))
1640- {
1641- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model),
1642- &iter,
1643- SHORTCUTS_COL_DATA, &col_data,
1644- SHORTCUTS_COL_IS_VOLUME, &is_volume,
1645- -1);
1646-
1647- if (col_data && !is_volume)
1648- combo_selected = gtk_file_path_copy (col_data);
1649- }
1650-
1651- if (impl->num_bookmarks > 0)
1652- shortcuts_remove_rows (impl,
1653- shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR),
1654- impl->num_bookmarks + 1);
1655-
1656- impl->num_bookmarks = 0;
1657-
1658- bookmarks = gtk_file_system_list_bookmarks (impl->file_system);
1659- shortcuts_append_paths (impl, bookmarks);
1660- gtk_file_paths_free (bookmarks);
1661-
1662- if (impl->num_bookmarks > 0)
1663- shortcuts_insert_separator (impl, SHORTCUTS_BOOKMARKS_SEPARATOR);
1664-
1665- if (impl->shortcuts_filter_model)
1666- gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model));
1667-
1668- if (list_selected)
1669- {
1670- shortcuts_find_folder (impl, list_selected);
1671- gtk_file_path_free (list_selected);
1672- }
1673-
1674- if (combo_selected)
1675- {
1676- gint pos;
1677-
1678- pos = shortcut_find_position (impl, combo_selected);
1679- if (pos != -1)
1680- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo),
1681- pos);
1682- gtk_file_path_free (combo_selected);
1683- }
1684-
1685- impl->changing_folder = old_changing_folders;
1686-
1687- profile_end ("end", NULL);
1688-}
1689-
1690-/* Appends a separator and a row to the shortcuts list for the current folder */
1691-static void
1692-shortcuts_add_current_folder (GtkFileChooserDefault *impl)
1693-{
1694- int pos;
1695- gboolean success;
1696-
1697- g_assert (!impl->shortcuts_current_folder_active);
1698-
1699- success = TRUE;
1700-
1701- g_assert (impl->current_folder != NULL);
1702-
1703- pos = shortcut_find_position (impl, impl->current_folder);
1704- if (pos == -1)
1705- {
1706- GtkFileSystemVolume *volume;
1707- GtkFilePath *base_path;
1708-
1709- /* Separator */
1710-
1711- shortcuts_insert_separator (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1712-
1713- /* Item */
1714-
1715- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER);
1716-
1717- volume = gtk_file_system_get_volume_for_path (impl->file_system, impl->current_folder);
1718- if (volume)
1719- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
1720- else
1721- base_path = NULL;
1722-
1723- if (base_path &&
1724- strcmp (gtk_file_path_get_string (base_path), gtk_file_path_get_string (impl->current_folder)) == 0)
1725- {
1726- shortcuts_insert_path (impl, pos, TRUE, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
1727- }
1728- else
1729- {
1730- shortcuts_insert_path (impl, pos, FALSE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
1731- if (volume)
1732- gtk_file_system_volume_free (impl->file_system, volume);
1733- }
1734-
1735- if (base_path)
1736- gtk_file_path_free (base_path);
1737- }
1738- else if (impl->save_folder_combo != NULL)
1739- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->save_folder_combo), pos);
1740-}
1741-
1742-/* Updates the current folder row in the shortcuts model */
1743-static void
1744-shortcuts_update_current_folder (GtkFileChooserDefault *impl)
1745-{
1746- int pos;
1747-
1748- pos = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
1749-
1750- if (impl->shortcuts_current_folder_active)
1751- {
1752- shortcuts_remove_rows (impl, pos, 2);
1753- impl->shortcuts_current_folder_active = FALSE;
1754- }
1755-
1756- shortcuts_add_current_folder (impl);
1757-}
1758-
1759-/* Filter function used for the shortcuts filter model */
1760-static gboolean
1761-shortcuts_filter_cb (GtkTreeModel *model,
1762- GtkTreeIter *iter,
1763- gpointer data)
1764-{
1765- GtkFileChooserDefault *impl;
1766- GtkTreePath *path;
1767- int pos;
1768-
1769- impl = GTK_FILE_CHOOSER_DEFAULT (data);
1770-
1771- path = gtk_tree_model_get_path (model, iter);
1772- if (!path)
1773- return FALSE;
1774-
1775- pos = *gtk_tree_path_get_indices (path);
1776- gtk_tree_path_free (path);
1777-
1778- return (pos < shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR));
1779-}
1780-
1781-/* Creates the list model for shortcuts */
1782-static void
1783-shortcuts_model_create (GtkFileChooserDefault *impl)
1784-{
1785- /* Keep this order in sync with the SHORCUTS_COL_* enum values */
1786- impl->shortcuts_model = gtk_list_store_new (SHORTCUTS_COL_NUM_COLUMNS,
1787- GDK_TYPE_PIXBUF, /* pixbuf */
1788- G_TYPE_STRING, /* name */
1789- G_TYPE_POINTER, /* path or volume */
1790- G_TYPE_BOOLEAN, /* is the previous column a volume? */
1791- G_TYPE_BOOLEAN, /* removable */
1792- G_TYPE_BOOLEAN, /* pixbuf cell visibility */
1793- G_TYPE_POINTER); /* GtkFileSystemHandle */
1794-
1795- if (impl->file_system)
1796- {
1797- shortcuts_append_home (impl);
1798- shortcuts_append_desktop (impl);
1799- shortcuts_add_volumes (impl);
1800- }
1801-
1802- impl->shortcuts_filter_model = shortcuts_model_filter_new (impl,
1803- GTK_TREE_MODEL (impl->shortcuts_model),
1804- NULL);
1805-
1806- gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model),
1807- shortcuts_filter_cb,
1808- impl,
1809- NULL);
1810-}
1811-
1812-/* Callback used when the "New Folder" button is clicked */
1813-static void
1814-new_folder_button_clicked (GtkButton *button,
1815- GtkFileChooserDefault *impl)
1816-{
1817- GtkTreeIter iter;
1818- GtkTreePath *path;
1819-
1820- if (!impl->browse_files_model)
1821- return; /* FIXME: this sucks. Disable the New Folder button or something. */
1822-
1823- /* Prevent button from being clicked twice */
1824- gtk_widget_set_sensitive (impl->browse_new_folder_button, FALSE);
1825-
1826- _gtk_file_system_model_add_editable (impl->browse_files_model, &iter);
1827-
1828- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->browse_files_model), &iter);
1829- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_files_tree_view),
1830- path, impl->list_name_column,
1831- FALSE, 0.0, 0.0);
1832-
1833- g_object_set (impl->list_name_renderer, "editable", TRUE, NULL);
1834- gtk_tree_view_set_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view),
1835- path,
1836- impl->list_name_column,
1837- TRUE);
1838-
1839- gtk_tree_path_free (path);
1840-}
1841-
1842-static void
1843-edited_idle_create_folder_cb (GtkFileSystemHandle *handle,
1844- const GtkFilePath *path,
1845- const GError *error,
1846- gpointer data)
1847-{
1848- gboolean cancelled = handle->cancelled;
1849- GtkFileChooserDefault *impl = data;
1850-
1851- if (!g_slist_find (impl->pending_handles, handle))
1852- goto out;
1853-
1854- impl->pending_handles = g_slist_remove (impl->pending_handles, handle);
1855-
1856- if (cancelled)
1857- goto out;
1858-
1859- if (!error)
1860- change_folder_and_display_error (impl, path, FALSE);
1861- else
1862- error_creating_folder_dialog (impl, path, g_error_copy (error));
1863-
1864- out:
1865- g_object_unref (impl);
1866- g_object_unref (handle);
1867-}
1868-
1869-/* Idle handler for creating a new folder after editing its name cell, or for
1870- * canceling the editing.
1871- */
1872-static gboolean
1873-edited_idle_cb (GtkFileChooserDefault *impl)
1874-{
1875- GDK_THREADS_ENTER ();
1876-
1877- g_source_destroy (impl->edited_idle);
1878- impl->edited_idle = NULL;
1879-
1880- _gtk_file_system_model_remove_editable (impl->browse_files_model);
1881- g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
1882-
1883- gtk_widget_set_sensitive (impl->browse_new_folder_button, TRUE);
1884-
1885- if (impl->edited_new_text) /* not cancelled? */
1886- {
1887- GError *error;
1888- GtkFilePath *file_path;
1889-
1890- error = NULL;
1891- file_path = gtk_file_system_make_path (impl->file_system,
1892- impl->current_folder,
1893- impl->edited_new_text,
1894- &error);
1895- if (file_path)
1896- {
1897- GtkFileSystemHandle *handle;
1898-
1899- handle = gtk_file_system_create_folder (impl->file_system, file_path,
1900- edited_idle_create_folder_cb,
1901- g_object_ref (impl));
1902- impl->pending_handles = g_slist_append (impl->pending_handles, handle);
1903-
1904- gtk_file_path_free (file_path);
1905- }
1906- else
1907- error_creating_folder_dialog (impl, file_path, error);
1908-
1909- g_free (impl->edited_new_text);
1910- impl->edited_new_text = NULL;
1911- }
1912-
1913- GDK_THREADS_LEAVE ();
1914-
1915- return FALSE;
1916-}
1917-
1918-static void
1919-queue_edited_idle (GtkFileChooserDefault *impl,
1920- const gchar *new_text)
1921-{
1922- /* We create the folder in an idle handler so that we don't modify the tree
1923- * just now.
1924- */
1925-
1926- if (!impl->edited_idle)
1927- {
1928- impl->edited_idle = g_idle_source_new ();
1929- g_source_set_closure (impl->edited_idle,
1930- g_cclosure_new_object (G_CALLBACK (edited_idle_cb),
1931- G_OBJECT (impl)));
1932- g_source_attach (impl->edited_idle, NULL);
1933- }
1934-
1935- g_free (impl->edited_new_text);
1936- impl->edited_new_text = g_strdup (new_text);
1937-}
1938-
1939-/* Callback used from the text cell renderer when the new folder is named */
1940-static void
1941-renderer_edited_cb (GtkCellRendererText *cell_renderer_text,
1942- const gchar *path,
1943- const gchar *new_text,
1944- GtkFileChooserDefault *impl)
1945-{
1946- /* work around bug #154921 */
1947- g_object_set (cell_renderer_text,
1948- "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
1949- queue_edited_idle (impl, new_text);
1950-}
1951-
1952-/* Callback used from the text cell renderer when the new folder edition gets
1953- * canceled.
1954- */
1955-static void
1956-renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text,
1957- GtkFileChooserDefault *impl)
1958-{
1959- /* work around bug #154921 */
1960- g_object_set (cell_renderer_text,
1961- "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
1962- queue_edited_idle (impl, NULL);
1963-}
1964-
1965-/* Creates the widgets for the filter combo box */
1966-static GtkWidget *
1967-filter_create (GtkFileChooserDefault *impl)
1968-{
1969- impl->filter_combo = gtk_combo_box_new_text ();
1970- gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (impl->filter_combo), FALSE);
1971-
1972- g_signal_connect (impl->filter_combo, "changed",
1973- G_CALLBACK (filter_combo_changed), impl);
1974-
1975- return impl->filter_combo;
1976-}
1977-
1978-static GtkWidget *
1979-button_new (GtkFileChooserDefault *impl,
1980- const char *text,
1981- const char *stock_id,
1982- gboolean sensitive,
1983- gboolean show,
1984- GCallback callback)
1985-{
1986- GtkWidget *button;
1987- GtkWidget *image;
1988-
1989- button = gtk_button_new_with_mnemonic (text);
1990- image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
1991- gtk_button_set_image (GTK_BUTTON (button), image);
1992-
1993- gtk_widget_set_sensitive (button, sensitive);
1994- g_signal_connect (button, "clicked", callback, impl);
1995-
1996- if (show)
1997- gtk_widget_show (button);
1998-
1999- return button;
2000-}
2001-
2002-/* Looks for a path among the shortcuts; returns its index or -1 if it doesn't exist */
2003-static int
2004-shortcut_find_position (GtkFileChooserDefault *impl,
2005- const GtkFilePath *path)
2006-{
2007- GtkTreeIter iter;
2008- int i;
2009- int current_folder_separator_idx;
2010-
2011- if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
2012- return -1;
2013-
2014- current_folder_separator_idx = shortcuts_get_index (impl, SHORTCUTS_CURRENT_FOLDER_SEPARATOR);
2015-
2016-#if 0
2017- /* FIXME: is this still needed? */
2018- if (current_folder_separator_idx >= impl->shortcuts_model->length)
2019- return -1;
2020-#endif
2021-
2022- for (i = 0; i < current_folder_separator_idx; i++)
2023- {
2024- gpointer col_data;
2025- gboolean is_volume;
2026-
2027- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2028- SHORTCUTS_COL_DATA, &col_data,
2029- SHORTCUTS_COL_IS_VOLUME, &is_volume,
2030- -1);
2031-
2032- if (col_data)
2033- {
2034- if (is_volume)
2035- {
2036- GtkFileSystemVolume *volume;
2037- GtkFilePath *base_path;
2038- gboolean exists;
2039-
2040- volume = col_data;
2041- base_path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
2042-
2043- exists = base_path && strcmp (gtk_file_path_get_string (path),
2044- gtk_file_path_get_string (base_path)) == 0;
2045- g_free (base_path);
2046-
2047- if (exists)
2048- return i;
2049- }
2050- else
2051- {
2052- GtkFilePath *model_path;
2053-
2054- model_path = col_data;
2055-
2056- if (model_path && gtk_file_path_compare (model_path, path) == 0)
2057- return i;
2058- }
2059- }
2060-
2061- if (i < current_folder_separator_idx - 1)
2062- {
2063- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
2064- g_assert_not_reached ();
2065- }
2066- }
2067-
2068- return -1;
2069-}
2070-
2071-/* Tries to add a bookmark from a path name */
2072-static gboolean
2073-shortcuts_add_bookmark_from_path (GtkFileChooserDefault *impl,
2074- const GtkFilePath *path,
2075- int pos)
2076-{
2077- GError *error;
2078-
2079- g_return_val_if_fail (path != NULL, FALSE);
2080-
2081- if (shortcut_find_position (impl, path) != -1)
2082- return FALSE;
2083-
2084- error = NULL;
2085- if (!gtk_file_system_insert_bookmark (impl->file_system, path, pos, &error))
2086- {
2087- error_adding_bookmark_dialog (impl, path, error);
2088- return FALSE;
2089- }
2090-
2091- return TRUE;
2092-}
2093-
2094-static void
2095-add_bookmark_foreach_cb (GtkTreeModel *model,
2096- GtkTreePath *path,
2097- GtkTreeIter *iter,
2098- gpointer data)
2099-{
2100- GtkFileChooserDefault *impl;
2101- GtkFileSystemModel *fs_model;
2102- GtkTreeIter child_iter;
2103- const GtkFilePath *file_path;
2104-
2105- impl = (GtkFileChooserDefault *) data;
2106-
2107- fs_model = impl->browse_files_model;
2108- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, iter);
2109-
2110- file_path = _gtk_file_system_model_get_path (fs_model, &child_iter);
2111- shortcuts_add_bookmark_from_path (impl, file_path, -1);
2112-}
2113-
2114-/* Adds a bookmark from the currently selected item in the file list */
2115-static void
2116-bookmarks_add_selected_folder (GtkFileChooserDefault *impl)
2117-{
2118- GtkTreeSelection *selection;
2119-
2120- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2121-
2122- if (gtk_tree_selection_count_selected_rows (selection) == 0)
2123- shortcuts_add_bookmark_from_path (impl, impl->current_folder, -1);
2124- else
2125- gtk_tree_selection_selected_foreach (selection,
2126- add_bookmark_foreach_cb,
2127- impl);
2128-}
2129-
2130-/* Callback used when the "Add bookmark" button is clicked */
2131-static void
2132-add_bookmark_button_clicked_cb (GtkButton *button,
2133- GtkFileChooserDefault *impl)
2134-{
2135- bookmarks_add_selected_folder (impl);
2136-}
2137-
2138-/* Returns TRUE plus an iter in the shortcuts_model if a row is selected;
2139- * returns FALSE if no shortcut is selected.
2140- */
2141-static gboolean
2142-shortcuts_get_selected (GtkFileChooserDefault *impl,
2143- GtkTreeIter *iter)
2144-{
2145- GtkTreeSelection *selection;
2146- GtkTreeIter parent_iter;
2147-
2148- if (!impl->browse_shortcuts_tree_view)
2149- return FALSE;
2150-
2151- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
2152-
2153- if (!gtk_tree_selection_get_selected (selection, NULL, &parent_iter))
2154- return FALSE;
2155-
2156- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model),
2157- iter,
2158- &parent_iter);
2159- return TRUE;
2160-}
2161-
2162-/* Removes the selected bookmarks */
2163-static void
2164-remove_selected_bookmarks (GtkFileChooserDefault *impl)
2165-{
2166- GtkTreeIter iter;
2167- gpointer col_data;
2168- GtkFilePath *path;
2169- gboolean removable;
2170- GError *error;
2171-
2172- if (!shortcuts_get_selected (impl, &iter))
2173- return;
2174-
2175- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2176- SHORTCUTS_COL_DATA, &col_data,
2177- SHORTCUTS_COL_REMOVABLE, &removable,
2178- -1);
2179- g_assert (col_data != NULL);
2180-
2181- if (!removable)
2182- return;
2183-
2184- path = col_data;
2185-
2186- error = NULL;
2187- if (!gtk_file_system_remove_bookmark (impl->file_system, path, &error))
2188- error_removing_bookmark_dialog (impl, path, error);
2189-}
2190-
2191-/* Callback used when the "Remove bookmark" button is clicked */
2192-static void
2193-remove_bookmark_button_clicked_cb (GtkButton *button,
2194- GtkFileChooserDefault *impl)
2195-{
2196- remove_selected_bookmarks (impl);
2197-}
2198-
2199-struct selection_check_closure {
2200- GtkFileChooserDefault *impl;
2201- int num_selected;
2202- gboolean all_files;
2203- gboolean all_folders;
2204-};
2205-
2206-/* Used from gtk_tree_selection_selected_foreach() */
2207-static void
2208-selection_check_foreach_cb (GtkTreeModel *model,
2209- GtkTreePath *path,
2210- GtkTreeIter *iter,
2211- gpointer data)
2212-{
2213- struct selection_check_closure *closure;
2214- GtkTreeIter child_iter;
2215- const GtkFileInfo *info;
2216- gboolean is_folder;
2217-
2218- closure = data;
2219- closure->num_selected++;
2220-
2221- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2222-
2223- info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
2224- is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE;
2225-
2226- closure->all_folders = closure->all_folders && is_folder;
2227- closure->all_files = closure->all_files && !is_folder;
2228-}
2229-
2230-/* Checks whether the selected items in the file list are all files or all folders */
2231-static void
2232-selection_check (GtkFileChooserDefault *impl,
2233- gint *num_selected,
2234- gboolean *all_files,
2235- gboolean *all_folders)
2236-{
2237- struct selection_check_closure closure;
2238- GtkTreeSelection *selection;
2239-
2240- closure.impl = impl;
2241- closure.num_selected = 0;
2242- closure.all_files = TRUE;
2243- closure.all_folders = TRUE;
2244-
2245- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2246- gtk_tree_selection_selected_foreach (selection,
2247- selection_check_foreach_cb,
2248- &closure);
2249-
2250- g_assert (closure.num_selected == 0 || !(closure.all_files && closure.all_folders));
2251-
2252- if (num_selected)
2253- *num_selected = closure.num_selected;
2254-
2255- if (all_files)
2256- *all_files = closure.all_files;
2257-
2258- if (all_folders)
2259- *all_folders = closure.all_folders;
2260-}
2261-
2262-struct get_selected_path_closure {
2263- GtkFileChooserDefault *impl;
2264- const GtkFilePath *path;
2265-};
2266-
2267-static void
2268-get_selected_path_foreach_cb (GtkTreeModel *model,
2269- GtkTreePath *path,
2270- GtkTreeIter *iter,
2271- gpointer data)
2272-{
2273- struct get_selected_path_closure *closure;
2274- GtkTreeIter child_iter;
2275-
2276- closure = data;
2277-
2278- gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
2279- closure->path = _gtk_file_system_model_get_path (closure->impl->browse_files_model, &child_iter);
2280-}
2281-
2282-/* Returns a selected path from the file list */
2283-static const GtkFilePath *
2284-get_selected_path (GtkFileChooserDefault *impl)
2285-{
2286- struct get_selected_path_closure closure;
2287- GtkTreeSelection *selection;
2288-
2289- closure.impl = impl;
2290- closure.path = NULL;
2291-
2292- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2293- gtk_tree_selection_selected_foreach (selection,
2294- get_selected_path_foreach_cb,
2295- &closure);
2296-
2297- return closure.path;
2298-}
2299-
2300-typedef struct {
2301- GtkFileChooserDefault *impl;
2302- gchar *tip;
2303-} UpdateTooltipData;
2304-
2305-static void
2306-update_tooltip (GtkTreeModel *model,
2307- GtkTreePath *path,
2308- GtkTreeIter *iter,
2309- gpointer data)
2310-{
2311- UpdateTooltipData *udata = data;
2312- GtkTreeIter child_iter;
2313- const GtkFileInfo *info;
2314-
2315- if (udata->tip == NULL)
2316- {
2317- gtk_tree_model_sort_convert_iter_to_child_iter (udata->impl->sort_model,
2318- &child_iter,
2319- iter);
2320-
2321- info = _gtk_file_system_model_get_info (udata->impl->browse_files_model, &child_iter);
2322- udata->tip = g_strdup_printf (_("Add the folder '%s' to the bookmarks"),
2323- gtk_file_info_get_display_name (info));
2324- }
2325-}
2326-
2327-
2328-/* Sensitize the "add bookmark" button if all the selected items are folders, or
2329- * if there are no selected items *and* the current folder is not in the
2330- * bookmarks list. De-sensitize the button otherwise.
2331- */
2332-static void
2333-bookmarks_check_add_sensitivity (GtkFileChooserDefault *impl)
2334-{
2335- gint num_selected;
2336- gboolean all_folders;
2337- gboolean active;
2338- gchar *tip;
2339-
2340- selection_check (impl, &num_selected, NULL, &all_folders);
2341-
2342- if (num_selected == 0)
2343- active = (impl->current_folder != NULL) && (shortcut_find_position (impl, impl->current_folder) == -1);
2344- else if (num_selected == 1)
2345- {
2346- const GtkFilePath *path;
2347-
2348- path = get_selected_path (impl);
2349- active = all_folders && (shortcut_find_position (impl, path) == -1);
2350- }
2351- else
2352- active = all_folders;
2353-
2354- gtk_widget_set_sensitive (impl->browse_shortcuts_add_button, active);
2355-
2356- if (impl->browse_files_popup_menu_add_shortcut_item)
2357- gtk_widget_set_sensitive (impl->browse_files_popup_menu_add_shortcut_item,
2358- (num_selected == 0) ? FALSE : active);
2359-
2360- if (active)
2361- {
2362- if (num_selected == 0)
2363- tip = g_strdup_printf (_("Add the current folder to the bookmarks"));
2364- else if (num_selected > 1)
2365- tip = g_strdup_printf (_("Add the selected folders to the bookmarks"));
2366- else
2367- {
2368- GtkTreeSelection *selection;
2369- UpdateTooltipData data;
2370-
2371- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
2372- data.impl = impl;
2373- data.tip = NULL;
2374- gtk_tree_selection_selected_foreach (selection, update_tooltip, &data);
2375- tip = data.tip;
2376-
2377- }
2378- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_add_button, tip, NULL);
2379- g_free (tip);
2380- }
2381-}
2382-
2383-/* Sets the sensitivity of the "remove bookmark" button depending on whether a
2384- * bookmark row is selected in the shortcuts tree.
2385- */
2386-static void
2387-bookmarks_check_remove_sensitivity (GtkFileChooserDefault *impl)
2388-{
2389- GtkTreeIter iter;
2390- gboolean removable = FALSE;
2391- gchar *name = NULL;
2392-
2393- if (shortcuts_get_selected (impl, &iter))
2394- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2395- SHORTCUTS_COL_REMOVABLE, &removable,
2396- SHORTCUTS_COL_NAME, &name,
2397- -1);
2398-
2399- gtk_widget_set_sensitive (impl->browse_shortcuts_remove_button, removable);
2400-
2401- if (removable)
2402- {
2403- gchar *tip;
2404-
2405- tip = g_strdup_printf (_("Remove the bookmark '%s'"), name);
2406- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_remove_button,
2407- tip, NULL);
2408- g_free (tip);
2409- }
2410-
2411- g_free (name);
2412-}
2413-
2414-static void
2415-shortcuts_check_popup_sensitivity (GtkFileChooserDefault *impl)
2416-{
2417- GtkTreeIter iter;
2418- gboolean removable = FALSE;
2419-
2420- if (impl->browse_shortcuts_popup_menu == NULL)
2421- return;
2422-
2423- if (shortcuts_get_selected (impl, &iter))
2424- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2425- SHORTCUTS_COL_REMOVABLE, &removable,
2426- -1);
2427-
2428- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_remove_item, removable);
2429- gtk_widget_set_sensitive (impl->browse_shortcuts_popup_menu_rename_item, removable);
2430-}
2431-
2432-/* GtkWidget::drag-begin handler for the shortcuts list. */
2433-static void
2434-shortcuts_drag_begin_cb (GtkWidget *widget,
2435- GdkDragContext *context,
2436- GtkFileChooserDefault *impl)
2437-{
2438-#if 0
2439- impl->shortcuts_drag_context = g_object_ref (context);
2440-#endif
2441-}
2442-
2443-#if 0
2444-/* Removes the idle handler for outside drags */
2445-static void
2446-shortcuts_cancel_drag_outside_idle (GtkFileChooserDefault *impl)
2447-{
2448- if (!impl->shortcuts_drag_outside_idle)
2449- return;
2450-
2451- g_source_destroy (impl->shortcuts_drag_outside_idle);
2452- impl->shortcuts_drag_outside_idle = NULL;
2453-}
2454-#endif
2455-
2456-/* GtkWidget::drag-end handler for the shortcuts list. */
2457-static void
2458-shortcuts_drag_end_cb (GtkWidget *widget,
2459- GdkDragContext *context,
2460- GtkFileChooserDefault *impl)
2461-{
2462-#if 0
2463- g_object_unref (impl->shortcuts_drag_context);
2464-
2465- shortcuts_cancel_drag_outside_idle (impl);
2466-
2467- if (!impl->shortcuts_drag_outside)
2468- return;
2469-
2470- gtk_button_clicked (GTK_BUTTON (impl->browse_shortcuts_remove_button));
2471-
2472- impl->shortcuts_drag_outside = FALSE;
2473-#endif
2474-}
2475-
2476-/* GtkWidget::drag-data-delete handler for the shortcuts list. */
2477-static void
2478-shortcuts_drag_data_delete_cb (GtkWidget *widget,
2479- GdkDragContext *context,
2480- GtkFileChooserDefault *impl)
2481-{
2482- g_signal_stop_emission_by_name (widget, "drag_data_delete");
2483-}
2484-
2485-#if 0
2486-/* Creates a suitable drag cursor to indicate that the selected bookmark will be
2487- * deleted or not.
2488- */
2489-static void
2490-shortcuts_drag_set_delete_cursor (GtkFileChooserDefault *impl,
2491- gboolean delete)
2492-{
2493- GtkTreeView *tree_view;
2494- GtkTreeIter iter;
2495- GtkTreePath *path;
2496- GdkPixmap *row_pixmap;
2497- GdkBitmap *mask;
2498- int row_pixmap_y;
2499- int cell_y;
2500-
2501- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view);
2502-
2503- /* Find the selected path and get its drag pixmap */
2504-
2505- if (!shortcuts_get_selected (impl, &iter))
2506- g_assert_not_reached ();
2507-
2508- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
2509-
2510- row_pixmap = gtk_tree_view_create_row_drag_icon (tree_view, path);
2511- gtk_tree_path_free (path);
2512-
2513- mask = NULL;
2514- row_pixmap_y = 0;
2515-
2516- if (delete)
2517- {
2518- GdkPixbuf *pixbuf;
2519-
2520- pixbuf = gtk_widget_render_icon (impl->browse_shortcuts_tree_view,
2521- GTK_STOCK_DELETE,
2522- GTK_ICON_SIZE_DND,
2523- NULL);
2524- if (pixbuf)
2525- {
2526- GdkPixmap *composite;
2527- int row_pixmap_width, row_pixmap_height;
2528- int pixbuf_width, pixbuf_height;
2529- int composite_width, composite_height;
2530- int pixbuf_x, pixbuf_y;
2531- GdkGC *gc, *mask_gc;
2532- GdkColor color;
2533- GdkBitmap *pixbuf_mask;
2534-
2535- /* Create pixmap and mask for composite image */
2536-
2537- gdk_drawable_get_size (row_pixmap, &row_pixmap_width, &row_pixmap_height);
2538- pixbuf_width = gdk_pixbuf_get_width (pixbuf);
2539- pixbuf_height = gdk_pixbuf_get_height (pixbuf);
2540-
2541- composite_width = MAX (row_pixmap_width, pixbuf_width);
2542- composite_height = MAX (row_pixmap_height, pixbuf_height);
2543-
2544- row_pixmap_y = (composite_height - row_pixmap_height) / 2;
2545-
2546- if (gtk_widget_get_direction (impl->browse_shortcuts_tree_view) == GTK_TEXT_DIR_RTL)
2547- pixbuf_x = 0;
2548- else
2549- pixbuf_x = composite_width - pixbuf_width;
2550-
2551- pixbuf_y = (composite_height - pixbuf_height) / 2;
2552-
2553- composite = gdk_pixmap_new (row_pixmap, composite_width, composite_height, -1);
2554- gc = gdk_gc_new (composite);
2555-
2556- mask = gdk_pixmap_new (row_pixmap, composite_width, composite_height, 1);
2557- mask_gc = gdk_gc_new (mask);
2558- color.pixel = 0;
2559- gdk_gc_set_foreground (mask_gc, &color);
2560- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, 0, composite_width, composite_height);
2561-
2562- color.red = 0xffff;
2563- color.green = 0xffff;
2564- color.blue = 0xffff;
2565- gdk_gc_set_rgb_fg_color (gc, &color);
2566- gdk_draw_rectangle (composite, gc, TRUE, 0, 0, composite_width, composite_height);
2567-
2568- /* Composite the row pixmap and the pixbuf */
2569-
2570- gdk_pixbuf_render_pixmap_and_mask_for_colormap
2571- (pixbuf,
2572- gtk_widget_get_colormap (impl->browse_shortcuts_tree_view),
2573- NULL, &pixbuf_mask, 128);
2574- gdk_draw_drawable (mask, mask_gc, pixbuf_mask,
2575- 0, 0,
2576- pixbuf_x, pixbuf_y,
2577- pixbuf_width, pixbuf_height);
2578- g_object_unref (pixbuf_mask);
2579-
2580- gdk_draw_drawable (composite, gc, row_pixmap,
2581- 0, 0,
2582- 0, row_pixmap_y,
2583- row_pixmap_width, row_pixmap_height);
2584- color.pixel = 1;
2585- gdk_gc_set_foreground (mask_gc, &color);
2586- gdk_draw_rectangle (mask, mask_gc, TRUE, 0, row_pixmap_y, row_pixmap_width, row_pixmap_height);
2587-
2588- gdk_draw_pixbuf (composite, gc, pixbuf,
2589- 0, 0,
2590- pixbuf_x, pixbuf_y,
2591- pixbuf_width, pixbuf_height,
2592- GDK_RGB_DITHER_MAX,
2593- 0, 0);
2594-
2595- g_object_unref (pixbuf);
2596- g_object_unref (row_pixmap);
2597-
2598- row_pixmap = composite;
2599- }
2600- }
2601-
2602- /* The hotspot offsets here are copied from gtk_tree_view_drag_begin(), ugh */
2603-
2604- gtk_tree_view_get_path_at_pos (tree_view,
2605- tree_view->priv->press_start_x,
2606- tree_view->priv->press_start_y,
2607- NULL,
2608- NULL,
2609- NULL,
2610- &cell_y);
2611-
2612- gtk_drag_set_icon_pixmap (impl->shortcuts_drag_context,
2613- gdk_drawable_get_colormap (row_pixmap),
2614- row_pixmap,
2615- mask,
2616- tree_view->priv->press_start_x + 1,
2617- row_pixmap_y + cell_y + 1);
2618-
2619- g_object_unref (row_pixmap);
2620- if (mask)
2621- g_object_unref (mask);
2622-}
2623-
2624-/* We set the delete cursor and the shortcuts_drag_outside flag in an idle
2625- * handler so that we can tell apart the drag_leave event that comes right
2626- * before a drag_drop, from a normal drag_leave. We don't want to set the
2627- * cursor nor the flag in the latter case.
2628- */
2629-static gboolean
2630-shortcuts_drag_outside_idle_cb (GtkFileChooserDefault *impl)
2631-{
2632- GDK_THREADS_ENTER ();
2633-
2634- shortcuts_drag_set_delete_cursor (impl, TRUE);
2635- impl->shortcuts_drag_outside = TRUE;
2636-
2637- shortcuts_cancel_drag_outside_idle (impl);
2638-
2639- GDK_THREADS_LEAVE ();
2640-
2641- return FALSE;
2642-}
2643-#endif
2644-
2645-/* GtkWidget::drag-leave handler for the shortcuts list. We unhighlight the
2646- * drop position.
2647- */
2648-static void
2649-shortcuts_drag_leave_cb (GtkWidget *widget,
2650- GdkDragContext *context,
2651- guint time_,
2652- GtkFileChooserDefault *impl)
2653-{
2654-#if 0
2655- if (gtk_drag_get_source_widget (context) == widget && !impl->shortcuts_drag_outside_idle)
2656- {
2657- impl->shortcuts_drag_outside_idle = g_idle_source_new ();
2658- g_source_set_closure (impl->shortcuts_drag_outside_idle,
2659- g_cclosure_new_object (G_CALLBACK (shortcuts_drag_outside_idle_cb),
2660- G_OBJECT (impl)));
2661- g_source_attach (impl->shortcuts_drag_outside_idle, NULL);
2662- }
2663-#endif
2664-
2665- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
2666- NULL,
2667- GTK_TREE_VIEW_DROP_BEFORE);
2668-
2669- g_signal_stop_emission_by_name (widget, "drag_leave");
2670-}
2671-
2672-/* Computes the appropriate row and position for dropping */
2673-static void
2674-shortcuts_compute_drop_position (GtkFileChooserDefault *impl,
2675- int x,
2676- int y,
2677- GtkTreePath **path,
2678- GtkTreeViewDropPosition *pos)
2679-{
2680- GtkTreeView *tree_view;
2681- GtkTreeViewColumn *column;
2682- int cell_y;
2683- GdkRectangle cell;
2684- int row;
2685- int bookmarks_index;
2686-
2687- tree_view = GTK_TREE_VIEW (impl->browse_shortcuts_tree_view);
2688-
2689- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2690-
2691- if (!gtk_tree_view_get_path_at_pos (tree_view,
2692- x,
2693- y - TREE_VIEW_HEADER_HEIGHT (tree_view),
2694- path,
2695- &column,
2696- NULL,
2697- &cell_y))
2698- {
2699- row = bookmarks_index + impl->num_bookmarks - 1;
2700- *path = gtk_tree_path_new_from_indices (row, -1);
2701- *pos = GTK_TREE_VIEW_DROP_AFTER;
2702- return;
2703- }
2704-
2705- row = *gtk_tree_path_get_indices (*path);
2706- gtk_tree_view_get_background_area (tree_view, *path, column, &cell);
2707- gtk_tree_path_free (*path);
2708-
2709- if (row < bookmarks_index)
2710- {
2711- row = bookmarks_index;
2712- *pos = GTK_TREE_VIEW_DROP_BEFORE;
2713- }
2714- else if (row > bookmarks_index + impl->num_bookmarks - 1)
2715- {
2716- row = bookmarks_index + impl->num_bookmarks - 1;
2717- *pos = GTK_TREE_VIEW_DROP_AFTER;
2718- }
2719- else
2720- {
2721- if (cell_y < cell.height / 2)
2722- *pos = GTK_TREE_VIEW_DROP_BEFORE;
2723- else
2724- *pos = GTK_TREE_VIEW_DROP_AFTER;
2725- }
2726-
2727- *path = gtk_tree_path_new_from_indices (row, -1);
2728-}
2729-
2730-/* GtkWidget::drag-motion handler for the shortcuts list. We basically
2731- * implement the destination side of DnD by hand, due to limitations in
2732- * GtkTreeView's DnD API.
2733+/* Idle handler for creating a new folder after editing its name cell, or for
2734+ * canceling the editing.
2735 */
2736 static gboolean
2737-shortcuts_drag_motion_cb (GtkWidget *widget,
2738- GdkDragContext *context,
2739- gint x,
2740- gint y,
2741- guint time_,
2742- GtkFileChooserDefault *impl)
2743-{
2744- GtkTreePath *path;
2745- GtkTreeViewDropPosition pos;
2746- GdkDragAction action;
2747-
2748-#if 0
2749- if (gtk_drag_get_source_widget (context) == widget)
2750- {
2751- shortcuts_cancel_drag_outside_idle (impl);
2752-
2753- if (impl->shortcuts_drag_outside)
2754- {
2755- shortcuts_drag_set_delete_cursor (impl, FALSE);
2756- impl->shortcuts_drag_outside = FALSE;
2757- }
2758- }
2759-#endif
2760-
2761- if (context->suggested_action == GDK_ACTION_COPY || (context->actions & GDK_ACTION_COPY) != 0)
2762- action = GDK_ACTION_COPY;
2763- else if (context->suggested_action == GDK_ACTION_MOVE || (context->actions & GDK_ACTION_MOVE) != 0)
2764- action = GDK_ACTION_MOVE;
2765- else
2766- {
2767- action = 0;
2768- goto out;
2769- }
2770-
2771- shortcuts_compute_drop_position (impl, x, y, &path, &pos);
2772- gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), path, pos);
2773- gtk_tree_path_free (path);
2774-
2775- out:
2776-
2777- g_signal_stop_emission_by_name (widget, "drag_motion");
2778-
2779- if (action != 0)
2780- {
2781- gdk_drag_status (context, action, time_);
2782- return TRUE;
2783- }
2784- else
2785- return FALSE;
2786-}
2787-
2788-/* GtkWidget::drag-drop handler for the shortcuts list. */
2789-static gboolean
2790-shortcuts_drag_drop_cb (GtkWidget *widget,
2791- GdkDragContext *context,
2792- gint x,
2793- gint y,
2794- guint time_,
2795- GtkFileChooserDefault *impl)
2796+edited_idle_cb (GtkFileChooserDefault *impl)
2797 {
2798-#if 0
2799- shortcuts_cancel_drag_outside_idle (impl);
2800-#endif
2801+ GDK_THREADS_ENTER ();
2802
2803- g_signal_stop_emission_by_name (widget, "drag_drop");
2804- return TRUE;
2805-}
2806+ g_source_destroy (impl->edited_idle);
2807+ impl->edited_idle = NULL;
2808
2809-/* Parses a "text/uri-list" string and inserts its URIs as bookmarks */
2810-static void
2811-shortcuts_drop_uris (GtkFileChooserDefault *impl,
2812- const char *data,
2813- int position)
2814-{
2815- gchar **uris;
2816- gint i;
2817+ _gtk_file_system_model_remove_editable (impl->browse_files_model);
2818+ g_object_set (impl->list_name_renderer, "editable", FALSE, NULL);
2819
2820- uris = g_uri_list_extract_uris (data);
2821+ gtk_widget_set_sensitive (impl->browse_new_folder_button, TRUE);
2822
2823- for (i = 0; uris[i]; i++)
2824+ if (impl->edited_new_text) /* not cancelled? */
2825 {
2826- char *uri;
2827- GtkFilePath *path;
2828-
2829- uri = uris[i];
2830- path = gtk_file_system_uri_to_path (impl->file_system, uri);
2831+ GError *error;
2832+ GtkFilePath *file_path;
2833
2834- if (path)
2835+ error = NULL;
2836+ file_path = gtk_file_system_make_path (impl->file_system,
2837+ impl->current_folder,
2838+ impl->edited_new_text,
2839+ &error);
2840+ if (file_path)
2841 {
2842- if (shortcuts_add_bookmark_from_path (impl, path, position))
2843- position++;
2844+ GtkFileSystemHandle *handle;
2845
2846- gtk_file_path_free (path);
2847- }
2848- else
2849- {
2850- GError *error;
2851+ handle = gtk_file_system_create_folder (impl->file_system, file_path,
2852+ edited_idle_create_folder_cb,
2853+ g_object_ref (impl));
2854+ impl->pending_handles = g_slist_append (impl->pending_handles, handle);
2855
2856- g_set_error (&error,
2857- GTK_FILE_CHOOSER_ERROR,
2858- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
2859- _("Could not add a bookmark for '%s' "
2860- "because it is an invalid path name."),
2861- uri);
2862- error_adding_bookmark_dialog (impl, path, error);
2863+ gtk_file_path_free (file_path);
2864 }
2865- }
2866-
2867- g_strfreev (uris);
2868-}
2869-
2870-/* Reorders the selected bookmark to the specified position */
2871-static void
2872-shortcuts_reorder (GtkFileChooserDefault *impl,
2873- int new_position)
2874-{
2875- GtkTreeIter iter;
2876- gpointer col_data;
2877- gboolean is_volume;
2878- GtkTreePath *path;
2879- int old_position;
2880- int bookmarks_index;
2881- const GtkFilePath *file_path;
2882- GtkFilePath *file_path_copy;
2883- GError *error;
2884- gchar *name;
2885-
2886- /* Get the selected path */
2887-
2888- if (!shortcuts_get_selected (impl, &iter))
2889- g_assert_not_reached ();
2890-
2891- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
2892- old_position = *gtk_tree_path_get_indices (path);
2893- gtk_tree_path_free (path);
2894-
2895- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2896- old_position -= bookmarks_index;
2897- g_assert (old_position >= 0 && old_position < impl->num_bookmarks);
2898-
2899- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
2900- SHORTCUTS_COL_NAME, &name,
2901- SHORTCUTS_COL_DATA, &col_data,
2902- SHORTCUTS_COL_IS_VOLUME, &is_volume,
2903- -1);
2904- g_assert (col_data != NULL);
2905- g_assert (!is_volume);
2906-
2907- file_path = col_data;
2908- file_path_copy = gtk_file_path_copy (file_path); /* removal below will free file_path, so we need a copy */
2909-
2910- /* Remove the path from the old position and insert it in the new one */
2911-
2912- if (new_position > old_position)
2913- new_position--;
2914-
2915- if (old_position == new_position)
2916- goto out;
2917+ else
2918+ error_creating_folder_dialog (impl, file_path, error);
2919
2920- error = NULL;
2921- if (gtk_file_system_remove_bookmark (impl->file_system, file_path_copy, &error))
2922- {
2923- shortcuts_add_bookmark_from_path (impl, file_path_copy, new_position);
2924- gtk_file_system_set_bookmark_label (impl->file_system, file_path_copy, name);
2925+ g_free (impl->edited_new_text);
2926+ impl->edited_new_text = NULL;
2927 }
2928- else
2929- error_adding_bookmark_dialog (impl, file_path_copy, error);
2930-
2931- out:
2932-
2933- gtk_file_path_free (file_path_copy);
2934-}
2935-
2936-/* Callback used when we get the drag data for the bookmarks list. We add the
2937- * received URIs as bookmarks if they are folders.
2938- */
2939-static void
2940-shortcuts_drag_data_received_cb (GtkWidget *widget,
2941- GdkDragContext *context,
2942- gint x,
2943- gint y,
2944- GtkSelectionData *selection_data,
2945- guint info,
2946- guint time_,
2947- gpointer data)
2948-{
2949- GtkFileChooserDefault *impl;
2950- GtkTreePath *tree_path;
2951- GtkTreeViewDropPosition tree_pos;
2952- int position;
2953- int bookmarks_index;
2954-
2955- impl = GTK_FILE_CHOOSER_DEFAULT (data);
2956-
2957- /* Compute position */
2958-
2959- bookmarks_index = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS);
2960-
2961- shortcuts_compute_drop_position (impl, x, y, &tree_path, &tree_pos);
2962- position = *gtk_tree_path_get_indices (tree_path);
2963- gtk_tree_path_free (tree_path);
2964-
2965- if (tree_pos == GTK_TREE_VIEW_DROP_AFTER)
2966- position++;
2967-
2968- g_assert (position >= bookmarks_index);
2969- position -= bookmarks_index;
2970-
2971- if (selection_data->target == gdk_atom_intern_static_string ("text/uri-list"))
2972- shortcuts_drop_uris (impl, (const char *) selection_data->data, position);
2973- else if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
2974- shortcuts_reorder (impl, position);
2975-
2976- g_signal_stop_emission_by_name (widget, "drag_data_received");
2977-}
2978-
2979-/* Callback used when the selection in the shortcuts tree changes */
2980-static void
2981-shortcuts_selection_changed_cb (GtkTreeSelection *selection,
2982- GtkFileChooserDefault *impl)
2983-{
2984- bookmarks_check_remove_sensitivity (impl);
2985- shortcuts_check_popup_sensitivity (impl);
2986-}
2987-
2988-static gboolean
2989-shortcuts_row_separator_func (GtkTreeModel *model,
2990- GtkTreeIter *iter,
2991- gpointer data)
2992-{
2993- gint column = GPOINTER_TO_INT (data);
2994- gchar *text;
2995-
2996- gtk_tree_model_get (model, iter, column, &text, -1);
2997-
2998- if (!text)
2999- return TRUE;
3000
3001- g_free (text);
3002-
3003- return FALSE;
3004-}
3005-
3006-/* Since GtkTreeView has a keybinding attached to '/', we need to catch
3007- * keypresses before the TreeView gets them.
3008- */
3009-static gboolean
3010-tree_view_keybinding_cb (GtkWidget *tree_view,
3011- GdkEventKey *event,
3012- GtkFileChooserDefault *impl)
3013-{
3014- if ((event->keyval == GDK_slash
3015- || event->keyval == GDK_KP_Divide
3016-#ifdef G_OS_UNIX
3017- || event->keyval == GDK_asciitilde
3018-#endif
3019- ) && ! (event->state & (~GDK_SHIFT_MASK & gtk_accelerator_get_default_mod_mask ())))
3020- {
3021- location_popup_handler (impl, event->string);
3022- return TRUE;
3023- }
3024+ GDK_THREADS_LEAVE ();
3025
3026 return FALSE;
3027 }
3028
3029-/* Callback used when the file list's popup menu is detached */
3030-static void
3031-shortcuts_popup_menu_detach_cb (GtkWidget *attach_widget,
3032- GtkMenu *menu)
3033-{
3034- GtkFileChooserDefault *impl;
3035-
3036- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
3037- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
3038-
3039- impl->browse_shortcuts_popup_menu = NULL;
3040- impl->browse_shortcuts_popup_menu_remove_item = NULL;
3041- impl->browse_shortcuts_popup_menu_rename_item = NULL;
3042-}
3043-
3044-static void
3045-remove_shortcut_cb (GtkMenuItem *item,
3046- GtkFileChooserDefault *impl)
3047-{
3048- remove_selected_bookmarks (impl);
3049-}
3050-
3051-/* Rename the selected bookmark */
3052-static void
3053-rename_selected_bookmark (GtkFileChooserDefault *impl)
3054-{
3055- GtkTreeIter iter;
3056- GtkTreePath *path;
3057- GtkTreeViewColumn *column;
3058- GtkCellRenderer *cell;
3059- GList *renderers;
3060-
3061- if (shortcuts_get_selected (impl, &iter))
3062- {
3063- path = gtk_tree_model_get_path (GTK_TREE_MODEL (impl->shortcuts_model), &iter);
3064- column = gtk_tree_view_get_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), 0);
3065- renderers = gtk_tree_view_column_get_cell_renderers (column);
3066- cell = g_list_nth_data (renderers, 1);
3067- g_list_free (renderers);
3068- g_object_set (cell, "editable", TRUE, NULL);
3069- gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3070- path, column, cell, TRUE);
3071- gtk_tree_path_free (path);
3072- }
3073-}
3074-
3075-static void
3076-rename_shortcut_cb (GtkMenuItem *item,
3077- GtkFileChooserDefault *impl)
3078-{
3079- rename_selected_bookmark (impl);
3080-}
3081-
3082-/* Constructs the popup menu for the file list if needed */
3083 static void
3084-shortcuts_build_popup_menu (GtkFileChooserDefault *impl)
3085-{
3086- GtkWidget *item;
3087-
3088- if (impl->browse_shortcuts_popup_menu)
3089- return;
3090-
3091- impl->browse_shortcuts_popup_menu = gtk_menu_new ();
3092- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_shortcuts_popup_menu),
3093- impl->browse_shortcuts_tree_view,
3094- shortcuts_popup_menu_detach_cb);
3095-
3096- item = gtk_image_menu_item_new_with_label (_("Remove"));
3097- impl->browse_shortcuts_popup_menu_remove_item = item;
3098- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
3099- gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
3100- g_signal_connect (item, "activate",
3101- G_CALLBACK (remove_shortcut_cb), impl);
3102- gtk_widget_show (item);
3103- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
3104-
3105- item = gtk_menu_item_new_with_label (_("Rename..."));
3106- impl->browse_shortcuts_popup_menu_rename_item = item;
3107- g_signal_connect (item, "activate",
3108- G_CALLBACK (rename_shortcut_cb), impl);
3109- gtk_widget_show (item);
3110- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
3111-
3112- shortcuts_check_popup_sensitivity (impl);
3113-}
3114-
3115-static void
3116-shortcuts_update_popup_menu (GtkFileChooserDefault *impl)
3117+queue_edited_idle (GtkFileChooserDefault *impl,
3118+ const gchar *new_text)
3119 {
3120- shortcuts_build_popup_menu (impl);
3121-}
3122-
3123-static void
3124-popup_position_func (GtkMenu *menu,
3125- gint *x,
3126- gint *y,
3127- gboolean *push_in,
3128- gpointer user_data);
3129+ /* We create the folder in an idle handler so that we don't modify the tree
3130+ * just now.
3131+ */
3132
3133-static void
3134-shortcuts_popup_menu (GtkFileChooserDefault *impl,
3135- GdkEventButton *event)
3136-{
3137- shortcuts_update_popup_menu (impl);
3138- if (event)
3139- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
3140- NULL, NULL, NULL, NULL,
3141- event->button, event->time);
3142- else
3143+ if (!impl->edited_idle)
3144 {
3145- gtk_menu_popup (GTK_MENU (impl->browse_shortcuts_popup_menu),
3146- NULL, NULL,
3147- popup_position_func, impl->browse_shortcuts_tree_view,
3148- 0, GDK_CURRENT_TIME);
3149- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu),
3150- FALSE);
3151+ impl->edited_idle = g_idle_source_new ();
3152+ g_source_set_closure (impl->edited_idle,
3153+ g_cclosure_new_object (G_CALLBACK (edited_idle_cb),
3154+ G_OBJECT (impl)));
3155+ g_source_attach (impl->edited_idle, NULL);
3156 }
3157-}
3158-
3159-/* Callback used for the GtkWidget::popup-menu signal of the shortcuts list */
3160-static gboolean
3161-shortcuts_popup_menu_cb (GtkWidget *widget,
3162- GtkFileChooserDefault *impl)
3163-{
3164- shortcuts_popup_menu (impl, NULL);
3165- return TRUE;
3166-}
3167-
3168-/* Callback used when a button is pressed on the shortcuts list.
3169- * We trap button 3 to bring up a popup menu.
3170- */
3171-static gboolean
3172-shortcuts_button_press_event_cb (GtkWidget *widget,
3173- GdkEventButton *event,
3174- GtkFileChooserDefault *impl)
3175-{
3176- static gboolean in_press = FALSE;
3177- gboolean handled;
3178-
3179- if (in_press)
3180- return FALSE;
3181-
3182- if (event->button != 3)
3183- return FALSE;
3184-
3185- in_press = TRUE;
3186- handled = gtk_widget_event (impl->browse_shortcuts_tree_view, (GdkEvent *) event);
3187- in_press = FALSE;
3188-
3189- if (!handled)
3190- return FALSE;
3191
3192- shortcuts_popup_menu (impl, event);
3193- return TRUE;
3194+ g_free (impl->edited_new_text);
3195+ impl->edited_new_text = g_strdup (new_text);
3196 }
3197
3198+/* Callback used from the text cell renderer when the new folder is named */
3199 static void
3200-shortcuts_edited (GtkCellRenderer *cell,
3201- gchar *path_string,
3202- gchar *new_text,
3203- GtkFileChooserDefault *impl)
3204+renderer_edited_cb (GtkCellRendererText *cell_renderer_text,
3205+ const gchar *path,
3206+ const gchar *new_text,
3207+ GtkFileChooserDefault *impl)
3208 {
3209- GtkTreePath *path;
3210- GtkTreeIter iter;
3211- GtkFilePath *shortcut;
3212-
3213- g_object_set (cell, "editable", FALSE, NULL);
3214-
3215- path = gtk_tree_path_new_from_string (path_string);
3216- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->shortcuts_model), &iter, path))
3217- g_assert_not_reached ();
3218-
3219- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
3220- SHORTCUTS_COL_DATA, &shortcut,
3221- -1);
3222- gtk_tree_path_free (path);
3223-
3224- gtk_file_system_set_bookmark_label (impl->file_system, shortcut, new_text);
3225+ /* work around bug #154921 */
3226+ g_object_set (cell_renderer_text,
3227+ "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
3228+ queue_edited_idle (impl, new_text);
3229 }
3230
3231+/* Callback used from the text cell renderer when the new folder edition gets
3232+ * canceled.
3233+ */
3234 static void
3235-shortcuts_editing_canceled (GtkCellRenderer *cell,
3236- GtkFileChooserDefault *impl)
3237+renderer_editing_canceled_cb (GtkCellRendererText *cell_renderer_text,
3238+ GtkFileChooserDefault *impl)
3239 {
3240- g_object_set (cell, "editable", FALSE, NULL);
3241+ /* work around bug #154921 */
3242+ g_object_set (cell_renderer_text,
3243+ "mode", GTK_CELL_RENDERER_MODE_INERT, NULL);
3244+ queue_edited_idle (impl, NULL);
3245 }
3246
3247-/* Creates the widgets for the shortcuts and bookmarks tree */
3248+/* Creates the widgets for the filter combo box */
3249 static GtkWidget *
3250-shortcuts_list_create (GtkFileChooserDefault *impl)
3251+filter_create (GtkFileChooserDefault *impl)
3252 {
3253- GtkWidget *swin;
3254- GtkTreeSelection *selection;
3255- GtkTreeViewColumn *column;
3256- GtkCellRenderer *renderer;
3257-
3258- /* Scrolled window */
3259-
3260- swin = gtk_scrolled_window_new (NULL, NULL);
3261- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swin),
3262- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3263- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swin),
3264- GTK_SHADOW_IN);
3265- gtk_widget_show (swin);
3266-
3267- /* Tree */
3268-
3269- impl->browse_shortcuts_tree_view = gtk_tree_view_new ();
3270-#ifdef PROFILE_FILE_CHOOSER
3271- g_object_set_data (G_OBJECT (impl->browse_shortcuts_tree_view), "fmq-name", "shortcuts");
3272-#endif
3273- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event",
3274- G_CALLBACK (tree_view_keybinding_cb), impl);
3275- g_signal_connect (impl->browse_shortcuts_tree_view, "popup_menu",
3276- G_CALLBACK (shortcuts_popup_menu_cb), impl);
3277- g_signal_connect (impl->browse_shortcuts_tree_view, "button_press_event",
3278- G_CALLBACK (shortcuts_button_press_event_cb), impl);
3279- /* Accessible object name for the file chooser's shortcuts pane */
3280- atk_object_set_name (gtk_widget_get_accessible (impl->browse_shortcuts_tree_view), _("Places"));
3281-
3282- gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), impl->shortcuts_filter_model);
3283-
3284- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3285- GDK_BUTTON1_MASK,
3286- shortcuts_source_targets,
3287- num_shortcuts_source_targets,
3288- GDK_ACTION_MOVE);
3289-
3290- gtk_drag_dest_set (impl->browse_shortcuts_tree_view,
3291- GTK_DEST_DEFAULT_ALL,
3292- shortcuts_dest_targets,
3293- num_shortcuts_dest_targets,
3294- GDK_ACTION_COPY | GDK_ACTION_MOVE);
3295-
3296- selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
3297- gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
3298- gtk_tree_selection_set_select_function (selection,
3299- shortcuts_select_func,
3300- impl, NULL);
3301-
3302- g_signal_connect (selection, "changed",
3303- G_CALLBACK (shortcuts_selection_changed_cb), impl);
3304-
3305- g_signal_connect (impl->browse_shortcuts_tree_view, "row_activated",
3306- G_CALLBACK (shortcuts_row_activated_cb), impl);
3307-
3308- g_signal_connect (impl->browse_shortcuts_tree_view, "key_press_event",
3309- G_CALLBACK (shortcuts_key_press_event_cb), impl);
3310+ impl->filter_combo = gtk_combo_box_new_text ();
3311+ gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (impl->filter_combo), FALSE);
3312
3313- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_begin",
3314- G_CALLBACK (shortcuts_drag_begin_cb), impl);
3315- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_end",
3316- G_CALLBACK (shortcuts_drag_end_cb), impl);
3317- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_delete",
3318- G_CALLBACK (shortcuts_drag_data_delete_cb), impl);
3319-
3320- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_leave",
3321- G_CALLBACK (shortcuts_drag_leave_cb), impl);
3322- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_motion",
3323- G_CALLBACK (shortcuts_drag_motion_cb), impl);
3324- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_drop",
3325- G_CALLBACK (shortcuts_drag_drop_cb), impl);
3326- g_signal_connect (impl->browse_shortcuts_tree_view, "drag_data_received",
3327- G_CALLBACK (shortcuts_drag_data_received_cb), impl);
3328+ g_signal_connect (impl->filter_combo, "changed",
3329+ G_CALLBACK (filter_combo_changed), impl);
3330
3331- gtk_container_add (GTK_CONTAINER (swin), impl->browse_shortcuts_tree_view);
3332- gtk_widget_show (impl->browse_shortcuts_tree_view);
3333+ return impl->filter_combo;
3334+}
3335
3336- /* Column */
3337+struct selection_check_closure {
3338+ GtkFileChooserDefault *impl;
3339+ int num_selected;
3340+ gboolean all_files;
3341+ gboolean all_folders;
3342+};
3343
3344- column = gtk_tree_view_column_new ();
3345- /* Column header for the file chooser's shortcuts pane */
3346- gtk_tree_view_column_set_title (column, _("_Places"));
3347+/* Used from gtk_tree_selection_selected_foreach() */
3348+static void
3349+selection_check_foreach_cb (GtkTreeModel *model,
3350+ GtkTreePath *path,
3351+ GtkTreeIter *iter,
3352+ gpointer data)
3353+{
3354+ struct selection_check_closure *closure;
3355+ GtkTreeIter child_iter;
3356+ const GtkFileInfo *info;
3357+ gboolean is_folder;
3358
3359- renderer = gtk_cell_renderer_pixbuf_new ();
3360- gtk_tree_view_column_pack_start (column, renderer, FALSE);
3361- gtk_tree_view_column_set_attributes (column, renderer,
3362- "pixbuf", SHORTCUTS_COL_PIXBUF,
3363- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
3364- NULL);
3365+ closure = data;
3366+ closure->num_selected++;
3367
3368- renderer = gtk_cell_renderer_text_new ();
3369- g_signal_connect (renderer, "edited",
3370- G_CALLBACK (shortcuts_edited), impl);
3371- g_signal_connect (renderer, "editing-canceled",
3372- G_CALLBACK (shortcuts_editing_canceled), impl);
3373- gtk_tree_view_column_pack_start (column, renderer, TRUE);
3374- gtk_tree_view_column_set_attributes (column, renderer,
3375- "text", SHORTCUTS_COL_NAME,
3376- NULL);
3377-
3378- gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
3379- shortcuts_row_separator_func,
3380- GINT_TO_POINTER (SHORTCUTS_COL_NAME),
3381- NULL);
3382+ gtk_tree_model_sort_convert_iter_to_child_iter (closure->impl->sort_model, &child_iter, iter);
3383
3384- gtk_tree_view_append_column (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view), column);
3385+ info = _gtk_file_system_model_get_info (closure->impl->browse_files_model, &child_iter);
3386+ is_folder = info ? gtk_file_info_get_is_folder (info) : FALSE;
3387
3388- return swin;
3389+ closure->all_folders = closure->all_folders && is_folder;
3390+ closure->all_files = closure->all_files && !is_folder;
3391 }
3392
3393-/* Creates the widgets for the shortcuts/bookmarks pane */
3394-static GtkWidget *
3395-shortcuts_pane_create (GtkFileChooserDefault *impl,
3396- GtkSizeGroup *size_group)
3397+/* Checks whether the selected items in the file list are all files or all folders */
3398+static void
3399+selection_check (GtkFileChooserDefault *impl,
3400+ gint *num_selected,
3401+ gboolean *all_files,
3402+ gboolean *all_folders)
3403 {
3404- GtkWidget *vbox;
3405- GtkWidget *hbox;
3406- GtkWidget *widget;
3407-
3408- vbox = gtk_vbox_new (FALSE, 6);
3409- gtk_widget_show (vbox);
3410-
3411- /* Shortcuts tree */
3412+ struct selection_check_closure closure;
3413+ GtkTreeSelection *selection;
3414
3415- widget = shortcuts_list_create (impl);
3416- gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
3417+ closure.impl = impl;
3418+ closure.num_selected = 0;
3419+ closure.all_files = TRUE;
3420+ closure.all_folders = TRUE;
3421
3422- /* Box for buttons */
3423+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
3424+ gtk_tree_selection_selected_foreach (selection,
3425+ selection_check_foreach_cb,
3426+ &closure);
3427
3428- hbox = gtk_hbox_new (TRUE, 6);
3429- gtk_size_group_add_widget (size_group, hbox);
3430- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
3431- gtk_widget_show (hbox);
3432+ g_assert (closure.num_selected == 0 || !(closure.all_files && closure.all_folders));
3433
3434- /* Add bookmark button */
3435+ if (num_selected)
3436+ *num_selected = closure.num_selected;
3437
3438- impl->browse_shortcuts_add_button = button_new (impl,
3439- _("_Add"),
3440- GTK_STOCK_ADD,
3441- FALSE,
3442- TRUE,
3443- G_CALLBACK (add_bookmark_button_clicked_cb));
3444- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_add_button, TRUE, TRUE, 0);
3445- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_add_button,
3446- _("Add the selected folder to the Bookmarks"), NULL);
3447-
3448- /* Remove bookmark button */
3449-
3450- impl->browse_shortcuts_remove_button = button_new (impl,
3451- _("_Remove"),
3452- GTK_STOCK_REMOVE,
3453- FALSE,
3454- TRUE,
3455- G_CALLBACK (remove_bookmark_button_clicked_cb));
3456- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_shortcuts_remove_button, TRUE, TRUE, 0);
3457- gtk_tooltips_set_tip (impl->tooltips, impl->browse_shortcuts_remove_button,
3458- _("Remove the selected bookmark"), NULL);
3459+ if (all_files)
3460+ *all_files = closure.all_files;
3461
3462- return vbox;
3463+ if (all_folders)
3464+ *all_folders = closure.all_folders;
3465 }
3466
3467+struct get_selected_path_closure {
3468+ GtkFileChooserDefault *impl;
3469+ const GtkFilePath *path;
3470+};
3471+
3472 /* Handles key press events on the file list, so that we can trap Enter to
3473 * activate the default button on our own. Also, checks to see if '/' has been
3474 * pressed. See comment by tree_view_keybinding_cb() for more details.
3475@@ -3662,17 +1175,6 @@
3476
3477 modifiers = gtk_accelerator_get_default_mod_mask ();
3478
3479- if ((event->keyval == GDK_slash
3480- || event->keyval == GDK_KP_Divide
3481-#ifdef G_OS_UNIX
3482- || event->keyval == GDK_asciitilde
3483-#endif
3484- ) && ! (event->state & (~GDK_SHIFT_MASK & modifiers)))
3485- {
3486- location_popup_handler (impl, event->string);
3487- return TRUE;
3488- }
3489-
3490 if ((event->keyval == GDK_Return
3491 || event->keyval == GDK_ISO_Enter
3492 || event->keyval == GDK_KP_Enter
3493@@ -3697,367 +1199,66 @@
3494 return FALSE;
3495 }
3496
3497-/* Callback used when the file list's popup menu is detached */
3498-static void
3499-popup_menu_detach_cb (GtkWidget *attach_widget,
3500- GtkMenu *menu)
3501-{
3502- GtkFileChooserDefault *impl;
3503-
3504- impl = g_object_get_data (G_OBJECT (attach_widget), "GtkFileChooserDefault");
3505- g_assert (GTK_IS_FILE_CHOOSER_DEFAULT (impl));
3506-
3507- impl->browse_files_popup_menu = NULL;
3508- impl->browse_files_popup_menu_add_shortcut_item = NULL;
3509- impl->browse_files_popup_menu_hidden_files_item = NULL;
3510-}
3511-
3512-/* Callback used when the "Add to Bookmarks" menu item is activated */
3513-static void
3514-add_to_shortcuts_cb (GtkMenuItem *item,
3515- GtkFileChooserDefault *impl)
3516-{
3517- bookmarks_add_selected_folder (impl);
3518-}
3519-
3520-/* Callback used when the "Show Hidden Files" menu item is toggled */
3521-static void
3522-show_hidden_toggled_cb (GtkCheckMenuItem *item,
3523- GtkFileChooserDefault *impl)
3524-{
3525- g_object_set (impl,
3526- "show-hidden", gtk_check_menu_item_get_active (item),
3527- NULL);
3528-}
3529-
3530-/* Shows an error dialog about not being able to select a dragged file */
3531-static void
3532-error_selecting_dragged_file_dialog (GtkFileChooserDefault *impl,
3533- const GtkFilePath *path,
3534- GError *error)
3535-{
3536- error_dialog (impl,
3537- _("Could not select file"),
3538- path, error);
3539-}
3540-
3541-static void
3542-file_list_drag_data_select_uris (GtkFileChooserDefault *impl,
3543- gchar **uris)
3544-{
3545- int i;
3546- char *uri;
3547- GtkFileChooser *chooser = GTK_FILE_CHOOSER (impl);
3548-
3549- for (i = 1; uris[i]; i++)
3550- {
3551- GtkFilePath *path;
3552-
3553- uri = uris[i];
3554- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3555-
3556- if (path)
3557- {
3558- GError *error = NULL;
3559-
3560- gtk_file_chooser_default_select_path (chooser, path, &error);
3561- if (error)
3562- error_selecting_dragged_file_dialog (impl, path, error);
3563-
3564- gtk_file_path_free (path);
3565- }
3566- }
3567-}
3568-
3569-struct FileListDragData
3570-{
3571- GtkFileChooserDefault *impl;
3572- gchar **uris;
3573- GtkFilePath *path;
3574-};
3575-
3576-static void
3577-file_list_drag_data_received_get_info_cb (GtkFileSystemHandle *handle,
3578- const GtkFileInfo *info,
3579- const GError *error,
3580- gpointer user_data)
3581-{
3582- gboolean cancelled = handle->cancelled;
3583- struct FileListDragData *data = user_data;
3584- GtkFileChooser *chooser = GTK_FILE_CHOOSER (data->impl);
3585-
3586- if (handle != data->impl->file_list_drag_data_received_handle)
3587- goto out;
3588-
3589- data->impl->file_list_drag_data_received_handle = NULL;
3590-
3591- if (cancelled || error)
3592- goto out;
3593-
3594- if ((data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
3595- data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) &&
3596- data->uris[1] == 0 && !error &&
3597- gtk_file_info_get_is_folder (info))
3598- change_folder_and_display_error (data->impl, data->path, FALSE);
3599- else
3600- {
3601- GError *error = NULL;
3602-
3603- gtk_file_chooser_default_unselect_all (chooser);
3604- gtk_file_chooser_default_select_path (chooser, data->path, &error);
3605- if (error)
3606- error_selecting_dragged_file_dialog (data->impl, data->path, error);
3607- else
3608- browse_files_center_selected_row (data->impl);
3609- }
3610-
3611- if (data->impl->select_multiple)
3612- file_list_drag_data_select_uris (data->impl, data->uris);
3613-
3614-out:
3615- g_object_unref (data->impl);
3616- g_strfreev (data->uris);
3617- gtk_file_path_free (data->path);
3618- g_free (data);
3619-
3620- g_object_unref (handle);
3621-}
3622-
3623-static void
3624-file_list_drag_data_received_cb (GtkWidget *widget,
3625- GdkDragContext *context,
3626- gint x,
3627- gint y,
3628- GtkSelectionData *selection_data,
3629- guint info,
3630- guint time_,
3631- gpointer data)
3632-{
3633- GtkFileChooserDefault *impl;
3634- GtkFileChooser *chooser;
3635- gchar **uris;
3636- char *uri;
3637- GtkFilePath *path;
3638- GError *error = NULL;
3639-
3640- impl = GTK_FILE_CHOOSER_DEFAULT (data);
3641- chooser = GTK_FILE_CHOOSER (data);
3642-
3643- /* Parse the text/uri-list string, navigate to the first one */
3644- uris = g_uri_list_extract_uris ((const char *) selection_data->data);
3645- if (uris[0])
3646- {
3647- uri = uris[0];
3648- path = gtk_file_system_uri_to_path (impl->file_system, uri);
3649-
3650- if (path)
3651- {
3652- struct FileListDragData *data;
3653-
3654- data = g_new0 (struct FileListDragData, 1);
3655- data->impl = g_object_ref (impl);
3656- data->uris = uris;
3657- data->path = path;
3658-
3659- if (impl->file_list_drag_data_received_handle)
3660- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle);
3661-
3662- impl->file_list_drag_data_received_handle =
3663- gtk_file_system_get_info (impl->file_system, path,
3664- GTK_FILE_INFO_IS_FOLDER,
3665- file_list_drag_data_received_get_info_cb,
3666- data);
3667- goto out;
3668- }
3669- else
3670- {
3671- g_set_error (&error,
3672- GTK_FILE_CHOOSER_ERROR,
3673- GTK_FILE_CHOOSER_ERROR_BAD_FILENAME,
3674- _("Could not select file '%s' "
3675- "because it is an invalid path name."),
3676- uri);
3677- error_selecting_dragged_file_dialog (impl, NULL, error);
3678- }
3679-
3680- if (impl->select_multiple)
3681- file_list_drag_data_select_uris (impl, uris);
3682- }
3683-
3684- g_strfreev (uris);
3685-
3686-out:
3687- g_signal_stop_emission_by_name (widget, "drag_data_received");
3688-}
3689-
3690-/* Don't do anything with the drag_drop signal */
3691-static gboolean
3692-file_list_drag_drop_cb (GtkWidget *widget,
3693- GdkDragContext *context,
3694- gint x,
3695- gint y,
3696- guint time_,
3697- GtkFileChooserDefault *impl)
3698-{
3699- g_signal_stop_emission_by_name (widget, "drag_drop");
3700- return TRUE;
3701-}
3702-
3703-/* Disable the normal tree drag motion handler, it makes it look like you're
3704- dropping the dragged item onto a tree item */
3705 static gboolean
3706-file_list_drag_motion_cb (GtkWidget *widget,
3707- GdkDragContext *context,
3708- gint x,
3709- gint y,
3710- guint time_,
3711- GtkFileChooserDefault *impl)
3712-{
3713- g_signal_stop_emission_by_name (widget, "drag_motion");
3714- return TRUE;
3715-}
3716-
3717-/* Constructs the popup menu for the file list if needed */
3718-static void
3719-file_list_build_popup_menu (GtkFileChooserDefault *impl)
3720-{
3721- GtkWidget *item;
3722-
3723- if (impl->browse_files_popup_menu)
3724- return;
3725-
3726- impl->browse_files_popup_menu = gtk_menu_new ();
3727- gtk_menu_attach_to_widget (GTK_MENU (impl->browse_files_popup_menu),
3728- impl->browse_files_tree_view,
3729- popup_menu_detach_cb);
3730-
3731- item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks"));
3732- impl->browse_files_popup_menu_add_shortcut_item = item;
3733- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
3734- gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
3735- gtk_widget_set_sensitive (item, FALSE);
3736- g_signal_connect (item, "activate",
3737- G_CALLBACK (add_to_shortcuts_cb), impl);
3738- gtk_widget_show (item);
3739- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3740-
3741- item = gtk_separator_menu_item_new ();
3742- gtk_widget_show (item);
3743- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3744-
3745- item = gtk_check_menu_item_new_with_mnemonic (_("Show _Hidden Files"));
3746- impl->browse_files_popup_menu_hidden_files_item = item;
3747- g_signal_connect (item, "toggled",
3748- G_CALLBACK (show_hidden_toggled_cb), impl);
3749- gtk_widget_show (item);
3750- gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
3751-}
3752-
3753-/* Updates the popup menu for the file list, creating it if necessary */
3754-static void
3755-file_list_update_popup_menu (GtkFileChooserDefault *impl)
3756-{
3757- file_list_build_popup_menu (impl);
3758-
3759- /* The sensitivity of the Add to Bookmarks item is set in
3760- * bookmarks_check_add_sensitivity()
3761- */
3762-
3763- g_signal_handlers_block_by_func (impl->browse_files_popup_menu_hidden_files_item,
3764- G_CALLBACK (show_hidden_toggled_cb), impl);
3765- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (impl->browse_files_popup_menu_hidden_files_item),
3766- impl->show_hidden);
3767- g_signal_handlers_unblock_by_func (impl->browse_files_popup_menu_hidden_files_item,
3768- G_CALLBACK (show_hidden_toggled_cb), impl);
3769-}
3770-
3771-static void
3772-popup_position_func (GtkMenu *menu,
3773- gint *x,
3774- gint *y,
3775- gboolean *push_in,
3776- gpointer user_data)
3777+list_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
3778 {
3779- GtkWidget *widget = GTK_WIDGET (user_data);
3780- GdkScreen *screen = gtk_widget_get_screen (widget);
3781- GtkRequisition req;
3782- gint monitor_num;
3783- GdkRectangle monitor;
3784-
3785- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
3786-
3787- gdk_window_get_origin (widget->window, x, y);
3788-
3789- gtk_widget_size_request (GTK_WIDGET (menu), &req);
3790-
3791- *x += (widget->allocation.width - req.width) / 2;
3792- *y += (widget->allocation.height - req.height) / 2;
3793-
3794- monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
3795- gtk_menu_set_monitor (menu, monitor_num);
3796- gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
3797-
3798- *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
3799- *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
3800-
3801- *push_in = FALSE;
3802-}
3803+ GtkTreeView * tree = GTK_TREE_VIEW (widget);
3804+ GtkFileChooserDefault *impl = data;
3805+ GtkTreePath *path;
3806
3807-static void
3808-file_list_popup_menu (GtkFileChooserDefault *impl,
3809- GdkEventButton *event)
3810-{
3811- file_list_update_popup_menu (impl);
3812- if (event)
3813- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
3814- NULL, NULL, NULL, NULL,
3815- event->button, event->time);
3816- else
3817+ if (event->type != GDK_BUTTON_PRESS ||
3818+ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y,
3819+ &path, NULL, NULL, NULL))
3820 {
3821- gtk_menu_popup (GTK_MENU (impl->browse_files_popup_menu),
3822- NULL, NULL,
3823- popup_position_func, impl->browse_files_tree_view,
3824- 0, GDK_CURRENT_TIME);
3825- gtk_menu_shell_select_first (GTK_MENU_SHELL (impl->browse_files_popup_menu),
3826- FALSE);
3827+ return FALSE;
3828 }
3829-
3830-}
3831-
3832-/* Callback used for the GtkWidget::popup-menu signal of the file list */
3833-static gboolean
3834-list_popup_menu_cb (GtkWidget *widget,
3835- GtkFileChooserDefault *impl)
3836-{
3837- file_list_popup_menu (impl, NULL);
3838- return TRUE;
3839+
3840+ impl->list_press_time = event->time;
3841+ impl->list_press_path = path;
3842+
3843+ return FALSE;
3844 }
3845
3846-/* Callback used when a button is pressed on the file list. We trap button 3 to
3847- * bring up a popup menu.
3848- */
3849 static gboolean
3850-list_button_press_event_cb (GtkWidget *widget,
3851- GdkEventButton *event,
3852- GtkFileChooserDefault *impl)
3853+list_button_release (GtkWidget *widget, GdkEventButton *event, gpointer data)
3854 {
3855- static gboolean in_press = FALSE;
3856- gboolean handled;
3857+ GtkTreeView * tree = GTK_TREE_VIEW (widget);
3858+ GtkFileChooserDefault *impl = data;
3859+ GtkTreePath *path = NULL;
3860+ gboolean retval = FALSE;
3861
3862- if (in_press)
3863- return FALSE;
3864+ if (!impl->list_press_time ||
3865+ !impl->list_press_path ||
3866+ event->type != GDK_BUTTON_RELEASE ||
3867+ !gtk_tree_view_get_path_at_pos (tree, (gint)event->x, (gint)event->y,
3868+ &path, NULL, NULL, NULL))
3869+ {
3870+ goto done;
3871+ }
3872
3873- if (event->button != 3)
3874- return FALSE;
3875+ if (event->time - impl->list_press_time > LONG_CLICK_LENGTH &&
3876+ !gtk_tree_path_compare (impl->list_press_path, path))
3877+ {
3878+ retval = TRUE;
3879+ list_row_activated (tree, path, NULL, impl);
3880+ }
3881+
3882+ done:
3883+ if (path)
3884+ gtk_tree_path_free (path);
3885
3886- in_press = TRUE;
3887- handled = gtk_widget_event (impl->browse_files_tree_view, (GdkEvent *) event);
3888- in_press = FALSE;
3889+ impl->list_press_time = 0;
3890
3891- file_list_popup_menu (impl, event);
3892- return TRUE;
3893+ if (impl->list_press_path)
3894+ {
3895+ gtk_tree_path_free (impl->list_press_path);
3896+ impl->list_press_path = NULL;
3897+ }
3898+
3899+ return FALSE;
3900 }
3901
3902+
3903 /* Creates the widgets for the file list */
3904 static GtkWidget *
3905 create_file_list (GtkFileChooserDefault *impl)
3906@@ -4087,37 +1288,19 @@
3907 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (impl->browse_files_tree_view), TRUE);
3908 gtk_container_add (GTK_CONTAINER (swin), impl->browse_files_tree_view);
3909
3910- gtk_drag_dest_set (impl->browse_files_tree_view,
3911- GTK_DEST_DEFAULT_ALL,
3912- file_list_dest_targets,
3913- num_file_list_dest_targets,
3914- GDK_ACTION_COPY | GDK_ACTION_MOVE);
3915-
3916 g_signal_connect (impl->browse_files_tree_view, "row_activated",
3917 G_CALLBACK (list_row_activated), impl);
3918 g_signal_connect (impl->browse_files_tree_view, "key_press_event",
3919 G_CALLBACK (trap_activate_cb), impl);
3920- g_signal_connect (impl->browse_files_tree_view, "popup_menu",
3921- G_CALLBACK (list_popup_menu_cb), impl);
3922 g_signal_connect (impl->browse_files_tree_view, "button_press_event",
3923- G_CALLBACK (list_button_press_event_cb), impl);
3924-
3925- g_signal_connect (impl->browse_files_tree_view, "drag_data_received",
3926- G_CALLBACK (file_list_drag_data_received_cb), impl);
3927- g_signal_connect (impl->browse_files_tree_view, "drag_drop",
3928- G_CALLBACK (file_list_drag_drop_cb), impl);
3929- g_signal_connect (impl->browse_files_tree_view, "drag_motion",
3930- G_CALLBACK (file_list_drag_motion_cb), impl);
3931+ G_CALLBACK (list_button_press), impl);
3932+ g_signal_connect (impl->browse_files_tree_view, "button_release_event",
3933+ G_CALLBACK (list_button_release), impl);
3934
3935 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
3936 gtk_tree_selection_set_select_function (selection,
3937 list_select_func,
3938 impl, NULL);
3939- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (impl->browse_files_tree_view),
3940- GDK_BUTTON1_MASK,
3941- file_list_source_targets,
3942- num_file_list_source_targets,
3943- GDK_ACTION_COPY);
3944
3945 g_signal_connect (selection, "changed",
3946 G_CALLBACK (list_selection_changed), impl);
3947@@ -4178,230 +1361,214 @@
3948 return swin;
3949 }
3950
3951-static GtkWidget *
3952-create_path_bar (GtkFileChooserDefault *impl)
3953-{
3954- GtkWidget *path_bar;
3955-
3956- path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
3957- _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->file_system);
3958-
3959- return path_bar;
3960-}
3961-
3962 static void
3963-set_filter_tooltip (GtkWidget *widget,
3964- gpointer data)
3965+up_button_clicked_cb (GtkButton *button, gpointer data)
3966 {
3967- GtkTooltips *tooltips = (GtkTooltips *)data;
3968-
3969- if (GTK_IS_BUTTON (widget))
3970- gtk_tooltips_set_tip (tooltips, widget,
3971- _("Select which types of files are shown"),
3972- NULL);
3973+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
3974+ up_folder_handler (impl);
3975 }
3976
3977 static void
3978-realize_filter_combo (GtkWidget *combo,
3979- gpointer data)
3980+volume_button_clicked_cb (GtkButton *button, gpointer data)
3981 {
3982- GtkFileChooserDefault *impl = (GtkFileChooserDefault *)data;
3983+ GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
3984+ GtkFilePath * path = g_object_get_data (G_OBJECT (button), "file-path");
3985
3986- gtk_container_forall (GTK_CONTAINER (combo),
3987- set_filter_tooltip,
3988- impl->tooltips);
3989+ change_folder_and_display_error (impl, path);
3990 }
3991
3992-/* Creates the widgets for the files/folders pane */
3993 static GtkWidget *
3994-file_pane_create (GtkFileChooserDefault *impl,
3995- GtkSizeGroup *size_group)
3996+create_bar (GtkFileChooserDefault *impl)
3997 {
3998- GtkWidget *vbox;
3999- GtkWidget *hbox;
4000- GtkWidget *widget;
4001+ GSList *list, *l;
4002+ int n;
4003+ GtkWidget *bar = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4004+ GtkWidget *img;
4005+ GtkWidget *label;
4006+
4007+ /* first the Up button */
4008+ img = gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_BUTTON);
4009+ gtk_widget_show (img);
4010+
4011+ impl->up_button = gtk_button_new ();
4012+ gtk_container_add (GTK_CONTAINER (impl->up_button), img);
4013+ gtk_widget_show (impl->up_button);
4014+ gtk_widget_set_sensitive (impl->up_button, FALSE);
4015+ gtk_button_set_focus_on_click (GTK_BUTTON (impl->up_button), FALSE);
4016+
4017+ g_signal_connect (impl->up_button, "clicked",
4018+ G_CALLBACK (up_button_clicked_cb), impl);
4019+ gtk_box_pack_start (GTK_BOX(bar), impl->up_button, FALSE, FALSE, 0);
4020
4021- vbox = gtk_vbox_new (FALSE, 6);
4022- gtk_widget_show (vbox);
4023+ impl->num_volumes = 0;
4024+ list = gtk_file_system_list_volumes (impl->file_system);
4025
4026- /* Box for lists and preview */
4027+ n = 0;
4028
4029- hbox = gtk_hbox_new (FALSE, PREVIEW_HBOX_SPACING);
4030- gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
4031- gtk_widget_show (hbox);
4032+ for (l = list; l; l = l->next, n++)
4033+ {
4034+ GtkFileSystemVolume *volume;
4035+ GdkPixbuf *pixbuf;
4036+ GtkWidget *button;
4037+ GtkWidget *image;
4038+ GtkFilePath *base_path;
4039+ gchar * file_name = NULL;
4040
4041- /* File list */
4042+ volume = l->data;
4043+ base_path =
4044+ gtk_file_system_volume_get_base_path (impl->file_system, volume);
4045
4046- widget = create_file_list (impl);
4047- gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
4048+ if (impl->local_only)
4049+ {
4050+ gboolean is_local =
4051+ gtk_file_system_path_is_local (impl->file_system, base_path);
4052
4053- /* Preview */
4054+ if (!is_local)
4055+ {
4056+ gtk_file_path_free (base_path);
4057+ gtk_file_system_volume_free (impl->file_system, volume);
4058+ continue;
4059+ }
4060+ }
4061
4062- impl->preview_box = gtk_vbox_new (FALSE, 12);
4063- gtk_box_pack_start (GTK_BOX (hbox), impl->preview_box, FALSE, FALSE, 0);
4064- /* Don't show preview box initially */
4065+#if 0
4066+ label_copy =
4067+ gtk_file_system_volume_get_display_name (impl->file_system, volume);
4068+#endif
4069+ pixbuf =
4070+ gtk_file_system_volume_render_icon (impl->file_system, volume,
4071+ GTK_WIDGET (impl),
4072+ impl->icon_size, NULL);
4073
4074- /* Filter combo */
4075+ button = gtk_button_new ();
4076+ image = gtk_image_new_from_pixbuf (pixbuf);
4077+ g_object_unref (G_OBJECT (pixbuf));
4078+ gtk_container_add (GTK_CONTAINER (button), image);
4079+ gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
4080+
4081+ file_name =
4082+ gtk_file_system_path_to_filename (impl->file_system, base_path);
4083+
4084+ if (file_name && impl->root_folder &&
4085+ strcmp (file_name, impl->root_folder) &&
4086+ !strncmp (file_name, impl->root_folder, strlen (file_name)))
4087+ {
4088+ /* The base path is below the root folder; we replace it with
4089+ * the root folder
4090+ */
4091+ gtk_file_path_free (base_path);
4092+ base_path = gtk_file_system_filename_to_path (impl->file_system,
4093+ impl->root_folder);
4094+ }
4095
4096- impl->filter_combo_hbox = gtk_hbox_new (FALSE, 12);
4097+ g_free (file_name);
4098+ gtk_widget_show_all (button);
4099
4100- widget = filter_create (impl);
4101+ g_object_set_data (G_OBJECT (button), "file-path", base_path);
4102
4103- g_signal_connect (widget, "realize",
4104- G_CALLBACK (realize_filter_combo), impl);
4105+ g_signal_connect (button, "clicked",
4106+ G_CALLBACK (volume_button_clicked_cb), impl);
4107
4108- gtk_widget_show (widget);
4109- gtk_box_pack_end (GTK_BOX (impl->filter_combo_hbox), widget, FALSE, FALSE, 0);
4110+ gtk_box_pack_start (GTK_BOX(bar), button, FALSE, FALSE, 0);
4111+ }
4112
4113- gtk_size_group_add_widget (size_group, impl->filter_combo_hbox);
4114- gtk_box_pack_end (GTK_BOX (vbox), impl->filter_combo_hbox, FALSE, FALSE, 0);
4115+ impl->num_volumes = n;
4116+ g_slist_free (list);
4117
4118- return vbox;
4119-}
4120+ label = impl->location_label = gtk_label_new (NULL);
4121+ gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
4122+ gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
4123+ gtk_label_set_text (GTK_LABEL (label), impl->root_folder);
4124+ gtk_widget_show (label);
4125+ gtk_box_pack_start (GTK_BOX(bar), label, TRUE, TRUE, 0);
4126
4127-/* Callback used when the "Browse for more folders" expander is toggled */
4128-static void
4129-expander_changed_cb (GtkExpander *expander,
4130- GParamSpec *pspec,
4131- GtkFileChooserDefault *impl)
4132-{
4133- impl->expand_folders = gtk_expander_get_expanded(GTK_EXPANDER (impl->save_expander));
4134- update_appearance (impl);
4135+ gtk_widget_show (bar);
4136+
4137+ return bar;
4138 }
4139
4140-/* Callback used when the selection changes in the save folder combo box */
4141-static void
4142-save_folder_combo_changed_cb (GtkComboBox *combo,
4143- GtkFileChooserDefault *impl)
4144+/* Creates the widgets for the files/folders pane */
4145+static GtkWidget *
4146+file_pane_create (GtkFileChooserDefault *impl)
4147 {
4148- GtkTreeIter iter;
4149+ GtkWidget *vbox;
4150+ GtkWidget *hbox;
4151+ GtkWidget *widget;
4152+ vbox = gtk_vbox_new (FALSE, DEFAULT_SPACING);
4153+ gtk_widget_show (vbox);
4154
4155- if (impl->changing_folder)
4156- return;
4157+ /* The volume bar and 'Create Folder' button */
4158+ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4159+ gtk_widget_show (hbox);
4160+ impl->bar = create_bar (impl);
4161+ gtk_widget_show_all (impl->bar);
4162+ gtk_box_pack_start (GTK_BOX (hbox), impl->bar, TRUE, TRUE, 0);
4163
4164- if (gtk_combo_box_get_active_iter (combo, &iter))
4165- shortcuts_activate_iter (impl, &iter);
4166-}
4167+ /* Create Folder */
4168+ widget = gtk_image_new_from_icon_name ("folder-new", GTK_ICON_SIZE_BUTTON);
4169+ gtk_widget_show (widget);
4170+ impl->browse_new_folder_button = gtk_button_new ();
4171+ gtk_container_add (GTK_CONTAINER (impl->browse_new_folder_button), widget);
4172+ gtk_button_set_focus_on_click (GTK_BUTTON (impl->browse_new_folder_button),
4173+ FALSE);
4174
4175-/* Creates the combo box with the save folders */
4176-static GtkWidget *
4177-save_folder_combo_create (GtkFileChooserDefault *impl)
4178-{
4179- GtkWidget *combo;
4180- GtkCellRenderer *cell;
4181+ g_signal_connect (impl->browse_new_folder_button, "clicked",
4182+ G_CALLBACK (new_folder_button_clicked), impl);
4183+ gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
4184+
4185+ widget = filter_create (impl);
4186+ gtk_widget_hide (widget);
4187+ gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
4188
4189- combo = g_object_new (GTK_TYPE_COMBO_BOX,
4190- "model", impl->shortcuts_model,
4191- "focus-on-click", FALSE,
4192- NULL);
4193- gtk_widget_show (combo);
4194-
4195- cell = gtk_cell_renderer_pixbuf_new ();
4196- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE);
4197- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
4198- "pixbuf", SHORTCUTS_COL_PIXBUF,
4199- "visible", SHORTCUTS_COL_PIXBUF_VISIBLE,
4200- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
4201- NULL);
4202-
4203- cell = gtk_cell_renderer_text_new ();
4204- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
4205- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
4206- "text", SHORTCUTS_COL_NAME,
4207- "sensitive", SHORTCUTS_COL_PIXBUF_VISIBLE,
4208- NULL);
4209-
4210- gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo),
4211- shortcuts_row_separator_func,
4212- GINT_TO_POINTER (SHORTCUTS_COL_NAME),
4213- NULL);
4214+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4215+
4216+ /* Box for lists */
4217+ hbox = gtk_hbox_new (FALSE, LIST_HBOX_SPACING);
4218+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
4219+ gtk_widget_show (hbox);
4220
4221- g_signal_connect (combo, "changed",
4222- G_CALLBACK (save_folder_combo_changed_cb), impl);
4223+ /* File list */
4224+
4225+ widget = create_file_list (impl);
4226+ gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
4227
4228- return combo;
4229+ return vbox;
4230 }
4231
4232 /* Creates the widgets specific to Save mode */
4233-static void
4234+static GtkWidget *
4235 save_widgets_create (GtkFileChooserDefault *impl)
4236 {
4237 GtkWidget *vbox;
4238- GtkWidget *table;
4239+ GtkWidget *hbox;
4240 GtkWidget *widget;
4241- GtkWidget *alignment;
4242-
4243- if (impl->save_widgets != NULL)
4244- return;
4245-
4246- location_switch_to_path_bar (impl);
4247-
4248- vbox = gtk_vbox_new (FALSE, 12);
4249
4250- table = gtk_table_new (2, 2, FALSE);
4251- gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
4252- gtk_widget_show (table);
4253- gtk_table_set_row_spacings (GTK_TABLE (table), 12);
4254- gtk_table_set_col_spacings (GTK_TABLE (table), 12);
4255+ vbox = gtk_vbox_new (FALSE, 0);
4256+ hbox = gtk_hbox_new (FALSE, DEFAULT_SPACING);
4257
4258- /* Label */
4259-
4260- widget = gtk_label_new_with_mnemonic (_("_Name:"));
4261+ widget = gtk_label_new (_("Name:"));
4262 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
4263- gtk_table_attach (GTK_TABLE (table), widget,
4264- 0, 1, 0, 1,
4265- GTK_FILL, GTK_FILL,
4266- 0, 0);
4267+ gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
4268 gtk_widget_show (widget);
4269
4270- /* Location entry */
4271-
4272 impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
4273 _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
4274 impl->file_system);
4275- gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
4276+/* gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45); */
4277 gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
4278- gtk_table_attach (GTK_TABLE (table), impl->location_entry,
4279- 1, 2, 0, 1,
4280- GTK_EXPAND | GTK_FILL, 0,
4281- 0, 0);
4282+ gtk_box_pack_start (GTK_BOX (hbox), impl->location_entry,
4283+ TRUE, TRUE, 0);
4284+
4285 gtk_widget_show (impl->location_entry);
4286- gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->location_entry);
4287
4288- /* Folder combo */
4289- impl->save_folder_label = gtk_label_new (NULL);
4290- gtk_misc_set_alignment (GTK_MISC (impl->save_folder_label), 0.0, 0.5);
4291- gtk_table_attach (GTK_TABLE (table), impl->save_folder_label,
4292- 0, 1, 1, 2,
4293- GTK_FILL, GTK_FILL,
4294- 0, 0);
4295- gtk_widget_show (impl->save_folder_label);
4296-
4297- impl->save_folder_combo = save_folder_combo_create (impl);
4298- gtk_table_attach (GTK_TABLE (table), impl->save_folder_combo,
4299- 1, 2, 1, 2,
4300- GTK_EXPAND | GTK_FILL, GTK_FILL,
4301- 0, 0);
4302- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->save_folder_combo);
4303-
4304- /* Expander */
4305- alignment = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
4306- gtk_box_pack_start (GTK_BOX (vbox), alignment, FALSE, FALSE, 0);
4307-
4308- impl->save_expander = gtk_expander_new_with_mnemonic (_("_Browse for other folders"));
4309- gtk_container_add (GTK_CONTAINER (alignment), impl->save_expander);
4310- g_signal_connect (impl->save_expander, "notify::expanded",
4311- G_CALLBACK (expander_changed_cb),
4312- impl);
4313- gtk_widget_show_all (alignment);
4314+ gtk_widget_show (hbox);
4315+ gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4316
4317- impl->save_widgets = vbox;
4318- gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
4319- gtk_box_reorder_child (GTK_BOX (impl), impl->save_widgets, 0);
4320- gtk_widget_show (impl->save_widgets);
4321+ return vbox;
4322 }
4323
4324 /* Destroys the widgets specific to Save mode */
4325+/* ??? */
4326 static void
4327 save_widgets_destroy (GtkFileChooserDefault *impl)
4328 {
4329@@ -4411,293 +1578,17 @@
4330 gtk_widget_destroy (impl->save_widgets);
4331 impl->save_widgets = NULL;
4332 impl->location_entry = NULL;
4333- impl->save_folder_label = NULL;
4334- impl->save_folder_combo = NULL;
4335- impl->save_expander = NULL;
4336-}
4337-
4338-/* Turns on the path bar widget. Can be called even if we are already in that
4339- * mode.
4340- */
4341-static void
4342-location_switch_to_path_bar (GtkFileChooserDefault *impl)
4343-{
4344- if (impl->location_entry)
4345- {
4346- gtk_widget_destroy (impl->location_entry);
4347- impl->location_entry = NULL;
4348- }
4349-
4350- gtk_widget_hide (impl->location_entry_box);
4351-}
4352-
4353-/* Sets the full path of the current folder as the text in the location entry. */
4354-static void
4355-location_entry_set_initial_text (GtkFileChooserDefault *impl)
4356-{
4357- char *text;
4358-
4359- if (!impl->current_folder)
4360- return;
4361-
4362- if (gtk_file_system_path_is_local (impl->file_system, impl->current_folder))
4363- {
4364- char *filename;
4365-
4366- filename = gtk_file_system_path_to_filename (impl->file_system, impl->current_folder);
4367- if (filename)
4368- {
4369- text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
4370- g_free (filename);
4371- }
4372- else
4373- text = NULL;
4374- }
4375- else
4376- text = gtk_file_system_path_to_uri (impl->file_system, impl->current_folder);
4377-
4378- if (text)
4379- {
4380- gboolean need_slash;
4381- int len;
4382-
4383- len = strlen (text);
4384- need_slash = (text[len - 1] != G_DIR_SEPARATOR);
4385-
4386- if (need_slash)
4387- {
4388- char *slash_text;
4389-
4390- slash_text = g_new (char, len + 2);
4391- strcpy (slash_text, text);
4392- slash_text[len] = G_DIR_SEPARATOR;
4393- slash_text[len + 1] = 0;
4394-
4395- g_free (text);
4396- text = slash_text;
4397- }
4398-
4399- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text);
4400- g_free (text);
4401- }
4402-}
4403-
4404-/* Turns on the location entry. Can be called even if we are already in that
4405- * mode.
4406- */
4407-static void
4408-location_switch_to_filename_entry (GtkFileChooserDefault *impl)
4409-{
4410- if (impl->location_entry)
4411- gtk_widget_destroy (impl->location_entry);
4412-
4413- /* Box */
4414-
4415- gtk_widget_show (impl->location_entry_box);
4416-
4417- /* Entry */
4418-
4419- impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
4420- _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
4421- impl->file_system);
4422- gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
4423- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
4424-
4425- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0);
4426- gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry);
4427-
4428- /* Configure the entry */
4429-
4430- _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder);
4431-
4432- /* Done */
4433-
4434- gtk_widget_show (impl->location_entry);
4435- gtk_widget_grab_focus (impl->location_entry);
4436-}
4437-
4438-/* Sets a new location mode. set_buttons determines whether the toggle button
4439- * for the mode will also be changed.
4440- */
4441-static void
4442-location_mode_set (GtkFileChooserDefault *impl,
4443- LocationMode new_mode,
4444- gboolean set_button)
4445-{
4446- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
4447- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
4448- {
4449- GtkWindow *toplevel;
4450- GtkWidget *current_focus;
4451- gboolean button_active;
4452- gboolean switch_to_file_list;
4453-
4454- switch (new_mode)
4455- {
4456- case LOCATION_MODE_PATH_BAR:
4457- button_active = FALSE;
4458-
4459- /* The location_entry will disappear when we switch to path bar mode. So,
4460- * we'll focus the file list in that case, to avoid having a window with
4461- * no focused widget.
4462- */
4463- toplevel = get_toplevel (GTK_WIDGET (impl));
4464- switch_to_file_list = FALSE;
4465- if (toplevel)
4466- {
4467- current_focus = gtk_window_get_focus (toplevel);
4468- if (!current_focus || current_focus == impl->location_entry)
4469- switch_to_file_list = TRUE;
4470- }
4471-
4472- location_switch_to_path_bar (impl);
4473-
4474- if (switch_to_file_list)
4475- gtk_widget_grab_focus (impl->browse_files_tree_view);
4476-
4477- break;
4478-
4479- case LOCATION_MODE_FILENAME_ENTRY:
4480- button_active = TRUE;
4481- location_switch_to_filename_entry (impl);
4482- break;
4483-
4484- default:
4485- g_assert_not_reached ();
4486- return;
4487- }
4488-
4489- if (set_button)
4490- {
4491- g_signal_handlers_block_by_func (impl->location_button,
4492- G_CALLBACK (location_button_toggled_cb), impl);
4493-
4494- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (impl->location_button), button_active);
4495-
4496- g_signal_handlers_unblock_by_func (impl->location_button,
4497- G_CALLBACK (location_button_toggled_cb), impl);
4498- }
4499- }
4500-
4501- impl->location_mode = new_mode;
4502-}
4503-
4504-static void
4505-toggle_location_mode (GtkFileChooserDefault *impl,
4506- gboolean set_button)
4507-{
4508- LocationMode new_mode;
4509-
4510- /* toggle value */
4511- new_mode = (impl->location_mode == LOCATION_MODE_PATH_BAR) ?
4512- LOCATION_MODE_FILENAME_ENTRY : LOCATION_MODE_PATH_BAR;
4513-
4514- location_mode_set (impl, new_mode, set_button);
4515-}
4516-
4517-static void
4518-location_toggle_popup_handler (GtkFileChooserDefault *impl)
4519-{
4520- toggle_location_mode (impl, TRUE);
4521-}
4522-
4523-/* Callback used when one of the location mode buttons is toggled */
4524-static void
4525-location_button_toggled_cb (GtkToggleButton *toggle,
4526- GtkFileChooserDefault *impl)
4527-{
4528- gboolean is_active;
4529-
4530- is_active = gtk_toggle_button_get_active (toggle);
4531-
4532- if (is_active)
4533- g_assert (impl->location_mode == LOCATION_MODE_PATH_BAR);
4534- else
4535- g_assert (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY);
4536-
4537- toggle_location_mode (impl, FALSE);
4538-}
4539-
4540-/* Creates a toggle button for the location entry. */
4541-static void
4542-location_button_create (GtkFileChooserDefault *impl)
4543-{
4544- GtkWidget *image;
4545- const char *str;
4546-
4547- image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON);
4548- gtk_widget_show (image);
4549-
4550- impl->location_button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
4551- "image", image,
4552- NULL);
4553-
4554- g_signal_connect (impl->location_button, "toggled",
4555- G_CALLBACK (location_button_toggled_cb), impl);
4556-
4557- str = _("Type a file name");
4558-
4559- gtk_tooltips_set_tip (impl->tooltips, impl->location_button, str, NULL);
4560- atk_object_set_name (gtk_widget_get_accessible (impl->location_button), str);
4561 }
4562
4563 /* Creates the main hpaned with the widgets shared by Open and Save mode */
4564 static GtkWidget *
4565 browse_widgets_create (GtkFileChooserDefault *impl)
4566 {
4567- GtkWidget *vbox;
4568- GtkWidget *hbox;
4569- GtkWidget *hpaned;
4570 GtkWidget *widget;
4571- GtkSizeGroup *size_group;
4572-
4573- /* size group is used by the [+][-] buttons and the filter combo */
4574- size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4575- vbox = gtk_vbox_new (FALSE, 12);
4576-
4577- /* Location widgets */
4578- hbox = gtk_hbox_new (FALSE, 12);
4579- gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
4580- gtk_widget_show (hbox);
4581-
4582- location_button_create (impl);
4583- gtk_box_pack_start (GTK_BOX (hbox), impl->location_button, FALSE, FALSE, 0);
4584-
4585- /* Path bar */
4586-
4587- impl->browse_path_bar = create_path_bar (impl);
4588- g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl);
4589- gtk_widget_show_all (impl->browse_path_bar);
4590- gtk_box_pack_start (GTK_BOX (hbox), impl->browse_path_bar, TRUE, TRUE, 0);
4591
4592- /* Create Folder */
4593- impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder"));
4594- g_signal_connect (impl->browse_new_folder_button, "clicked",
4595- G_CALLBACK (new_folder_button_clicked), impl);
4596- gtk_box_pack_end (GTK_BOX (hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
4597-
4598- /* Box for the location label and entry */
4599+ widget = file_pane_create (impl);
4600
4601- impl->location_entry_box = gtk_hbox_new (FALSE, 12);
4602- gtk_box_pack_start (GTK_BOX (vbox), impl->location_entry_box, FALSE, FALSE, 0);
4603-
4604- impl->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
4605- gtk_widget_show (impl->location_label);
4606- gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0);
4607-
4608- /* Paned widget */
4609- hpaned = gtk_hpaned_new ();
4610- gtk_widget_show (hpaned);
4611- gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
4612-
4613- widget = shortcuts_pane_create (impl, size_group);
4614- gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE);
4615- widget = file_pane_create (impl, size_group);
4616- gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE);
4617-
4618- g_object_unref (size_group);
4619-
4620- return vbox;
4621+ return widget;
4622 }
4623
4624 static GObject*
4625@@ -4719,52 +1610,20 @@
4626
4627 gtk_widget_push_composite_child ();
4628
4629- /* Shortcuts model */
4630-
4631- shortcuts_model_create (impl);
4632+ /* Widgets for Save mode */
4633+ impl->save_widgets = save_widgets_create (impl);
4634+ gtk_box_pack_start (GTK_BOX (impl), impl->save_widgets, FALSE, FALSE, 0);
4635
4636 /* The browse widgets */
4637 impl->browse_widgets = browse_widgets_create (impl);
4638 gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets, TRUE, TRUE, 0);
4639
4640- /* Alignment to hold extra widget */
4641- impl->extra_align = gtk_alignment_new (0.0, 0.5, 1.0, 1.0);
4642- gtk_box_pack_start (GTK_BOX (impl), impl->extra_align, FALSE, FALSE, 0);
4643-
4644- gtk_widget_pop_composite_child ();
4645- update_appearance (impl);
4646-
4647- profile_end ("end", NULL);
4648-
4649- return object;
4650-}
4651-
4652-/* Sets the extra_widget by packing it in the appropriate place */
4653-static void
4654-set_extra_widget (GtkFileChooserDefault *impl,
4655- GtkWidget *extra_widget)
4656-{
4657- if (extra_widget)
4658- {
4659- g_object_ref (extra_widget);
4660- /* FIXME: is this right ? */
4661- gtk_widget_show (extra_widget);
4662- }
4663-
4664- if (impl->extra_widget)
4665- {
4666- gtk_container_remove (GTK_CONTAINER (impl->extra_align), impl->extra_widget);
4667- g_object_unref (impl->extra_widget);
4668- }
4669+ gtk_widget_pop_composite_child ();
4670+ update_appearance (impl);
4671
4672- impl->extra_widget = extra_widget;
4673- if (impl->extra_widget)
4674- {
4675- gtk_container_add (GTK_CONTAINER (impl->extra_align), impl->extra_widget);
4676- gtk_widget_show (impl->extra_align);
4677- }
4678- else
4679- gtk_widget_hide (impl->extra_align);
4680+ profile_end ("end", NULL);
4681+
4682+ return object;
4683 }
4684
4685 static void
4686@@ -4775,12 +1634,6 @@
4687 {
4688 impl->local_only = local_only;
4689
4690- if (impl->shortcuts_model && impl->file_system)
4691- {
4692- shortcuts_add_volumes (impl);
4693- shortcuts_add_bookmarks (impl);
4694- }
4695-
4696 if (local_only &&
4697 !gtk_file_system_path_is_local (impl->file_system, impl->current_folder))
4698 {
4699@@ -4807,19 +1660,7 @@
4700 volumes_changed_cb (GtkFileSystem *file_system,
4701 GtkFileChooserDefault *impl)
4702 {
4703- shortcuts_add_volumes (impl);
4704-}
4705-
4706-/* Callback used when the set of bookmarks changes in the file system */
4707-static void
4708-bookmarks_changed_cb (GtkFileSystem *file_system,
4709- GtkFileChooserDefault *impl)
4710-{
4711- shortcuts_add_bookmarks (impl);
4712-
4713- bookmarks_check_add_sensitivity (impl);
4714- bookmarks_check_remove_sensitivity (impl);
4715- shortcuts_check_popup_sensitivity (impl);
4716+ /* FIXME -- update the bar */
4717 }
4718
4719 /* Sets the file chooser to multiple selection mode */
4720@@ -4841,8 +1682,6 @@
4721
4722 impl->select_multiple = select_multiple;
4723 g_object_notify (G_OBJECT (impl), "select-multiple");
4724-
4725- check_preview_change (impl);
4726 }
4727
4728 static void
4729@@ -4855,8 +1694,6 @@
4730 {
4731 g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
4732 impl->volumes_changed_id = 0;
4733- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
4734- impl->bookmarks_changed_id = 0;
4735 g_object_unref (impl->file_system);
4736 }
4737
4738@@ -4892,14 +1729,28 @@
4739 impl->volumes_changed_id = g_signal_connect (impl->file_system, "volumes-changed",
4740 G_CALLBACK (volumes_changed_cb),
4741 impl);
4742- impl->bookmarks_changed_id = g_signal_connect (impl->file_system, "bookmarks-changed",
4743- G_CALLBACK (bookmarks_changed_cb),
4744- impl);
4745 }
4746
4747 profile_end ("end", NULL);
4748 }
4749
4750+static void
4751+show_new_folder_button (GtkFileChooserDefault *impl)
4752+{
4753+ if ((impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
4754+ impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) &&
4755+ impl->show_create_folder)
4756+ {
4757+ gtk_widget_show (impl->browse_new_folder_button);
4758+ gtk_misc_set_alignment (GTK_MISC (impl->location_label), 0.5, 0.5);
4759+ }
4760+ else
4761+ {
4762+ gtk_widget_hide (impl->browse_new_folder_button);
4763+ gtk_misc_set_alignment (GTK_MISC (impl->location_label), 1.0, 0.5);
4764+ }
4765+}
4766+
4767 /* This function is basically a do_all function.
4768 *
4769 * It sets the visibility on all the widgets based on the current state, and
4770@@ -4911,32 +1762,8 @@
4771 if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
4772 impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
4773 {
4774- const char *text;
4775-
4776- gtk_widget_hide (impl->location_button);
4777- save_widgets_create (impl);
4778-
4779- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
4780- text = _("Save in _folder:");
4781- else
4782- text = _("Create in _folder:");
4783-
4784- gtk_label_set_text_with_mnemonic (GTK_LABEL (impl->save_folder_label), text);
4785-
4786- if (gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)))
4787- {
4788- gtk_widget_set_sensitive (impl->save_folder_label, FALSE);
4789- gtk_widget_set_sensitive (impl->save_folder_combo, FALSE);
4790- gtk_widget_show (impl->browse_widgets);
4791- }
4792- else
4793- {
4794- gtk_widget_set_sensitive (impl->save_folder_label, TRUE);
4795- gtk_widget_set_sensitive (impl->save_folder_combo, TRUE);
4796- gtk_widget_hide (impl->browse_widgets);
4797- }
4798-
4799- gtk_widget_show (impl->browse_new_folder_button);
4800+ gtk_widget_show (impl->save_widgets);
4801+ gtk_widget_show (impl->browse_widgets);
4802
4803 if (impl->select_multiple)
4804 {
4805@@ -4948,23 +1775,12 @@
4806 else if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
4807 impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
4808 {
4809- gtk_widget_show (impl->location_button);
4810- save_widgets_destroy (impl);
4811+ gtk_widget_hide (impl->save_widgets);
4812 gtk_widget_show (impl->browse_widgets);
4813- location_mode_set (impl, impl->location_mode, TRUE);
4814 }
4815
4816- if (impl->location_entry)
4817- _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
4818-
4819- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
4820- gtk_widget_hide (impl->browse_new_folder_button);
4821- else
4822- gtk_widget_show (impl->browse_new_folder_button);
4823+ show_new_folder_button (impl);
4824
4825- /* This *is* needed; we need to redraw the file list because the "sensitivity"
4826- * of files may change depending whether we are in a file or folder-only mode.
4827- */
4828 gtk_widget_queue_draw (impl->browse_files_tree_view);
4829
4830 g_signal_emit_by_name (impl, "default-size-changed");
4831@@ -5016,24 +1832,6 @@
4832 set_local_only (impl, g_value_get_boolean (value));
4833 break;
4834
4835- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4836- set_preview_widget (impl, g_value_get_object (value));
4837- break;
4838-
4839- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4840- impl->preview_widget_active = g_value_get_boolean (value);
4841- update_preview_widget_visibility (impl);
4842- break;
4843-
4844- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4845- impl->use_preview_label = g_value_get_boolean (value);
4846- update_preview_widget_visibility (impl);
4847- break;
4848-
4849- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
4850- set_extra_widget (impl, g_value_get_object (value));
4851- break;
4852-
4853 case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
4854 {
4855 gboolean select_multiple = g_value_get_boolean (value);
4856@@ -5070,6 +1868,51 @@
4857 }
4858 break;
4859
4860+ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER:
4861+ {
4862+ GtkFilePath * path;
4863+ gchar * new_root = g_strdup (g_value_get_string (value));
4864+
4865+ if (!new_root)
4866+ {
4867+ new_root = g_strdup ("/");
4868+ }
4869+
4870+ path = gtk_file_system_filename_to_path (impl->file_system,
4871+ new_root);
4872+ if (change_folder (impl, path, FALSE))
4873+ {
4874+ g_free (impl->root_folder);
4875+ impl->root_folder = new_root;
4876+ }
4877+ else
4878+ {
4879+ g_warning ("Unable to set [%s] as root folder", new_root);
4880+ g_free (new_root);
4881+ }
4882+
4883+ gtk_file_path_free (path);
4884+ }
4885+ break;
4886+
4887+ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER:
4888+ {
4889+ gboolean show = g_value_get_boolean (value);
4890+ if (show != impl->show_create_folder)
4891+ {
4892+ impl->show_create_folder = show;
4893+ show_new_folder_button (impl);
4894+ }
4895+ }
4896+ break;
4897+
4898+ /* These are not supported */
4899+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4900+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4901+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4902+ case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
4903+ break;
4904+
4905 default:
4906 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4907 break;
4908@@ -5098,28 +1941,32 @@
4909 g_value_set_boolean (value, impl->local_only);
4910 break;
4911
4912- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4913- g_value_set_object (value, impl->preview_widget);
4914+ case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
4915+ g_value_set_boolean (value, impl->select_multiple);
4916 break;
4917
4918- case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4919- g_value_set_boolean (value, impl->preview_widget_active);
4920+ case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
4921+ g_value_set_boolean (value, impl->show_hidden);
4922 break;
4923
4924- case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4925- g_value_set_boolean (value, impl->use_preview_label);
4926+ case GTK_FILE_CHOOSER_PROP_ROOT_FOLDER:
4927+ g_value_set_string (value, impl->root_folder);
4928 break;
4929
4930- case GTK_FILE_CHOOSER_PROP_EXTRA_WIDGET:
4931- g_value_set_object (value, impl->extra_widget);
4932+ case GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER:
4933+ g_value_set_boolean (value, impl->show_create_folder);
4934 break;
4935
4936- case GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE:
4937- g_value_set_boolean (value, impl->select_multiple);
4938+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET:
4939+ g_value_set_object (value, NULL);
4940 break;
4941
4942- case GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN:
4943- g_value_set_boolean (value, impl->show_hidden);
4944+ case GTK_FILE_CHOOSER_PROP_PREVIEW_WIDGET_ACTIVE:
4945+ g_value_set_boolean (value, FALSE);
4946+ break;
4947+
4948+ case GTK_FILE_CHOOSER_PROP_USE_PREVIEW_LABEL:
4949+ g_value_set_boolean (value, FALSE);
4950 break;
4951
4952 case GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION:
4953@@ -5154,24 +2001,12 @@
4954 GSList *l;
4955 GtkFileChooserDefault *impl = (GtkFileChooserDefault *) object;
4956
4957- if (impl->extra_widget)
4958- {
4959- g_object_unref (impl->extra_widget);
4960- impl->extra_widget = NULL;
4961- }
4962-
4963 if (impl->volumes_changed_id > 0)
4964 {
4965 g_signal_handler_disconnect (impl->file_system, impl->volumes_changed_id);
4966 impl->volumes_changed_id = 0;
4967 }
4968
4969- if (impl->bookmarks_changed_id > 0)
4970- {
4971- g_signal_handler_disconnect (impl->file_system, impl->bookmarks_changed_id);
4972- impl->bookmarks_changed_id = 0;
4973- }
4974-
4975 pending_select_paths_free (impl);
4976
4977 /* cancel all pending operations */
4978@@ -5197,23 +2032,6 @@
4979 impl->reload_icon_handles = NULL;
4980 }
4981
4982- if (impl->loading_shortcuts)
4983- {
4984- for (l = impl->loading_shortcuts; l; l = l->next)
4985- {
4986- GtkFileSystemHandle *handle =l->data;
4987- gtk_file_system_cancel_operation (handle);
4988- }
4989- g_slist_free (impl->loading_shortcuts);
4990- impl->loading_shortcuts = NULL;
4991- }
4992-
4993- if (impl->file_list_drag_data_received_handle)
4994- {
4995- gtk_file_system_cancel_operation (impl->file_list_drag_data_received_handle);
4996- impl->file_list_drag_data_received_handle = NULL;
4997- }
4998-
4999 if (impl->update_current_folder_handle)
5000 {
5001 gtk_file_system_cancel_operation (impl->update_current_folder_handle);
5002@@ -5238,12 +2056,6 @@
5003 impl->update_from_entry_handle = NULL;
5004 }
5005
5006- if (impl->shortcuts_activate_iter_handle)
5007- {
5008- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle);
5009- impl->shortcuts_activate_iter_handle = NULL;
5010- }
5011-
5012 remove_settings_signal (impl, gtk_widget_get_screen (GTK_WIDGET (impl)));
5013
5014 G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->dispose (object);
5015@@ -5256,12 +2068,7 @@
5016 static void
5017 gtk_file_chooser_default_show_all (GtkWidget *widget)
5018 {
5019- GtkFileChooserDefault *impl = (GtkFileChooserDefault *) widget;
5020-
5021 gtk_widget_show (widget);
5022-
5023- if (impl->extra_widget)
5024- gtk_widget_show_all (impl->extra_widget);
5025 }
5026
5027 /* Handler for GtkWindow::set-focus; this is where we save the last-focused
5028@@ -5322,7 +2129,6 @@
5029 else
5030 impl->icon_size = FALLBACK_ICON_SIZE;
5031
5032- shortcuts_reload_icons (impl);
5033 gtk_widget_queue_resize (impl->browse_files_tree_view);
5034
5035 profile_end ("end", NULL);
5036@@ -5441,15 +2247,6 @@
5037
5038 impl->default_width = allocation->width;
5039 impl->default_height = allocation->height;
5040-
5041- if (impl->preview_widget_active &&
5042- impl->preview_widget &&
5043- GTK_WIDGET_DRAWABLE (impl->preview_widget))
5044- impl->default_width -= impl->preview_widget->allocation.width + PREVIEW_HBOX_SPACING;
5045-
5046- if (impl->extra_widget &&
5047- GTK_WIDGET_DRAWABLE (impl->extra_widget))
5048- impl->default_height -= GTK_BOX (widget)->spacing + impl->extra_widget->allocation.height;
5049 }
5050
5051 static gboolean
5052@@ -5503,23 +2300,18 @@
5053 settings_load (GtkFileChooserDefault *impl)
5054 {
5055 GtkFileChooserSettings *settings;
5056- LocationMode location_mode;
5057 gboolean show_hidden;
5058 gboolean expand_folders;
5059
5060 settings = _gtk_file_chooser_settings_new ();
5061
5062- location_mode = _gtk_file_chooser_settings_get_location_mode (settings);
5063 show_hidden = _gtk_file_chooser_settings_get_show_hidden (settings);
5064 expand_folders = _gtk_file_chooser_settings_get_expand_folders (settings);
5065
5066 g_object_unref (settings);
5067
5068- location_mode_set (impl, location_mode, TRUE);
5069 gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (impl), show_hidden);
5070 impl->expand_folders = expand_folders;
5071- if (impl->save_expander)
5072- gtk_expander_set_expanded (GTK_EXPANDER (impl->save_expander), expand_folders);
5073 }
5074
5075 static void
5076@@ -5529,7 +2321,6 @@
5077
5078 settings = _gtk_file_chooser_settings_new ();
5079
5080- _gtk_file_chooser_settings_set_location_mode (settings, impl->location_mode);
5081 _gtk_file_chooser_settings_set_show_hidden (settings, gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
5082 _gtk_file_chooser_settings_set_expand_folders (settings, impl->expand_folders);
5083
5084@@ -5570,7 +2361,7 @@
5085 if (impl->current_folder)
5086 {
5087 pending_select_paths_store_selection (impl);
5088- change_folder_and_display_error (impl, impl->current_folder, FALSE);
5089+ change_folder_and_display_error (impl, impl->current_folder);
5090 }
5091 break;
5092
5093@@ -5578,8 +2369,6 @@
5094 g_assert_not_reached ();
5095 }
5096
5097- bookmarks_changed_cb (impl->file_system, impl);
5098-
5099 settings_load (impl);
5100
5101 profile_end ("end", NULL);
5102@@ -5897,12 +2686,10 @@
5103 gpointer user_data)
5104 {
5105 gboolean have_hidden;
5106- gboolean have_filtered;
5107 GSList *l;
5108 struct ShowAndSelectPathsData *data = user_data;
5109
5110 have_hidden = FALSE;
5111- have_filtered = FALSE;
5112
5113 for (l = data->paths; l; l = l->next)
5114 {
5115@@ -5918,12 +2705,9 @@
5116 if (!have_hidden)
5117 have_hidden = gtk_file_info_get_is_hidden (info);
5118
5119- if (!have_filtered)
5120- have_filtered = !gtk_file_info_get_is_folder (info) && get_is_file_filtered (data->impl, path, info);
5121-
5122 gtk_file_info_free (info);
5123
5124- if (have_hidden && have_filtered)
5125+ if (have_hidden)
5126 break; /* we now have all the information we need */
5127 }
5128 }
5129@@ -5937,9 +2721,6 @@
5130 if (have_hidden)
5131 g_object_set (data->impl, "show-hidden", TRUE, NULL);
5132
5133- if (have_filtered)
5134- set_current_filter (data->impl, NULL);
5135-
5136 for (l = data->paths; l; l = l->next)
5137 {
5138 const GtkFilePath *path;
5139@@ -6197,9 +2978,8 @@
5140
5141 if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5142 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5143- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5144- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5145- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)))
5146+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5147+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
5148 return;
5149
5150 g_assert (impl->location_entry != NULL);
5151@@ -6387,9 +3167,6 @@
5152 if (!gtk_file_info_get_is_folder (info))
5153 goto out;
5154
5155- if (!_gtk_path_bar_set_path (GTK_PATH_BAR (impl->browse_path_bar), data->path, data->keep_trail, NULL))
5156- goto out;
5157-
5158 if (impl->current_folder != data->path)
5159 {
5160 if (impl->current_folder)
5161@@ -6400,17 +3177,6 @@
5162 impl->reload_state = RELOAD_HAS_FOLDER;
5163 }
5164
5165- /* Update the widgets that may trigger a folder change themselves. */
5166-
5167- if (!impl->changing_folder)
5168- {
5169- impl->changing_folder = TRUE;
5170-
5171- shortcuts_update_current_folder (impl);
5172-
5173- impl->changing_folder = FALSE;
5174- }
5175-
5176 /* Set the folder on the save entry */
5177
5178 if (impl->location_entry)
5179@@ -6430,13 +3196,7 @@
5180
5181 /* Refresh controls */
5182
5183- shortcuts_find_current_folder (impl);
5184-
5185 g_signal_emit_by_name (impl, "current-folder-changed", 0);
5186-
5187- check_preview_change (impl);
5188- bookmarks_check_add_sensitivity (impl);
5189-
5190 g_signal_emit_by_name (impl, "selection-changed", 0);
5191
5192 out:
5193@@ -6698,9 +3458,8 @@
5194
5195 g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5196 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5197- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5198- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5199- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY));
5200+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5201+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5202
5203 chooser_entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry);
5204
5205@@ -6878,17 +3637,6 @@
5206 return g_slist_reverse (info.result);
5207 }
5208
5209-static GtkFilePath *
5210-gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser)
5211-{
5212- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5213-
5214- if (impl->preview_path)
5215- return gtk_file_path_copy (impl->preview_path);
5216- else
5217- return NULL;
5218-}
5219-
5220 static GtkFileSystem *
5221 gtk_file_chooser_default_get_file_system (GtkFileChooser *chooser)
5222 {
5223@@ -6903,9 +3651,9 @@
5224 gboolean show)
5225 {
5226 if (show)
5227- gtk_widget_show (impl->filter_combo_hbox);
5228+ gtk_widget_show (impl->filter_combo);
5229 else
5230- gtk_widget_hide (impl->filter_combo_hbox);
5231+ gtk_widget_hide (impl->filter_combo);
5232 }
5233
5234 static void
5235@@ -6915,6 +3663,8 @@
5236 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5237 const gchar *name;
5238
5239+ g_debug ("adding filter");
5240+
5241 if (g_slist_find (impl->filters, filter))
5242 {
5243 g_warning ("gtk_file_chooser_add_filter() called on filter already in list\n");
5244@@ -6925,291 +3675,62 @@
5245 impl->filters = g_slist_append (impl->filters, filter);
5246
5247 name = gtk_file_filter_get_name (filter);
5248- if (!name)
5249- name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
5250-
5251- gtk_combo_box_append_text (GTK_COMBO_BOX (impl->filter_combo), name);
5252-
5253- if (!g_slist_find (impl->filters, impl->current_filter))
5254- set_current_filter (impl, filter);
5255-
5256- show_filters (impl, TRUE);
5257-}
5258-
5259-static void
5260-gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
5261- GtkFileFilter *filter)
5262-{
5263- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5264- GtkTreeModel *model;
5265- GtkTreeIter iter;
5266- gint filter_index;
5267-
5268- filter_index = g_slist_index (impl->filters, filter);
5269-
5270- if (filter_index < 0)
5271- {
5272- g_warning ("gtk_file_chooser_remove_filter() called on filter not in list\n");
5273- return;
5274- }
5275-
5276- impl->filters = g_slist_remove (impl->filters, filter);
5277-
5278- if (filter == impl->current_filter)
5279- {
5280- if (impl->filters)
5281- set_current_filter (impl, impl->filters->data);
5282- else
5283- set_current_filter (impl, NULL);
5284- }
5285-
5286- /* Remove row from the combo box */
5287- model = gtk_combo_box_get_model (GTK_COMBO_BOX (impl->filter_combo));
5288- if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, filter_index))
5289- g_assert_not_reached ();
5290-
5291- gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
5292-
5293- g_object_unref (filter);
5294-
5295- if (!impl->filters)
5296- show_filters (impl, FALSE);
5297-}
5298-
5299-static GSList *
5300-gtk_file_chooser_default_list_filters (GtkFileChooser *chooser)
5301-{
5302- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5303-
5304- return g_slist_copy (impl->filters);
5305-}
5306-
5307-/* Returns the position in the shortcuts tree where the nth specified shortcut would appear */
5308-static int
5309-shortcuts_get_pos_for_shortcut_folder (GtkFileChooserDefault *impl,
5310- int pos)
5311-{
5312- return pos + shortcuts_get_index (impl, SHORTCUTS_SHORTCUTS);
5313-}
5314-
5315-struct AddShortcutData
5316-{
5317- GtkFileChooserDefault *impl;
5318- GtkFilePath *path;
5319-};
5320-
5321-static void
5322-add_shortcut_get_info_cb (GtkFileSystemHandle *handle,
5323- const GtkFileInfo *info,
5324- const GError *error,
5325- gpointer user_data)
5326-{
5327- int pos;
5328- gboolean cancelled = handle->cancelled;
5329- struct AddShortcutData *data = user_data;
5330-
5331- if (!g_slist_find (data->impl->loading_shortcuts, handle))
5332- goto out;
5333-
5334- data->impl->loading_shortcuts = g_slist_remove (data->impl->loading_shortcuts, handle);
5335-
5336- if (cancelled || error || !gtk_file_info_get_is_folder (info))
5337- goto out;
5338-
5339- pos = shortcuts_get_pos_for_shortcut_folder (data->impl, data->impl->num_shortcuts);
5340-
5341- shortcuts_insert_path (data->impl, pos, FALSE, NULL, data->path, NULL, FALSE, SHORTCUTS_SHORTCUTS);
5342-
5343-out:
5344- g_object_unref (data->impl);
5345- gtk_file_path_free (data->path);
5346- g_free (data);
5347-
5348- g_object_unref (handle);
5349-}
5350-
5351-static gboolean
5352-gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
5353- const GtkFilePath *path,
5354- GError **error)
5355-{
5356- GtkFileSystemHandle *handle;
5357- GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5358- struct AddShortcutData *data;
5359- GSList *l;
5360- int pos;
5361-
5362- /* Avoid adding duplicates */
5363- pos = shortcut_find_position (impl, path);
5364- if (pos >= 0 && pos < shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR))
5365- {
5366- gchar *uri;
5367-
5368- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5369- /* translators, "Shortcut" means "Bookmark" here */
5370- g_set_error (error,
5371- GTK_FILE_CHOOSER_ERROR,
5372- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
5373- _("Shortcut %s already exists"),
5374- uri);
5375- g_free (uri);
5376-
5377- return FALSE;
5378- }
5379-
5380- for (l = impl->loading_shortcuts; l; l = l->next)
5381- {
5382- GtkFileSystemHandle *h = l->data;
5383- GtkFilePath *p;
5384-
5385- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key");
5386- if (p && !gtk_file_path_compare (path, p))
5387- {
5388- gchar *uri;
5389-
5390- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5391- g_set_error (error,
5392- GTK_FILE_CHOOSER_ERROR,
5393- GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS,
5394- _("Shortcut %s already exists"),
5395- uri);
5396- g_free (uri);
5397-
5398- return FALSE;
5399- }
5400- }
5401-
5402- data = g_new0 (struct AddShortcutData, 1);
5403- data->impl = g_object_ref (impl);
5404- data->path = gtk_file_path_copy (path);
5405-
5406- handle = gtk_file_system_get_info (impl->file_system, path,
5407- GTK_FILE_INFO_IS_FOLDER,
5408- add_shortcut_get_info_cb, data);
5409+ if (!name)
5410+ name = "Untitled filter"; /* Place-holder, doesn't need to be marked for translation */
5411
5412- if (!handle)
5413- return FALSE;
5414+ gtk_combo_box_append_text (GTK_COMBO_BOX (impl->filter_combo), name);
5415
5416- impl->loading_shortcuts = g_slist_append (impl->loading_shortcuts, handle);
5417- g_object_set_data (G_OBJECT (handle), "add-shortcut-path-key", data->path);
5418+ if (!g_slist_find (impl->filters, impl->current_filter))
5419+ set_current_filter (impl, filter);
5420
5421- return TRUE;
5422+ show_filters (impl, g_slist_length (impl->filters) > 1);
5423 }
5424
5425-static gboolean
5426-gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
5427- const GtkFilePath *path,
5428- GError **error)
5429+static void
5430+gtk_file_chooser_default_remove_filter (GtkFileChooser *chooser,
5431+ GtkFileFilter *filter)
5432 {
5433 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5434- int pos;
5435+ GtkTreeModel *model;
5436 GtkTreeIter iter;
5437- GSList *l;
5438- char *uri;
5439- int i;
5440+ gint filter_index;
5441
5442- for (l = impl->loading_shortcuts; l; l = l->next)
5443- {
5444- GtkFileSystemHandle *h = l->data;
5445- GtkFilePath *p;
5446+ filter_index = g_slist_index (impl->filters, filter);
5447
5448- p = g_object_get_data (G_OBJECT (h), "add-shortcut-path-key");
5449- if (p && !gtk_file_path_compare (path, p))
5450- {
5451- impl->loading_shortcuts = g_slist_remove (impl->loading_shortcuts, h);
5452- gtk_file_system_cancel_operation (h);
5453- return TRUE;
5454- }
5455+ if (filter_index < 0)
5456+ {
5457+ g_warning ("gtk_file_chooser_remove_filter() called on filter not in list\n");
5458+ return;
5459 }
5460
5461- if (impl->num_shortcuts == 0)
5462- goto out;
5463-
5464- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
5465- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
5466- g_assert_not_reached ();
5467+ impl->filters = g_slist_remove (impl->filters, filter);
5468
5469- for (i = 0; i < impl->num_shortcuts; i++)
5470+ if (filter == impl->current_filter)
5471 {
5472- gpointer col_data;
5473- gboolean is_volume;
5474- GtkFilePath *shortcut;
5475-
5476- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
5477- SHORTCUTS_COL_DATA, &col_data,
5478- SHORTCUTS_COL_IS_VOLUME, &is_volume,
5479- -1);
5480- g_assert (col_data != NULL);
5481- g_assert (!is_volume);
5482-
5483- shortcut = col_data;
5484- if (gtk_file_path_compare (shortcut, path) == 0)
5485- {
5486- shortcuts_remove_rows (impl, pos + i, 1);
5487- impl->num_shortcuts--;
5488- return TRUE;
5489- }
5490-
5491- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
5492- g_assert_not_reached ();
5493+ if (impl->filters)
5494+ set_current_filter (impl, impl->filters->data);
5495+ else
5496+ set_current_filter (impl, NULL);
5497 }
5498
5499- out:
5500+ /* Remove row from the combo box */
5501+ model = gtk_combo_box_get_model (GTK_COMBO_BOX (impl->filter_combo));
5502+ if (!gtk_tree_model_iter_nth_child (model, &iter, NULL, filter_index))
5503+ g_assert_not_reached ();
5504
5505- uri = gtk_file_system_path_to_uri (impl->file_system, path);
5506- /* translators, "Shortcut" means "Bookmark" here */
5507- g_set_error (error,
5508- GTK_FILE_CHOOSER_ERROR,
5509- GTK_FILE_CHOOSER_ERROR_NONEXISTENT,
5510- _("Shortcut %s does not exist"),
5511- uri);
5512- g_free (uri);
5513+ gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
5514
5515- return FALSE;
5516+ g_object_unref (filter);
5517+
5518+ show_filters (impl, g_slist_length (impl->filters) > 1);
5519 }
5520
5521 static GSList *
5522-gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
5523+gtk_file_chooser_default_list_filters (GtkFileChooser *chooser)
5524 {
5525 GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (chooser);
5526- int pos;
5527- GtkTreeIter iter;
5528- int i;
5529- GSList *list;
5530-
5531- if (impl->num_shortcuts == 0)
5532- return NULL;
5533-
5534- pos = shortcuts_get_pos_for_shortcut_folder (impl, 0);
5535- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
5536- g_assert_not_reached ();
5537-
5538- list = NULL;
5539-
5540- for (i = 0; i < impl->num_shortcuts; i++)
5541- {
5542- gpointer col_data;
5543- gboolean is_volume;
5544- GtkFilePath *shortcut;
5545-
5546- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), &iter,
5547- SHORTCUTS_COL_DATA, &col_data,
5548- SHORTCUTS_COL_IS_VOLUME, &is_volume,
5549- -1);
5550- g_assert (col_data != NULL);
5551- g_assert (!is_volume);
5552-
5553- shortcut = col_data;
5554- list = g_slist_prepend (list, gtk_file_path_copy (shortcut));
5555
5556- if (i != impl->num_shortcuts - 1)
5557- {
5558- if (!gtk_tree_model_iter_next (GTK_TREE_MODEL (impl->shortcuts_model), &iter))
5559- g_assert_not_reached ();
5560- }
5561- }
5562-
5563- return g_slist_reverse (list);
5564+ return g_slist_copy (impl->filters);
5565 }
5566
5567 /* Guesses a size based upon font sizes */
5568@@ -7256,25 +3777,9 @@
5569 gint *default_height)
5570 {
5571 GtkFileChooserDefault *impl;
5572- GtkRequisition req;
5573
5574 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
5575 find_good_size_from_style (GTK_WIDGET (chooser_embed), default_width, default_height);
5576-
5577- if (impl->preview_widget_active &&
5578- impl->preview_widget &&
5579- GTK_WIDGET_VISIBLE (impl->preview_widget))
5580- {
5581- gtk_widget_size_request (impl->preview_box, &req);
5582- *default_width += PREVIEW_HBOX_SPACING + req.width;
5583- }
5584-
5585- if (impl->extra_widget &&
5586- GTK_WIDGET_VISIBLE (impl->extra_widget))
5587- {
5588- gtk_widget_size_request (impl->extra_align, &req);
5589- *default_height += GTK_BOX (chooser_embed)->spacing + req.height;
5590- }
5591 }
5592
5593 static gboolean
5594@@ -7285,8 +3790,7 @@
5595 impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
5596
5597 return (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
5598- impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
5599- gtk_expander_get_expanded (GTK_EXPANDER (impl->save_expander)));
5600+ impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5601 }
5602
5603 struct switch_folder_closure {
5604@@ -7333,7 +3837,7 @@
5605
5606 g_assert (closure.path && closure.num_selected == 1);
5607
5608- change_folder_and_display_error (impl, closure.path, FALSE);
5609+ change_folder_and_display_error (impl, closure.path);
5610 }
5611
5612 /* Gets the GtkFileInfo for the selected row in the file list; assumes single
5613@@ -7628,7 +4132,7 @@
5614 else
5615 {
5616 /* This will display an error, which is what we want */
5617- change_folder_and_display_error (data->impl, data->parent_path, FALSE);
5618+ change_folder_and_display_error (data->impl, data->parent_path);
5619 }
5620
5621 out:
5622@@ -7706,50 +4210,6 @@
5623 g_object_unref (handle);
5624 }
5625
5626-static void
5627-paste_text_received (GtkClipboard *clipboard,
5628- const gchar *text,
5629- GtkFileChooserDefault *impl)
5630-{
5631- GtkFilePath *path;
5632-
5633- if (!text)
5634- return;
5635-
5636- path = gtk_file_system_uri_to_path (impl->file_system, text);
5637- if (!path)
5638- {
5639- if (!g_path_is_absolute (text))
5640- {
5641- location_popup_handler (impl, text);
5642- return;
5643- }
5644-
5645- path = gtk_file_system_filename_to_path (impl->file_system, text);
5646- if (!path)
5647- {
5648- location_popup_handler (impl, text);
5649- return;
5650- }
5651- }
5652-
5653- if (!gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (impl), path, NULL))
5654- location_popup_handler (impl, text);
5655-
5656- gtk_file_path_free (path);
5657-}
5658-
5659-/* Handler for the "location-popup-on-paste" keybinding signal */
5660-static void
5661-location_popup_on_paste_handler (GtkFileChooserDefault *impl)
5662-{
5663- GtkClipboard *clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl),
5664- GDK_SELECTION_CLIPBOARD);
5665- gtk_clipboard_request_text (clipboard,
5666- (GtkClipboardTextReceivedFunc) paste_text_received,
5667- impl);
5668-}
5669-
5670
5671 /* Implementation for GtkFileChooserEmbed::should_respond() */
5672 static gboolean
5673@@ -7855,9 +4315,8 @@
5674
5675 g_assert (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5676 || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
5677- || ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5678- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5679- && impl->location_mode == LOCATION_MODE_FILENAME_ENTRY));
5680+ || impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5681+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
5682
5683 entry = GTK_FILE_CHOOSER_ENTRY (impl->location_entry);
5684 check_save_entry (impl, &path, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
5685@@ -7873,7 +4332,7 @@
5686 if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5687 || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
5688 {
5689- change_folder_and_display_error (impl, path, TRUE);
5690+ change_folder_and_display_error (impl, path);
5691 retval = FALSE;
5692 }
5693 else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
5694@@ -7896,430 +4355,126 @@
5695
5696 /* We need to check whether path exists and is not a folder */
5697
5698- data = g_new0 (struct FileExistsData, 1);
5699- data->impl = g_object_ref (impl);
5700- data->path = gtk_file_path_copy (path);
5701- data->parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
5702-
5703- if (impl->file_exists_get_info_handle)
5704- gtk_file_system_cancel_operation (impl->file_exists_get_info_handle);
5705-
5706- impl->file_exists_get_info_handle =
5707- gtk_file_system_get_info (impl->file_system, path,
5708- GTK_FILE_INFO_IS_FOLDER,
5709- file_exists_get_info_cb,
5710- data);
5711-
5712- set_busy_cursor (impl, TRUE);
5713- retval = FALSE;
5714-
5715- if (error != NULL)
5716- g_error_free (error);
5717- }
5718-
5719- gtk_file_path_free (path);
5720- return retval;
5721- }
5722- else if (impl->toplevel_last_focus_widget == impl->browse_shortcuts_tree_view)
5723- {
5724- /* The focus is on a dialog's action area button, *and* the widget that
5725- * was focused immediately before it is the shortcuts list. Switch to the
5726- * selected shortcut and tell the caller not to respond.
5727- */
5728- GtkTreeIter iter;
5729-
5730- if (shortcuts_get_selected (impl, &iter))
5731- {
5732- shortcuts_activate_iter (impl, &iter);
5733-
5734- gtk_widget_grab_focus (impl->browse_files_tree_view);
5735- }
5736- else
5737- goto file_list;
5738-
5739- return FALSE;
5740- }
5741- else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
5742- {
5743- /* The focus is on a dialog's action area button, *and* the widget that
5744- * was focused immediately before it is the file list.
5745- */
5746- goto file_list;
5747- }
5748- else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry)
5749- {
5750- /* The focus is on a dialog's action area button, *and* the widget that
5751- * was focused immediately before it is the location entry.
5752- */
5753- goto save_entry;
5754- }
5755- else
5756- /* The focus is on a dialog's action area button or something else */
5757- if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5758- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5759- goto save_entry;
5760- else
5761- goto file_list;
5762-
5763- g_assert_not_reached ();
5764- return FALSE;
5765-}
5766-
5767-/* Implementation for GtkFileChooserEmbed::initial_focus() */
5768-static void
5769-gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
5770-{
5771- GtkFileChooserDefault *impl;
5772- GtkWidget *widget;
5773-
5774- impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
5775-
5776- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
5777- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
5778- {
5779- if (impl->location_mode == LOCATION_MODE_PATH_BAR)
5780- widget = impl->browse_files_tree_view;
5781- else
5782- widget = impl->location_entry;
5783- }
5784- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
5785- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
5786- widget = impl->location_entry;
5787- else
5788- {
5789- g_assert_not_reached ();
5790- widget = NULL;
5791- }
5792-
5793- g_assert (widget != NULL);
5794- gtk_widget_grab_focus (widget);
5795-}
5796-
5797-static void
5798-set_current_filter (GtkFileChooserDefault *impl,
5799- GtkFileFilter *filter)
5800-{
5801- if (impl->current_filter != filter)
5802- {
5803- int filter_index;
5804-
5805- /* NULL filters are allowed to reset to non-filtered status
5806- */
5807- filter_index = g_slist_index (impl->filters, filter);
5808- if (impl->filters && filter && filter_index < 0)
5809- return;
5810-
5811- if (impl->current_filter)
5812- g_object_unref (impl->current_filter);
5813- impl->current_filter = filter;
5814- if (impl->current_filter)
5815- {
5816- g_object_ref_sink (impl->current_filter);
5817- }
5818-
5819- if (impl->filters)
5820- gtk_combo_box_set_active (GTK_COMBO_BOX (impl->filter_combo),
5821- filter_index);
5822-
5823- if (impl->browse_files_model)
5824- install_list_model_filter (impl);
5825-
5826- g_object_notify (G_OBJECT (impl), "filter");
5827- }
5828-}
5829-
5830-static void
5831-filter_combo_changed (GtkComboBox *combo_box,
5832- GtkFileChooserDefault *impl)
5833-{
5834- gint new_index = gtk_combo_box_get_active (combo_box);
5835- GtkFileFilter *new_filter = g_slist_nth_data (impl->filters, new_index);
5836-
5837- set_current_filter (impl, new_filter);
5838-}
5839-
5840-static void
5841-check_preview_change (GtkFileChooserDefault *impl)
5842-{
5843- GtkTreePath *cursor_path;
5844- const GtkFilePath *new_path;
5845- const GtkFileInfo *new_info;
5846-
5847- gtk_tree_view_get_cursor (GTK_TREE_VIEW (impl->browse_files_tree_view), &cursor_path, NULL);
5848- if (cursor_path && impl->sort_model)
5849- {
5850- GtkTreeIter iter;
5851- GtkTreeIter child_iter;
5852-
5853- if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (impl->sort_model), &iter, cursor_path))
5854- g_assert_not_reached ();
5855-
5856- gtk_tree_path_free (cursor_path);
5857-
5858- gtk_tree_model_sort_convert_iter_to_child_iter (impl->sort_model, &child_iter, &iter);
5859-
5860- new_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
5861- new_info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
5862- }
5863- else
5864- {
5865- new_path = NULL;
5866- new_info = NULL;
5867- }
5868-
5869- if (new_path != impl->preview_path &&
5870- !(new_path && impl->preview_path &&
5871- gtk_file_path_compare (new_path, impl->preview_path) == 0))
5872- {
5873- if (impl->preview_path)
5874- {
5875- gtk_file_path_free (impl->preview_path);
5876- g_free (impl->preview_display_name);
5877- }
5878-
5879- if (new_path)
5880- {
5881- impl->preview_path = gtk_file_path_copy (new_path);
5882- impl->preview_display_name = g_strdup (gtk_file_info_get_display_name (new_info));
5883- }
5884- else
5885- {
5886- impl->preview_path = NULL;
5887- impl->preview_display_name = NULL;
5888- }
5889-
5890- if (impl->use_preview_label && impl->preview_label)
5891- gtk_label_set_text (GTK_LABEL (impl->preview_label), impl->preview_display_name);
5892-
5893- g_signal_emit_by_name (impl, "update-preview");
5894- }
5895-}
5896-
5897-static void
5898-shortcuts_activate_volume_mount_cb (GtkFileSystemHandle *handle,
5899- GtkFileSystemVolume *volume,
5900- const GError *error,
5901- gpointer data)
5902-{
5903- GtkFilePath *path;
5904- gboolean cancelled = handle->cancelled;
5905- GtkFileChooserDefault *impl = data;
5906-
5907- if (handle != impl->shortcuts_activate_iter_handle)
5908- goto out;
5909-
5910- impl->shortcuts_activate_iter_handle = NULL;
5911-
5912- set_busy_cursor (impl, FALSE);
5913+ data = g_new0 (struct FileExistsData, 1);
5914+ data->impl = g_object_ref (impl);
5915+ data->path = gtk_file_path_copy (path);
5916+ data->parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry));
5917
5918- if (cancelled)
5919- goto out;
5920+ if (impl->file_exists_get_info_handle)
5921+ gtk_file_system_cancel_operation (impl->file_exists_get_info_handle);
5922
5923- if (error)
5924- {
5925- char *msg;
5926+ impl->file_exists_get_info_handle =
5927+ gtk_file_system_get_info (impl->file_system, path,
5928+ GTK_FILE_INFO_IS_FOLDER,
5929+ file_exists_get_info_cb,
5930+ data);
5931
5932- msg = g_strdup_printf (_("Could not mount %s"),
5933- gtk_file_system_volume_get_display_name (impl->file_system, volume));
5934- error_message (impl, msg, error->message);
5935- g_free (msg);
5936+ set_busy_cursor (impl, TRUE);
5937+ retval = FALSE;
5938
5939- goto out;
5940- }
5941+ if (error != NULL)
5942+ g_error_free (error);
5943+ }
5944
5945- path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
5946- if (path != NULL)
5947- {
5948- change_folder_and_display_error (impl, path, FALSE);
5949 gtk_file_path_free (path);
5950+ return retval;
5951 }
5952-
5953-out:
5954- g_object_unref (impl);
5955- g_object_unref (handle);
5956-}
5957-
5958-
5959-/* Activates a volume by mounting it if necessary and then switching to its
5960- * base path.
5961- */
5962-static void
5963-shortcuts_activate_volume (GtkFileChooserDefault *impl,
5964- GtkFileSystemVolume *volume)
5965-{
5966- GtkFilePath *path;
5967-
5968- /* We ref the file chooser since volume_mount() may run a main loop, and the
5969- * user could close the file chooser window in the meantime.
5970- */
5971- g_object_ref (impl);
5972-
5973- if (!gtk_file_system_volume_get_is_mounted (impl->file_system, volume))
5974+ else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
5975 {
5976- set_busy_cursor (impl, TRUE);
5977-
5978- impl->shortcuts_activate_iter_handle =
5979- gtk_file_system_volume_mount (impl->file_system, volume,
5980- shortcuts_activate_volume_mount_cb,
5981- g_object_ref (impl));
5982+ /* The focus is on a dialog's action area button, *and* the widget that
5983+ * was focused immediately before it is the file list.
5984+ */
5985+ goto file_list;
5986 }
5987- else
5988+ else if (impl->location_entry && impl->toplevel_last_focus_widget == impl->location_entry)
5989 {
5990- path = gtk_file_system_volume_get_base_path (impl->file_system, volume);
5991- if (path != NULL)
5992- {
5993- change_folder_and_display_error (impl, path, FALSE);
5994- gtk_file_path_free (path);
5995- }
5996+ /* The focus is on a dialog's action area button, *and* the widget that
5997+ * was focused immediately before it is the location entry.
5998+ */
5999+ goto save_entry;
6000 }
6001-
6002- g_object_unref (impl);
6003-}
6004-
6005-/* Opens the folder or volume at the specified iter in the shortcuts model */
6006-struct ShortcutsActivateData
6007-{
6008- GtkFileChooserDefault *impl;
6009- GtkFilePath *path;
6010-};
6011-
6012-static void
6013-shortcuts_activate_get_info_cb (GtkFileSystemHandle *handle,
6014- const GtkFileInfo *info,
6015- const GError *error,
6016- gpointer user_data)
6017-{
6018- gboolean cancelled = handle->cancelled;
6019- struct ShortcutsActivateData *data = user_data;
6020-
6021- if (handle != data->impl->shortcuts_activate_iter_handle)
6022- goto out;
6023-
6024- data->impl->shortcuts_activate_iter_handle = NULL;
6025-
6026- if (cancelled)
6027- goto out;
6028-
6029- if (!error && gtk_file_info_get_is_folder (info))
6030- change_folder_and_display_error (data->impl, data->path, FALSE);
6031 else
6032- gtk_file_chooser_default_select_path (GTK_FILE_CHOOSER (data->impl), data->path, NULL);
6033-
6034-out:
6035- g_object_unref (data->impl);
6036- gtk_file_path_free (data->path);
6037- g_free (data);
6038+ /* The focus is on a dialog's action area button or something else */
6039+ if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6040+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6041+ goto save_entry;
6042+ else
6043+ goto file_list;
6044
6045- g_object_unref (handle);
6046+ g_assert_not_reached ();
6047+ return FALSE;
6048 }
6049
6050+/* Implementation for GtkFileChooserEmbed::initial_focus() */
6051 static void
6052-shortcuts_activate_iter (GtkFileChooserDefault *impl,
6053- GtkTreeIter *iter)
6054+gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
6055 {
6056- gpointer col_data;
6057- gboolean is_volume;
6058-
6059- if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY && impl->action != GTK_FILE_CHOOSER_ACTION_SAVE)
6060- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
6061-
6062- gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
6063- SHORTCUTS_COL_DATA, &col_data,
6064- SHORTCUTS_COL_IS_VOLUME, &is_volume,
6065- -1);
6066+ GtkFileChooserDefault *impl;
6067+ GtkWidget *widget;
6068
6069- if (!col_data)
6070- return; /* We are on a separator */
6071+ impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
6072
6073- if (impl->shortcuts_activate_iter_handle)
6074+ if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6075+ || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6076 {
6077- gtk_file_system_cancel_operation (impl->shortcuts_activate_iter_handle);
6078- impl->shortcuts_activate_iter_handle = NULL;
6079+ widget = impl->browse_files_tree_view;
6080 }
6081-
6082- if (is_volume)
6083+ else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6084+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6085 {
6086- GtkFileSystemVolume *volume;
6087-
6088- volume = col_data;
6089-
6090- shortcuts_activate_volume (impl, volume);
6091+ widget = impl->location_entry;
6092 }
6093 else
6094 {
6095- struct ShortcutsActivateData *data;
6096-
6097- data = g_new0 (struct ShortcutsActivateData, 1);
6098- data->impl = g_object_ref (impl);
6099- data->path = gtk_file_path_copy (col_data);
6100-
6101- impl->shortcuts_activate_iter_handle =
6102- gtk_file_system_get_info (impl->file_system, data->path,
6103- GTK_FILE_INFO_IS_FOLDER,
6104- shortcuts_activate_get_info_cb, data);
6105+ g_assert_not_reached ();
6106+ widget = NULL;
6107 }
6108+
6109+ g_assert (widget != NULL);
6110+ gtk_widget_grab_focus (widget);
6111 }
6112
6113-/* Callback used when a row in the shortcuts list is activated */
6114 static void
6115-shortcuts_row_activated_cb (GtkTreeView *tree_view,
6116- GtkTreePath *path,
6117- GtkTreeViewColumn *column,
6118- GtkFileChooserDefault *impl)
6119+set_current_filter (GtkFileChooserDefault *impl,
6120+ GtkFileFilter *filter)
6121 {
6122- GtkTreeIter iter;
6123- GtkTreeIter child_iter;
6124-
6125- if (!gtk_tree_model_get_iter (impl->shortcuts_filter_model, &iter, path))
6126- return;
6127-
6128- gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (impl->shortcuts_filter_model),
6129- &child_iter,
6130- &iter);
6131- shortcuts_activate_iter (impl, &child_iter);
6132+ if (impl->current_filter != filter)
6133+ {
6134+ int filter_index;
6135
6136- gtk_widget_grab_focus (impl->browse_files_tree_view);
6137-}
6138+ /* NULL filters are allowed to reset to non-filtered status
6139+ */
6140+ filter_index = g_slist_index (impl->filters, filter);
6141+ if (impl->filters && filter && filter_index < 0)
6142+ return;
6143
6144-/* Handler for GtkWidget::key-press-event on the shortcuts list */
6145-static gboolean
6146-shortcuts_key_press_event_cb (GtkWidget *widget,
6147- GdkEventKey *event,
6148- GtkFileChooserDefault *impl)
6149-{
6150- guint modifiers;
6151+ if (impl->current_filter)
6152+ g_object_unref (impl->current_filter);
6153+ impl->current_filter = filter;
6154+ if (impl->current_filter)
6155+ {
6156+ g_object_ref_sink (impl->current_filter);
6157+ }
6158
6159- modifiers = gtk_accelerator_get_default_mod_mask ();
6160+ if (impl->filters)
6161+ gtk_combo_box_set_active (GTK_COMBO_BOX (impl->filter_combo),
6162+ filter_index);
6163
6164- if ((event->keyval == GDK_BackSpace
6165- || event->keyval == GDK_Delete
6166- || event->keyval == GDK_KP_Delete)
6167- && (event->state & modifiers) == 0)
6168- {
6169- remove_selected_bookmarks (impl);
6170- return TRUE;
6171- }
6172+ if (impl->browse_files_model)
6173+ install_list_model_filter (impl);
6174
6175- if ((event->keyval == GDK_F2)
6176- && (event->state & modifiers) == 0)
6177- {
6178- rename_selected_bookmark (impl);
6179- return TRUE;
6180+ g_object_notify (G_OBJECT (impl), "filter");
6181 }
6182-
6183- return FALSE;
6184 }
6185
6186-static gboolean
6187-shortcuts_select_func (GtkTreeSelection *selection,
6188- GtkTreeModel *model,
6189- GtkTreePath *path,
6190- gboolean path_currently_selected,
6191- gpointer data)
6192+static void
6193+filter_combo_changed (GtkComboBox *combo_box,
6194+ GtkFileChooserDefault *impl)
6195 {
6196- GtkFileChooserDefault *impl = data;
6197+ gint new_index = gtk_combo_box_get_active (combo_box);
6198+ GtkFileFilter *new_filter = g_slist_nth_data (impl->filters, new_index);
6199
6200- return (*gtk_tree_path_get_indices (path) != shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS_SEPARATOR));
6201+ set_current_filter (impl, new_filter);
6202 }
6203
6204 static gboolean
6205@@ -8373,8 +4528,6 @@
6206
6207 if (impl->location_entry)
6208 update_chooser_entry (impl);
6209- check_preview_change (impl);
6210- bookmarks_check_add_sensitivity (impl);
6211
6212 g_signal_emit_by_name (impl, "selection-changed", 0);
6213 }
6214@@ -8401,7 +4554,8 @@
6215 const GtkFilePath *file_path;
6216
6217 file_path = _gtk_file_system_model_get_path (impl->browse_files_model, &child_iter);
6218- change_folder_and_display_error (impl, file_path, FALSE);
6219+
6220+ change_folder_and_display_error (impl, file_path);
6221
6222 return;
6223 }
6224@@ -8411,27 +4565,6 @@
6225 g_signal_emit_by_name (impl, "file-activated");
6226 }
6227
6228-static void
6229-path_bar_clicked (GtkPathBar *path_bar,
6230- GtkFilePath *file_path,
6231- GtkFilePath *child_path,
6232- gboolean child_is_hidden,
6233- GtkFileChooserDefault *impl)
6234-{
6235- if (child_path)
6236- pending_select_paths_add (impl, child_path);
6237-
6238- if (!change_folder_and_display_error (impl, file_path, FALSE))
6239- return;
6240-
6241- /* Say we have "/foo/bar/[.baz]" and the user clicks on "bar". We should then
6242- * show hidden files so that ".baz" appears in the file list, as it will still
6243- * be shown in the path bar: "/foo/[bar]/.baz"
6244- */
6245- if (child_is_hidden)
6246- g_object_set (impl, "show-hidden", TRUE, NULL);
6247-}
6248-
6249 static const GtkFileInfo *
6250 get_list_file_info (GtkFileChooserDefault *impl,
6251 GtkTreeIter *iter)
6252@@ -8659,210 +4792,73 @@
6253 NULL);
6254 }
6255
6256-static void
6257-location_set_user_text (GtkFileChooserDefault *impl,
6258- const gchar *path)
6259-{
6260- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), path);
6261- gtk_editable_set_position (GTK_EDITABLE (impl->location_entry), -1);
6262-}
6263-
6264-static void
6265-location_popup_handler (GtkFileChooserDefault *impl,
6266- const gchar *path)
6267-{
6268- if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
6269- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
6270- {
6271- LocationMode new_mode;
6272-
6273- if (path != NULL)
6274- {
6275- /* since the user typed something, we unconditionally want to turn on the entry */
6276- new_mode = LOCATION_MODE_FILENAME_ENTRY;
6277- }
6278- else if (impl->location_mode == LOCATION_MODE_PATH_BAR)
6279- new_mode = LOCATION_MODE_FILENAME_ENTRY;
6280- else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
6281- new_mode = LOCATION_MODE_PATH_BAR;
6282- else
6283- {
6284- g_assert_not_reached ();
6285- return;
6286- }
6287-
6288- location_mode_set (impl, new_mode, TRUE);
6289- if (new_mode == LOCATION_MODE_FILENAME_ENTRY)
6290- {
6291- if (path != NULL)
6292- location_set_user_text (impl, path);
6293- else
6294- {
6295- location_entry_set_initial_text (impl);
6296- gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1);
6297- }
6298- }
6299- }
6300- else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
6301- || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
6302- {
6303- gtk_widget_grab_focus (impl->location_entry);
6304- if (path != NULL)
6305- location_set_user_text (impl, path);
6306- }
6307- else
6308- g_assert_not_reached ();
6309-}
6310-
6311 /* Handler for the "up-folder" keybinding signal */
6312 static void
6313 up_folder_handler (GtkFileChooserDefault *impl)
6314 {
6315- _gtk_path_bar_up (GTK_PATH_BAR (impl->browse_path_bar));
6316+ GtkFilePath * parent;
6317+ pending_select_paths_add (impl, impl->current_folder);
6318+
6319+ if (gtk_file_system_get_parent (impl->file_system, impl->current_folder,
6320+ &parent, NULL) && parent)
6321+ {
6322+ impl->path_history = g_slist_prepend (impl->path_history,
6323+ gtk_file_path_copy (impl->current_folder));
6324+
6325+ change_folder_and_display_error (impl, parent);
6326+ gtk_file_path_free (parent);
6327+ }
6328 }
6329
6330 /* Handler for the "down-folder" keybinding signal */
6331 static void
6332 down_folder_handler (GtkFileChooserDefault *impl)
6333 {
6334- _gtk_path_bar_down (GTK_PATH_BAR (impl->browse_path_bar));
6335-}
6336-
6337-/* Switches to the shortcut in the specified index */
6338-static void
6339-switch_to_shortcut (GtkFileChooserDefault *impl,
6340- int pos)
6341-{
6342- GtkTreeIter iter;
6343-
6344- if (!gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (impl->shortcuts_model), &iter, NULL, pos))
6345- g_assert_not_reached ();
6346-
6347- shortcuts_activate_iter (impl, &iter);
6348+ if (impl->path_history)
6349+ {
6350+ GtkFilePath * path = impl->path_history->data;
6351+
6352+ change_folder_and_display_error (impl, path);
6353+ impl->path_history = g_slist_remove (impl->path_history, path);
6354+ gtk_file_path_free (path);
6355+ }
6356 }
6357
6358 /* Handler for the "home-folder" keybinding signal */
6359 static void
6360 home_folder_handler (GtkFileChooserDefault *impl)
6361 {
6362- if (impl->has_home)
6363- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_HOME));
6364-}
6365-
6366-/* Handler for the "desktop-folder" keybinding signal */
6367-static void
6368-desktop_folder_handler (GtkFileChooserDefault *impl)
6369-{
6370- if (impl->has_desktop)
6371- switch_to_shortcut (impl, shortcuts_get_index (impl, SHORTCUTS_DESKTOP));
6372-}
6373-
6374-static void
6375-quick_bookmark_handler (GtkFileChooserDefault *impl,
6376- gint bookmark_index)
6377-{
6378- int bookmark_pos;
6379- GtkTreePath *path;
6380-
6381- if (bookmark_index < 0 || bookmark_index >= impl->num_bookmarks)
6382- return;
6383-
6384- bookmark_pos = shortcuts_get_index (impl, SHORTCUTS_BOOKMARKS) + bookmark_index;
6385-
6386- path = gtk_tree_path_new_from_indices (bookmark_pos, -1);
6387- gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view),
6388- path, NULL,
6389- FALSE, 0.0, 0.0);
6390- gtk_tree_path_free (path);
6391-
6392- switch_to_shortcut (impl, bookmark_pos);
6393 }
6394
6395 static void
6396 show_hidden_handler (GtkFileChooserDefault *impl)
6397 {
6398- g_object_set (impl,
6399- "show-hidden", !impl->show_hidden,
6400- NULL);
6401-}
6402-
6403-
6404-/* Drag and drop interfaces */
6405-
6406-static void
6407-_shortcuts_model_filter_class_init (ShortcutsModelFilterClass *class)
6408-{
6409 }
6410
6411-static void
6412-_shortcuts_model_filter_init (ShortcutsModelFilter *model)
6413+static GtkFilePath *
6414+gtk_file_chooser_default_get_preview_path (GtkFileChooser *chooser)
6415 {
6416- model->impl = NULL;
6417+ return NULL;
6418 }
6419
6420-/* GtkTreeDragSource::row_draggable implementation for the shortcuts filter model */
6421 static gboolean
6422-shortcuts_model_filter_row_draggable (GtkTreeDragSource *drag_source,
6423- GtkTreePath *path)
6424+gtk_file_chooser_default_add_shortcut_folder (GtkFileChooser *chooser,
6425+ const GtkFilePath *path,
6426+ GError **error)
6427 {
6428- ShortcutsModelFilter *model;
6429- int pos;
6430- int bookmarks_pos;
6431-
6432- model = SHORTCUTS_MODEL_FILTER (drag_source);
6433-
6434- pos = *gtk_tree_path_get_indices (path);
6435- bookmarks_pos = shortcuts_get_index (model->impl, SHORTCUTS_BOOKMARKS);
6436-
6437- return (pos >= bookmarks_pos && pos < bookmarks_pos + model->impl->num_bookmarks);
6438+ return FALSE;
6439 }
6440
6441-/* GtkTreeDragSource::drag_data_get implementation for the shortcuts filter model */
6442 static gboolean
6443-shortcuts_model_filter_drag_data_get (GtkTreeDragSource *drag_source,
6444- GtkTreePath *path,
6445- GtkSelectionData *selection_data)
6446-{
6447- ShortcutsModelFilter *model;
6448-
6449- model = SHORTCUTS_MODEL_FILTER (drag_source);
6450-
6451- /* FIXME */
6452-
6453- return FALSE;
6454-}
6455-
6456-/* Fill the GtkTreeDragSourceIface vtable */
6457-static void
6458-shortcuts_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface)
6459+gtk_file_chooser_default_remove_shortcut_folder (GtkFileChooser *chooser,
6460+ const GtkFilePath *path,
6461+ GError **error)
6462 {
6463- iface->row_draggable = shortcuts_model_filter_row_draggable;
6464- iface->drag_data_get = shortcuts_model_filter_drag_data_get;
6465+ return TRUE;
6466 }
6467
6468-#if 0
6469-/* Fill the GtkTreeDragDestIface vtable */
6470-static void
6471-shortcuts_model_filter_drag_dest_iface_init (GtkTreeDragDestIface *iface)
6472+static GSList *
6473+gtk_file_chooser_default_list_shortcut_folders (GtkFileChooser *chooser)
6474 {
6475- iface->drag_data_received = shortcuts_model_filter_drag_data_received;
6476- iface->row_drop_possible = shortcuts_model_filter_row_drop_possible;
6477-}
6478-#endif
6479-
6480-static GtkTreeModel *
6481-shortcuts_model_filter_new (GtkFileChooserDefault *impl,
6482- GtkTreeModel *child_model,
6483- GtkTreePath *root)
6484-{
6485- ShortcutsModelFilter *model;
6486-
6487- model = g_object_new (SHORTCUTS_MODEL_FILTER_TYPE,
6488- "child-model", child_model,
6489- "virtual-root", root,
6490- NULL);
6491-
6492- model->impl = impl;
6493-
6494- return GTK_TREE_MODEL (model);
6495+ return NULL;
6496 }
6497Index: gtk+-2.10.14/gtk/gtkfilechooserprivate.h
6498===================================================================
6499--- gtk+-2.10.14.orig/gtk/gtkfilechooserprivate.h 2007-07-16 20:44:17.000000000 +0100
6500+++ gtk+-2.10.14/gtk/gtkfilechooserprivate.h 2007-08-29 18:12:02.000000000 +0100
6501@@ -153,36 +153,19 @@
6502
6503 /* Save mode widgets */
6504 GtkWidget *save_widgets;
6505-
6506- GtkWidget *save_folder_label;
6507- GtkWidget *save_folder_combo;
6508- GtkWidget *save_expander;
6509+ GtkWidget *save_file_name_entry;
6510
6511 /* The file browsing widgets */
6512 GtkWidget *browse_widgets;
6513- GtkWidget *browse_shortcuts_tree_view;
6514- GtkWidget *browse_shortcuts_add_button;
6515- GtkWidget *browse_shortcuts_remove_button;
6516- GtkWidget *browse_shortcuts_popup_menu;
6517- GtkWidget *browse_shortcuts_popup_menu_remove_item;
6518- GtkWidget *browse_shortcuts_popup_menu_rename_item;
6519 GtkWidget *browse_files_tree_view;
6520- GtkWidget *browse_files_popup_menu;
6521- GtkWidget *browse_files_popup_menu_add_shortcut_item;
6522- GtkWidget *browse_files_popup_menu_hidden_files_item;
6523 GtkWidget *browse_new_folder_button;
6524- GtkWidget *browse_path_bar;
6525+ GtkWidget *bar;
6526+ GtkWidget *up_button;
6527
6528 GtkFileSystemModel *browse_files_model;
6529- char *browse_files_last_selected_name;
6530+ char *browse_files_last_selected_name; /* ??? */
6531
6532- GtkWidget *filter_combo_hbox;
6533 GtkWidget *filter_combo;
6534- GtkWidget *preview_box;
6535- GtkWidget *preview_label;
6536- GtkWidget *preview_widget;
6537- GtkWidget *extra_align;
6538- GtkWidget *extra_widget;
6539
6540 GtkWidget *location_button;
6541 GtkWidget *location_entry_box;
6542@@ -198,7 +181,6 @@
6543 /* Handles */
6544 GSList *loading_shortcuts;
6545 GSList *reload_icon_handles;
6546- GtkFileSystemHandle *file_list_drag_data_received_handle;
6547 GtkFileSystemHandle *update_current_folder_handle;
6548 GtkFileSystemHandle *show_and_select_paths_handle;
6549 GtkFileSystemHandle *should_respond_get_info_handle;
6550@@ -212,29 +194,24 @@
6551 guint load_timeout_id;
6552
6553 GSList *pending_select_paths;
6554+ GSList *path_history;
6555
6556 GtkFileFilter *current_filter;
6557 GSList *filters;
6558
6559 GtkTooltips *tooltips;
6560
6561- gboolean has_home;
6562- gboolean has_desktop;
6563-
6564 int num_volumes;
6565- int num_shortcuts;
6566- int num_bookmarks;
6567
6568 gulong volumes_changed_id;
6569- gulong bookmarks_changed_id;
6570
6571 GtkFilePath *current_volume_path;
6572 GtkFilePath *current_folder;
6573- GtkFilePath *preview_path;
6574- char *preview_display_name;
6575
6576 GtkTreeViewColumn *list_name_column;
6577 GtkCellRenderer *list_name_renderer;
6578+ guint32 list_press_time;
6579+ GtkTreePath *list_press_path;
6580
6581 GSource *edited_idle;
6582 char *edited_new_text;
6583@@ -245,10 +222,7 @@
6584 gulong toplevel_set_focus_id;
6585 GtkWidget *toplevel_last_focus_widget;
6586
6587-#if 0
6588- GdkDragContext *shortcuts_drag_context;
6589- GSource *shortcuts_drag_outside_idle;
6590-#endif
6591+ gchar * root_folder;
6592
6593 gint default_width;
6594 gint default_height;
6595@@ -256,19 +230,13 @@
6596 /* Flags */
6597
6598 guint local_only : 1;
6599- guint preview_widget_active : 1;
6600- guint use_preview_label : 1;
6601 guint select_multiple : 1;
6602 guint show_hidden : 1;
6603+ guint show_create_folder : 1;
6604 guint do_overwrite_confirmation : 1;
6605 guint list_sort_ascending : 1;
6606 guint changing_folder : 1;
6607- guint shortcuts_current_folder_active : 1;
6608 guint expand_folders : 1;
6609-
6610-#if 0
6611- guint shortcuts_drag_outside : 1;
6612-#endif
6613 };
6614
6615
6616Index: gtk+-2.10.14/tests/autotestfilechooser.c
6617===================================================================
6618--- gtk+-2.10.14.orig/tests/autotestfilechooser.c 2007-07-16 20:45:12.000000000 +0100
6619+++ gtk+-2.10.14/tests/autotestfilechooser.c 2007-08-29 18:12:02.000000000 +0100
6620@@ -452,9 +452,6 @@
6621 && (impl->location_mode == LOCATION_MODE_PATH_BAR
6622 ? impl->location_entry == NULL
6623 : impl->location_entry != NULL)
6624- && impl->save_folder_label == NULL
6625- && impl->save_folder_combo == NULL
6626- && impl->save_expander == NULL
6627 && GTK_IS_CONTAINER (impl->browse_widgets) && GTK_WIDGET_DRAWABLE (impl->browse_widgets));
6628 }
6629 else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action))
6630@@ -465,9 +462,6 @@
6631 */
6632 passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && GTK_WIDGET_DRAWABLE (impl->save_widgets)
6633 && impl->location_entry != NULL && GTK_WIDGET_DRAWABLE (impl->location_entry)
6634- && GTK_IS_LABEL (impl->save_folder_label) && GTK_WIDGET_DRAWABLE (impl->save_folder_label)
6635- && GTK_IS_COMBO_BOX (impl->save_folder_combo) && GTK_WIDGET_DRAWABLE (impl->save_folder_combo)
6636- && GTK_IS_EXPANDER (impl->save_expander) && GTK_WIDGET_DRAWABLE (impl->save_expander)
6637 && GTK_IS_CONTAINER (impl->browse_widgets));
6638
6639 /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of
6640@@ -968,11 +962,6 @@
6641 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), base_dir);
6642 sleep_in_main_loop (500);
6643
6644- g_signal_emit_by_name (impl->browse_path_bar, "path-clicked",
6645- (GtkFilePath *) cwd_path,
6646- (GtkFilePath *) base_dir_path,
6647- FALSE);
6648- sleep_in_main_loop (500);
6649 passed = passed && (gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (dialog)) == txt_filter);
6650
6651 log_test (passed, "test_folder_switch_and_filters(): filter after changing folder");
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch
deleted file mode 100644
index 0de8e02dce..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/filechooser-respect-style.patch
+++ /dev/null
@@ -1,77 +0,0 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooserdialog.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooserdialog.c 2007-08-29 18:03:04.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooserdialog.c 2007-08-29 18:04:27.000000000 +0100
5@@ -50,8 +50,6 @@
6
7 static void gtk_file_chooser_dialog_map (GtkWidget *widget);
8 static void gtk_file_chooser_dialog_unmap (GtkWidget *widget);
9-static void gtk_file_chooser_dialog_style_set (GtkWidget *widget,
10- GtkStyle *previous_style);
11
12 static void response_cb (GtkDialog *dialog,
13 gint response_id);
14@@ -73,7 +71,6 @@
15
16 widget_class->map = gtk_file_chooser_dialog_map;
17 widget_class->unmap = gtk_file_chooser_dialog_unmap;
18- widget_class->style_set = gtk_file_chooser_dialog_style_set;
19
20 _gtk_file_chooser_install_properties (gobject_class);
21
22@@ -86,10 +83,16 @@
23 GtkFileChooserDialogPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
24 GTK_TYPE_FILE_CHOOSER_DIALOG,
25 GtkFileChooserDialogPrivate);
26+
27+ GtkDialog *fc_dialog = GTK_DIALOG (dialog);
28+
29 dialog->priv = priv;
30 dialog->priv->response_requested = FALSE;
31
32- gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
33+ gtk_dialog_set_has_separator (fc_dialog, FALSE);
34+ gtk_container_set_border_width (GTK_CONTAINER (fc_dialog), 5);
35+ gtk_box_set_spacing (GTK_BOX (fc_dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
36+ gtk_container_set_border_width (GTK_CONTAINER (fc_dialog->action_area), 5);
37
38 /* We do a signal connection here rather than overriding the method in
39 * class_init because GtkDialog::response is a RUN_LAST signal. We want *our*
40@@ -285,6 +288,7 @@
41 g_signal_connect (priv->widget, "response-requested",
42 G_CALLBACK (file_chooser_widget_response_requested), object);
43
44+ gtk_container_set_border_width (GTK_CONTAINER (priv->widget), 5);
45 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->widget, TRUE, TRUE, 0);
46
47 gtk_widget_show (priv->widget);
48@@ -414,29 +418,6 @@
49 gtk_widget_unmap (priv->widget);
50 }
51
52-static void
53-gtk_file_chooser_dialog_style_set (GtkWidget *widget,
54- GtkStyle *previous_style)
55-{
56- GtkDialog *dialog;
57-
58- if (GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->style_set)
59- GTK_WIDGET_CLASS (gtk_file_chooser_dialog_parent_class)->style_set (widget, previous_style);
60-
61- dialog = GTK_DIALOG (widget);
62-
63- /* Override the style properties with HIG-compliant spacings. Ugh.
64- * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
65- * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
66- */
67-
68- gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
69- gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
70-
71- gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
72- gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
73-}
74-
75 /* GtkDialog::response handler */
76 static void
77 response_cb (GtkDialog *dialog,
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch
deleted file mode 100644
index c22ccba377..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/filechooser-utils.patch
+++ /dev/null
@@ -1,32 +0,0 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooserutils.h
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooserutils.h 2007-08-24 08:37:40.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooserutils.h 2007-08-24 08:51:59.000000000 +0100
5@@ -41,7 +41,9 @@
6 GTK_FILE_CHOOSER_PROP_SELECT_MULTIPLE,
7 GTK_FILE_CHOOSER_PROP_SHOW_HIDDEN,
8 GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION,
9- GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION
10+ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
11+ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER,
12+ GTK_FILE_CHOOSER_PROP_LAST = GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER
13 } GtkFileChooserProp;
14
15 void _gtk_file_chooser_install_properties (GObjectClass *klass);
16Index: gtk+-2.10.14/gtk/gtkfilechooserutils.c
17===================================================================
18--- gtk+-2.10.14.orig/gtk/gtkfilechooserutils.c 2007-08-24 08:37:28.000000000 +0100
19+++ gtk+-2.10.14/gtk/gtkfilechooserutils.c 2007-08-24 08:51:47.000000000 +0100
20@@ -117,6 +117,12 @@
21 g_object_class_override_property (klass,
22 GTK_FILE_CHOOSER_PROP_DO_OVERWRITE_CONFIRMATION,
23 "do-overwrite-confirmation");
24+ g_object_class_override_property (klass,
25+ GTK_FILE_CHOOSER_PROP_ROOT_FOLDER,
26+ "root-folder");
27+ g_object_class_override_property (klass,
28+ GTK_FILE_CHOOSER_PROP_SHOW_CREATE_FOLDER,
29+ "show-create-folder");
30 }
31
32 /**
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filechooser.patch b/meta/packages/gtk+/gtk+-2.10.14/filechooser.patch
deleted file mode 100644
index bb09049865..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/filechooser.patch
+++ /dev/null
@@ -1,25 +0,0 @@
1Index: gtk+-2.10.14/gtk/gtkfilechooser.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilechooser.c 2007-08-24 08:52:32.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilechooser.c 2007-08-24 08:57:21.000000000 +0100
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 /**
diff --git a/meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch b/meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch
deleted file mode 100644
index ec15ea3f5d..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/filesystem-volumes.patch
+++ /dev/null
@@ -1,198 +0,0 @@
1Index: gtk+-2.10.14/gtk/gtkfilesystemunix.c
2===================================================================
3--- gtk+-2.10.14.orig/gtk/gtkfilesystemunix.c 2007-07-16 20:44:17.000000000 +0100
4+++ gtk+-2.10.14/gtk/gtkfilesystemunix.c 2007-08-24 08:29:43.000000000 +0100
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@@ -475,7 +476,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@@ -489,13 +538,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@@ -1143,7 +1197,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@@ -1177,7 +1231,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@@ -1265,10 +1344,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.10.14/gtklabel-resize-patch b/meta/packages/gtk+/gtk+-2.10.14/gtklabel-resize-patch
deleted file mode 100644
index df29656343..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/gtklabel-resize-patch
+++ /dev/null
@@ -1,10 +0,0 @@
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.10.14/hardcoded_libtool.patch b/meta/packages/gtk+/gtk+-2.10.14/hardcoded_libtool.patch
deleted file mode 100644
index 6adb0cfef6..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/hardcoded_libtool.patch
+++ /dev/null
@@ -1,29 +0,0 @@
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.10.14/menu-deactivate.patch b/meta/packages/gtk+/gtk+-2.10.14/menu-deactivate.patch
deleted file mode 100644
index cfb8849e9f..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/menu-deactivate.patch
+++ /dev/null
@@ -1,51 +0,0 @@
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.10.14/no-demos.patch b/meta/packages/gtk+/gtk+-2.10.14/no-demos.patch
deleted file mode 100644
index 0fc4c48d1a..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/no-demos.patch
+++ /dev/null
@@ -1,10 +0,0 @@
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.10.14/pangoxft2.10.6.diff b/meta/packages/gtk+/gtk+-2.10.14/pangoxft2.10.6.diff
deleted file mode 100644
index 63828cec63..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/pangoxft2.10.6.diff
+++ /dev/null
@@ -1,2456 +0,0 @@
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.10.14/range-no-redraw.patch b/meta/packages/gtk+/gtk+-2.10.14/range-no-redraw.patch
deleted file mode 100644
index e3603d7700..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/range-no-redraw.patch
+++ /dev/null
@@ -1,41 +0,0 @@
1Index: gtk/gtkrange.c
2===================================================================
3--- gtk/gtkrange.c (revision 18523)
4+++ gtk/gtkrange.c (working copy)
5@@ -99,6 +99,8 @@
6
7 GtkSensitivityType lower_sensitivity;
8 GtkSensitivityType upper_sensitivity;
9+
10+ guint motion_idle;
11 };
12
13
14@@ -1721,6 +1723,16 @@
15 &handled);
16 }
17
18+static gboolean
19+update_slider_position_idle (GtkRange *range)
20+{
21+ update_slider_position (range, range->layout->mouse_x,range->layout->mouse_y);
22+
23+ range->layout->motion_idle = 0;
24+
25+ return FALSE;
26+}
27+
28 static void
29 stop_scrolling (GtkRange *range)
30 {
31@@ -1860,8 +1872,8 @@
32 if (gtk_range_update_mouse_location (range))
33 gtk_widget_queue_draw (widget);
34
35- if (range->layout->grab_location == MOUSE_SLIDER)
36- update_slider_position (range, x, y);
37+ if (range->layout->grab_location == MOUSE_SLIDER && !range->layout->motion_idle)
38+ range->layout->motion_idle = g_idle_add ((GSourceFunc)update_slider_position_idle, range);
39
40 /* We handled the event if the mouse was in the range_rect */
41 return range->layout->mouse_location != MOUSE_OUTSIDE;
diff --git a/meta/packages/gtk+/gtk+-2.10.14/run-iconcache.patch b/meta/packages/gtk+/gtk+-2.10.14/run-iconcache.patch
deleted file mode 100644
index ac15e9ab24..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/run-iconcache.patch
+++ /dev/null
@@ -1,19 +0,0 @@
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.10.14/scrolled-placement.patch b/meta/packages/gtk+/gtk+-2.10.14/scrolled-placement.patch
deleted file mode 100644
index 09ded531ea..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/scrolled-placement.patch
+++ /dev/null
@@ -1,35 +0,0 @@
1Index: gtk/gtkscrolledwindow.c
2===================================================================
3--- gtk/gtkscrolledwindow.c (revision 18493)
4+++ gtk/gtkscrolledwindow.c (working copy)
5@@ -885,7 +885,7 @@
6 if (GTK_IS_SCROLLED_WINDOW (widget))
7 {
8 gtk_scrolled_window_update_real_placement (GTK_SCROLLED_WINDOW (widget));
9- gtk_widget_queue_draw (widget);
10+ gtk_widget_queue_resize (widget);
11 }
12 else if (GTK_IS_CONTAINER (widget))
13 gtk_container_forall (GTK_CONTAINER (widget), traverse_container, NULL);
14Index: gdk/x11/gdksettings.c
15===================================================================
16--- gdk/x11/gdksettings.c (revision 18493)
17+++ gdk/x11/gdksettings.c (working copy)
18@@ -65,7 +65,8 @@
19 "Xft/RGBA\0" "gtk-xft-rgba\0"
20 "Xft/DPI\0" "gtk-xft-dpi\0"
21 "Net/FallbackIconTheme\0" "gtk-fallback-icon-theme\0"
22- "Gtk/TouchscreenMode\0" "gtk-touchscreen-mode\0";
23+ "Gtk/TouchscreenMode\0" "gtk-touchscreen-mode\0"
24+ "Gtk/ScrolledWindowPlacement\0" "gtk-scrolled-window-placement\0";
25
26 static const struct
27 {
28@@ -107,5 +108,6 @@
29 { 1197, 1206 },
30 { 1219, 1227 },
31 { 1239, 1261 },
32- { 1285, 1305 }
33+ { 1285, 1305 },
34+ { 1326, 1354 }
35 };
diff --git a/meta/packages/gtk+/gtk+-2.10.14/toggle-font.diff b/meta/packages/gtk+/gtk+-2.10.14/toggle-font.diff
deleted file mode 100644
index 928da72430..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/toggle-font.diff
+++ /dev/null
@@ -1,100 +0,0 @@
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 12
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.10.14/xsettings.patch b/meta/packages/gtk+/gtk+-2.10.14/xsettings.patch
deleted file mode 100644
index b63e262d34..0000000000
--- a/meta/packages/gtk+/gtk+-2.10.14/xsettings.patch
+++ /dev/null
@@ -1,16 +0,0 @@
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.3/cellrenderer-cairo.patch b/meta/packages/gtk+/gtk+-2.13.3/cellrenderer-cairo.patch
deleted file mode 100644
index 4439e69fb6..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/cellrenderer-cairo.patch
+++ /dev/null
@@ -1,32 +0,0 @@
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.3/combo-arrow-size.patch b/meta/packages/gtk+/gtk+-2.13.3/combo-arrow-size.patch
deleted file mode 100644
index d44c454ce3..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/combo-arrow-size.patch
+++ /dev/null
@@ -1,67 +0,0 @@
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.3/entry-cairo.patch b/meta/packages/gtk+/gtk+-2.13.3/entry-cairo.patch
deleted file mode 100644
index 3313e7f132..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/entry-cairo.patch
+++ /dev/null
@@ -1,103 +0,0 @@
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.3/filechooser-default.patch b/meta/packages/gtk+/gtk+-2.13.3/filechooser-default.patch
deleted file mode 100644
index 146316c9c1..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/filechooser-default.patch
+++ /dev/null
@@ -1,9521 +0,0 @@
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.3/filechooser-props.patch b/meta/packages/gtk+/gtk+-2.13.3/filechooser-props.patch
deleted file mode 100644
index 7d55f3cbb9..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/filechooser-props.patch
+++ /dev/null
@@ -1,57 +0,0 @@
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.3/filechooser-sizefix.patch b/meta/packages/gtk+/gtk+-2.13.3/filechooser-sizefix.patch
deleted file mode 100644
index 694b059b9a..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/filechooser-sizefix.patch
+++ /dev/null
@@ -1,35 +0,0 @@
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.3/filesystem-volumes.patch b/meta/packages/gtk+/gtk+-2.13.3/filesystem-volumes.patch
deleted file mode 100644
index 826fd6bee0..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/filesystem-volumes.patch
+++ /dev/null
@@ -1,198 +0,0 @@
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.3/gtklabel-resize-patch b/meta/packages/gtk+/gtk+-2.13.3/gtklabel-resize-patch
deleted file mode 100644
index df29656343..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/gtklabel-resize-patch
+++ /dev/null
@@ -1,10 +0,0 @@
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.3/hardcoded_libtool.patch b/meta/packages/gtk+/gtk+-2.13.3/hardcoded_libtool.patch
deleted file mode 100644
index 1c2cd0576d..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/hardcoded_libtool.patch
+++ /dev/null
@@ -1,29 +0,0 @@
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.3/menu-deactivate.patch b/meta/packages/gtk+/gtk+-2.13.3/menu-deactivate.patch
deleted file mode 100644
index cfb8849e9f..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/menu-deactivate.patch
+++ /dev/null
@@ -1,51 +0,0 @@
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.3/no-demos.patch b/meta/packages/gtk+/gtk+-2.13.3/no-demos.patch
deleted file mode 100644
index 0fc4c48d1a..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/no-demos.patch
+++ /dev/null
@@ -1,10 +0,0 @@
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.3/pangoxft2.10.6.diff b/meta/packages/gtk+/gtk+-2.13.3/pangoxft2.10.6.diff
deleted file mode 100644
index 63828cec63..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/pangoxft2.10.6.diff
+++ /dev/null
@@ -1,2456 +0,0 @@
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.3/range-no-redraw.patch b/meta/packages/gtk+/gtk+-2.13.3/range-no-redraw.patch
deleted file mode 100644
index 14387b8a2e..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/range-no-redraw.patch
+++ /dev/null
@@ -1,127 +0,0 @@
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.3/run-iconcache.patch b/meta/packages/gtk+/gtk+-2.13.3/run-iconcache.patch
deleted file mode 100644
index ac15e9ab24..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/run-iconcache.patch
+++ /dev/null
@@ -1,19 +0,0 @@
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.3/toggle-font.diff b/meta/packages/gtk+/gtk+-2.13.3/toggle-font.diff
deleted file mode 100644
index 59ad150b2f..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/toggle-font.diff
+++ /dev/null
@@ -1,100 +0,0 @@
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.3/xsettings.patch b/meta/packages/gtk+/gtk+-2.13.3/xsettings.patch
deleted file mode 100644
index b63e262d34..0000000000
--- a/meta/packages/gtk+/gtk+-2.13.3/xsettings.patch
+++ /dev/null
@@ -1,16 +0,0 @@
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.10.14.bb b/meta/packages/gtk+/gtk+_2.10.14.bb
deleted file mode 100644
index 2bc7217d49..0000000000
--- a/meta/packages/gtk+/gtk+_2.10.14.bb
+++ /dev/null
@@ -1,50 +0,0 @@
1require gtk+.inc
2
3PR = "r20"
4
5SRC_URI = "ftp://ftp.gtk.org/pub/gtk/v2.10/gtk+-${PV}.tar.bz2 \
6 file://gtklabel-resize-patch;patch=1 \
7 file://menu-deactivate.patch;patch=1 \
8 file://run-iconcache.patch;patch=1 \
9 file://disable-print.patch;patch=1 \
10 file://hardcoded_libtool.patch;patch=1 \
11 file://no-demos.patch;patch=1 \
12 file://cellrenderer-cairo.patch;patch=1;pnum=0 \
13 file://entry-cairo.patch;patch=1;pnum=0 \
14 file://toggle-font.diff;patch=1;pnum=0 \
15 file://combo-arrow-size.patch;patch=1;pnum=0 \
16 file://range-no-redraw.patch;patch=1;pnum=0 \
17 file://scrolled-placement.patch;patch=1;pnum=0 \
18 file://filesystem-volumes.patch;patch=1 \
19 file://filechooser-utils.patch;patch=1 \
20 file://filechooser.patch;patch=1 \
21 file://filechooser-default.patch;patch=1 \
22 file://filechooser-respect-style.patch;patch=1"
23#file://xsettings.patch;patch=1 \
24#file://pangoxft2.10.6.diff;patch=1"
25
26
27EXTRA_OECONF = "--without-libtiff --disable-xkb --disable-glibtest --enable-display-migration"
28
29LIBV = "2.10.0"
30
31PACKAGES_DYNAMIC = "gdk-pixbuf-loader-* gtk-immodule-* gtk-printbackend-*"
32
33python populate_packages_prepend () {
34 import os.path
35
36 prologue = bb.data.getVar("postinst_prologue", d, 1)
37 postinst_pixbufloader = bb.data.getVar("postinst_pixbufloader", d, 1)
38
39 gtk_libdir = bb.data.expand('${libdir}/gtk-2.0/${LIBV}', d)
40 loaders_root = os.path.join(gtk_libdir, 'loaders')
41 immodules_root = os.path.join(gtk_libdir, 'immodules')
42 printmodules_root = os.path.join(gtk_libdir, 'printbackends');
43
44 do_split_packages(d, loaders_root, '^libpixbufloader-(.*)\.so$', 'gdk-pixbuf-loader-%s', 'GDK pixbuf loader for %s', postinst_pixbufloader)
45 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')
46 do_split_packages(d, printmodules_root, '^libprintbackend-(.*)\.so$', 'gtk-printbackend-%s', 'GTK printbackend module for %s')
47
48 if (bb.data.getVar('DEBIAN_NAMES', d, 1)):
49 bb.data.setVar('PKG_${PN}', 'libgtk-2.0', d)
50}
diff --git a/meta/packages/gtk+/gtk+_2.13.3.bb b/meta/packages/gtk+/gtk+_2.13.3.bb
deleted file mode 100644
index 8797550597..0000000000
--- a/meta/packages/gtk+/gtk+_2.13.3.bb
+++ /dev/null
@@ -1,47 +0,0 @@
1require gtk+.inc
2
3PR = "r1"
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# TO MERGE
14# file://filesystem-volumes.patch;patch=1 \
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}