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