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