1 /* vi:set et ai sw=2 sts=2 ts=2: */
2 /*-
3 * Copyright (c) 2005-2007 Benedikt Meurer <benny@xfce.org>
4 * Copyright (c) 2009-2011 Jannis Pohlmann <jannis@xfce.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29 #ifdef HAVE_LOCALE_H
30 #include <locale.h>
31 #endif
32
33 #include <gdk/gdkkeysyms.h>
34
35 #include <thunar/thunar-application.h>
36 #include <thunar/thunar-browser.h>
37 #include <thunar/thunar-clipboard-manager.h>
38 #include <thunar/thunar-compact-view.h>
39 #include <thunar/thunar-details-view.h>
40 #include <thunar/thunar-dialogs.h>
41 #include <thunar/thunar-shortcuts-pane.h>
42 #include <thunar/thunar-gio-extensions.h>
43 #include <thunar/thunar-gobject-extensions.h>
44 #include <thunar/thunar-gtk-extensions.h>
45 #include <thunar/thunar-history.h>
46 #include <thunar/thunar-icon-view.h>
47 #include <thunar/thunar-launcher.h>
48 #include <thunar/thunar-location-buttons.h>
49 #include <thunar/thunar-location-entry.h>
50 #include <thunar/thunar-marshal.h>
51 #include <thunar/thunar-menu.h>
52 #include <thunar/thunar-pango-extensions.h>
53 #include <thunar/thunar-preferences-dialog.h>
54 #include <thunar/thunar-preferences.h>
55 #include <thunar/thunar-private.h>
56 #include <thunar/thunar-util.h>
57 #include <thunar/thunar-statusbar.h>
58 #include <thunar/thunar-tree-pane.h>
59 #include <thunar/thunar-window.h>
60 #include <thunar/thunar-device-monitor.h>
61
62 #include <glib.h>
63
64
65
66 /* Property identifiers */
67 enum
68 {
69 PROP_0,
70 PROP_CURRENT_DIRECTORY,
71 PROP_ZOOM_LEVEL,
72 PROP_DIRECTORY_SPECIFIC_SETTINGS,
73 };
74
75 /* Signal identifiers */
76 enum
77 {
78 BACK,
79 RELOAD,
80 TOGGLE_SIDEPANE,
81 TOGGLE_MENUBAR,
82 ZOOM_IN,
83 ZOOM_OUT,
84 ZOOM_RESET,
85 TAB_CHANGE,
86 LAST_SIGNAL,
87 };
88
89 struct _ThunarBookmark
90 {
91 GFile *g_file;
92 gchar *name;
93 };
94 typedef struct _ThunarBookmark ThunarBookmark;
95
96
97
98 static void thunar_window_screen_changed (GtkWidget *widget,
99 GdkScreen *old_screen,
100 gpointer userdata);
101 static void thunar_window_dispose (GObject *object);
102 static void thunar_window_finalize (GObject *object);
103 static gboolean thunar_window_delete (GtkWidget *widget,
104 GdkEvent *event,
105 gpointer data);
106 static void thunar_window_get_property (GObject *object,
107 guint prop_id,
108 GValue *value,
109 GParamSpec *pspec);
110 static void thunar_window_set_property (GObject *object,
111 guint prop_id,
112 const GValue *value,
113 GParamSpec *pspec);
114 static gboolean thunar_window_reload (ThunarWindow *window,
115 gboolean reload_info);
116 static gboolean thunar_window_toggle_sidepane (ThunarWindow *window);
117 static gboolean thunar_window_zoom_in (ThunarWindow *window);
118 static gboolean thunar_window_zoom_out (ThunarWindow *window);
119 static gboolean thunar_window_zoom_reset (ThunarWindow *window);
120 static gboolean thunar_window_tab_change (ThunarWindow *window,
121 gint nth);
122 static void thunar_window_realize (GtkWidget *widget);
123 static void thunar_window_unrealize (GtkWidget *widget);
124 static gboolean thunar_window_configure_event (GtkWidget *widget,
125 GdkEventConfigure *event);
126 static void thunar_window_notebook_switch_page (GtkWidget *notebook,
127 GtkWidget *page,
128 guint page_num,
129 ThunarWindow *window);
130 static void thunar_window_notebook_page_added (GtkWidget *notebook,
131 GtkWidget *page,
132 guint page_num,
133 ThunarWindow *window);
134 static void thunar_window_notebook_page_removed (GtkWidget *notebook,
135 GtkWidget *page,
136 guint page_num,
137 ThunarWindow *window);
138 static gboolean thunar_window_notebook_button_press_event(GtkWidget *notebook,
139 GdkEventButton *event,
140 ThunarWindow *window);
141 static gboolean thunar_window_notebook_popup_menu (GtkWidget *notebook,
142 ThunarWindow *window);
143 static gpointer thunar_window_notebook_create_window (GtkWidget *notebook,
144 GtkWidget *page,
145 gint x,
146 gint y,
147 ThunarWindow *window);
148 static GtkWidget*thunar_window_notebook_insert (ThunarWindow *window,
149 ThunarFile *directory,
150 GType view_type,
151 gint position,
152 ThunarHistory *history);
153 static void thunar_window_update_location_bar_visible(ThunarWindow *window);
154 static void thunar_window_handle_reload_request (ThunarWindow *window);
155 static void thunar_window_install_sidepane (ThunarWindow *window,
156 GType type);
157 static void thunar_window_start_open_location (ThunarWindow *window,
158 const gchar *initial_text);
159 static void thunar_window_action_open_new_tab (ThunarWindow *window,
160 GtkWidget *menu_item);
161 static void thunar_window_action_open_new_window (ThunarWindow *window,
162 GtkWidget *menu_item);
163 static void thunar_window_action_detach_tab (ThunarWindow *window,
164 GtkWidget *menu_item);
165 static void thunar_window_action_close_all_windows (ThunarWindow *window,
166 GtkWidget *menu_item);
167 static void thunar_window_action_close_tab (ThunarWindow *window,
168 GtkWidget *menu_item);
169 static void thunar_window_action_close_window (ThunarWindow *window,
170 GtkWidget *menu_item);
171 static void thunar_window_action_preferences (ThunarWindow *window,
172 GtkWidget *menu_item);
173 static void thunar_window_action_reload (ThunarWindow *window,
174 GtkWidget *menu_item);
175 static void thunar_window_action_switch_next_tab (ThunarWindow *window);
176 static void thunar_window_action_switch_previous_tab (ThunarWindow *window);
177 static void thunar_window_action_pathbar_changed (ThunarWindow *window);
178 static void thunar_window_action_toolbar_changed (ThunarWindow *window);
179 static void thunar_window_action_shortcuts_changed (ThunarWindow *window);
180 static void thunar_window_action_tree_changed (ThunarWindow *window);
181 static void thunar_window_action_statusbar_changed (ThunarWindow *window);
182 static void thunar_window_action_menubar_update (ThunarWindow *window);
183 static void thunar_window_action_menubar_changed (ThunarWindow *window);
184 static void thunar_window_action_detailed_view (ThunarWindow *window);
185 static void thunar_window_action_icon_view (ThunarWindow *window);
186 static void thunar_window_action_compact_view (ThunarWindow *window);
187 static void thunar_window_replace_view (ThunarWindow *window,
188 GtkWidget *view,
189 GType view_type);
190 static void thunar_window_action_view_changed (ThunarWindow *window,
191 GType view_type);
192 static void thunar_window_action_go_up (ThunarWindow *window);
193 static void thunar_window_action_back (ThunarWindow *window);
194 static void thunar_window_action_forward (ThunarWindow *window);
195 static void thunar_window_action_open_home (ThunarWindow *window);
196 static void thunar_window_action_open_desktop (ThunarWindow *window);
197 static void thunar_window_action_open_computer (ThunarWindow *window);
198 static void thunar_window_action_open_templates (ThunarWindow *window);
199 static void thunar_window_action_open_file_system (ThunarWindow *window);
200 static void thunar_window_action_open_trash (ThunarWindow *window);
201 static void thunar_window_action_open_network (ThunarWindow *window);
202 static void thunar_window_action_open_bookmark (GFile *g_file);
203 static void thunar_window_action_open_location (ThunarWindow *window);
204 static void thunar_window_action_contents (ThunarWindow *window);
205 static void thunar_window_action_about (ThunarWindow *window);
206 static void thunar_window_action_show_hidden (ThunarWindow *window);
207 static gboolean thunar_window_propagate_key_event (GtkWindow *window,
208 GdkEvent *key_event,
209 gpointer user_data);
210 static void thunar_window_action_open_file_menu (ThunarWindow *window);
211 static void thunar_window_current_directory_changed (ThunarFile *current_directory,
212 ThunarWindow *window);
213 static void thunar_window_menu_item_selected (ThunarWindow *window,
214 GtkWidget *menu_item);
215 static void thunar_window_menu_item_deselected (ThunarWindow *window,
216 GtkWidget *menu_item);
217 static void thunar_window_notify_loading (ThunarView *view,
218 GParamSpec *pspec,
219 ThunarWindow *window);
220 static void thunar_window_device_pre_unmount (ThunarDeviceMonitor *device_monitor,
221 ThunarDevice *device,
222 GFile *root_file,
223 ThunarWindow *window);
224 static void thunar_window_device_changed (ThunarDeviceMonitor *device_monitor,
225 ThunarDevice *device,
226 ThunarWindow *window);
227 static gboolean thunar_window_save_paned (ThunarWindow *window);
228 static gboolean thunar_window_save_geometry_timer (gpointer user_data);
229 static void thunar_window_save_geometry_timer_destroy(gpointer user_data);
230 static void thunar_window_set_zoom_level (ThunarWindow *window,
231 ThunarZoomLevel zoom_level);
232 static void thunar_window_update_window_icon (ThunarWindow *window);
233 static void thunar_window_create_menu (ThunarWindow *window,
234 ThunarWindowAction action,
235 GCallback cb_update_menu);
236 static void thunar_window_update_file_menu (ThunarWindow *window,
237 GtkWidget *menu);
238 static void thunar_window_update_edit_menu (ThunarWindow *window,
239 GtkWidget *menu);
240 static void thunar_window_update_view_menu (ThunarWindow *window,
241 GtkWidget *menu);
242 static void thunar_window_update_go_menu (ThunarWindow *window,
243 GtkWidget *menu);
244 static void thunar_window_update_help_menu (ThunarWindow *window,
245 GtkWidget *menu);
246 static void thunar_window_binding_create (ThunarWindow *window,
247 gpointer src_object,
248 const gchar *src_prop,
249 gpointer dst_object,
250 const gchar *dst_prop,
251 GBindingFlags flags);
252 static gboolean thunar_window_history_clicked (GtkWidget *button,
253 GdkEventButton *event,
254 GtkWidget *window);
255 static gboolean thunar_window_button_press_event (GtkWidget *view,
256 GdkEventButton *event,
257 ThunarWindow *window);
258 static void thunar_window_history_changed (ThunarWindow *window);
259 static void thunar_window_update_bookmarks (ThunarWindow *window);
260 static void thunar_window_free_bookmarks (ThunarWindow *window);
261 static void thunar_window_menu_add_bookmarks (ThunarWindow *window,
262 GtkMenuShell *view_menu);
263 static gboolean thunar_window_check_uca_key_activation (ThunarWindow *window,
264 GdkEventKey *key_event,
265 gpointer user_data);
266 static void thunar_window_set_directory_specific_settings (ThunarWindow *window,
267 gboolean directory_specific_settings);
268 static void thunar_window_set_current_directory_gfile (ThunarWindow *window,
269 GFile *current_directory);
270 static GType thunar_window_view_type_for_directory (ThunarWindow *window,
271 ThunarFile *directory);
272 static void thunar_window_action_clear_directory_specific_settings (ThunarWindow *window);
273
274
275
276 struct _ThunarWindowClass
277 {
278 GtkWindowClass __parent__;
279
280 /* internal action signals */
281 gboolean (*reload) (ThunarWindow *window,
282 gboolean reload_info);
283 gboolean (*zoom_in) (ThunarWindow *window);
284 gboolean (*zoom_out) (ThunarWindow *window);
285 gboolean (*zoom_reset) (ThunarWindow *window);
286 gboolean (*tab_change) (ThunarWindow *window,
287 gint idx);
288 };
289
290 struct _ThunarWindow
291 {
292 GtkWindow __parent__;
293
294 /* support for custom preferences actions */
295 ThunarxProviderFactory *provider_factory;
296 GList *thunarx_preferences_providers;
297
298 GFile *bookmark_file;
299 GList *bookmarks;
300 GFileMonitor *bookmark_monitor;
301
302 ThunarClipboardManager *clipboard;
303
304 ThunarPreferences *preferences;
305
306 ThunarIconFactory *icon_factory;
307
308 /* to be able to change folder on "device-pre-unmount" if required */
309 ThunarDeviceMonitor *device_monitor;
310
311 GtkWidget *grid;
312 GtkWidget *menubar;
313 GtkWidget *spinner;
314 GtkWidget *paned;
315 GtkWidget *sidepane;
316 GtkWidget *view_box;
317 GtkWidget *notebook;
318 GtkWidget *view;
319 GtkWidget *statusbar;
320
321 GType view_type;
322 GSList *view_bindings;
323
324 /* support for two different styles of location bars */
325 GtkWidget *location_bar;
326 GtkWidget *location_toolbar;
327
328 /* we need to maintain pointers to be able to toggle sensitivity */
329 GtkWidget *location_toolbar_item_back;
330 GtkWidget *location_toolbar_item_forward;
331 GtkWidget *location_toolbar_item_parent;
332
333 ThunarLauncher *launcher;
334
335 gulong signal_handler_id_history_changed;
336
337 ThunarFile *current_directory;
338 GtkAccelGroup *accel_group;
339
340 /* zoom-level support */
341 ThunarZoomLevel zoom_level;
342
343 gboolean show_hidden;
344
345 gboolean directory_specific_settings;
346
347 /* support to remember window geometry */
348 guint save_geometry_timer_id;
349
350 /* support to toggle side pane using F9,
351 * see the toggle_sidepane() function.
352 */
353 GType toggle_sidepane_type;
354
355 /* Takes care to select a file after e.g. rename/create */
356 GClosure *select_files_closure;
357 };
358
359
360
361 static XfceGtkActionEntry thunar_window_action_entries[] =
362 {
363 { THUNAR_WINDOW_ACTION_FILE_MENU, "<Actions>/ThunarWindow/file-menu", "", XFCE_GTK_MENU_ITEM, N_ ("_File"), NULL, NULL, NULL,},
364 { THUNAR_WINDOW_ACTION_NEW_TAB, "<Actions>/ThunarWindow/new-tab", "<Primary>t", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("New _Tab"), N_ ("Open a new tab for the displayed location"), "tab-new", G_CALLBACK (thunar_window_action_open_new_tab), },
365 { THUNAR_WINDOW_ACTION_NEW_WINDOW, "<Actions>/ThunarWindow/new-window", "<Primary>n", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("New _Window"), N_ ("Open a new Thunar window for the displayed location"), "window-new", G_CALLBACK (thunar_window_action_open_new_window), },
366 { THUNAR_WINDOW_ACTION_DETACH_TAB, "<Actions>/ThunarWindow/detach-tab", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Detac_h Tab"), N_ ("Open current folder in a new window"), NULL, G_CALLBACK (thunar_window_action_detach_tab), },
367 { THUNAR_WINDOW_ACTION_CLOSE_TAB, "<Actions>/ThunarWindow/close-tab", "<Primary>w", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("C_lose Tab"), N_ ("Close this folder"), "window-close", G_CALLBACK (thunar_window_action_close_tab), },
368 { THUNAR_WINDOW_ACTION_CLOSE_WINDOW, "<Actions>/ThunarWindow/close-window", "<Primary>q", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Close Window"), N_ ("Close this window"), "application-exit", G_CALLBACK (thunar_window_action_close_window), },
369 { THUNAR_WINDOW_ACTION_CLOSE_ALL_WINDOWS, "<Actions>/ThunarWindow/close-all-windows", "<Primary><Shift>w", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Close _All Windows"), N_ ("Close all Thunar windows"), NULL, G_CALLBACK (thunar_window_action_close_all_windows), },
370
371 { THUNAR_WINDOW_ACTION_EDIT_MENU, "<Actions>/ThunarWindow/edit-menu", "", XFCE_GTK_MENU_ITEM, N_ ("_Edit"), NULL, NULL, NULL, },
372 { THUNAR_WINDOW_ACTION_PREFERENCES, "<Actions>/ThunarWindow/preferences", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Pr_eferences..."), N_ ("Edit Thunars Preferences"), "preferences-system", G_CALLBACK (thunar_window_action_preferences), },
373
374 { THUNAR_WINDOW_ACTION_VIEW_MENU, "<Actions>/ThunarWindow/view-menu", "", XFCE_GTK_MENU_ITEM, N_ ("_View"), NULL, NULL, NULL, },
375 { THUNAR_WINDOW_ACTION_RELOAD, "<Actions>/ThunarWindow/reload", "<Primary>r", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Reload"), N_ ("Reload the current folder"), "view-refresh-symbolic", G_CALLBACK (thunar_window_action_reload), },
376 { THUNAR_WINDOW_ACTION_RELOAD_ALT, "<Actions>/ThunarWindow/reload-alt", "F5", XFCE_GTK_IMAGE_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_action_reload), },
377 { THUNAR_WINDOW_ACTION_VIEW_LOCATION_SELECTOR_MENU, "<Actions>/ThunarWindow/view-location-selector-menu", "", XFCE_GTK_MENU_ITEM, N_ ("_Location Selector"), NULL, NULL, NULL, },
378 { THUNAR_WINDOW_ACTION_VIEW_LOCATION_SELECTOR_PATHBAR, "<Actions>/ThunarWindow/view-location-selector-pathbar", "", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Pathbar Style"), N_ ("Modern approach with buttons that correspond to folders"), NULL, G_CALLBACK (thunar_window_action_pathbar_changed), },
379 { THUNAR_WINDOW_ACTION_VIEW_LOCATION_SELECTOR_TOOLBAR, "<Actions>/ThunarWindow/view-location-selector-toolbar", "", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Toolbar Style"), N_ ("Traditional approach with location bar and navigation buttons"), NULL, G_CALLBACK (thunar_window_action_toolbar_changed), },
380 { THUNAR_WINDOW_ACTION_VIEW_SIDE_PANE_MENU, "<Actions>/ThunarWindow/view-side-pane-menu", "", XFCE_GTK_MENU_ITEM, N_ ("_Side Pane"), NULL, NULL, NULL, },
381 { THUNAR_WINDOW_ACTION_VIEW_SIDE_PANE_SHORTCUTS, "<Actions>/ThunarWindow/view-side-pane-shortcuts", "<Primary>b", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Shortcuts"), N_ ("Toggles the visibility of the shortcuts pane"), NULL, G_CALLBACK (thunar_window_action_shortcuts_changed), },
382 { THUNAR_WINDOW_ACTION_VIEW_SIDE_PANE_TREE, "<Actions>/ThunarWindow/view-side-pane-tree", "<Primary>e", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Tree"), N_ ("Toggles the visibility of the tree pane"), NULL, G_CALLBACK (thunar_window_action_tree_changed), },
383 { THUNAR_WINDOW_ACTION_TOGGLE_SIDE_PANE, "<Actions>/ThunarWindow/toggle-side-pane", "F9", XFCE_GTK_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_toggle_sidepane), },
384 { THUNAR_WINDOW_ACTION_VIEW_STATUSBAR, "<Actions>/ThunarWindow/view-statusbar", "", XFCE_GTK_CHECK_MENU_ITEM, N_ ("St_atusbar"), N_ ("Change the visibility of this window's statusbar"), NULL, G_CALLBACK (thunar_window_action_statusbar_changed), },
385 { THUNAR_WINDOW_ACTION_VIEW_MENUBAR, "<Actions>/ThunarWindow/view-menubar", "<Primary>m", XFCE_GTK_CHECK_MENU_ITEM, N_ ("_Menubar"), N_ ("Change the visibility of this window's menubar"), NULL, G_CALLBACK (thunar_window_action_menubar_changed), },
386 { THUNAR_WINDOW_ACTION_SHOW_HIDDEN, "<Actions>/ThunarWindow/show-hidden", "<Primary>h", XFCE_GTK_CHECK_MENU_ITEM, N_ ("Show _Hidden Files"), N_ ("Toggles the display of hidden files in the current window"), NULL, G_CALLBACK (thunar_window_action_show_hidden), },
387 { THUNAR_WINDOW_ACTION_ZOOM_IN, "<Actions>/ThunarWindow/zoom-in", "<Primary>KP_Add", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Zoom I_n"), N_ ("Show the contents in more detail"), "zoom-in-symbolic", G_CALLBACK (thunar_window_zoom_in), },
388 { THUNAR_WINDOW_ACTION_ZOOM_IN_ALT_1, "<Actions>/ThunarWindow/zoom-in-alt1", "<Primary>plus", XFCE_GTK_IMAGE_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_zoom_in), },
389 { THUNAR_WINDOW_ACTION_ZOOM_IN_ALT_2, "<Actions>/ThunarWindow/zoom-in-alt2", "<Primary>equal", XFCE_GTK_IMAGE_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_zoom_in), },
390 { THUNAR_WINDOW_ACTION_ZOOM_OUT, "<Actions>/ThunarWindow/zoom-out", "<Primary>KP_Subtract", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Zoom _Out"), N_ ("Show the contents in less detail"), "zoom-out-symbolic", G_CALLBACK (thunar_window_zoom_out), },
391 { THUNAR_WINDOW_ACTION_ZOOM_OUT_ALT, "<Actions>/ThunarWindow/zoom-out-alt", "<Primary>minus", XFCE_GTK_IMAGE_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_zoom_out), },
392 { THUNAR_WINDOW_ACTION_ZOOM_RESET, "<Actions>/ThunarWindow/zoom-reset", "<Primary>KP_0", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Normal Si_ze"), N_ ("Show the contents at the normal size"), "zoom-original-symbolic", G_CALLBACK (thunar_window_zoom_reset), },
393 { THUNAR_WINDOW_ACTION_ZOOM_RESET_ALT, "<Actions>/ThunarWindow/zoom-reset-alt", "<Primary>0", XFCE_GTK_IMAGE_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_zoom_reset), },
394 { THUNAR_WINDOW_ACTION_CLEAR_DIRECTORY_SPECIFIC_SETTINGS,"<Actions>/ThunarWindow/clear-directory-specific-settings","", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Clear Saved _Folder View Settings"), N_ ("Delete saved view settings for this folder"), NULL, G_CALLBACK (thunar_window_action_clear_directory_specific_settings), },
395 { THUNAR_WINDOW_ACTION_VIEW_AS_ICONS, "<Actions>/ThunarWindow/view-as-icons", "<Primary>1", XFCE_GTK_RADIO_MENU_ITEM, N_ ("_Icon View"), N_ ("Display folder content in an icon view"), NULL, G_CALLBACK (thunar_window_action_icon_view), },
396 { THUNAR_WINDOW_ACTION_VIEW_AS_DETAILED_LIST, "<Actions>/ThunarWindow/view-as-detailed-list", "<Primary>2", XFCE_GTK_RADIO_MENU_ITEM, N_ ("_List View"), N_ ("Display folder content in a detailed list view"), NULL, G_CALLBACK (thunar_window_action_detailed_view), },
397 { THUNAR_WINDOW_ACTION_VIEW_AS_COMPACT_LIST, "<Actions>/ThunarWindow/view-as-compact-list", "<Primary>3", XFCE_GTK_RADIO_MENU_ITEM, N_ ("_Compact View"), N_ ("Display folder content in a compact list view"), NULL, G_CALLBACK (thunar_window_action_compact_view), },
398
399 { THUNAR_WINDOW_ACTION_GO_MENU, "<Actions>/ThunarWindow/go-menu", "", XFCE_GTK_MENU_ITEM, N_ ("_Go"), NULL, NULL, NULL },
400 { THUNAR_WINDOW_ACTION_OPEN_FILE_SYSTEM, "<Actions>/ThunarWindow/open-file-system", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("File System"), N_ ("Browse the file system"), "drive-harddisk", G_CALLBACK (thunar_window_action_open_file_system), },
401 { THUNAR_WINDOW_ACTION_OPEN_COMPUTER, "<Actions>/ThunarWindow/open-computer", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Computer"), N_ ("Go to the computer folder"), "computer", G_CALLBACK (thunar_window_action_open_computer), },
402 { THUNAR_WINDOW_ACTION_OPEN_HOME, "<Actions>/ThunarWindow/open-home", "<Alt>Home", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Home"), N_ ("Go to the home folder"), "go-home-symbolic", G_CALLBACK (thunar_window_action_open_home), },
403 { THUNAR_WINDOW_ACTION_OPEN_DESKTOP, "<Actions>/ThunarWindow/open-desktop", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Desktop"), N_ ("Go to the desktop folder"), "user-desktop", G_CALLBACK (thunar_window_action_open_desktop), },
404 { THUNAR_WINDOW_ACTION_OPEN_COMPUTER, "<Actions>/ThunarWindow/open-computer", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Computer"), N_ ("Browse all local and remote disks and folders accessible from this computer"), "computer", G_CALLBACK (thunar_window_action_open_computer), },
405 { THUNAR_WINDOW_ACTION_OPEN_TRASH, "<Actions>/ThunarWindow/open-trash", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("T_rash"), N_ ("Display the contents of the trash can"), NULL, G_CALLBACK (thunar_window_action_open_trash), },
406 { THUNAR_WINDOW_ACTION_OPEN_PARENT, "<Actions>/ThunarWindow/open-parent", "<Alt>Up", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Open _Parent"), N_ ("Open the parent folder"), "go-up-symbolic", G_CALLBACK (thunar_window_action_go_up), },
407 { THUNAR_WINDOW_ACTION_OPEN_LOCATION, "<Actions>/ThunarWindow/open-location", "<Primary>l", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Open Location..."), N_ ("Specify a location to open"), NULL, G_CALLBACK (thunar_window_action_open_location), },
408 { THUNAR_WINDOW_ACTION_OPEN_LOCATION_ALT, "<Actions>/ThunarWindow/open-location-alt", "<Alt>d", XFCE_GTK_MENU_ITEM, "open-location-alt", NULL, NULL, G_CALLBACK (thunar_window_action_open_location), },
409 { THUNAR_WINDOW_ACTION_OPEN_TEMPLATES, "<Actions>/ThunarWindow/open-templates", "", XFCE_GTK_IMAGE_MENU_ITEM, N_("T_emplates"), N_ ("Go to the templates folder"), "text-x-generic-template", G_CALLBACK (thunar_window_action_open_templates), },
410 { THUNAR_WINDOW_ACTION_OPEN_NETWORK, "<Actions>/ThunarWindow/open-network", "", XFCE_GTK_IMAGE_MENU_ITEM, N_("B_rowse Network"), N_ ("Browse local network connections"), "network-workgroup", G_CALLBACK (thunar_window_action_open_network), },
411
412 { THUNAR_WINDOW_ACTION_HELP_MENU, "<Actions>/ThunarWindow/contents/help-menu", "", XFCE_GTK_MENU_ITEM , N_ ("_Help"), NULL, NULL, NULL},
413 { THUNAR_WINDOW_ACTION_CONTENTS, "<Actions>/ThunarWindow/contents", "F1", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Contents"), N_ ("Display Thunar user manual"), "help-browser", G_CALLBACK (thunar_window_action_contents), },
414 { THUNAR_WINDOW_ACTION_ABOUT, "<Actions>/ThunarWindow/about", "", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_About"), N_ ("Display information about Thunar"), "help-about", G_CALLBACK (thunar_window_action_about), },
415 { THUNAR_WINDOW_ACTION_BACK, "<Actions>/ThunarStandardView/back", "<Alt>Left", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Back"), N_ ("Go to the previous visited folder"), "go-previous-symbolic", G_CALLBACK (thunar_window_action_back), },
416 { THUNAR_WINDOW_ACTION_BACK_ALT, "<Actions>/ThunarStandardView/back-alt", "BackSpace", XFCE_GTK_IMAGE_MENU_ITEM, NULL, NULL, NULL, G_CALLBACK (thunar_window_action_back), },
417 { THUNAR_WINDOW_ACTION_FORWARD, "<Actions>/ThunarStandardView/forward", "<Alt>Right", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("Forward"), N_ ("Go to the next visited folder"), "go-next-symbolic", G_CALLBACK (thunar_window_action_forward), },
418 { THUNAR_WINDOW_ACTION_SWITCH_PREV_TAB, "<Actions>/ThunarWindow/switch-previous-tab", "<Primary>Page_Up", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Previous Tab"), N_ ("Switch to Previous Tab"), "go-previous", G_CALLBACK (thunar_window_action_switch_previous_tab), },
419 { THUNAR_WINDOW_ACTION_SWITCH_NEXT_TAB, "<Actions>/ThunarWindow/switch-next-tab", "<Primary>Page_Down", XFCE_GTK_IMAGE_MENU_ITEM, N_ ("_Next Tab"), N_ ("Switch to Next Tab"), "go-next", G_CALLBACK (thunar_window_action_switch_next_tab), },
420 { 0, "<Actions>/ThunarWindow/open-file-menu", "F10", 0, NULL, NULL, NULL, G_CALLBACK (thunar_window_action_open_file_menu), },
421 };
422
423 #define get_action_entry(id) xfce_gtk_get_action_entry_by_id(thunar_window_action_entries,G_N_ELEMENTS(thunar_window_action_entries),id)
424
425
426
427 static guint window_signals[LAST_SIGNAL];
428
429
430
G_DEFINE_TYPE_WITH_CODE(ThunarWindow,thunar_window,GTK_TYPE_WINDOW,G_IMPLEMENT_INTERFACE (THUNAR_TYPE_BROWSER,NULL))431 G_DEFINE_TYPE_WITH_CODE (ThunarWindow, thunar_window, GTK_TYPE_WINDOW,
432 G_IMPLEMENT_INTERFACE (THUNAR_TYPE_BROWSER, NULL))
433
434
435
436 static void
437 thunar_window_class_init (ThunarWindowClass *klass)
438 {
439 GtkWidgetClass *gtkwidget_class;
440 GtkBindingSet *binding_set;
441 GObjectClass *gobject_class;
442 guint i;
443
444 gobject_class = G_OBJECT_CLASS (klass);
445 gobject_class->dispose = thunar_window_dispose;
446 gobject_class->finalize = thunar_window_finalize;
447 gobject_class->get_property = thunar_window_get_property;
448 gobject_class->set_property = thunar_window_set_property;
449
450 gtkwidget_class = GTK_WIDGET_CLASS (klass);
451 gtkwidget_class->realize = thunar_window_realize;
452 gtkwidget_class->unrealize = thunar_window_unrealize;
453 gtkwidget_class->configure_event = thunar_window_configure_event;
454
455 klass->reload = thunar_window_reload;
456 klass->zoom_in = thunar_window_zoom_in;
457 klass->zoom_out = thunar_window_zoom_out;
458 klass->zoom_reset = thunar_window_zoom_reset;
459 klass->tab_change = thunar_window_tab_change;
460
461 xfce_gtk_translate_action_entries (thunar_window_action_entries, G_N_ELEMENTS (thunar_window_action_entries));
462
463 /**
464 * ThunarWindow:current-directory:
465 *
466 * The directory currently displayed within this #ThunarWindow
467 * or %NULL.
468 **/
469 g_object_class_install_property (gobject_class,
470 PROP_CURRENT_DIRECTORY,
471 g_param_spec_object ("current-directory",
472 "current-directory",
473 "current-directory",
474 THUNAR_TYPE_FILE,
475 EXO_PARAM_READWRITE));
476
477 /**
478 * ThunarWindow:zoom-level:
479 *
480 * The #ThunarZoomLevel applied to the #ThunarView currently
481 * shown within this window.
482 **/
483 g_object_class_install_property (gobject_class,
484 PROP_ZOOM_LEVEL,
485 g_param_spec_enum ("zoom-level",
486 "zoom-level",
487 "zoom-level",
488 THUNAR_TYPE_ZOOM_LEVEL,
489 THUNAR_ZOOM_LEVEL_100_PERCENT,
490 EXO_PARAM_READWRITE));
491
492 /**
493 * ThunarWindow:directory-specific-settings:
494 *
495 * Whether to use directory specific settings.
496 **/
497 g_object_class_install_property (gobject_class,
498 PROP_DIRECTORY_SPECIFIC_SETTINGS,
499 g_param_spec_boolean ("directory-specific-settings",
500 "directory-specific-settings",
501 "directory-specific-settings",
502 FALSE,
503 EXO_PARAM_READWRITE));
504
505 /**
506 * ThunarWindow::reload:
507 * @window : a #ThunarWindow instance.
508 *
509 * Emitted whenever the user requests to reload the contents
510 * of the currently displayed folder.
511 **/
512 window_signals[RELOAD] =
513 g_signal_new (I_("reload"),
514 G_TYPE_FROM_CLASS (klass),
515 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
516 G_STRUCT_OFFSET (ThunarWindowClass, reload),
517 g_signal_accumulator_true_handled, NULL,
518 _thunar_marshal_BOOLEAN__BOOLEAN,
519 G_TYPE_BOOLEAN, 1,
520 G_TYPE_BOOLEAN);
521
522 /**
523 * ThunarWindow::zoom-in:
524 * @window : a #ThunarWindow instance.
525 *
526 * Emitted whenever the user requests to zoom in. This
527 * is an internal signal used to bind the action to keys.
528 **/
529 window_signals[ZOOM_IN] =
530 g_signal_new (I_("zoom-in"),
531 G_TYPE_FROM_CLASS (klass),
532 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
533 G_STRUCT_OFFSET (ThunarWindowClass, zoom_in),
534 g_signal_accumulator_true_handled, NULL,
535 _thunar_marshal_BOOLEAN__VOID,
536 G_TYPE_BOOLEAN, 0);
537
538 /**
539 * ThunarWindow::zoom-out:
540 * @window : a #ThunarWindow instance.
541 *
542 * Emitted whenever the user requests to zoom out. This
543 * is an internal signal used to bind the action to keys.
544 **/
545 window_signals[ZOOM_OUT] =
546 g_signal_new (I_("zoom-out"),
547 G_TYPE_FROM_CLASS (klass),
548 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
549 G_STRUCT_OFFSET (ThunarWindowClass, zoom_out),
550 g_signal_accumulator_true_handled, NULL,
551 _thunar_marshal_BOOLEAN__VOID,
552 G_TYPE_BOOLEAN, 0);
553
554 /**
555 * ThunarWindow::zoom-reset:
556 * @window : a #ThunarWindow instance.
557 *
558 * Emitted whenever the user requests reset the zoom level.
559 * This is an internal signal used to bind the action to keys.
560 **/
561 window_signals[ZOOM_RESET] =
562 g_signal_new (I_("zoom-reset"),
563 G_TYPE_FROM_CLASS (klass),
564 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
565 G_STRUCT_OFFSET (ThunarWindowClass, zoom_reset),
566 g_signal_accumulator_true_handled, NULL,
567 _thunar_marshal_BOOLEAN__VOID,
568 G_TYPE_BOOLEAN, 0);
569
570 /**
571 * ThunarWindow::tab-change:
572 * @window : a #ThunarWindow instance.
573 * @idx : tab index,
574 *
575 * Emitted whenever the user uses a Alt+N combination to
576 * switch tabs.
577 **/
578 window_signals[TAB_CHANGE] =
579 g_signal_new (I_("tab-change"),
580 G_TYPE_FROM_CLASS (klass),
581 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
582 G_STRUCT_OFFSET (ThunarWindowClass, tab_change),
583 g_signal_accumulator_true_handled, NULL,
584 _thunar_marshal_BOOLEAN__INT,
585 G_TYPE_BOOLEAN, 1,
586 G_TYPE_INT);
587
588 /* setup the key bindings for the windows */
589 binding_set = gtk_binding_set_by_class (klass);
590
591 /* setup the key bindings for Alt+N */
592 for (i = 0; i < 10; i++)
593 {
594 gtk_binding_entry_add_signal (binding_set, GDK_KEY_0 + i, GDK_MOD1_MASK,
595 "tab-change", 1, G_TYPE_UINT, i - 1);
596 }
597 }
598
599
600
601 static void
thunar_window_init(ThunarWindow * window)602 thunar_window_init (ThunarWindow *window)
603 {
604 GtkWidget *label;
605 GtkWidget *infobar;
606 GtkWidget *item;
607 gboolean last_menubar_visible;
608 gchar *last_location_bar;
609 gchar *last_side_pane;
610 GType type;
611 gint last_separator_position;
612 gint last_window_width;
613 gint last_window_height;
614 gboolean last_window_maximized;
615 gboolean last_statusbar_visible;
616 GtkToolItem *tool_item;
617 gboolean small_icons;
618 GtkStyleContext *context;
619
620 /* unset the view type */
621 window->view_type = G_TYPE_NONE;
622
623 /* grab a reference on the provider factory and load the providers*/
624 window->provider_factory = thunarx_provider_factory_get_default ();
625 window->thunarx_preferences_providers = thunarx_provider_factory_list_providers (window->provider_factory, THUNARX_TYPE_PREFERENCES_PROVIDER);
626
627 /* grab a reference on the preferences */
628 window->preferences = thunar_preferences_get ();
629
630 window->accel_group = gtk_accel_group_new ();
631 xfce_gtk_accel_map_add_entries (thunar_window_action_entries, G_N_ELEMENTS (thunar_window_action_entries));
632 xfce_gtk_accel_group_connect_action_entries (window->accel_group,
633 thunar_window_action_entries,
634 G_N_ELEMENTS (thunar_window_action_entries),
635 window);
636
637 gtk_window_add_accel_group (GTK_WINDOW (window), window->accel_group);
638
639 /* get all properties for init */
640 g_object_get (G_OBJECT (window->preferences),
641 "last-show-hidden", &window->show_hidden,
642 "last-window-width", &last_window_width,
643 "last-window-height", &last_window_height,
644 "last-window-maximized", &last_window_maximized,
645 "last-menubar-visible", &last_menubar_visible,
646 "last-separator-position", &last_separator_position,
647 "last-location-bar", &last_location_bar,
648 "last-side-pane", &last_side_pane,
649 "last-statusbar-visible", &last_statusbar_visible,
650 "misc-small-toolbar-icons", &small_icons,
651 NULL);
652
653 /* update the visual on screen_changed events */
654 g_signal_connect (window, "screen-changed", G_CALLBACK (thunar_window_screen_changed), NULL);
655
656 /* invoke the thunar_window_screen_changed function to initially set the best possible visual.*/
657 thunar_window_screen_changed (GTK_WIDGET (window), NULL, NULL);
658
659 /* set up a handler to confirm exit when there are multiple tabs open */
660 g_signal_connect (window, "delete-event", G_CALLBACK (thunar_window_delete), NULL);
661
662 /* connect to the volume monitor */
663 window->device_monitor = thunar_device_monitor_get ();
664 g_signal_connect (window->device_monitor, "device-pre-unmount", G_CALLBACK (thunar_window_device_pre_unmount), window);
665 g_signal_connect (window->device_monitor, "device-removed", G_CALLBACK (thunar_window_device_changed), window);
666 g_signal_connect (window->device_monitor, "device-changed", G_CALLBACK (thunar_window_device_changed), window);
667
668 window->icon_factory = thunar_icon_factory_get_default ();
669
670 /* Catch key events before accelerators get processed */
671 g_signal_connect (window, "key-press-event", G_CALLBACK (thunar_window_propagate_key_event), NULL);
672 g_signal_connect (window, "key-release-event", G_CALLBACK (thunar_window_propagate_key_event), NULL);
673
674
675 window->select_files_closure = g_cclosure_new_swap (G_CALLBACK (thunar_window_select_files), window, NULL);
676 g_closure_ref (window->select_files_closure);
677 g_closure_sink (window->select_files_closure);
678 window->launcher = g_object_new (THUNAR_TYPE_LAUNCHER, "widget", GTK_WIDGET (window),
679 "select-files-closure", window->select_files_closure, NULL);
680
681 exo_binding_new (G_OBJECT (window), "current-directory", G_OBJECT (window->launcher), "current-directory");
682 g_signal_connect_swapped (G_OBJECT (window->launcher), "change-directory", G_CALLBACK (thunar_window_set_current_directory), window);
683 g_signal_connect_swapped (G_OBJECT (window->launcher), "open-new-tab", G_CALLBACK (thunar_window_notebook_open_new_tab), window);
684 thunar_launcher_append_accelerators (window->launcher, window->accel_group);
685
686 /* determine the default window size from the preferences */
687 gtk_window_set_default_size (GTK_WINDOW (window), last_window_width, last_window_height);
688
689 /* restore the maxized state of the window */
690 if (G_UNLIKELY (last_window_maximized))
691 gtk_window_maximize (GTK_WINDOW (window));
692
693 /* add thunar style class for easier theming */
694 context = gtk_widget_get_style_context (GTK_WIDGET (window));
695 gtk_style_context_add_class (context, "thunar");
696
697 window->grid = gtk_grid_new ();
698 gtk_container_add (GTK_CONTAINER (window), window->grid);
699 gtk_widget_show (window->grid);
700
701 /* build the menubar */
702 window->menubar = gtk_menu_bar_new ();
703 thunar_window_create_menu (window, THUNAR_WINDOW_ACTION_FILE_MENU, G_CALLBACK (thunar_window_update_file_menu));
704 thunar_window_create_menu (window, THUNAR_WINDOW_ACTION_EDIT_MENU, G_CALLBACK (thunar_window_update_edit_menu));
705 thunar_window_create_menu (window, THUNAR_WINDOW_ACTION_VIEW_MENU, G_CALLBACK (thunar_window_update_view_menu));
706 thunar_window_create_menu (window, THUNAR_WINDOW_ACTION_GO_MENU, G_CALLBACK (thunar_window_update_go_menu));
707 thunar_window_create_menu (window, THUNAR_WINDOW_ACTION_HELP_MENU, G_CALLBACK (thunar_window_update_help_menu));
708 gtk_widget_show_all (window->menubar);
709
710 if (last_menubar_visible == FALSE)
711 gtk_widget_hide (window->menubar);
712 gtk_widget_set_hexpand (window->menubar, TRUE);
713 gtk_grid_attach (GTK_GRID (window->grid), window->menubar, 0, 0, 1, 1);
714
715 /* append the menu item for the spinner */
716 item = gtk_menu_item_new ();
717 gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
718 g_object_set (G_OBJECT (item), "right-justified", TRUE, NULL);
719 gtk_menu_shell_append (GTK_MENU_SHELL (window->menubar), item);
720 gtk_widget_show (item);
721
722 /* Required if F10 is pushed while the menu is hidden */
723 g_signal_connect_swapped (G_OBJECT (window->menubar), "deactivate", G_CALLBACK (thunar_window_action_menubar_update), window);
724
725 /* place the spinner into the menu item */
726 window->spinner = gtk_spinner_new ();
727 gtk_container_add (GTK_CONTAINER (item), window->spinner);
728 exo_binding_new (G_OBJECT (window->spinner), "active",
729 G_OBJECT (window->spinner), "visible");
730
731 /* check if we need to add the root warning */
732 if (G_UNLIKELY (geteuid () == 0))
733 {
734 /* add the bar for the root warning */
735 infobar = gtk_info_bar_new ();
736 gtk_info_bar_set_message_type (GTK_INFO_BAR (infobar), GTK_MESSAGE_WARNING);
737 gtk_widget_set_hexpand (infobar, TRUE);
738 gtk_grid_attach (GTK_GRID (window->grid), infobar, 0, 2, 1, 1);
739 gtk_widget_show (infobar);
740
741 /* add the label with the root warning */
742 label = gtk_label_new (_("Warning: you are using the root account. You may harm your system."));
743 gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (infobar))), label);
744 gtk_widget_show (label);
745 }
746
747 window->paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
748 gtk_container_set_border_width (GTK_CONTAINER (window->paned), 0);
749 gtk_widget_set_hexpand (window->paned, TRUE);
750 gtk_widget_set_vexpand (window->paned, TRUE);
751 gtk_grid_attach (GTK_GRID (window->grid), window->paned, 0, 4, 1, 1);
752 gtk_widget_show (window->paned);
753
754 /* determine the last separator position and apply it to the paned view */
755 gtk_paned_set_position (GTK_PANED (window->paned), last_separator_position);
756 g_signal_connect_swapped (window->paned, "accept-position", G_CALLBACK (thunar_window_save_paned), window);
757 g_signal_connect_swapped (window->paned, "button-release-event", G_CALLBACK (thunar_window_save_paned), window);
758
759 window->view_box = gtk_grid_new ();
760 gtk_paned_pack2 (GTK_PANED (window->paned), window->view_box, TRUE, FALSE);
761 gtk_widget_show (window->view_box);
762
763 /* tabs */
764 window->notebook = gtk_notebook_new ();
765 gtk_widget_set_hexpand (window->notebook, TRUE);
766 gtk_widget_set_vexpand (window->notebook, TRUE);
767 gtk_grid_attach (GTK_GRID (window->view_box), window->notebook, 0, 1, 1, 1);
768 g_signal_connect (G_OBJECT (window->notebook), "switch-page", G_CALLBACK (thunar_window_notebook_switch_page), window);
769 g_signal_connect (G_OBJECT (window->notebook), "page-added", G_CALLBACK (thunar_window_notebook_page_added), window);
770 g_signal_connect (G_OBJECT (window->notebook), "page-removed", G_CALLBACK (thunar_window_notebook_page_removed), window);
771 g_signal_connect_after (G_OBJECT (window->notebook), "button-press-event", G_CALLBACK (thunar_window_notebook_button_press_event), window);
772 g_signal_connect (G_OBJECT (window->notebook), "popup-menu", G_CALLBACK (thunar_window_notebook_popup_menu), window);
773 g_signal_connect (G_OBJECT (window->notebook), "create-window", G_CALLBACK (thunar_window_notebook_create_window), window);
774 gtk_notebook_set_show_border (GTK_NOTEBOOK (window->notebook), FALSE);
775 gtk_notebook_set_scrollable (GTK_NOTEBOOK (window->notebook), TRUE);
776 gtk_container_set_border_width (GTK_CONTAINER (window->notebook), 0);
777 gtk_notebook_set_group_name (GTK_NOTEBOOK (window->notebook), "thunar-tabs");
778 gtk_widget_show (window->notebook);
779
780 /* allocate the new location bar widget */
781 window->location_bar = thunar_location_bar_new ();
782 g_object_bind_property (G_OBJECT (window), "current-directory", G_OBJECT (window->location_bar), "current-directory", G_BINDING_SYNC_CREATE);
783 g_signal_connect_swapped (G_OBJECT (window->location_bar), "change-directory", G_CALLBACK (thunar_window_set_current_directory), window);
784 g_signal_connect_swapped (G_OBJECT (window->location_bar), "open-new-tab", G_CALLBACK (thunar_window_notebook_open_new_tab), window);
785 g_signal_connect_swapped (G_OBJECT (window->location_bar), "reload-requested", G_CALLBACK (thunar_window_handle_reload_request), window);
786 g_signal_connect_swapped (G_OBJECT (window->location_bar), "entry-done", G_CALLBACK (thunar_window_update_location_bar_visible), window);
787
788 /* setup the toolbar for the location bar */
789 window->location_toolbar = gtk_toolbar_new ();
790 gtk_toolbar_set_style (GTK_TOOLBAR (window->location_toolbar), GTK_TOOLBAR_ICONS);
791 gtk_toolbar_set_icon_size (GTK_TOOLBAR (window->location_toolbar),
792 small_icons ? GTK_ICON_SIZE_SMALL_TOOLBAR : GTK_ICON_SIZE_LARGE_TOOLBAR);
793 gtk_widget_set_hexpand (window->location_toolbar, TRUE);
794 gtk_grid_attach (GTK_GRID (window->grid), window->location_toolbar, 0, 1, 1, 1);
795
796 window->location_toolbar_item_back = xfce_gtk_tool_button_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_BACK), G_OBJECT (window), GTK_TOOLBAR (window->location_toolbar));
797 window->location_toolbar_item_forward = xfce_gtk_tool_button_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_FORWARD), G_OBJECT (window), GTK_TOOLBAR (window->location_toolbar));
798 window->location_toolbar_item_parent = xfce_gtk_tool_button_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_PARENT), G_OBJECT (window), GTK_TOOLBAR (window->location_toolbar));
799 xfce_gtk_tool_button_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_HOME), G_OBJECT (window), GTK_TOOLBAR (window->location_toolbar));
800
801 g_signal_connect (G_OBJECT (window->location_toolbar_item_back), "button-press-event", G_CALLBACK (thunar_window_history_clicked), G_OBJECT (window));
802 g_signal_connect (G_OBJECT (window->location_toolbar_item_forward), "button-press-event", G_CALLBACK (thunar_window_history_clicked), G_OBJECT (window));
803 g_signal_connect (G_OBJECT (window), "button-press-event", G_CALLBACK (thunar_window_button_press_event), G_OBJECT (window));
804 window->signal_handler_id_history_changed = 0;
805
806 /* The UCA shortcuts need to be checked 'by hand', since we dont want to permanently keep menu items for them */
807 g_signal_connect (window, "key-press-event", G_CALLBACK (thunar_window_check_uca_key_activation), NULL);
808
809 /* add the location bar to the toolbar */
810 tool_item = gtk_tool_item_new ();
811 gtk_tool_item_set_expand (tool_item, TRUE);
812 gtk_toolbar_insert (GTK_TOOLBAR (window->location_toolbar), tool_item, -1);
813 gtk_toolbar_set_show_arrow (GTK_TOOLBAR (window->location_toolbar), FALSE);
814
815 /* add the location bar itself */
816 gtk_container_add (GTK_CONTAINER (tool_item), window->location_bar);
817
818 /* display the toolbar */
819 gtk_widget_show_all (window->location_toolbar);
820
821 g_free (last_location_bar);
822
823 /* setup setting the location bar visibility on-demand */
824 g_signal_connect_object (G_OBJECT (window->preferences), "notify::last-location-bar", G_CALLBACK (thunar_window_update_location_bar_visible), window, G_CONNECT_SWAPPED);
825 thunar_window_update_location_bar_visible (window);
826
827 /* update window icon whenever preferences change */
828 g_signal_connect_object (G_OBJECT (window->preferences), "notify::misc-change-window-icon", G_CALLBACK (thunar_window_update_window_icon), window, G_CONNECT_SWAPPED);
829
830 /* determine the selected side pane */
831 if (exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_SHORTCUTS_PANE)))
832 type = THUNAR_TYPE_SHORTCUTS_PANE;
833 else if (exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_TREE_PANE)))
834 type = THUNAR_TYPE_TREE_PANE;
835 else
836 type = G_TYPE_NONE;
837 thunar_window_install_sidepane (window, type);
838 g_free (last_side_pane);
839
840 /* synchronise the "directory-specific-settings" property with the global "misc-directory-specific-settings" property */
841 exo_binding_new (G_OBJECT (window->preferences), "misc-directory-specific-settings", G_OBJECT (window), "directory-specific-settings");
842
843 /* setup a new statusbar */
844 window->statusbar = thunar_statusbar_new ();
845 gtk_widget_set_hexpand (window->statusbar, TRUE);
846 gtk_grid_attach (GTK_GRID (window->view_box), window->statusbar, 0, 2, 1, 1);
847 if (last_statusbar_visible)
848 gtk_widget_show (window->statusbar);
849
850 if (G_LIKELY (window->view != NULL))
851 thunar_window_binding_create (window, window->view, "statusbar-text", window->statusbar, "text", G_BINDING_SYNC_CREATE);
852
853 /* ensure that all the view types are registered */
854 g_type_ensure (THUNAR_TYPE_ICON_VIEW);
855 g_type_ensure (THUNAR_TYPE_DETAILS_VIEW);
856 g_type_ensure (THUNAR_TYPE_COMPACT_VIEW);
857
858 /* load the bookmarks file and monitor */
859 window->bookmarks = NULL;
860 window->bookmark_file = thunar_g_file_new_for_bookmarks ();
861 window->bookmark_monitor = g_file_monitor_file (window->bookmark_file, G_FILE_MONITOR_NONE, NULL, NULL);
862 if (G_LIKELY (window->bookmark_monitor != NULL))
863 g_signal_connect_swapped (window->bookmark_monitor, "changed", G_CALLBACK (thunar_window_update_bookmarks), window);
864
865 /* initial load of the bookmarks */
866 thunar_window_update_bookmarks (window);
867 }
868
869
870 static void
thunar_window_screen_changed(GtkWidget * widget,GdkScreen * old_screen,gpointer userdata)871 thunar_window_screen_changed (GtkWidget *widget,
872 GdkScreen *old_screen,
873 gpointer userdata)
874 {
875 GdkScreen *screen = gdk_screen_get_default ();
876 GdkVisual *visual = gdk_screen_get_rgba_visual (screen);
877
878 if (visual == NULL || !gdk_screen_is_composited (screen))
879 visual = gdk_screen_get_system_visual (screen);
880
881 gtk_widget_set_visual (GTK_WIDGET (widget), visual);
882 }
883
884
885 /**
886 * thunar_window_select_files:
887 * @window : a #ThunarWindow instance.
888 * @files_to_selected : a list of #GFile<!---->s
889 *
890 * Visually selects the files, given by the list
891 **/
892 void
thunar_window_select_files(ThunarWindow * window,GList * files_to_selected)893 thunar_window_select_files (ThunarWindow *window,
894 GList *files_to_selected)
895 {
896 GList *thunar_files = NULL;
897 ThunarFolder *thunar_folder;
898
899 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
900
901 /* If possible, reload the current directory to make sure new files got added to the view */
902 thunar_folder = thunar_folder_get_for_file (window->current_directory);
903 if (thunar_folder != NULL)
904 {
905 thunar_folder_reload (thunar_folder, FALSE);
906 g_object_unref (thunar_folder);
907 }
908
909 for (GList *lp = files_to_selected; lp != NULL; lp = lp->next)
910 thunar_files = g_list_append (thunar_files, thunar_file_get (G_FILE (lp->data), NULL));
911 thunar_view_set_selected_files (THUNAR_VIEW (window->view), thunar_files);
912 g_list_free_full (thunar_files, g_object_unref);
913 }
914
915
916
917 static void
thunar_window_create_menu(ThunarWindow * window,ThunarWindowAction action,GCallback cb_update_menu)918 thunar_window_create_menu (ThunarWindow *window,
919 ThunarWindowAction action,
920 GCallback cb_update_menu)
921 {
922 GtkWidget *item;
923 GtkWidget *submenu;
924
925 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
926
927 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (action), G_OBJECT (window), GTK_MENU_SHELL (window->menubar));
928
929 submenu = g_object_new (THUNAR_TYPE_MENU, "menu-type", THUNAR_MENU_TYPE_WINDOW, "launcher", window->launcher, NULL);
930 gtk_menu_set_accel_group (GTK_MENU (submenu), window->accel_group);
931 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), GTK_WIDGET (submenu));
932 g_signal_connect_swapped (G_OBJECT (submenu), "show", G_CALLBACK (cb_update_menu), window);
933 }
934
935
936
937 static void
thunar_window_update_file_menu(ThunarWindow * window,GtkWidget * menu)938 thunar_window_update_file_menu (ThunarWindow *window,
939 GtkWidget *menu)
940 {
941 GtkWidget *item;
942
943 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
944
945 thunar_gtk_menu_clean (GTK_MENU (menu));
946 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_NEW_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
947 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_NEW_WINDOW), G_OBJECT (window), GTK_MENU_SHELL (menu));
948 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
949 thunar_menu_add_sections (THUNAR_MENU (menu), THUNAR_MENU_SECTION_OPEN
950 | THUNAR_MENU_SECTION_SENDTO
951 | THUNAR_MENU_SECTION_CREATE_NEW_FILES
952 | THUNAR_MENU_SECTION_EMPTY_TRASH
953 | THUNAR_MENU_SECTION_CUSTOM_ACTIONS
954 | THUNAR_MENU_SECTION_PROPERTIES);
955 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
956 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_DETACH_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
957 gtk_widget_set_sensitive (item, gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) > 1);
958 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_CLOSE_ALL_WINDOWS), G_OBJECT (window), GTK_MENU_SHELL (menu));
959 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_CLOSE_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
960 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_CLOSE_WINDOW), G_OBJECT (window), GTK_MENU_SHELL (menu));
961
962 gtk_widget_show_all (GTK_WIDGET (menu));
963 thunar_window_redirect_menu_tooltips_to_statusbar (window, GTK_MENU (menu));
964 }
965
966
967
968 static void
thunar_window_update_edit_menu(ThunarWindow * window,GtkWidget * menu)969 thunar_window_update_edit_menu (ThunarWindow *window,
970 GtkWidget *menu)
971 {
972 GtkWidget *gtk_menu_item;
973 GList *thunarx_menu_items;
974 GList *pp, *lp;
975
976 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
977
978 thunar_gtk_menu_clean (GTK_MENU (menu));
979 thunar_menu_add_sections (THUNAR_MENU (menu), THUNAR_MENU_SECTION_CUT
980 | THUNAR_MENU_SECTION_COPY_PASTE
981 | THUNAR_MENU_SECTION_TRASH_DELETE);
982 if (window->view != NULL)
983 {
984 thunar_standard_view_append_menu_item (THUNAR_STANDARD_VIEW (window->view),
985 GTK_MENU (menu), THUNAR_STANDARD_VIEW_ACTION_SELECT_ALL_FILES);
986 thunar_standard_view_append_menu_item (THUNAR_STANDARD_VIEW (window->view),
987 GTK_MENU (menu), THUNAR_STANDARD_VIEW_ACTION_SELECT_BY_PATTERN);
988 thunar_standard_view_append_menu_item (THUNAR_STANDARD_VIEW (window->view),
989 GTK_MENU (menu), THUNAR_STANDARD_VIEW_ACTION_INVERT_SELECTION);
990 }
991 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
992 thunar_menu_add_sections (THUNAR_MENU (menu), THUNAR_MENU_SECTION_DUPLICATE
993 | THUNAR_MENU_SECTION_MAKELINK
994 | THUNAR_MENU_SECTION_RENAME
995 | THUNAR_MENU_SECTION_RESTORE);
996
997 /* determine the available preferences providers */
998 if (G_LIKELY (window->thunarx_preferences_providers != NULL))
999 {
1000 /* add menu items from all providers */
1001 for (pp = window->thunarx_preferences_providers; pp != NULL; pp = pp->next)
1002 {
1003 /* determine the available menu items for the provider */
1004 thunarx_menu_items = thunarx_preferences_provider_get_menu_items (THUNARX_PREFERENCES_PROVIDER (pp->data), GTK_WIDGET (window));
1005 for (lp = thunarx_menu_items; lp != NULL; lp = lp->next)
1006 {
1007 gtk_menu_item = thunar_gtk_menu_thunarx_menu_item_new (lp->data, GTK_MENU_SHELL (menu));
1008
1009 /* Each thunarx_menu_item will be destroyed together with its related gtk_menu_item */
1010 g_signal_connect_swapped (G_OBJECT (gtk_menu_item), "destroy", G_CALLBACK (g_object_unref), lp->data);
1011 }
1012
1013 /* release the list */
1014 g_list_free (thunarx_menu_items);
1015 }
1016 }
1017 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_PREFERENCES), G_OBJECT (window), GTK_MENU_SHELL (menu));
1018 gtk_widget_show_all (GTK_WIDGET (menu));
1019
1020 thunar_window_redirect_menu_tooltips_to_statusbar (window, GTK_MENU (menu));
1021 }
1022
1023
1024
1025 static void
thunar_window_update_view_menu(ThunarWindow * window,GtkWidget * menu)1026 thunar_window_update_view_menu (ThunarWindow *window,
1027 GtkWidget *menu)
1028 {
1029 GtkWidget *item;
1030 GtkWidget *sub_items;
1031 gchar *last_location_bar;
1032 gchar *last_side_pane;
1033
1034 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1035
1036 thunar_gtk_menu_clean (GTK_MENU (menu));
1037 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_RELOAD), G_OBJECT (window), GTK_MENU_SHELL (menu));
1038 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1039 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_LOCATION_SELECTOR_MENU), G_OBJECT (window), GTK_MENU_SHELL (menu));
1040 sub_items = gtk_menu_new();
1041 gtk_menu_set_accel_group (GTK_MENU (sub_items), window->accel_group);
1042 g_object_get (window->preferences, "last-location-bar", &last_location_bar, NULL);
1043 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_LOCATION_SELECTOR_PATHBAR), G_OBJECT (window),
1044 exo_str_is_equal (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_ENTRY)), GTK_MENU_SHELL (sub_items));
1045 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_LOCATION_SELECTOR_TOOLBAR), G_OBJECT (window),
1046 exo_str_is_equal (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_BUTTONS)), GTK_MENU_SHELL (sub_items));
1047 g_free (last_location_bar);
1048 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), GTK_WIDGET (sub_items));
1049 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_SIDE_PANE_MENU), G_OBJECT (window), GTK_MENU_SHELL (menu));
1050 sub_items = gtk_menu_new();
1051 gtk_menu_set_accel_group (GTK_MENU (sub_items), window->accel_group);
1052 g_object_get (window->preferences, "last-side-pane", &last_side_pane, NULL);
1053 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_SIDE_PANE_SHORTCUTS), G_OBJECT (window),
1054 exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_SHORTCUTS_PANE)), GTK_MENU_SHELL (sub_items));
1055 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_SIDE_PANE_TREE), G_OBJECT (window),
1056 exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_TREE_PANE)), GTK_MENU_SHELL (sub_items));
1057 g_free (last_side_pane);
1058 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), GTK_WIDGET (sub_items));
1059 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_STATUSBAR), G_OBJECT (window),
1060 gtk_widget_get_visible (window->statusbar), GTK_MENU_SHELL (menu));
1061 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_MENUBAR), G_OBJECT (window),
1062 gtk_widget_get_visible (window->menubar), GTK_MENU_SHELL (menu));
1063 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1064 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_SHOW_HIDDEN), G_OBJECT (window),
1065 window->show_hidden, GTK_MENU_SHELL (menu));
1066 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1067 if (window->view != NULL)
1068 thunar_standard_view_append_menu_items (THUNAR_STANDARD_VIEW (window->view), GTK_MENU (menu), window->accel_group);
1069 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1070 thunar_window_append_menu_item (window, GTK_MENU_SHELL (menu), THUNAR_WINDOW_ACTION_ZOOM_IN);
1071 thunar_window_append_menu_item (window, GTK_MENU_SHELL (menu), THUNAR_WINDOW_ACTION_ZOOM_OUT);
1072 thunar_window_append_menu_item (window, GTK_MENU_SHELL (menu), THUNAR_WINDOW_ACTION_ZOOM_RESET);
1073 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1074
1075 if (window->directory_specific_settings)
1076 {
1077 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_CLEAR_DIRECTORY_SPECIFIC_SETTINGS),
1078 G_OBJECT (window), GTK_MENU_SHELL (menu));
1079 gtk_widget_set_sensitive (item, thunar_file_has_directory_specific_settings (window->current_directory));
1080 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1081 }
1082
1083 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_AS_ICONS),
1084 G_OBJECT (window), window->view_type == THUNAR_TYPE_ICON_VIEW, GTK_MENU_SHELL (menu));
1085 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_AS_DETAILED_LIST),
1086 G_OBJECT (window), window->view_type == THUNAR_TYPE_DETAILS_VIEW, GTK_MENU_SHELL (menu));
1087 xfce_gtk_toggle_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_VIEW_AS_COMPACT_LIST),
1088 G_OBJECT (window), window->view_type == THUNAR_TYPE_COMPACT_VIEW, GTK_MENU_SHELL (menu));
1089
1090 gtk_widget_show_all (GTK_WIDGET (menu));
1091
1092 thunar_window_redirect_menu_tooltips_to_statusbar (window, GTK_MENU (menu));
1093 }
1094
1095
1096
1097 static void
thunar_window_update_go_menu(ThunarWindow * window,GtkWidget * menu)1098 thunar_window_update_go_menu (ThunarWindow *window,
1099 GtkWidget *menu)
1100 {
1101 gchar *icon_name;
1102 const XfceGtkActionEntry *action_entry;
1103 ThunarHistory *history = NULL;
1104 GtkWidget *item;
1105
1106 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1107
1108 if (window->view != NULL)
1109 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
1110
1111 thunar_gtk_menu_clean (GTK_MENU (menu));
1112 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_PARENT), G_OBJECT (window), GTK_MENU_SHELL (menu));
1113 gtk_widget_set_sensitive (item, !thunar_g_file_is_root (thunar_file_get_file (window->current_directory)));
1114 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_BACK), G_OBJECT (window), GTK_MENU_SHELL (menu));
1115 if (history != NULL)
1116 gtk_widget_set_sensitive (item, thunar_history_has_back (history));
1117 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_FORWARD), G_OBJECT (window), GTK_MENU_SHELL (menu));
1118 if (history != NULL)
1119 gtk_widget_set_sensitive (item, thunar_history_has_forward (history));
1120 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1121 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_COMPUTER), G_OBJECT (window), GTK_MENU_SHELL (menu));
1122 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_HOME), G_OBJECT (window), GTK_MENU_SHELL (menu));
1123 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_DESKTOP), G_OBJECT (window), GTK_MENU_SHELL (menu));
1124 if (thunar_g_vfs_is_uri_scheme_supported ("trash"))
1125 {
1126 GFile *gfile;
1127 ThunarFile *trash_folder;
1128
1129 /* try to connect to the trash bin */
1130 gfile = thunar_g_file_new_for_trash ();
1131 if (gfile != NULL)
1132 {
1133 trash_folder = thunar_file_get (gfile, NULL);
1134 if (trash_folder != NULL)
1135 {
1136 action_entry = get_action_entry (THUNAR_WINDOW_ACTION_OPEN_TRASH);
1137 if (action_entry != NULL)
1138 {
1139 if (thunar_file_get_item_count (trash_folder) > 0)
1140 icon_name = "user-trash-full";
1141 else
1142 icon_name = "user-trash";
1143 xfce_gtk_image_menu_item_new_from_icon_name (action_entry->menu_item_label_text, action_entry->menu_item_tooltip_text,
1144 action_entry->accel_path, action_entry->callback, G_OBJECT (window), icon_name, GTK_MENU_SHELL (menu));
1145 }
1146 g_object_unref (trash_folder);
1147 }
1148 g_object_unref (gfile);
1149 }
1150 }
1151 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_TEMPLATES), G_OBJECT (window), GTK_MENU_SHELL (menu));
1152 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1153 thunar_window_menu_add_bookmarks (window, GTK_MENU_SHELL (menu));
1154 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1155 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_FILE_SYSTEM), G_OBJECT (window), GTK_MENU_SHELL (menu));
1156 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1157 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_NETWORK), G_OBJECT (window), GTK_MENU_SHELL (menu));
1158 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1159 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_OPEN_LOCATION), G_OBJECT (window), GTK_MENU_SHELL (menu));
1160 gtk_widget_show_all (GTK_WIDGET (menu));
1161
1162 thunar_window_redirect_menu_tooltips_to_statusbar (window, GTK_MENU (menu));
1163 }
1164
1165
1166
1167 static void
thunar_window_update_help_menu(ThunarWindow * window,GtkWidget * menu)1168 thunar_window_update_help_menu (ThunarWindow *window,
1169 GtkWidget *menu)
1170 {
1171 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1172
1173 thunar_gtk_menu_clean (GTK_MENU (menu));
1174 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_CONTENTS), G_OBJECT (window), GTK_MENU_SHELL (menu));
1175 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_ABOUT), G_OBJECT (window), GTK_MENU_SHELL (menu));
1176 gtk_widget_show_all (GTK_WIDGET (menu));
1177
1178 thunar_window_redirect_menu_tooltips_to_statusbar (window, GTK_MENU (menu));
1179 }
1180
1181
1182
1183 static void
thunar_window_dispose(GObject * object)1184 thunar_window_dispose (GObject *object)
1185 {
1186 ThunarWindow *window = THUNAR_WINDOW (object);
1187
1188 /* indicate that history items are out of use */
1189 window->location_toolbar_item_back = NULL;
1190 window->location_toolbar_item_forward = NULL;
1191
1192 if (window->accel_group != NULL)
1193 {
1194 gtk_accel_group_disconnect (window->accel_group, NULL);
1195 gtk_window_remove_accel_group (GTK_WINDOW (window), window->accel_group);
1196 g_object_unref (window->accel_group);
1197 window->accel_group = NULL;
1198 }
1199
1200 /* destroy the save geometry timer source */
1201 if (G_UNLIKELY (window->save_geometry_timer_id != 0))
1202 g_source_remove (window->save_geometry_timer_id);
1203
1204 /* disconnect from the current-directory */
1205 thunar_window_set_current_directory (window, NULL);
1206
1207 (*G_OBJECT_CLASS (thunar_window_parent_class)->dispose) (object);
1208 }
1209
1210
1211
1212 static void
thunar_window_finalize(GObject * object)1213 thunar_window_finalize (GObject *object)
1214 {
1215 ThunarWindow *window = THUNAR_WINDOW (object);
1216
1217 /* disconnect from the volume monitor */
1218 g_signal_handlers_disconnect_matched (window->device_monitor, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
1219 g_object_unref (window->device_monitor);
1220
1221 g_object_unref (window->icon_factory);
1222 g_object_unref (window->launcher);
1223
1224 if (window->bookmark_file != NULL)
1225 g_object_unref (window->bookmark_file);
1226
1227 if (window->bookmark_monitor != NULL)
1228 {
1229 g_file_monitor_cancel (window->bookmark_monitor);
1230 g_object_unref (window->bookmark_monitor);
1231 }
1232
1233 /* release our reference on the provider factory */
1234 g_object_unref (window->provider_factory);
1235
1236 /* release the preferences reference */
1237 g_object_unref (window->preferences);
1238
1239 g_closure_invalidate (window->select_files_closure);
1240 g_closure_unref (window->select_files_closure);
1241
1242 (*G_OBJECT_CLASS (thunar_window_parent_class)->finalize) (object);
1243 }
1244
1245
1246
thunar_window_delete(GtkWidget * widget,GdkEvent * event,gpointer data)1247 static gboolean thunar_window_delete (GtkWidget *widget,
1248 GdkEvent *event,
1249 gpointer data )
1250 {
1251 GtkNotebook *notebook;
1252 gboolean confirm_close_multiple_tabs, do_not_ask_again;
1253 gint response, n_tabs;
1254
1255 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (widget),FALSE);
1256
1257 /* if we don't have muliple tabs then just exit */
1258 notebook = GTK_NOTEBOOK (THUNAR_WINDOW (widget)->notebook);
1259 n_tabs = gtk_notebook_get_n_pages (GTK_NOTEBOOK (THUNAR_WINDOW (widget)->notebook));
1260 if (n_tabs < 2)
1261 return FALSE;
1262
1263 /* check if the user has disabled confirmation of closing multiple tabs, and just exit if so */
1264 g_object_get (G_OBJECT (THUNAR_WINDOW (widget)->preferences),
1265 "misc-confirm-close-multiple-tabs", &confirm_close_multiple_tabs,
1266 NULL);
1267 if(!confirm_close_multiple_tabs)
1268 return FALSE;
1269
1270 /* ask the user for confirmation */
1271 do_not_ask_again = FALSE;
1272 response = xfce_dialog_confirm_close_tabs (GTK_WINDOW (widget), n_tabs, TRUE, &do_not_ask_again);
1273
1274 /* if the user requested not to be asked again, store this preference */
1275 if (response != GTK_RESPONSE_CANCEL && do_not_ask_again)
1276 g_object_set (G_OBJECT (THUNAR_WINDOW (widget)->preferences),
1277 "misc-confirm-close-multiple-tabs", FALSE, NULL);
1278
1279 if(response == GTK_RESPONSE_YES)
1280 return FALSE;
1281 if(response == GTK_RESPONSE_CLOSE)
1282 gtk_notebook_remove_page (notebook, gtk_notebook_get_current_page(notebook));
1283 return TRUE;
1284 }
1285
1286
1287
1288 static void
thunar_window_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)1289 thunar_window_get_property (GObject *object,
1290 guint prop_id,
1291 GValue *value,
1292 GParamSpec *pspec)
1293 {
1294 ThunarWindow *window = THUNAR_WINDOW (object);
1295
1296 switch (prop_id)
1297 {
1298 case PROP_CURRENT_DIRECTORY:
1299 g_value_set_object (value, thunar_window_get_current_directory (window));
1300 break;
1301
1302 case PROP_ZOOM_LEVEL:
1303 g_value_set_enum (value, window->zoom_level);
1304 break;
1305
1306 default:
1307 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1308 break;
1309 }
1310 }
1311
1312
1313
1314 static void
thunar_window_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)1315 thunar_window_set_property (GObject *object,
1316 guint prop_id,
1317 const GValue *value,
1318 GParamSpec *pspec)
1319 {
1320 ThunarWindow *window = THUNAR_WINDOW (object);
1321
1322 switch (prop_id)
1323 {
1324 case PROP_CURRENT_DIRECTORY:
1325 thunar_window_set_current_directory (window, g_value_get_object (value));
1326 break;
1327
1328 case PROP_ZOOM_LEVEL:
1329 thunar_window_set_zoom_level (window, g_value_get_enum (value));
1330 break;
1331
1332 case PROP_DIRECTORY_SPECIFIC_SETTINGS:
1333 thunar_window_set_directory_specific_settings (window, g_value_get_boolean (value));
1334 break;
1335
1336 default:
1337 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1338 break;
1339 }
1340 }
1341
1342
1343
1344 static gboolean
thunar_window_reload(ThunarWindow * window,gboolean reload_info)1345 thunar_window_reload (ThunarWindow *window,
1346 gboolean reload_info)
1347 {
1348 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1349
1350 /* force the view to reload */
1351 if (G_LIKELY (window->view != NULL))
1352 {
1353 thunar_view_reload (THUNAR_VIEW (window->view), reload_info);
1354 return TRUE;
1355 }
1356
1357 return FALSE;
1358 }
1359
1360
1361
1362 /**
1363 * thunar_window_has_shortcut_sidepane:
1364 * @window : a #ThunarWindow instance.
1365 *
1366 * Return value: True, if this window is running a shortcut sidepane
1367 **/
1368 gboolean
thunar_window_has_shortcut_sidepane(ThunarWindow * window)1369 thunar_window_has_shortcut_sidepane (ThunarWindow *window)
1370 {
1371 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1372
1373 /* check if a side pane is currently active */
1374 if (G_LIKELY (window->sidepane != NULL))
1375 {
1376 return G_OBJECT_TYPE (window->sidepane) == THUNAR_TYPE_SHORTCUTS_PANE;
1377 }
1378 return FALSE;
1379 }
1380
1381
1382
1383 /**
1384 * thunar_window_get_sidepane:
1385 * @window : a #ThunarWindow instance.
1386 *
1387 * Return value: (transfer none): The #ThunarSidePane of this window, or NULL if not available
1388 **/
thunar_window_get_sidepane(ThunarWindow * window)1389 GtkWidget* thunar_window_get_sidepane (ThunarWindow *window)
1390 {
1391 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1392 return GTK_WIDGET (window->sidepane);
1393 }
1394
1395
1396
1397 static gboolean
thunar_window_toggle_sidepane(ThunarWindow * window)1398 thunar_window_toggle_sidepane (ThunarWindow *window)
1399 {
1400 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1401
1402 /* check if a side pane is currently active */
1403 if (G_LIKELY (window->sidepane != NULL))
1404 {
1405 /* determine the currently active side pane type */
1406 window->toggle_sidepane_type = G_OBJECT_TYPE (window->sidepane);
1407 thunar_window_install_sidepane (window, G_TYPE_NONE);
1408 }
1409 else
1410 {
1411 /* check if we have a previously remembered toggle type */
1412 if (window->toggle_sidepane_type == THUNAR_TYPE_TREE_PANE || window->toggle_sidepane_type == THUNAR_TYPE_SHORTCUTS_PANE)
1413 thunar_window_install_sidepane (window, window->toggle_sidepane_type);
1414 }
1415
1416 return TRUE;
1417 }
1418
1419
1420
1421 static gboolean
thunar_window_zoom_in(ThunarWindow * window)1422 thunar_window_zoom_in (ThunarWindow *window)
1423 {
1424 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1425
1426 /* check if we can still zoom in */
1427 if (G_LIKELY (window->zoom_level < THUNAR_ZOOM_N_LEVELS - 1))
1428 {
1429 thunar_window_set_zoom_level (window, window->zoom_level + 1);
1430 return TRUE;
1431 }
1432
1433 return FALSE;
1434 }
1435
1436
1437
1438 static gboolean
thunar_window_zoom_out(ThunarWindow * window)1439 thunar_window_zoom_out (ThunarWindow *window)
1440 {
1441 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1442
1443 /* check if we can still zoom out */
1444 if (G_LIKELY (window->zoom_level > 0))
1445 {
1446 thunar_window_set_zoom_level (window, window->zoom_level - 1);
1447 return TRUE;
1448 }
1449
1450 return FALSE;
1451 }
1452
1453
1454
1455 static gboolean
thunar_window_zoom_reset(ThunarWindow * window)1456 thunar_window_zoom_reset (ThunarWindow *window)
1457 {
1458 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1459
1460 /* tell the view to reset it's zoom level */
1461 if (G_LIKELY (window->view != NULL))
1462 {
1463 thunar_view_reset_zoom_level (THUNAR_VIEW (window->view));
1464 return TRUE;
1465 }
1466
1467 return FALSE;
1468 }
1469
1470
1471
1472 static gboolean
thunar_window_tab_change(ThunarWindow * window,gint nth)1473 thunar_window_tab_change (ThunarWindow *window,
1474 gint nth)
1475 {
1476 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
1477
1478 /* Alt+0 is 10th tab */
1479 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook),
1480 nth == -1 ? 9 : nth);
1481
1482 return TRUE;
1483 }
1484
1485
1486
1487 static void
thunar_window_action_switch_next_tab(ThunarWindow * window)1488 thunar_window_action_switch_next_tab (ThunarWindow *window)
1489 {
1490 gint current_page;
1491 gint new_page;
1492 gint pages;
1493
1494 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1495
1496 current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
1497 pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
1498 new_page = (current_page + 1) % pages;
1499
1500 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), new_page);
1501 }
1502
1503
1504
1505 static void
thunar_window_action_switch_previous_tab(ThunarWindow * window)1506 thunar_window_action_switch_previous_tab (ThunarWindow *window)
1507 {
1508 gint current_page;
1509 gint new_page;
1510 gint pages;
1511
1512 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1513
1514 current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
1515 pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
1516 new_page = (current_page - 1) % pages;
1517
1518 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), new_page);
1519 }
1520
1521
1522
1523 static void
thunar_window_clipboard_manager_changed(GtkWidget * widget)1524 thunar_window_clipboard_manager_changed (GtkWidget *widget)
1525 {
1526 ThunarWindow *window = THUNAR_WINDOW (widget);
1527
1528 thunar_window_reload (window, FALSE);
1529 }
1530
1531
1532
1533 static void
thunar_window_realize(GtkWidget * widget)1534 thunar_window_realize (GtkWidget *widget)
1535 {
1536 ThunarWindow *window = THUNAR_WINDOW (widget);
1537
1538 /* let the GtkWidget class perform the realize operation */
1539 (*GTK_WIDGET_CLASS (thunar_window_parent_class)->realize) (widget);
1540
1541 /* connect to the clipboard manager of the new display and be sure to redraw the window
1542 * whenever the clipboard contents change to make sure we always display up2date state.
1543 */
1544 window->clipboard = thunar_clipboard_manager_get_for_display (gtk_widget_get_display (widget));
1545 g_signal_connect_swapped (G_OBJECT (window->clipboard), "changed",
1546 G_CALLBACK (thunar_window_clipboard_manager_changed), widget);
1547 }
1548
1549
1550
1551 static void
thunar_window_unrealize(GtkWidget * widget)1552 thunar_window_unrealize (GtkWidget *widget)
1553 {
1554 ThunarWindow *window = THUNAR_WINDOW (widget);
1555
1556 /* disconnect from the clipboard manager */
1557 g_signal_handlers_disconnect_by_func (G_OBJECT (window->clipboard), thunar_window_clipboard_manager_changed, widget);
1558
1559 /* let the GtkWidget class unrealize the window */
1560 (*GTK_WIDGET_CLASS (thunar_window_parent_class)->unrealize) (widget);
1561
1562 /* drop the reference on the clipboard manager, we do this after letting the GtkWidget class
1563 * unrealise the window to prevent the clipboard being disposed during the unrealize */
1564 g_object_unref (G_OBJECT (window->clipboard));
1565 }
1566
1567
1568
1569 static gboolean
thunar_window_configure_event(GtkWidget * widget,GdkEventConfigure * event)1570 thunar_window_configure_event (GtkWidget *widget,
1571 GdkEventConfigure *event)
1572 {
1573 ThunarWindow *window = THUNAR_WINDOW (widget);
1574 GtkAllocation widget_allocation;
1575
1576 gtk_widget_get_allocation (widget, &widget_allocation);
1577
1578 /* check if we have a new dimension here */
1579 if (widget_allocation.width != event->width || widget_allocation.height != event->height)
1580 {
1581 /* drop any previous timer source */
1582 if (window->save_geometry_timer_id != 0)
1583 g_source_remove (window->save_geometry_timer_id);
1584
1585 /* check if we should schedule another save timer */
1586 if (gtk_widget_get_visible (widget))
1587 {
1588 /* save the geometry one second after the last configure event */
1589 window->save_geometry_timer_id = g_timeout_add_seconds_full (G_PRIORITY_LOW, 1, thunar_window_save_geometry_timer,
1590 window, thunar_window_save_geometry_timer_destroy);
1591 }
1592 }
1593
1594 /* let Gtk+ handle the configure event */
1595 return (*GTK_WIDGET_CLASS (thunar_window_parent_class)->configure_event) (widget, event);
1596 }
1597
1598
1599
1600 static void
thunar_window_binding_destroyed(gpointer data,GObject * binding)1601 thunar_window_binding_destroyed (gpointer data,
1602 GObject *binding)
1603 {
1604 ThunarWindow *window = THUNAR_WINDOW (data);
1605
1606 if (window->view_bindings != NULL)
1607 window->view_bindings = g_slist_remove (window->view_bindings, binding);
1608 }
1609
1610
1611
1612 static void
thunar_window_binding_create(ThunarWindow * window,gpointer src_object,const gchar * src_prop,gpointer dst_object,const gchar * dst_prop,GBindingFlags flags)1613 thunar_window_binding_create (ThunarWindow *window,
1614 gpointer src_object,
1615 const gchar *src_prop,
1616 gpointer dst_object,
1617 const gchar *dst_prop,
1618 GBindingFlags flags)
1619 {
1620 GBinding *binding;
1621
1622 _thunar_return_if_fail (G_IS_OBJECT (src_object));
1623 _thunar_return_if_fail (G_IS_OBJECT (dst_object));
1624
1625 binding = g_object_bind_property (G_OBJECT (src_object), src_prop,
1626 G_OBJECT (dst_object), dst_prop,
1627 flags);
1628
1629 g_object_weak_ref (G_OBJECT (binding), thunar_window_binding_destroyed, window);
1630 window->view_bindings = g_slist_prepend (window->view_bindings, binding);
1631 }
1632
1633
1634
1635 static void
thunar_window_notebook_switch_page(GtkWidget * notebook,GtkWidget * page,guint page_num,ThunarWindow * window)1636 thunar_window_notebook_switch_page (GtkWidget *notebook,
1637 GtkWidget *page,
1638 guint page_num,
1639 ThunarWindow *window)
1640 {
1641 GSList *view_bindings;
1642 ThunarFile *current_directory;
1643 ThunarHistory *history;
1644
1645 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1646 _thunar_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1647 _thunar_return_if_fail (THUNAR_IS_VIEW (page));
1648 _thunar_return_if_fail (window->notebook == notebook);
1649
1650 /* leave if nothing changed */
1651 if (window->view == page)
1652 return;
1653
1654 /* Use accelerators only on the current active tab */
1655 if (window->view != NULL)
1656 g_object_set (G_OBJECT (window->view), "accel-group", NULL, NULL);
1657 g_object_set (G_OBJECT (page), "accel-group", window->accel_group, NULL);
1658
1659 if (G_LIKELY (window->view != NULL))
1660 {
1661 /* disconnect from previous history */
1662 if (window->signal_handler_id_history_changed != 0)
1663 {
1664 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
1665 g_signal_handler_disconnect (history, window->signal_handler_id_history_changed);
1666 window->signal_handler_id_history_changed = 0;
1667 }
1668
1669 /* unset view during switch */
1670 window->view = NULL;
1671 }
1672
1673 /* disconnect existing bindings */
1674 view_bindings = window->view_bindings;
1675 window->view_bindings = NULL;
1676 g_slist_free_full (view_bindings, g_object_unref);
1677
1678 /* update the directory of the current window */
1679 current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (page));
1680 thunar_window_set_current_directory (window, current_directory);
1681
1682 /* add stock bindings */
1683 thunar_window_binding_create (window, window, "current-directory", page, "current-directory", G_BINDING_DEFAULT);
1684 thunar_window_binding_create (window, page, "loading", window->spinner, "active", G_BINDING_SYNC_CREATE);
1685 thunar_window_binding_create (window, page, "selected-files", window->launcher, "selected-files", G_BINDING_SYNC_CREATE);
1686 thunar_window_binding_create (window, page, "zoom-level", window, "zoom-level", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
1687
1688 /* connect to the sidepane (if any) */
1689 if (G_LIKELY (window->sidepane != NULL))
1690 {
1691 thunar_window_binding_create (window, page, "selected-files",
1692 window->sidepane, "selected-files",
1693 G_BINDING_SYNC_CREATE);
1694 }
1695
1696 /* connect to the statusbar (if any) */
1697 if (G_LIKELY (window->statusbar != NULL))
1698 {
1699 thunar_window_binding_create (window, page, "statusbar-text",
1700 window->statusbar, "text",
1701 G_BINDING_SYNC_CREATE);
1702 }
1703
1704 /* activate new view */
1705 window->view = page;
1706 window->view_type = G_TYPE_FROM_INSTANCE (page);
1707
1708 /* remember the last view type if directory specific settings are not enabled */
1709 if (!window->directory_specific_settings && window->view_type != G_TYPE_NONE)
1710 g_object_set (G_OBJECT (window->preferences), "last-view", g_type_name (window->view_type), NULL);
1711
1712 /* connect to the new history */
1713 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
1714 if (history != NULL)
1715 {
1716 window->signal_handler_id_history_changed = g_signal_connect_swapped (G_OBJECT (history), "history-changed", G_CALLBACK (thunar_window_history_changed), window);
1717 thunar_window_history_changed (window);
1718 }
1719
1720 /* update the selection */
1721 thunar_standard_view_selection_changed (THUNAR_STANDARD_VIEW (page));
1722
1723 gtk_widget_grab_focus (page);
1724 }
1725
1726
1727
1728 static void
thunar_window_notebook_show_tabs(ThunarWindow * window)1729 thunar_window_notebook_show_tabs (ThunarWindow *window)
1730 {
1731 gint n_pages;
1732 gboolean show_tabs = TRUE;
1733
1734 /* check if tabs should be visible */
1735 n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
1736 if (n_pages < 2)
1737 {
1738 g_object_get (G_OBJECT (window->preferences),
1739 "misc-always-show-tabs", &show_tabs, NULL);
1740 }
1741
1742 /* update visibility */
1743 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->notebook), show_tabs);
1744 }
1745
1746
1747
1748 static void
thunar_window_history_changed(ThunarWindow * window)1749 thunar_window_history_changed (ThunarWindow *window)
1750 {
1751 ThunarHistory *history;
1752
1753 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1754
1755 if (window->view == NULL)
1756 return;
1757
1758 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
1759 if (history == NULL)
1760 return;
1761
1762 if (window->location_toolbar_item_back != NULL)
1763 gtk_widget_set_sensitive (window->location_toolbar_item_back, thunar_history_has_back (history));
1764
1765 if (window->location_toolbar_item_forward != NULL)
1766 gtk_widget_set_sensitive (window->location_toolbar_item_forward, thunar_history_has_forward (history));
1767 }
1768
1769
1770
1771 static void
thunar_window_notebook_page_added(GtkWidget * notebook,GtkWidget * page,guint page_num,ThunarWindow * window)1772 thunar_window_notebook_page_added (GtkWidget *notebook,
1773 GtkWidget *page,
1774 guint page_num,
1775 ThunarWindow *window)
1776 {
1777 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1778 _thunar_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1779 _thunar_return_if_fail (THUNAR_IS_VIEW (page));
1780 _thunar_return_if_fail (window->notebook == notebook);
1781
1782 /* connect signals */
1783 g_signal_connect (G_OBJECT (page), "notify::loading", G_CALLBACK (thunar_window_notify_loading), window);
1784 g_signal_connect_swapped (G_OBJECT (page), "start-open-location", G_CALLBACK (thunar_window_start_open_location), window);
1785 g_signal_connect_swapped (G_OBJECT (page), "change-directory", G_CALLBACK (thunar_window_set_current_directory), window);
1786 g_signal_connect_swapped (G_OBJECT (page), "open-new-tab", G_CALLBACK (thunar_window_notebook_open_new_tab), window);
1787
1788 /* update tab visibility */
1789 thunar_window_notebook_show_tabs (window);
1790
1791 /* set default type if not set yet */
1792 if (window->view_type == G_TYPE_NONE)
1793 window->view_type = G_OBJECT_TYPE (page);
1794 }
1795
1796
1797
1798 static void
thunar_window_notebook_page_removed(GtkWidget * notebook,GtkWidget * page,guint page_num,ThunarWindow * window)1799 thunar_window_notebook_page_removed (GtkWidget *notebook,
1800 GtkWidget *page,
1801 guint page_num,
1802 ThunarWindow *window)
1803 {
1804 gint n_pages;
1805
1806 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
1807 _thunar_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1808 _thunar_return_if_fail (THUNAR_IS_VIEW (page));
1809 _thunar_return_if_fail (window->notebook == notebook);
1810
1811 /* drop connected signals */
1812 g_signal_handlers_disconnect_matched (page, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, window);
1813
1814 n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook));
1815 if (n_pages == 0)
1816 {
1817 /* destroy the window */
1818 gtk_widget_destroy (GTK_WIDGET (window));
1819 }
1820 else
1821 {
1822 /* update tab visibility */
1823 thunar_window_notebook_show_tabs (window);
1824 }
1825 }
1826
1827
1828
1829 static gboolean
thunar_window_notebook_button_press_event(GtkWidget * notebook,GdkEventButton * event,ThunarWindow * window)1830 thunar_window_notebook_button_press_event (GtkWidget *notebook,
1831 GdkEventButton *event,
1832 ThunarWindow *window)
1833 {
1834 gint page_num = 0;
1835 GtkWidget *page;
1836 GtkWidget *label_box;
1837 GtkAllocation alloc;
1838 gint x, y;
1839 gboolean close_tab;
1840
1841 if ((event->button == 2 || event->button == 3)
1842 && event->type == GDK_BUTTON_PRESS)
1843 {
1844 /* get real window coordinates */
1845 gdk_window_get_position (event->window, &x, &y);
1846 x += event->x;
1847 y += event->y;
1848
1849 /* lookup the clicked tab */
1850 while ((page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), page_num)) != NULL)
1851 {
1852 label_box = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook), page);
1853 gtk_widget_get_allocation (label_box, &alloc);
1854
1855 if (x >= alloc.x && x < alloc.x + alloc.width
1856 && y >= alloc.y && y < alloc.y + alloc.height)
1857 break;
1858
1859 page_num++;
1860 }
1861
1862 /* leave if no tab could be found */
1863 if (page == NULL)
1864 return FALSE;
1865
1866 if (event->button == 2)
1867 {
1868 /* check if we should close the tab */
1869 g_object_get (window->preferences, "misc-tab-close-middle-click", &close_tab, NULL);
1870 if (close_tab)
1871 gtk_widget_destroy (page);
1872 }
1873 else if (event->button == 3)
1874 {
1875 /* update the current tab before we show the menu */
1876 gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), page_num);
1877
1878 /* show the tab menu */
1879 thunar_window_notebook_popup_menu (notebook, window);
1880 }
1881
1882 return TRUE;
1883 }
1884
1885 return FALSE;
1886 }
1887
1888
1889
1890 static gboolean
thunar_window_notebook_popup_menu(GtkWidget * notebook,ThunarWindow * window)1891 thunar_window_notebook_popup_menu (GtkWidget *notebook,
1892 ThunarWindow *window)
1893 {
1894 GtkWidget *menu;
1895
1896 menu = gtk_menu_new ();
1897 gtk_menu_set_accel_group (GTK_MENU (menu), window->accel_group);
1898 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_NEW_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
1899 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1900 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_DETACH_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
1901 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_SWITCH_PREV_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
1902 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_SWITCH_NEXT_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
1903 xfce_gtk_menu_append_seperator (GTK_MENU_SHELL (menu));
1904 xfce_gtk_menu_item_new_from_action_entry (get_action_entry (THUNAR_WINDOW_ACTION_CLOSE_TAB), G_OBJECT (window), GTK_MENU_SHELL (menu));
1905 gtk_widget_show_all (menu);
1906 thunar_gtk_menu_run (GTK_MENU (menu));
1907 return TRUE;
1908 }
1909
1910
1911
1912 static gpointer
thunar_window_notebook_create_window(GtkWidget * notebook,GtkWidget * page,gint x,gint y,ThunarWindow * window)1913 thunar_window_notebook_create_window (GtkWidget *notebook,
1914 GtkWidget *page,
1915 gint x,
1916 gint y,
1917 ThunarWindow *window)
1918 {
1919 GtkWidget *new_window;
1920 ThunarApplication *application;
1921 gint width, height;
1922 GdkMonitor *monitor;
1923 GdkScreen *screen;
1924 GdkRectangle geo;
1925
1926 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), NULL);
1927 _thunar_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
1928 _thunar_return_val_if_fail (window->notebook == notebook, NULL);
1929 _thunar_return_val_if_fail (THUNAR_IS_VIEW (page), NULL);
1930
1931 /* do nothing if this window has only 1 tab */
1932 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) < 2)
1933 return NULL;
1934
1935 /* create new window */
1936 application = thunar_application_get ();
1937 screen = gtk_window_get_screen (GTK_WINDOW (window));
1938 new_window = thunar_application_open_window (application, NULL, screen, NULL, TRUE);
1939 g_object_unref (application);
1940
1941 /* make sure the new window has the same size */
1942 gtk_window_get_size (GTK_WINDOW (window), &width, &height);
1943 gtk_window_resize (GTK_WINDOW (new_window), width, height);
1944
1945 /* move the window to the drop position */
1946 if (x >= 0 && y >= 0)
1947 {
1948 /* get the monitor geometry */
1949 monitor = gdk_display_get_monitor_at_point (gdk_display_get_default (), x, y);
1950 gdk_monitor_get_geometry (monitor, &geo);
1951
1952 /* calculate window position, but keep it on the current monitor */
1953 x = CLAMP (x - width / 2, geo.x, geo.x + geo.width - width);
1954 y = CLAMP (y - height / 2, geo.y, geo.y + geo.height - height);
1955
1956 /* move the window */
1957 gtk_window_move (GTK_WINDOW (new_window), MAX (0, x), MAX (0, y));
1958 }
1959
1960 /* insert page in new notebook */
1961 return THUNAR_WINDOW (new_window)->notebook;
1962 }
1963
1964
1965
1966 static GtkWidget*
thunar_window_notebook_insert(ThunarWindow * window,ThunarFile * directory,GType view_type,gint position,ThunarHistory * history)1967 thunar_window_notebook_insert (ThunarWindow *window,
1968 ThunarFile *directory,
1969 GType view_type,
1970 gint position,
1971 ThunarHistory *history)
1972 {
1973 GtkWidget *view;
1974 GtkWidget *label;
1975 GtkWidget *label_box;
1976 GtkWidget *button;
1977 GtkWidget *icon;
1978
1979 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), NULL);
1980 _thunar_return_val_if_fail (THUNAR_IS_FILE (directory), NULL);
1981 _thunar_return_val_if_fail (view_type != G_TYPE_NONE, NULL);
1982 _thunar_return_val_if_fail (history == NULL || THUNAR_IS_HISTORY (history), NULL);
1983
1984 /* allocate and setup a new view */
1985 view = g_object_new (view_type, "current-directory", directory, NULL);
1986 thunar_view_set_show_hidden (THUNAR_VIEW (view), window->show_hidden);
1987 gtk_widget_show (view);
1988
1989 /* set the history of the view if a history is provided */
1990 if (history != NULL)
1991 {
1992 /* history only is updated on 'change-directory' signal. */
1993 /* For inserting a new tab, we need to update it manually */
1994 thunar_history_add (history, directory);
1995
1996 thunar_standard_view_set_history (THUNAR_STANDARD_VIEW (view), history);
1997 }
1998
1999 label_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
2000
2001 label = gtk_label_new (NULL);
2002 exo_binding_new (G_OBJECT (view), "display-name", G_OBJECT (label), "label");
2003 exo_binding_new (G_OBJECT (view), "tooltip-text", G_OBJECT (label), "tooltip-text");
2004 gtk_widget_set_has_tooltip (label, TRUE);
2005 gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
2006 gtk_widget_set_margin_start (GTK_WIDGET(label), 3);
2007 gtk_widget_set_margin_end (GTK_WIDGET(label), 3);
2008 gtk_widget_set_margin_top (GTK_WIDGET(label), 3);
2009 gtk_widget_set_margin_bottom (GTK_WIDGET(label), 3);
2010 gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
2011 gtk_label_set_single_line_mode (GTK_LABEL (label), TRUE);
2012 gtk_box_pack_start (GTK_BOX (label_box), label, TRUE, TRUE, 0);
2013 gtk_widget_show (label);
2014
2015 button = gtk_button_new ();
2016 gtk_box_pack_start (GTK_BOX (label_box), button, FALSE, FALSE, 0);
2017 gtk_widget_set_can_default (button, FALSE);
2018 gtk_widget_set_focus_on_click (button, FALSE);
2019 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
2020 gtk_widget_set_tooltip_text (button, _("Close tab"));
2021 g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (gtk_widget_destroy), view);
2022 gtk_widget_show (button);
2023
2024 icon = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_MENU);
2025 gtk_container_add (GTK_CONTAINER (button), icon);
2026 gtk_widget_show (icon);
2027
2028 /* insert the new page */
2029 gtk_notebook_insert_page (GTK_NOTEBOOK (window->notebook), view, label_box, position);
2030
2031 /* set tab child properties */
2032 gtk_container_child_set (GTK_CONTAINER (window->notebook), view, "tab-expand", TRUE, NULL);
2033 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (window->notebook), view, TRUE);
2034 gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (window->notebook), view, TRUE);
2035
2036 return view;
2037 }
2038
2039
2040
2041 void
thunar_window_notebook_open_new_tab(ThunarWindow * window,ThunarFile * directory)2042 thunar_window_notebook_open_new_tab (ThunarWindow *window,
2043 ThunarFile *directory)
2044 {
2045 ThunarHistory *history = NULL;
2046 GtkWidget *view;
2047 gint page_num;
2048 GType view_type;
2049
2050 /* save the history of the current view */
2051 if (THUNAR_IS_STANDARD_VIEW (window->view))
2052 {
2053 history = thunar_standard_view_copy_history (THUNAR_STANDARD_VIEW (window->view));
2054 }
2055
2056 /* find the correct view type */
2057 view_type = thunar_window_view_type_for_directory (window, directory);
2058
2059 /* insert the new view */
2060 page_num = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
2061 view = thunar_window_notebook_insert (window, directory, view_type, page_num + 1, history);
2062
2063 /* switch to the new view */
2064 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), view);
2065 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page_num);
2066
2067 /* take focus on the new view */
2068 gtk_widget_grab_focus (view);
2069 }
2070
2071
2072
2073 void
thunar_window_update_directories(ThunarWindow * window,ThunarFile * old_directory,ThunarFile * new_directory)2074 thunar_window_update_directories (ThunarWindow *window,
2075 ThunarFile *old_directory,
2076 ThunarFile *new_directory)
2077 {
2078 GtkWidget *view;
2079 ThunarFile *directory;
2080 gint n;
2081 gint n_pages;
2082 gint active_page;
2083
2084 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2085 _thunar_return_if_fail (THUNAR_IS_FILE (old_directory));
2086 _thunar_return_if_fail (THUNAR_IS_FILE (new_directory));
2087
2088 n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
2089 if (G_UNLIKELY (n_pages == 0))
2090 return;
2091
2092 active_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
2093
2094 for (n = 0; n < n_pages; n++)
2095 {
2096 /* get the view */
2097 view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), n);
2098 if (! THUNAR_IS_NAVIGATOR (view))
2099 continue;
2100
2101 /* get the directory of the view */
2102 directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (view));
2103 if (! THUNAR_IS_FILE (directory))
2104 continue;
2105
2106 /* if it matches the old directory, change to the new one */
2107 if (directory == old_directory)
2108 {
2109 if (n == active_page)
2110 thunar_navigator_change_directory (THUNAR_NAVIGATOR (view), new_directory);
2111 else
2112 thunar_navigator_set_current_directory (THUNAR_NAVIGATOR (view), new_directory);
2113 }
2114 }
2115 }
2116
2117
2118
2119 static void
thunar_window_update_location_bar_visible(ThunarWindow * window)2120 thunar_window_update_location_bar_visible (ThunarWindow *window)
2121 {
2122 gchar *last_location_bar = NULL;
2123
2124 g_object_get (window->preferences, "last-location-bar", &last_location_bar, NULL);
2125
2126 if (exo_str_is_equal (last_location_bar, g_type_name (G_TYPE_NONE)))
2127 {
2128 gtk_widget_hide (window->location_toolbar);
2129 gtk_widget_grab_focus (window->view);
2130 }
2131 else
2132 gtk_widget_show (window->location_toolbar);
2133
2134 g_free (last_location_bar);
2135 }
2136
2137
2138
2139 static void
thunar_window_update_window_icon(ThunarWindow * window)2140 thunar_window_update_window_icon (ThunarWindow *window)
2141 {
2142 gboolean change_window_icon;
2143 GtkIconTheme *icon_theme;
2144 const gchar *icon_name = "folder";
2145
2146 g_object_get (window->preferences, "misc-change-window-icon", &change_window_icon, NULL);
2147
2148 if (change_window_icon)
2149 {
2150 icon_theme = gtk_icon_theme_get_for_screen (gtk_window_get_screen (GTK_WINDOW (window)));
2151 icon_name = thunar_file_get_icon_name (window->current_directory,
2152 THUNAR_FILE_ICON_STATE_DEFAULT,
2153 icon_theme);
2154 }
2155
2156 gtk_window_set_icon_name (GTK_WINDOW (window), icon_name);
2157 }
2158
2159
2160
2161 static void
thunar_window_handle_reload_request(ThunarWindow * window)2162 thunar_window_handle_reload_request (ThunarWindow *window)
2163 {
2164 gboolean result;
2165
2166 /* force the view to reload */
2167 g_signal_emit (G_OBJECT (window), window_signals[RELOAD], 0, TRUE, &result);
2168 }
2169
2170
2171
2172 static void
thunar_window_install_sidepane(ThunarWindow * window,GType type)2173 thunar_window_install_sidepane (ThunarWindow *window,
2174 GType type)
2175 {
2176 GtkStyleContext *context;
2177
2178 _thunar_return_if_fail (type == G_TYPE_NONE || g_type_is_a (type, THUNAR_TYPE_SIDE_PANE));
2179 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2180
2181 /* drop the previous side pane (if any) */
2182 if (G_UNLIKELY (window->sidepane != NULL))
2183 {
2184 gtk_widget_destroy (window->sidepane);
2185 window->sidepane = NULL;
2186 }
2187
2188 /* check if we have a new sidepane widget */
2189 if (G_LIKELY (type != G_TYPE_NONE))
2190 {
2191 /* allocate the new side pane widget */
2192 window->sidepane = g_object_new (type, NULL);
2193 gtk_widget_set_size_request (window->sidepane, 0, -1);
2194 exo_binding_new (G_OBJECT (window), "current-directory", G_OBJECT (window->sidepane), "current-directory");
2195 g_signal_connect_swapped (G_OBJECT (window->sidepane), "change-directory", G_CALLBACK (thunar_window_set_current_directory), window);
2196 g_signal_connect_swapped (G_OBJECT (window->sidepane), "open-new-tab", G_CALLBACK (thunar_window_notebook_open_new_tab), window);
2197 context = gtk_widget_get_style_context (window->sidepane);
2198 gtk_style_context_add_class (context, "sidebar");
2199 gtk_paned_pack1 (GTK_PANED (window->paned), window->sidepane, FALSE, FALSE);
2200 gtk_widget_show (window->sidepane);
2201
2202 /* connect the side pane widget to the view (if any) */
2203 if (G_LIKELY (window->view != NULL))
2204 thunar_window_binding_create (window, window->view, "selected-files", window->sidepane, "selected-files", G_BINDING_SYNC_CREATE);
2205
2206 /* apply show_hidden config to tree pane */
2207 if (type == THUNAR_TYPE_TREE_PANE)
2208 thunar_side_pane_set_show_hidden (THUNAR_SIDE_PANE (window->sidepane), window->show_hidden);
2209 }
2210
2211 /* remember the setting */
2212 if (gtk_widget_get_visible (GTK_WIDGET (window)))
2213 g_object_set (G_OBJECT (window->preferences), "last-side-pane", g_type_name (type), NULL);
2214 }
2215
2216
2217
2218 static gchar*
thunar_window_bookmark_get_accel_path(GFile * bookmark_file)2219 thunar_window_bookmark_get_accel_path (GFile *bookmark_file)
2220 {
2221 GChecksum *checksum;
2222 gchar *uri;
2223 gchar *accel_path;
2224 const gchar *unique_name;
2225
2226 _thunar_return_val_if_fail (G_IS_FILE (bookmark_file), NULL);
2227
2228 /* create unique id based on the uri */
2229 uri = g_file_get_uri (bookmark_file);
2230 checksum = g_checksum_new (G_CHECKSUM_MD5);
2231 g_checksum_update (checksum, (const guchar *) uri, strlen (uri));
2232 unique_name = g_checksum_get_string (checksum);
2233 accel_path = g_strconcat("<Actions>/ThunarBookmarks/", unique_name, NULL);
2234
2235 g_free (uri);
2236 g_checksum_free (checksum);
2237 return accel_path;
2238 }
2239
2240
2241
2242 static void
thunar_window_menu_add_bookmarks(ThunarWindow * window,GtkMenuShell * view_menu)2243 thunar_window_menu_add_bookmarks (ThunarWindow *window,
2244 GtkMenuShell *view_menu)
2245 {
2246 GList *lp;
2247 ThunarBookmark *bookmark;
2248 ThunarFile *thunar_file;
2249 gchar *parse_name;
2250 gchar *accel_path;
2251 gchar *tooltip;
2252 const gchar *name;
2253 gchar *remote_name;
2254 GtkIconTheme *icon_theme;
2255 const gchar *icon_name;
2256
2257 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2258
2259 for (lp = window->bookmarks; lp != NULL; lp = lp->next)
2260 {
2261 bookmark = lp->data;
2262 accel_path = thunar_window_bookmark_get_accel_path (bookmark->g_file);
2263 parse_name = g_file_get_parse_name (bookmark->g_file);
2264 tooltip = g_strdup_printf (_("Open the location \"%s\""), parse_name);
2265 g_free (parse_name);
2266
2267 if (g_file_has_uri_scheme (bookmark->g_file, "file"))
2268 {
2269 /* try to open the file corresponding to the uri */
2270 thunar_file = thunar_file_get (bookmark->g_file, NULL);
2271 if (G_LIKELY (thunar_file != NULL))
2272 {
2273 /* make sure the file refers to a directory */
2274 if (G_UNLIKELY (thunar_file_is_directory (thunar_file)))
2275 {
2276 name = bookmark->name;
2277 if (bookmark->name == NULL)
2278 name = thunar_file_get_display_name (thunar_file);
2279
2280 icon_theme = gtk_icon_theme_get_for_screen (gtk_window_get_screen (GTK_WINDOW (window)));
2281 icon_name = thunar_file_get_icon_name (thunar_file, THUNAR_FILE_ICON_STATE_DEFAULT, icon_theme);
2282 xfce_gtk_image_menu_item_new_from_icon_name (name, tooltip, accel_path, G_CALLBACK (thunar_window_action_open_bookmark), G_OBJECT (bookmark->g_file), icon_name, view_menu);
2283 }
2284 g_object_unref (thunar_file);
2285 }
2286 }
2287 else
2288 {
2289 if (bookmark->name == NULL)
2290 remote_name = thunar_g_file_get_display_name_remote (bookmark->g_file);
2291 else
2292 remote_name = g_strdup (bookmark->name);
2293 xfce_gtk_image_menu_item_new_from_icon_name (remote_name, tooltip, accel_path, G_CALLBACK (thunar_window_action_open_bookmark), G_OBJECT (bookmark->g_file), "folder-remote", view_menu);
2294 g_free (remote_name);
2295 }
2296
2297 g_free (tooltip);
2298 g_free (accel_path);
2299 }
2300 }
2301
2302
2303
2304 static ThunarBookmark *
thunar_window_bookmark_add(ThunarWindow * window,GFile * g_file,const gchar * name)2305 thunar_window_bookmark_add (ThunarWindow *window,
2306 GFile *g_file,
2307 const gchar *name)
2308 {
2309 ThunarBookmark *bookmark;
2310
2311 bookmark = g_slice_new0 (ThunarBookmark);
2312 bookmark->g_file = g_object_ref (g_file);
2313 bookmark->name = g_strdup (name);
2314
2315 window->bookmarks = g_list_append (window->bookmarks, bookmark);
2316 return bookmark;
2317 }
2318
2319
2320
2321 static void
thunar_window_free_bookmarks(ThunarWindow * window)2322 thunar_window_free_bookmarks (ThunarWindow *window)
2323 {
2324 GList *lp;
2325 ThunarBookmark *bookmark;
2326
2327 for (lp = window->bookmarks; lp != NULL; lp = lp->next)
2328 {
2329 bookmark = lp->data;
2330 g_object_unref (bookmark->g_file);
2331 g_free (bookmark->name);
2332 g_slice_free (ThunarBookmark, lp->data);
2333 }
2334 window->bookmarks = NULL;
2335 }
2336
2337
2338
2339 static void
thunar_window_update_bookmark(GFile * g_file,const gchar * name,gint line_num,gpointer user_data)2340 thunar_window_update_bookmark (GFile *g_file,
2341 const gchar *name,
2342 gint line_num,
2343 gpointer user_data)
2344 {
2345 ThunarWindow *window = THUNAR_WINDOW (user_data);
2346 gchar *accel_path;
2347 XfceGtkActionEntry entry[1];
2348
2349 _thunar_return_if_fail (G_IS_FILE (g_file));
2350 _thunar_return_if_fail (name == NULL || g_utf8_validate (name, -1, NULL));
2351 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2352
2353 /* Add the bookmark to our internal list of bookmarks */
2354 thunar_window_bookmark_add (window, g_file, name);
2355
2356 /* Add ref to window to each g_file, will be needed in callback */
2357 g_object_set_data_full (G_OBJECT (g_file), I_("thunar-window"), window, NULL);
2358
2359 /* Build a minimal XfceGtkActionEntry in order to be able to use the methods below */
2360 accel_path = thunar_window_bookmark_get_accel_path (g_file);
2361 entry[0].accel_path = accel_path;
2362 entry[0].callback = G_CALLBACK (thunar_window_action_open_bookmark);
2363 entry[0].default_accelerator = "";
2364
2365 /* Add entry, so that the bookmark can loaded/saved to acceels.scm (will be skipped if already available)*/
2366 xfce_gtk_accel_map_add_entries (entry, G_N_ELEMENTS (entry));
2367
2368 /* Link action with callback */
2369 xfce_gtk_accel_group_disconnect_action_entries (window->accel_group, entry, G_N_ELEMENTS (entry));
2370 xfce_gtk_accel_group_connect_action_entries (window->accel_group, entry, G_N_ELEMENTS (entry), g_file);
2371 g_free (accel_path);
2372 }
2373
2374
2375
2376 static void
thunar_window_update_bookmarks(ThunarWindow * window)2377 thunar_window_update_bookmarks (ThunarWindow *window)
2378 {
2379 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2380
2381 thunar_window_free_bookmarks (window);
2382
2383 /* re-create our internal bookmarks according to the bookmark file */
2384 thunar_util_load_bookmarks (window->bookmark_file,
2385 thunar_window_update_bookmark,
2386 window);
2387 }
2388
2389
2390
2391 static void
thunar_window_open_or_launch(ThunarWindow * window,ThunarFile * file)2392 thunar_window_open_or_launch (ThunarWindow *window,
2393 ThunarFile *file)
2394 {
2395 GError *error = NULL;
2396
2397 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2398 _thunar_return_if_fail (THUNAR_IS_FILE (file));
2399
2400 if (thunar_file_is_directory (file))
2401 {
2402 /* open the new directory */
2403 thunar_window_set_current_directory (window, file);
2404 }
2405 else
2406 {
2407 /* try to launch the selected file */
2408 if (!thunar_file_launch (file, window, NULL, &error))
2409 {
2410 thunar_dialogs_show_error (window, error, _("Failed to launch \"%s\""),
2411 thunar_file_get_display_name (file));
2412 g_error_free (error);
2413 }
2414 }
2415 }
2416
2417
2418
2419 static void
thunar_window_poke_file_finish(ThunarBrowser * browser,ThunarFile * file,ThunarFile * target_file,GError * error,gpointer ignored)2420 thunar_window_poke_file_finish (ThunarBrowser *browser,
2421 ThunarFile *file,
2422 ThunarFile *target_file,
2423 GError *error,
2424 gpointer ignored)
2425 {
2426 _thunar_return_if_fail (THUNAR_IS_WINDOW (browser));
2427 _thunar_return_if_fail (THUNAR_IS_FILE (file));
2428
2429 if (error == NULL)
2430 {
2431 thunar_window_open_or_launch (THUNAR_WINDOW (browser), target_file);
2432 }
2433 else
2434 {
2435 thunar_dialogs_show_error (GTK_WIDGET (browser), error,
2436 _("Failed to open \"%s\""),
2437 thunar_file_get_display_name (file));
2438 }
2439 }
2440
2441
2442
2443 static void
thunar_window_start_open_location(ThunarWindow * window,const gchar * initial_text)2444 thunar_window_start_open_location (ThunarWindow *window,
2445 const gchar *initial_text)
2446 {
2447 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2448
2449 /* temporary show the location toolbar, even if it is normally hidden */
2450 gtk_widget_show (window->location_toolbar);
2451 thunar_location_bar_request_entry (THUNAR_LOCATION_BAR (window->location_bar), initial_text);
2452 }
2453
2454
2455
2456 static void
thunar_window_action_open_new_tab(ThunarWindow * window,GtkWidget * menu_item)2457 thunar_window_action_open_new_tab (ThunarWindow *window,
2458 GtkWidget *menu_item)
2459 {
2460 /* open new tab with current directory as default */
2461 thunar_window_notebook_open_new_tab (window, thunar_window_get_current_directory (window));
2462 }
2463
2464
2465
2466 static void
thunar_window_action_open_new_window(ThunarWindow * window,GtkWidget * menu_item)2467 thunar_window_action_open_new_window (ThunarWindow *window,
2468 GtkWidget *menu_item)
2469 {
2470 ThunarApplication *application;
2471 ThunarHistory *history;
2472 ThunarWindow *new_window;
2473 ThunarFile *start_file;
2474
2475 /* popup a new window */
2476 application = thunar_application_get ();
2477 new_window = THUNAR_WINDOW (thunar_application_open_window (application, window->current_directory,
2478 gtk_widget_get_screen (GTK_WIDGET (window)), NULL, TRUE));
2479 g_object_unref (G_OBJECT (application));
2480
2481 /* if we have no origin view we are done */
2482 if (window->view == NULL)
2483 return;
2484
2485 /* let the view of the new window inherit the history of the origin view */
2486 history = thunar_standard_view_copy_history (THUNAR_STANDARD_VIEW (window->view));
2487 if (history != NULL)
2488 {
2489 thunar_standard_view_set_history (THUNAR_STANDARD_VIEW (new_window->view), history);
2490 thunar_window_history_changed (new_window);
2491
2492 /* connect to the new history */
2493 window->signal_handler_id_history_changed = g_signal_connect_swapped (G_OBJECT (history), "history-changed", G_CALLBACK (thunar_window_history_changed), new_window);
2494 }
2495
2496 /* determine the first visible file in the current window */
2497 if (thunar_view_get_visible_range (THUNAR_VIEW (window->view), &start_file, NULL))
2498 {
2499 /* scroll the new window to the same file */
2500 thunar_window_scroll_to_file (new_window, start_file, FALSE, TRUE, 0.1f, 0.1f);
2501
2502 /* release the file reference */
2503 g_object_unref (G_OBJECT (start_file));
2504 }
2505 }
2506
2507
2508
2509 static void
thunar_window_action_detach_tab(ThunarWindow * window,GtkWidget * menu_item)2510 thunar_window_action_detach_tab (ThunarWindow *window,
2511 GtkWidget *menu_item)
2512 {
2513 GtkWidget *notebook;
2514 GtkWidget *label;
2515 GtkWidget *view = window->view;
2516
2517 _thunar_return_if_fail (THUNAR_IS_VIEW (view));
2518 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2519
2520 /* create a new window */
2521 notebook = thunar_window_notebook_create_window (window->notebook, view, -1, -1, window);
2522 if (notebook == NULL)
2523 return;
2524
2525 /* get the current label */
2526 label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (window->notebook), view);
2527 _thunar_return_if_fail (GTK_IS_WIDGET (label));
2528
2529 /* ref object so they don't destroy when removed from the container */
2530 g_object_ref (label);
2531 g_object_ref (view);
2532
2533 /* remove view from the current notebook */
2534 gtk_container_remove (GTK_CONTAINER (window->notebook), view);
2535
2536 /* insert in the new notebook */
2537 gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), view, label, 0);
2538
2539 /* set tab child properties */
2540 gtk_container_child_set (GTK_CONTAINER (notebook), view, "tab-expand", TRUE, NULL);
2541 gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (notebook), view, TRUE);
2542 gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (notebook), view, TRUE);
2543
2544 /* release */
2545 g_object_unref (label);
2546 g_object_unref (view);
2547 }
2548
2549
2550
2551 static void
thunar_window_action_close_all_windows(ThunarWindow * window,GtkWidget * menu_item)2552 thunar_window_action_close_all_windows (ThunarWindow *window,
2553 GtkWidget *menu_item)
2554 {
2555 ThunarApplication *application;
2556 GList *windows;
2557
2558 /* query the list of currently open windows */
2559 application = thunar_application_get ();
2560 windows = thunar_application_get_windows (application);
2561 g_object_unref (G_OBJECT (application));
2562
2563 /* destroy all open windows */
2564 g_list_free_full (windows, (GDestroyNotify) gtk_widget_destroy);
2565 }
2566
2567
2568
2569 static void
thunar_window_action_close_tab(ThunarWindow * window,GtkWidget * menu_item)2570 thunar_window_action_close_tab (ThunarWindow *window,
2571 GtkWidget *menu_item)
2572 {
2573 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) == 1)
2574 gtk_widget_destroy (GTK_WIDGET (window));
2575 else if (window->view != NULL)
2576 gtk_widget_destroy (window->view);
2577 }
2578
2579
2580
2581 static void
thunar_window_action_close_window(ThunarWindow * window,GtkWidget * menu_item)2582 thunar_window_action_close_window (ThunarWindow *window,
2583 GtkWidget *menu_item)
2584 {
2585 gtk_widget_destroy (GTK_WIDGET (window));
2586 }
2587
2588
2589
2590 static void
thunar_window_action_preferences(ThunarWindow * window,GtkWidget * menu_item)2591 thunar_window_action_preferences (ThunarWindow *window,
2592 GtkWidget *menu_item)
2593 {
2594 GtkWidget *dialog;
2595 ThunarApplication *application;
2596
2597 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2598
2599 /* allocate and display a preferences dialog */;
2600 dialog = thunar_preferences_dialog_new (GTK_WINDOW (window));
2601 gtk_widget_show (dialog);
2602
2603 /* ...and let the application take care of it */
2604 application = thunar_application_get ();
2605 thunar_application_take_window (application, GTK_WINDOW (dialog));
2606 g_object_unref (G_OBJECT (application));
2607 }
2608
2609
2610
2611 static void
thunar_window_action_reload(ThunarWindow * window,GtkWidget * menu_item)2612 thunar_window_action_reload (ThunarWindow *window,
2613 GtkWidget *menu_item)
2614 {
2615 gboolean result;
2616
2617 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2618
2619 /* force the view to reload */
2620 g_signal_emit (G_OBJECT (window), window_signals[RELOAD], 0, TRUE, &result);
2621
2622 /* update the location bar to show the current directory */
2623 if (window->location_bar != NULL)
2624 g_object_notify (G_OBJECT (window->location_bar), "current-directory");
2625 }
2626
2627
2628
2629 static void
thunar_window_action_pathbar_changed(ThunarWindow * window)2630 thunar_window_action_pathbar_changed (ThunarWindow *window)
2631 {
2632 gchar *last_location_bar;
2633 gboolean pathbar_checked;
2634
2635 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2636
2637 g_object_get (window->preferences, "last-location-bar", &last_location_bar, NULL);
2638 pathbar_checked = exo_str_is_equal (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_ENTRY));
2639 g_free (last_location_bar);
2640
2641 if (pathbar_checked)
2642 g_object_set (window->preferences, "last-location-bar", g_type_name (G_TYPE_NONE), NULL);
2643 else
2644 g_object_set (window->preferences, "last-location-bar", g_type_name (THUNAR_TYPE_LOCATION_ENTRY), NULL);
2645 }
2646
2647
2648
2649 static void
thunar_window_action_toolbar_changed(ThunarWindow * window)2650 thunar_window_action_toolbar_changed (ThunarWindow *window)
2651 {
2652 gchar *last_location_bar;
2653 gboolean toolbar_checked;
2654
2655 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2656
2657 g_object_get (window->preferences, "last-location-bar", &last_location_bar, NULL);
2658 toolbar_checked = exo_str_is_equal (last_location_bar, g_type_name (THUNAR_TYPE_LOCATION_BUTTONS));
2659 g_free (last_location_bar);
2660
2661 if (toolbar_checked)
2662 g_object_set (window->preferences, "last-location-bar", g_type_name (G_TYPE_NONE), NULL);
2663 else
2664 g_object_set (window->preferences, "last-location-bar", g_type_name (THUNAR_TYPE_LOCATION_BUTTONS), NULL);
2665 }
2666
2667
2668
2669 static void
thunar_window_action_shortcuts_changed(ThunarWindow * window)2670 thunar_window_action_shortcuts_changed (ThunarWindow *window)
2671 {
2672 gchar *last_side_pane;
2673 gboolean shortcuts_checked;
2674 GType type = G_TYPE_NONE;
2675
2676 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2677
2678 g_object_get (window->preferences, "last-side-pane", &last_side_pane, NULL);
2679 shortcuts_checked = exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_SHORTCUTS_PANE));
2680 g_free (last_side_pane);
2681
2682 if (shortcuts_checked)
2683 type = G_TYPE_NONE;
2684 else
2685 type = THUNAR_TYPE_SHORTCUTS_PANE;
2686
2687 thunar_window_install_sidepane (window, type);
2688 }
2689
2690
2691
2692 static void
thunar_window_action_tree_changed(ThunarWindow * window)2693 thunar_window_action_tree_changed (ThunarWindow *window)
2694 {
2695 gchar *last_side_pane;
2696 gboolean tree_view_checked;
2697 GType type = G_TYPE_NONE;
2698
2699 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2700
2701 g_object_get (window->preferences, "last-side-pane", &last_side_pane, NULL);
2702 tree_view_checked = exo_str_is_equal (last_side_pane, g_type_name (THUNAR_TYPE_TREE_PANE));
2703 g_free (last_side_pane);
2704
2705 if (tree_view_checked)
2706 type = G_TYPE_NONE;
2707 else
2708 type = THUNAR_TYPE_TREE_PANE;
2709
2710 thunar_window_install_sidepane (window, type);
2711 }
2712
2713
2714
2715 static void
thunar_window_action_statusbar_changed(ThunarWindow * window)2716 thunar_window_action_statusbar_changed (ThunarWindow *window)
2717 {
2718 gboolean last_statusbar_visible;
2719
2720 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2721
2722 g_object_get (window->preferences, "last-statusbar-visible", &last_statusbar_visible, NULL);
2723
2724 gtk_widget_set_visible (window->statusbar, !last_statusbar_visible);
2725
2726 g_object_set (G_OBJECT (window->preferences), "last-statusbar-visible", !last_statusbar_visible, NULL);
2727 }
2728
2729
2730
2731 static void
thunar_window_action_menubar_update(ThunarWindow * window)2732 thunar_window_action_menubar_update (ThunarWindow *window)
2733 {
2734 gboolean last_menubar_visible;
2735
2736 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2737
2738 g_object_get (window->preferences, "last-menubar-visible", &last_menubar_visible, NULL);
2739
2740 gtk_widget_set_visible (window->menubar, last_menubar_visible);
2741 }
2742
2743
2744
2745 static void
thunar_window_action_menubar_changed(ThunarWindow * window)2746 thunar_window_action_menubar_changed (ThunarWindow *window)
2747 {
2748 gboolean last_menubar_visible;
2749
2750 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2751
2752 g_object_get (window->preferences, "last-menubar-visible", &last_menubar_visible, NULL);
2753
2754 gtk_widget_set_visible (window->menubar, !last_menubar_visible);
2755
2756 g_object_set (G_OBJECT (window->preferences), "last-menubar-visible", !last_menubar_visible, NULL);
2757 }
2758
2759
2760
2761 static void
thunar_window_action_clear_directory_specific_settings(ThunarWindow * window)2762 thunar_window_action_clear_directory_specific_settings (ThunarWindow *window)
2763 {
2764 GType view_type;
2765 gboolean result;
2766
2767 /* clear the settings */
2768 thunar_file_clear_directory_specific_settings (window->current_directory);
2769
2770 /* get the correct view type for the current directory */
2771 view_type = thunar_window_view_type_for_directory (window, window->current_directory);
2772
2773 /* force the view to reload so that any changes to the settings are applied */
2774 g_signal_emit (G_OBJECT (window), window_signals[RELOAD], 0, TRUE, &result);
2775
2776 /* replace the active view with a new one of the correct type */
2777 thunar_window_replace_view (window, window->view, view_type);
2778 }
2779
2780
2781
2782 static void
thunar_window_action_detailed_view(ThunarWindow * window)2783 thunar_window_action_detailed_view (ThunarWindow *window)
2784 {
2785 thunar_window_action_view_changed (window, THUNAR_TYPE_DETAILS_VIEW);
2786 }
2787
2788
2789
2790 static void
thunar_window_action_icon_view(ThunarWindow * window)2791 thunar_window_action_icon_view (ThunarWindow *window)
2792 {
2793 thunar_window_action_view_changed (window, THUNAR_TYPE_ICON_VIEW);
2794 }
2795
2796
2797
2798 static void
thunar_window_action_compact_view(ThunarWindow * window)2799 thunar_window_action_compact_view (ThunarWindow *window)
2800 {
2801 thunar_window_action_view_changed (window, THUNAR_TYPE_COMPACT_VIEW);
2802 }
2803
2804
2805
2806 static void
thunar_window_replace_view(ThunarWindow * window,GtkWidget * view,GType view_type)2807 thunar_window_replace_view (ThunarWindow *window,
2808 GtkWidget *view,
2809 GType view_type)
2810 {
2811 ThunarFile *file = NULL;
2812 ThunarFile *current_directory = NULL;
2813 GtkWidget *new_view;
2814 ThunarHistory *history = NULL;
2815 GList *selected_files = NULL;
2816 gint page_num;
2817 gboolean is_current_view;
2818
2819 _thunar_return_if_fail (view_type != G_TYPE_NONE);
2820
2821 /* if the view already has the correct type then just return */
2822 if (view != NULL && G_TYPE_FROM_INSTANCE (view) == view_type)
2823 return;
2824
2825 /* is the view we are replacing the active view?
2826 * (note that this will be true if both view and window->view are NULL) */
2827 is_current_view = (view == window->view);
2828
2829 /* save some settings from the old view for the new view */
2830 if (view != NULL)
2831 {
2832 /* disconnect from previous history if the old view is the active view */
2833 if (is_current_view && window->signal_handler_id_history_changed != 0)
2834 {
2835 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (view));
2836 g_signal_handler_disconnect (history, window->signal_handler_id_history_changed);
2837 window->signal_handler_id_history_changed = 0;
2838 }
2839
2840 /* get first visible file in the old view */
2841 if (!thunar_view_get_visible_range (THUNAR_VIEW (view), &file, NULL))
2842 file = NULL;
2843
2844 /* store the active directory from the old view */
2845 current_directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (view));
2846 if (current_directory != NULL)
2847 g_object_ref (current_directory);
2848
2849 /* remember the file selection from the old view */
2850 selected_files = thunar_g_file_list_copy (thunar_component_get_selected_files (THUNAR_COMPONENT (view)));
2851
2852 /* save the history of the current view */
2853 history = NULL;
2854 if (THUNAR_IS_STANDARD_VIEW (view))
2855 history = thunar_standard_view_copy_history (THUNAR_STANDARD_VIEW (view));
2856 }
2857
2858 if (is_current_view)
2859 window->view_type = view_type;
2860
2861 /* if we have not got a current directory from the old view, use the window's current directory */
2862 if (current_directory == NULL && window->current_directory != NULL)
2863 current_directory = g_object_ref (window->current_directory);
2864
2865 _thunar_assert (current_directory != NULL);
2866
2867 /* find where to insert the new view */
2868 if (view != NULL)
2869 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), view);
2870 else
2871 page_num = -1;
2872
2873 /* insert the new view */
2874 new_view = thunar_window_notebook_insert (window, current_directory, view_type, page_num + 1, history);
2875
2876 /* if we are replacing the active view, make the new view the active view */
2877 if (is_current_view)
2878 {
2879 /* switch to the new view */
2880 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->notebook), new_view);
2881 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), page_num);
2882
2883 /* take focus on the new view */
2884 gtk_widget_grab_focus (new_view);
2885 }
2886
2887 /* scroll to the previously visible file in the old view */
2888 if (G_UNLIKELY (file != NULL))
2889 thunar_view_scroll_to_file (THUNAR_VIEW (new_view), file, FALSE, TRUE, 0.0f, 0.0f);
2890
2891 /* destroy the old view */
2892 if (view != NULL)
2893 gtk_widget_destroy (view);
2894
2895 /* restore the file selection */
2896 thunar_component_set_selected_files (THUNAR_COMPONENT (new_view), selected_files);
2897 thunar_g_file_list_free (selected_files);
2898
2899 /* remember the last view type if this is the active view and directory specific settings are not enabled */
2900 if (is_current_view && !window->directory_specific_settings && gtk_widget_get_visible (GTK_WIDGET (window)) && view_type != G_TYPE_NONE)
2901 g_object_set (G_OBJECT (window->preferences), "last-view", g_type_name (view_type), NULL);
2902
2903 /* release the file references */
2904 if (G_UNLIKELY (file != NULL))
2905 g_object_unref (G_OBJECT (file));
2906 if (G_UNLIKELY (current_directory != NULL))
2907 g_object_unref (G_OBJECT (current_directory));
2908
2909 /* connect to the new history if this is the active view */
2910 if (is_current_view)
2911 {
2912 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (new_view));
2913 window->signal_handler_id_history_changed = g_signal_connect_swapped (G_OBJECT (history),
2914 "history-changed",
2915 G_CALLBACK (thunar_window_history_changed),
2916 window);
2917 }
2918 }
2919
2920
2921
2922 static void
thunar_window_action_view_changed(ThunarWindow * window,GType view_type)2923 thunar_window_action_view_changed (ThunarWindow *window,
2924 GType view_type)
2925 {
2926 thunar_window_replace_view (window, window->view, view_type);
2927
2928 /* if directory specific settings are enabled, save the view type for this directory */
2929 if (window->directory_specific_settings)
2930 thunar_file_set_metadata_setting (window->current_directory, "view-type", g_type_name (view_type));
2931 }
2932
2933
2934
2935 static void
thunar_window_action_go_up(ThunarWindow * window)2936 thunar_window_action_go_up (ThunarWindow *window)
2937 {
2938 ThunarFile *parent;
2939 GError *error = NULL;
2940
2941 parent = thunar_file_get_parent (window->current_directory, &error);
2942 if (G_LIKELY (parent != NULL))
2943 {
2944 thunar_window_set_current_directory (window, parent);
2945 g_object_unref (G_OBJECT (parent));
2946 }
2947 else
2948 {
2949 /* the root folder '/' has no parent. In this special case we do not need a dialog */
2950 if (error->code != G_FILE_ERROR_NOENT)
2951 {
2952 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to open parent folder"));
2953 }
2954 g_error_free (error);
2955 }
2956 }
2957
2958
2959
2960 static void
thunar_window_action_back(ThunarWindow * window)2961 thunar_window_action_back (ThunarWindow *window)
2962 {
2963 ThunarHistory *history;
2964
2965 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2966
2967 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
2968 thunar_history_action_back (history);
2969 }
2970
2971
2972
2973 static void
thunar_window_action_forward(ThunarWindow * window)2974 thunar_window_action_forward (ThunarWindow *window)
2975 {
2976 ThunarHistory *history;
2977
2978 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2979
2980 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
2981 thunar_history_action_forward (history);
2982 }
2983
2984
2985
2986 static void
thunar_window_action_open_home(ThunarWindow * window)2987 thunar_window_action_open_home (ThunarWindow *window)
2988 {
2989 GFile *home;
2990 ThunarFile *home_file;
2991 GError *error = NULL;
2992
2993 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
2994
2995 /* determine the path to the home directory */
2996 home = thunar_g_file_new_for_home ();
2997
2998 /* determine the file for the home directory */
2999 home_file = thunar_file_get (home, &error);
3000 if (G_UNLIKELY (home_file == NULL))
3001 {
3002 /* display an error to the user */
3003 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to open the home folder"));
3004 g_error_free (error);
3005 }
3006 else
3007 {
3008 /* open the home folder */
3009 thunar_window_set_current_directory (window, home_file);
3010 g_object_unref (G_OBJECT (home_file));
3011 }
3012
3013 /* release our reference on the home path */
3014 g_object_unref (home);
3015 }
3016
3017
3018
3019 static gboolean
thunar_window_open_user_folder(ThunarWindow * window,GUserDirectory thunar_user_dir,const gchar * default_name)3020 thunar_window_open_user_folder (ThunarWindow *window,
3021 GUserDirectory thunar_user_dir,
3022 const gchar *default_name)
3023 {
3024 ThunarFile *user_file = NULL;
3025 gboolean result = FALSE;
3026 GError *error = NULL;
3027 GFile *home_dir;
3028 GFile *user_dir;
3029 const gchar *path;
3030 gint response;
3031 GtkWidget *dialog;
3032 gchar *parse_name;
3033
3034 path = g_get_user_special_dir (thunar_user_dir);
3035 home_dir = thunar_g_file_new_for_home ();
3036
3037 /* check if there is an entry in user-dirs.dirs */
3038 path = g_get_user_special_dir (thunar_user_dir);
3039 if (G_LIKELY (path != NULL))
3040 {
3041 user_dir = g_file_new_for_path (path);
3042
3043 /* if equal to home, leave */
3044 if (g_file_equal (user_dir, home_dir))
3045 goto is_homedir;
3046 }
3047 else
3048 {
3049 /* build a name */
3050 user_dir = g_file_resolve_relative_path (home_dir, default_name);
3051 }
3052
3053 /* try to load the user dir */
3054 user_file = thunar_file_get (user_dir, NULL);
3055
3056 /* check if the directory exists */
3057 if (G_UNLIKELY (user_file == NULL || !thunar_file_exists (user_file)))
3058 {
3059 /* release the instance if it does not exist */
3060 if (user_file != NULL)
3061 {
3062 g_object_unref (user_file);
3063 user_file = NULL;
3064 }
3065
3066 /* ask the user to create the directory */
3067 parse_name = g_file_get_parse_name (user_dir);
3068 dialog = gtk_message_dialog_new (GTK_WINDOW (window),
3069 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
3070 GTK_MESSAGE_QUESTION,
3071 GTK_BUTTONS_YES_NO,
3072 _("The directory \"%s\" does not exist. Do you want to create it?"),
3073 parse_name);
3074 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);
3075 response = gtk_dialog_run (GTK_DIALOG (dialog));
3076 gtk_widget_destroy (dialog);
3077 g_free (parse_name);
3078
3079 if (response == GTK_RESPONSE_YES
3080 && g_file_make_directory_with_parents (user_dir, NULL, &error))
3081 {
3082 /* try again */
3083 user_file = thunar_file_get (user_dir, &error);
3084 }
3085 }
3086
3087 if (G_LIKELY (user_file != NULL))
3088 {
3089 /* open the folder */
3090 thunar_window_set_current_directory (window, user_file);
3091 g_object_unref (G_OBJECT (user_file));
3092 result = TRUE;
3093 }
3094 else if (error != NULL)
3095 {
3096 parse_name = g_file_get_parse_name (user_dir);
3097 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to open directory \"%s\""), parse_name);
3098 g_free (parse_name);
3099 g_error_free (error);
3100 }
3101
3102 is_homedir:
3103
3104 g_object_unref (user_dir);
3105 g_object_unref (home_dir);
3106
3107 return result;
3108 }
3109
3110
3111
3112 static void
thunar_window_action_open_desktop(ThunarWindow * window)3113 thunar_window_action_open_desktop (ThunarWindow *window)
3114 {
3115 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3116
3117 thunar_window_open_user_folder (window, G_USER_DIRECTORY_DESKTOP, "Desktop");
3118 }
3119
3120
3121
3122 static void
thunar_window_action_open_computer(ThunarWindow * window)3123 thunar_window_action_open_computer (ThunarWindow *window)
3124 {
3125 GFile *computer;
3126 ThunarFile *computer_file;
3127 GError *error = NULL;
3128
3129 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3130
3131 /* determine the computer location */
3132 computer = g_file_new_for_uri ("computer://");
3133
3134 /* determine the file for this location */
3135 computer_file = thunar_file_get (computer, &error);
3136 if (G_UNLIKELY (computer_file == NULL))
3137 {
3138 /* display an error to the user */
3139 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to browse the computer"));
3140 g_error_free (error);
3141 }
3142 else
3143 {
3144 /* open the computer location */
3145 thunar_window_set_current_directory (window, computer_file);
3146 g_object_unref (G_OBJECT (computer_file));
3147 }
3148
3149 /* release our reference on the location itself */
3150 g_object_unref (computer);
3151 }
3152
3153
3154
3155 static void
thunar_window_action_open_templates(ThunarWindow * window)3156 thunar_window_action_open_templates (ThunarWindow *window)
3157 {
3158 GtkWidget *dialog;
3159 GtkWidget *button;
3160 GtkWidget *label;
3161 GtkWidget *image;
3162 GtkWidget *hbox;
3163 GtkWidget *vbox;
3164 gboolean show_about_templates;
3165 gboolean success;
3166
3167 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3168
3169 success = thunar_window_open_user_folder (window, G_USER_DIRECTORY_TEMPLATES, "Templates");
3170
3171 /* check whether we should display the "About Templates" dialog */
3172 g_object_get (G_OBJECT (window->preferences),
3173 "misc-show-about-templates", &show_about_templates,
3174 NULL);
3175
3176 if (G_UNLIKELY(show_about_templates && success))
3177 {
3178 /* display the "About Templates" dialog */
3179 dialog = gtk_dialog_new_with_buttons (_("About Templates"), GTK_WINDOW (window),
3180 GTK_DIALOG_DESTROY_WITH_PARENT,
3181 _("_OK"), GTK_RESPONSE_OK,
3182 NULL);
3183
3184 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
3185
3186 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
3187 gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
3188 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, TRUE, TRUE, 0);
3189 gtk_widget_show (hbox);
3190
3191 image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_DIALOG);
3192 gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
3193 gtk_widget_set_valign (image, GTK_ALIGN_START);
3194 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
3195 gtk_widget_show (image);
3196
3197 vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
3198 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
3199 gtk_widget_show (vbox);
3200
3201 label = gtk_label_new (_("All files in this folder will appear in the \"Create Document\" menu."));
3202 gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
3203 gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_big_bold ());
3204 gtk_label_set_line_wrap (GTK_LABEL (label), FALSE);
3205 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
3206 gtk_widget_show (label);
3207
3208 label = gtk_label_new (_("If you frequently create certain kinds "
3209 " of documents, make a copy of one and put it in this "
3210 "folder. Thunar will add an entry for this document in the"
3211 " \"Create Document\" menu.\n\n"
3212 "You can then select the entry from the \"Create Document\" "
3213 "menu and a copy of the document will be created in the "
3214 "directory you are viewing."));
3215 gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
3216 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3217 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3218 gtk_widget_show (label);
3219
3220 button = gtk_check_button_new_with_mnemonic (_("Do _not display this message again"));
3221 exo_mutual_binding_new_with_negation (G_OBJECT (window->preferences), "misc-show-about-templates", G_OBJECT (button), "active");
3222 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3223 gtk_widget_show (button);
3224
3225 gtk_window_set_default_size (GTK_WINDOW (dialog), 600, -1);
3226
3227 gtk_dialog_run (GTK_DIALOG (dialog));
3228 gtk_widget_destroy (dialog);
3229 }
3230 }
3231
3232
3233
3234 static void
thunar_window_action_open_file_system(ThunarWindow * window)3235 thunar_window_action_open_file_system (ThunarWindow *window)
3236 {
3237 GFile *root;
3238 ThunarFile *root_file;
3239 GError *error = NULL;
3240
3241 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3242
3243 /* determine the path to the root directory */
3244 root = thunar_g_file_new_for_root ();
3245
3246 /* determine the file for the root directory */
3247 root_file = thunar_file_get (root, &error);
3248 if (G_UNLIKELY (root_file == NULL))
3249 {
3250 /* display an error to the user */
3251 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to open the file system root folder"));
3252 g_error_free (error);
3253 }
3254 else
3255 {
3256 /* open the root folder */
3257 thunar_window_set_current_directory (window, root_file);
3258 g_object_unref (G_OBJECT (root_file));
3259 }
3260
3261 /* release our reference on the home path */
3262 g_object_unref (root);
3263 }
3264
3265
3266
3267 static void
thunar_window_action_open_trash(ThunarWindow * window)3268 thunar_window_action_open_trash (ThunarWindow *window)
3269 {
3270 GFile *trash_bin;
3271 ThunarFile *trash_bin_file;
3272 GError *error = NULL;
3273
3274 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3275
3276 /* determine the path to the trash bin */
3277 trash_bin = thunar_g_file_new_for_trash ();
3278
3279 /* determine the file for the trash bin */
3280 trash_bin_file = thunar_file_get (trash_bin, &error);
3281 if (G_UNLIKELY (trash_bin_file == NULL))
3282 {
3283 /* display an error to the user */
3284 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to display the contents of the trash can"));
3285 g_error_free (error);
3286 }
3287 else
3288 {
3289 /* open the trash folder */
3290 thunar_window_set_current_directory (window, trash_bin_file);
3291 g_object_unref (G_OBJECT (trash_bin_file));
3292 }
3293
3294 /* release our reference on the trash bin path */
3295 g_object_unref (trash_bin);
3296 }
3297
3298
3299
3300 static void
thunar_window_action_open_network(ThunarWindow * window)3301 thunar_window_action_open_network (ThunarWindow *window)
3302 {
3303 ThunarFile *network_file;
3304 GError *error = NULL;
3305 GFile *network;
3306
3307 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3308
3309 /* determine the network root location */
3310 network = g_file_new_for_uri ("network://");
3311
3312 /* determine the file for this location */
3313 network_file = thunar_file_get (network, &error);
3314 if (G_UNLIKELY (network_file == NULL))
3315 {
3316 /* display an error to the user */
3317 thunar_dialogs_show_error (GTK_WIDGET (window), error, _("Failed to browse the network"));
3318 g_error_free (error);
3319 }
3320 else
3321 {
3322 /* open the network root location */
3323 thunar_window_set_current_directory (window, network_file);
3324 g_object_unref (G_OBJECT (network_file));
3325 }
3326
3327 /* release our reference on the location itself */
3328 g_object_unref (network);
3329 }
3330
3331
3332
3333 static gboolean
thunar_window_check_uca_key_activation(ThunarWindow * window,GdkEventKey * key_event,gpointer user_data)3334 thunar_window_check_uca_key_activation (ThunarWindow *window,
3335 GdkEventKey *key_event,
3336 gpointer user_data)
3337 {
3338 if (thunar_launcher_check_uca_key_activation (window->launcher, key_event))
3339 return GDK_EVENT_STOP;
3340 return GDK_EVENT_PROPAGATE;
3341 }
3342
3343
3344
3345 static gboolean
thunar_window_propagate_key_event(GtkWindow * window,GdkEvent * key_event,gpointer user_data)3346 thunar_window_propagate_key_event (GtkWindow* window,
3347 GdkEvent *key_event,
3348 gpointer user_data)
3349 {
3350 GtkWidget* focused_widget;
3351
3352 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), GDK_EVENT_PROPAGATE);
3353
3354 focused_widget = gtk_window_get_focus (window);
3355
3356 /* Turn the accelerator priority around globally,
3357 * so that the focused widget always gets the accels first.
3358 * Implementing this cleanly while maintaining some wanted accels
3359 * (like Ctrl+N and exo accels) is a lot of work. So we resort to
3360 * only priorize GtkEditable, because that is the easiest way to
3361 * fix the right-ahead problem. */
3362 if (focused_widget != NULL && GTK_IS_EDITABLE (focused_widget))
3363 return gtk_window_propagate_key_event (window, (GdkEventKey *) key_event);
3364
3365 return GDK_EVENT_PROPAGATE;
3366 }
3367
3368
3369
3370 static void
thunar_window_poke_location_finish(ThunarBrowser * browser,GFile * location,ThunarFile * file,ThunarFile * target_file,GError * error,gpointer ignored)3371 thunar_window_poke_location_finish (ThunarBrowser *browser,
3372 GFile *location,
3373 ThunarFile *file,
3374 ThunarFile *target_file,
3375 GError *error,
3376 gpointer ignored)
3377 {
3378 _thunar_return_if_fail (THUNAR_IS_WINDOW (browser));
3379 _thunar_return_if_fail (THUNAR_IS_FILE (file));
3380
3381 thunar_window_poke_file_finish (browser, file, target_file, error, ignored);
3382 }
3383
3384
3385
3386 static void
thunar_window_action_open_bookmark(GFile * g_file)3387 thunar_window_action_open_bookmark (GFile *g_file)
3388 {
3389 GtkWindow *window;
3390
3391 window = g_object_get_data (G_OBJECT (g_file), I_("thunar-window"));
3392
3393 thunar_window_set_current_directory_gfile (THUNAR_WINDOW (window), g_file);
3394 }
3395
3396
3397
3398 static void
thunar_window_action_open_location(ThunarWindow * window)3399 thunar_window_action_open_location (ThunarWindow *window)
3400 {
3401 /* just use the "start-open-location" callback */
3402 thunar_window_start_open_location (window, NULL);
3403 }
3404
3405
3406
3407 static void
thunar_window_action_contents(ThunarWindow * window)3408 thunar_window_action_contents (ThunarWindow *window)
3409 {
3410 /* display the documentation index */
3411 xfce_dialog_show_help (GTK_WINDOW (window), "thunar", NULL, NULL);
3412 }
3413
3414
3415
3416 static void
thunar_window_action_about(ThunarWindow * window)3417 thunar_window_action_about (ThunarWindow *window)
3418 {
3419 /* just popup the about dialog */
3420 thunar_dialogs_show_about (GTK_WINDOW (window), PACKAGE_NAME,
3421 _("Thunar is a fast and easy to use file manager\n"
3422 "for the Xfce Desktop Environment."));
3423 }
3424
3425
3426
3427 static void
thunar_window_action_show_hidden(ThunarWindow * window)3428 thunar_window_action_show_hidden (ThunarWindow *window)
3429 {
3430 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3431
3432 window->show_hidden = !window->show_hidden;
3433 gtk_container_foreach (GTK_CONTAINER (window->notebook), (GtkCallback) (void (*)(void)) thunar_view_set_show_hidden, GINT_TO_POINTER (window->show_hidden));
3434
3435 if (G_LIKELY (window->sidepane != NULL))
3436 thunar_side_pane_set_show_hidden (THUNAR_SIDE_PANE (window->sidepane), window->show_hidden);
3437
3438 g_object_set (G_OBJECT (window->preferences), "last-show-hidden", window->show_hidden, NULL);
3439 }
3440
3441
3442
3443 static void
thunar_window_action_open_file_menu(ThunarWindow * window)3444 thunar_window_action_open_file_menu (ThunarWindow *window)
3445 {
3446 gboolean ret;
3447 GList *children;
3448
3449 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3450
3451 /* In case the menubar is hidden, we make it visible (e.g. when F10 is pressed) */
3452 gtk_widget_set_visible (window->menubar, TRUE);
3453
3454 children = gtk_container_get_children (GTK_CONTAINER (window->menubar));
3455 g_signal_emit_by_name (children->data, "button-press-event", NULL, &ret);
3456 g_list_free (children);
3457 gtk_menu_shell_select_first (GTK_MENU_SHELL (window->menubar), TRUE);
3458 }
3459
3460
3461
3462 static void
thunar_window_current_directory_changed(ThunarFile * current_directory,ThunarWindow * window)3463 thunar_window_current_directory_changed (ThunarFile *current_directory,
3464 ThunarWindow *window)
3465 {
3466 gboolean show_full_path;
3467 gchar *parse_name = NULL;
3468 const gchar *name;
3469
3470 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3471 _thunar_return_if_fail (THUNAR_IS_FILE (current_directory));
3472 _thunar_return_if_fail (window->current_directory == current_directory);
3473
3474 /* get name of directory or full path */
3475 g_object_get (G_OBJECT (window->preferences), "misc-full-path-in-title", &show_full_path, NULL);
3476 if (G_UNLIKELY (show_full_path))
3477 name = parse_name = g_file_get_parse_name (thunar_file_get_file (current_directory));
3478 else
3479 name = thunar_file_get_display_name (current_directory);
3480
3481 /* set window title */
3482 gtk_window_set_title (GTK_WINDOW (window), name);
3483 g_free (parse_name);
3484
3485 /* set window icon */
3486 thunar_window_update_window_icon (window);
3487 }
3488
3489
3490
3491 static void
thunar_window_menu_item_selected(ThunarWindow * window,GtkWidget * menu_item)3492 thunar_window_menu_item_selected (ThunarWindow *window,
3493 GtkWidget *menu_item)
3494 {
3495 gchar *tooltip;
3496 gint id;
3497
3498 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3499
3500 /* we can only display tooltips if we have a statusbar */
3501 if (G_LIKELY (window->statusbar != NULL))
3502 {
3503 tooltip = gtk_widget_get_tooltip_text (menu_item);
3504 if (G_LIKELY (tooltip != NULL))
3505 {
3506 /* push to the statusbar */
3507 id = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->statusbar), "Menu tooltip");
3508 gtk_statusbar_push (GTK_STATUSBAR (window->statusbar), id, tooltip);
3509 g_free (tooltip);
3510 }
3511 }
3512 }
3513
3514
3515
3516 static void
thunar_window_menu_item_deselected(ThunarWindow * window,GtkWidget * menu_item)3517 thunar_window_menu_item_deselected (ThunarWindow *window,
3518 GtkWidget *menu_item)
3519 {
3520 gint id;
3521
3522 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3523
3524 /* we can only undisplay tooltips if we have a statusbar */
3525 if (G_LIKELY (window->statusbar != NULL))
3526 {
3527 /* drop the last tooltip from the statusbar */
3528 id = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->statusbar), "Menu tooltip");
3529 gtk_statusbar_pop (GTK_STATUSBAR (window->statusbar), id);
3530 }
3531 }
3532
3533
3534
3535 static void
thunar_window_notify_loading(ThunarView * view,GParamSpec * pspec,ThunarWindow * window)3536 thunar_window_notify_loading (ThunarView *view,
3537 GParamSpec *pspec,
3538 ThunarWindow *window)
3539 {
3540 GdkCursor *cursor;
3541
3542 _thunar_return_if_fail (THUNAR_IS_VIEW (view));
3543 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3544
3545 if (gtk_widget_get_realized (GTK_WIDGET (window))
3546 && window->view == GTK_WIDGET (view))
3547 {
3548 /* setup the proper cursor */
3549 if (thunar_view_get_loading (view))
3550 {
3551 cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (view)), GDK_WATCH);
3552 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), cursor);
3553 g_object_unref (cursor);
3554 }
3555 else
3556 {
3557 gdk_window_set_cursor (gtk_widget_get_window (GTK_WIDGET (window)), NULL);
3558 }
3559 }
3560 }
3561
3562
3563
3564 static void
thunar_window_device_pre_unmount(ThunarDeviceMonitor * device_monitor,ThunarDevice * device,GFile * root_file,ThunarWindow * window)3565 thunar_window_device_pre_unmount (ThunarDeviceMonitor *device_monitor,
3566 ThunarDevice *device,
3567 GFile *root_file,
3568 ThunarWindow *window)
3569 {
3570 _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (device_monitor));
3571 _thunar_return_if_fail (window->device_monitor == device_monitor);
3572 _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
3573 _thunar_return_if_fail (G_IS_FILE (root_file));
3574 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3575
3576 /* nothing to do if we don't have a current directory */
3577 if (G_UNLIKELY (window->current_directory == NULL))
3578 return;
3579
3580 /* check if the file is the current directory or an ancestor of the current directory */
3581 if (g_file_equal (thunar_file_get_file (window->current_directory), root_file)
3582 || thunar_file_is_gfile_ancestor (window->current_directory, root_file))
3583 {
3584 /* change to the home folder */
3585 thunar_window_action_open_home (window);
3586 }
3587 }
3588
3589
3590
3591 static void
thunar_window_device_changed(ThunarDeviceMonitor * device_monitor,ThunarDevice * device,ThunarWindow * window)3592 thunar_window_device_changed (ThunarDeviceMonitor *device_monitor,
3593 ThunarDevice *device,
3594 ThunarWindow *window)
3595 {
3596 GFile *root_file;
3597
3598 _thunar_return_if_fail (THUNAR_IS_DEVICE_MONITOR (device_monitor));
3599 _thunar_return_if_fail (window->device_monitor == device_monitor);
3600 _thunar_return_if_fail (THUNAR_IS_DEVICE (device));
3601 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3602
3603 if (thunar_device_is_mounted (device))
3604 return;
3605
3606 root_file = thunar_device_get_root (device);
3607 if (root_file != NULL)
3608 {
3609 thunar_window_device_pre_unmount (device_monitor, device, root_file, window);
3610 g_object_unref (root_file);
3611 }
3612 }
3613
3614
3615
3616 static gboolean
thunar_window_save_paned(ThunarWindow * window)3617 thunar_window_save_paned (ThunarWindow *window)
3618 {
3619 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
3620
3621 g_object_set (G_OBJECT (window->preferences), "last-separator-position",
3622 gtk_paned_get_position (GTK_PANED (window->paned)), NULL);
3623
3624 /* for button release event */
3625 return FALSE;
3626 }
3627
3628
3629
3630 static gboolean
thunar_window_save_geometry_timer(gpointer user_data)3631 thunar_window_save_geometry_timer (gpointer user_data)
3632 {
3633 GdkWindowState state;
3634 ThunarWindow *window = THUNAR_WINDOW (user_data);
3635 gboolean remember_geometry;
3636 gint width;
3637 gint height;
3638
3639 THUNAR_THREADS_ENTER
3640
3641 /* check if we should remember the window geometry */
3642 g_object_get (G_OBJECT (window->preferences), "misc-remember-geometry", &remember_geometry, NULL);
3643 if (G_LIKELY (remember_geometry))
3644 {
3645 /* check if the window is still visible */
3646 if (gtk_widget_get_visible (GTK_WIDGET (window)))
3647 {
3648 /* determine the current state of the window */
3649 state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
3650
3651 /* don't save geometry for maximized or fullscreen windows */
3652 if ((state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)) == 0)
3653 {
3654 /* determine the current width/height of the window... */
3655 gtk_window_get_size (GTK_WINDOW (window), &width, &height);
3656
3657 /* ...and remember them as default for new windows */
3658 g_object_set (G_OBJECT (window->preferences), "last-window-width", width, "last-window-height", height,
3659 "last-window-maximized", FALSE, NULL);
3660 }
3661 else
3662 {
3663 /* only store that the window is full screen */
3664 g_object_set (G_OBJECT (window->preferences), "last-window-maximized", TRUE, NULL);
3665 }
3666 }
3667 }
3668
3669 THUNAR_THREADS_LEAVE
3670
3671 return FALSE;
3672 }
3673
3674
3675
3676 static void
thunar_window_save_geometry_timer_destroy(gpointer user_data)3677 thunar_window_save_geometry_timer_destroy (gpointer user_data)
3678 {
3679 THUNAR_WINDOW (user_data)->save_geometry_timer_id = 0;
3680 }
3681
3682
3683
3684 /**
3685 * thunar_window_set_zoom_level:
3686 * @window : a #ThunarWindow instance.
3687 * @zoom_level : the new zoom level for @window.
3688 *
3689 * Sets the zoom level for @window to @zoom_level.
3690 **/
3691 void
thunar_window_set_zoom_level(ThunarWindow * window,ThunarZoomLevel zoom_level)3692 thunar_window_set_zoom_level (ThunarWindow *window,
3693 ThunarZoomLevel zoom_level)
3694 {
3695 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3696 _thunar_return_if_fail (zoom_level < THUNAR_ZOOM_N_LEVELS);
3697
3698 /* check if we have a new zoom level */
3699 if (G_LIKELY (window->zoom_level != zoom_level))
3700 {
3701 /* remember the new zoom level */
3702 window->zoom_level = zoom_level;
3703
3704 /* notify listeners */
3705 g_object_notify (G_OBJECT (window), "zoom-level");
3706 }
3707 }
3708
3709
3710
3711 /**
3712 * thunar_window_set_directory_specific_settings:
3713 * @window : a #ThunarWindow instance.
3714 * @directory_specific_settings : whether to use directory specific settings in @window.
3715 *
3716 * Toggles the use of directory specific settings in @window according to @directory_specific_settings.
3717 **/
3718 void
thunar_window_set_directory_specific_settings(ThunarWindow * window,gboolean directory_specific_settings)3719 thunar_window_set_directory_specific_settings (ThunarWindow *window,
3720 gboolean directory_specific_settings)
3721 {
3722 GList *tabs, *lp;
3723 ThunarFile *directory;
3724 GType view_type;
3725 gchar *type_name;
3726
3727 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3728
3729 /* reset to the default view type if we are turning directory specific settings off */
3730 if (!directory_specific_settings && window->directory_specific_settings)
3731 {
3732 /* determine the default view type */
3733 g_object_get (G_OBJECT (window->preferences), "default-view", &type_name, NULL);
3734 view_type = g_type_from_name (type_name);
3735 g_free (type_name);
3736
3737 /* set the last view type */
3738 if (!g_type_is_a (view_type, G_TYPE_NONE) && !g_type_is_a (view_type, G_TYPE_INVALID))
3739 g_object_set (G_OBJECT (window->preferences), "last-view", g_type_name (view_type), NULL);
3740 }
3741
3742 /* save the setting */
3743 window->directory_specific_settings = directory_specific_settings;
3744
3745 /* get all of the window's tabs */
3746 tabs = gtk_container_get_children (GTK_CONTAINER (window->notebook));
3747
3748 /* replace each tab with a tab of the correct view type */
3749 for (lp = tabs; lp != NULL; lp = lp->next)
3750 {
3751 if (!THUNAR_IS_STANDARD_VIEW (lp->data))
3752 continue;
3753
3754 directory = thunar_navigator_get_current_directory (lp->data);
3755
3756 if (!THUNAR_IS_FILE (directory))
3757 continue;
3758
3759 /* find the correct view type for the new view */
3760 view_type = thunar_window_view_type_for_directory (window, directory);
3761
3762 /* replace the old view with a new one */
3763 thunar_window_replace_view (window, lp->data, view_type);
3764 }
3765
3766 g_list_free (tabs);
3767 }
3768
3769
3770
3771 /**
3772 * thunar_window_get_current_directory:
3773 * @window : a #ThunarWindow instance.
3774 *
3775 * Queries the #ThunarFile instance, which represents the directory
3776 * currently displayed within @window. %NULL is returned if @window
3777 * is not currently associated with any directory.
3778 *
3779 * Return value: the directory currently displayed within @window or %NULL.
3780 **/
3781 ThunarFile*
thunar_window_get_current_directory(ThunarWindow * window)3782 thunar_window_get_current_directory (ThunarWindow *window)
3783 {
3784 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), NULL);
3785 return window->current_directory;
3786 }
3787
3788
3789
3790 /**
3791 * thunar_window_set_current_directory:
3792 * @window : a #ThunarWindow instance.
3793 * @current_directory : the new directory or %NULL.
3794 **/
3795 void
thunar_window_set_current_directory(ThunarWindow * window,ThunarFile * current_directory)3796 thunar_window_set_current_directory (ThunarWindow *window,
3797 ThunarFile *current_directory)
3798 {
3799 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3800 _thunar_return_if_fail (current_directory == NULL || THUNAR_IS_FILE (current_directory));
3801
3802 /* check if we already display the requested directory */
3803 if (G_UNLIKELY (window->current_directory == current_directory))
3804 return;
3805
3806 /* disconnect from the previously active directory */
3807 if (G_LIKELY (window->current_directory != NULL))
3808 {
3809 /* disconnect signals and release reference */
3810 g_signal_handlers_disconnect_by_func (G_OBJECT (window->current_directory), thunar_window_current_directory_changed, window);
3811 g_object_unref (G_OBJECT (window->current_directory));
3812 }
3813
3814 /* connect to the new directory */
3815 if (G_LIKELY (current_directory != NULL))
3816 {
3817 GType type;
3818 gchar *type_name;
3819 gint num_pages;
3820
3821 /* take a reference on the file */
3822 g_object_ref (G_OBJECT (current_directory));
3823
3824 num_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
3825
3826 /* if the window is new, get the default-view type and set it as the last-view type (if it is a valid type)
3827 * so that it will be used as the initial view type for directories with no saved directory specific view type */
3828 if (num_pages == 0)
3829 {
3830 /* determine the default view type */
3831 g_object_get (G_OBJECT (window->preferences), "default-view", &type_name, NULL);
3832 type = g_type_from_name (type_name);
3833 g_free (type_name);
3834
3835 /* set the last view type to the default view type if there is a default view type */
3836 if (!g_type_is_a (type, G_TYPE_NONE) && !g_type_is_a (type, G_TYPE_INVALID))
3837 g_object_set (G_OBJECT (window->preferences), "last-view", g_type_name (type), NULL);
3838 }
3839
3840 type = thunar_window_view_type_for_directory (window, current_directory);
3841
3842 if (num_pages == 0) /* create a new view if the window is new */
3843 {
3844 window->current_directory = current_directory;
3845 thunar_window_replace_view (window, window->view, type);
3846 }
3847 else /* change the view type if necessary, and set the current directory */
3848 {
3849 if (window->view != NULL && window->view_type != type)
3850 thunar_window_replace_view (window, window->view, type);
3851
3852 window->current_directory = current_directory;
3853 }
3854
3855 /* connect the "changed"/"destroy" signals */
3856 g_signal_connect (G_OBJECT (current_directory), "changed", G_CALLBACK (thunar_window_current_directory_changed), window);
3857
3858 /* update window icon and title */
3859 thunar_window_current_directory_changed (current_directory, window);
3860
3861 if (G_LIKELY (window->view != NULL))
3862 {
3863 /* grab the focus to the main view */
3864 gtk_widget_grab_focus (window->view);
3865 }
3866
3867 thunar_window_history_changed (window);
3868 gtk_widget_set_sensitive (window->location_toolbar_item_parent, !thunar_g_file_is_root (thunar_file_get_file (current_directory)));
3869 }
3870
3871 /* tell everybody that we have a new "current-directory",
3872 * we do this first so other widgets display the new
3873 * state already while the folder view is loading.
3874 */
3875 g_object_notify (G_OBJECT (window), "current-directory");
3876 }
3877
3878
3879
3880 static void
thunar_window_set_current_directory_gfile(ThunarWindow * window,GFile * current_directory)3881 thunar_window_set_current_directory_gfile (ThunarWindow *window,
3882 GFile *current_directory)
3883 {
3884 ThunarFile *thunar_file;
3885
3886 /* remote files possibly need to be poked first */
3887 if (g_file_has_uri_scheme (current_directory, "file"))
3888 {
3889 thunar_file = thunar_file_get (current_directory, NULL);
3890 thunar_window_set_current_directory (THUNAR_WINDOW (window), thunar_file);
3891 g_object_unref (thunar_file);
3892 }
3893 else
3894 {
3895 thunar_browser_poke_location (THUNAR_BROWSER (window), current_directory, THUNAR_WINDOW (window),
3896 thunar_window_poke_location_finish, NULL);
3897 }
3898 }
3899
3900
3901
3902 /**
3903 * thunar_window_scroll_to_file:
3904 * @window : a #ThunarWindow instance.
3905 * @file : a #ThunarFile.
3906 * @select_file : if %TRUE the @file will also be selected.
3907 * @use_align : %TRUE to use the alignment arguments.
3908 * @row_align : the vertical alignment.
3909 * @col_align : the horizontal alignment.
3910 *
3911 * Tells the @window to scroll to the @file
3912 * in the current view.
3913 **/
3914 void
thunar_window_scroll_to_file(ThunarWindow * window,ThunarFile * file,gboolean select_file,gboolean use_align,gfloat row_align,gfloat col_align)3915 thunar_window_scroll_to_file (ThunarWindow *window,
3916 ThunarFile *file,
3917 gboolean select_file,
3918 gboolean use_align,
3919 gfloat row_align,
3920 gfloat col_align)
3921 {
3922 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
3923 _thunar_return_if_fail (THUNAR_IS_FILE (file));
3924
3925 /* verify that we have a valid view */
3926 if (G_LIKELY (window->view != NULL))
3927 thunar_view_scroll_to_file (THUNAR_VIEW (window->view), file, select_file, use_align, row_align, col_align);
3928 }
3929
3930
3931
3932 gchar **
thunar_window_get_directories(ThunarWindow * window,gint * active_page)3933 thunar_window_get_directories (ThunarWindow *window,
3934 gint *active_page)
3935 {
3936 gint n;
3937 gint n_pages;
3938 gchar **uris;
3939 GtkWidget *view;
3940 ThunarFile *directory;
3941
3942 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), NULL);
3943
3944 n_pages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook));
3945 if (G_UNLIKELY (n_pages == 0))
3946 return NULL;
3947
3948 /* create array of uris */
3949 uris = g_new0 (gchar *, n_pages + 1);
3950 for (n = 0; n < n_pages; n++)
3951 {
3952 /* get the view */
3953 view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (window->notebook), n);
3954 _thunar_return_val_if_fail (THUNAR_IS_NAVIGATOR (view), FALSE);
3955
3956 /* get the directory of the view */
3957 directory = thunar_navigator_get_current_directory (THUNAR_NAVIGATOR (view));
3958 _thunar_return_val_if_fail (THUNAR_IS_FILE (directory), FALSE);
3959
3960 /* add to array */
3961 uris[n] = thunar_file_dup_uri (directory);
3962 }
3963
3964 /* selected tab */
3965 if (active_page != NULL)
3966 *active_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook));
3967
3968 return uris;
3969 }
3970
3971
3972
3973 gboolean
thunar_window_set_directories(ThunarWindow * window,gchar ** uris,gint active_page)3974 thunar_window_set_directories (ThunarWindow *window,
3975 gchar **uris,
3976 gint active_page)
3977 {
3978 ThunarFile *directory;
3979 guint n;
3980
3981 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
3982 _thunar_return_val_if_fail (uris != NULL, FALSE);
3983
3984 for (n = 0; uris[n] != NULL; n++)
3985 {
3986 /* check if the string looks like an uri */
3987 if (!exo_str_looks_like_an_uri (uris[n]))
3988 continue;
3989
3990 /* get the file for the uri */
3991 directory = thunar_file_get_for_uri (uris[n], NULL);
3992 if (G_UNLIKELY (directory == NULL))
3993 continue;
3994
3995 /* open the directory in a new notebook */
3996 if (thunar_file_is_directory (directory))
3997 {
3998 if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) == 0)
3999 thunar_window_set_current_directory (window, directory);
4000 else
4001 thunar_window_notebook_open_new_tab (window, directory);
4002 }
4003
4004 g_object_unref (G_OBJECT (directory));
4005 }
4006
4007 /* select the page */
4008 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->notebook), active_page);
4009
4010 /* we succeeded if new pages have been opened */
4011 return gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->notebook)) > 0;
4012 }
4013
4014
4015
4016 /**
4017 * thunar_window_get_action_entry:
4018 * @window : Instance of a #ThunarWindow
4019 * @action : #ThunarWindowAction for which the #XfceGtkActionEntry is requested
4020 *
4021 * returns a reference to the requested #XfceGtkActionEntry
4022 *
4023 * Return value: (transfer none): The reference to the #XfceGtkActionEntry
4024 **/
4025 const XfceGtkActionEntry*
thunar_window_get_action_entry(ThunarWindow * window,ThunarWindowAction action)4026 thunar_window_get_action_entry (ThunarWindow *window,
4027 ThunarWindowAction action)
4028 {
4029 return get_action_entry (action);
4030 }
4031
4032
4033
4034 /**
4035 * thunar_window_append_menu_item:
4036 * @window : Instance of a #ThunarWindow
4037 * @menu : #GtkMenuShell to which the item should be added
4038 * @action : #ThunarWindowAction to select which item should be added
4039 *
4040 * Adds the selected, widget specific #GtkMenuItem to the passed #GtkMenuShell
4041 **/
4042 void
thunar_window_append_menu_item(ThunarWindow * window,GtkMenuShell * menu,ThunarWindowAction action)4043 thunar_window_append_menu_item (ThunarWindow *window,
4044 GtkMenuShell *menu,
4045 ThunarWindowAction action)
4046 {
4047 GtkWidget *item;
4048
4049 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
4050
4051 item = xfce_gtk_menu_item_new_from_action_entry (get_action_entry (action), G_OBJECT (window), menu);
4052
4053 if (action == THUNAR_WINDOW_ACTION_ZOOM_IN)
4054 gtk_widget_set_sensitive (item, G_LIKELY (window->zoom_level < THUNAR_ZOOM_N_LEVELS - 1));
4055 if (action == THUNAR_WINDOW_ACTION_ZOOM_OUT)
4056 gtk_widget_set_sensitive (item, G_LIKELY (window->zoom_level > 0));
4057 }
4058
4059
4060
4061 /**
4062 * thunar_window_get_launcher:
4063 * @window : a #ThunarWindow instance.
4064 *
4065 * Return value: (transfer none): The single #ThunarLauncher of this #ThunarWindow
4066 **/
4067 ThunarLauncher*
thunar_window_get_launcher(ThunarWindow * window)4068 thunar_window_get_launcher (ThunarWindow *window)
4069 {
4070 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), NULL);
4071
4072 return window->launcher;
4073 }
4074
4075
4076
4077 static void
thunar_window_redirect_menu_tooltips_to_statusbar_recursive(GtkWidget * menu_item,ThunarWindow * window)4078 thunar_window_redirect_menu_tooltips_to_statusbar_recursive (GtkWidget *menu_item,
4079 ThunarWindow *window)
4080 {
4081 GtkWidget *submenu;
4082
4083 if (GTK_IS_MENU_ITEM (menu_item))
4084 {
4085 submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item));
4086 if (submenu != NULL)
4087 gtk_container_foreach (GTK_CONTAINER (submenu), (GtkCallback) (void (*)(void)) thunar_window_redirect_menu_tooltips_to_statusbar_recursive, window);
4088
4089 /* this disables to show the tooltip on hover */
4090 gtk_widget_set_has_tooltip (menu_item, FALSE);
4091
4092 /* These method will put the tooltip on the statusbar */
4093 g_signal_connect_swapped (G_OBJECT (menu_item), "select", G_CALLBACK (thunar_window_menu_item_selected), window);
4094 g_signal_connect_swapped (G_OBJECT (menu_item), "deselect", G_CALLBACK (thunar_window_menu_item_deselected), window);
4095 }
4096 }
4097
4098
4099
4100 /**
4101 * thunar_window_redirect_menu_tooltips_to_statusbar:
4102 * @window : a #ThunarWindow instance.
4103 * @menu : #GtkMenu for which all tooltips should be shown in the statusbar
4104 *
4105 * All tooltips of the provided #GtkMenu and any submenu will not be shown directly any more.
4106 * Instead they will be shown in the status bar of the passed #ThunarWindow
4107 **/
4108 void
thunar_window_redirect_menu_tooltips_to_statusbar(ThunarWindow * window,GtkMenu * menu)4109 thunar_window_redirect_menu_tooltips_to_statusbar (ThunarWindow *window, GtkMenu *menu)
4110 {
4111 _thunar_return_if_fail (THUNAR_IS_WINDOW (window));
4112 _thunar_return_if_fail (GTK_IS_MENU (menu));
4113
4114 gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) (void (*)(void)) thunar_window_redirect_menu_tooltips_to_statusbar_recursive, window);
4115 }
4116
4117
4118
4119 static gboolean
thunar_window_button_press_event(GtkWidget * view,GdkEventButton * event,ThunarWindow * window)4120 thunar_window_button_press_event (GtkWidget *view,
4121 GdkEventButton *event,
4122 ThunarWindow *window)
4123 {
4124 const XfceGtkActionEntry* action_entry;
4125
4126 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), FALSE);
4127
4128 if (event->type == GDK_BUTTON_PRESS)
4129 {
4130 if (G_UNLIKELY (event->button == 8))
4131 {
4132 action_entry = get_action_entry (THUNAR_WINDOW_ACTION_BACK);
4133 ((void(*)(GtkWindow*))action_entry->callback)(GTK_WINDOW (window));
4134 return GDK_EVENT_STOP;
4135 }
4136 if (G_UNLIKELY (event->button == 9))
4137 {
4138 action_entry = get_action_entry (THUNAR_WINDOW_ACTION_FORWARD);
4139 ((void(*)(GtkWindow*))action_entry->callback)(GTK_WINDOW (window));
4140 return GDK_EVENT_STOP;
4141 }
4142 }
4143
4144 return GDK_EVENT_PROPAGATE;
4145 }
4146
4147
4148
4149 static gboolean
thunar_window_history_clicked(GtkWidget * button,GdkEventButton * event,GtkWidget * data)4150 thunar_window_history_clicked (GtkWidget *button,
4151 GdkEventButton *event,
4152 GtkWidget *data)
4153 {
4154 ThunarHistory *history;
4155 ThunarWindow *window;
4156
4157 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (data), FALSE);
4158
4159 window = THUNAR_WINDOW (data);
4160
4161 if (event->button == 3)
4162 {
4163 history = thunar_standard_view_get_history (THUNAR_STANDARD_VIEW (window->view));
4164
4165 if (button == window->location_toolbar_item_back)
4166 thunar_history_show_menu (history, THUNAR_HISTORY_MENU_BACK, button);
4167 else if (button == window->location_toolbar_item_forward)
4168 thunar_history_show_menu (history, THUNAR_HISTORY_MENU_FORWARD, button);
4169 else
4170 g_warning ("This button is not able to spawn a history menu");
4171 }
4172
4173 return FALSE;
4174 }
4175
4176
4177
4178 /**
4179 * thunar_window_view_type_for_directory:
4180 * @window : a #ThunarWindow instance.
4181 * @directory : #ThunarFile representing the directory
4182 *
4183 * Return value: the #GType representing the view type which
4184 * @window would use to display @directory.
4185 **/
4186 GType
thunar_window_view_type_for_directory(ThunarWindow * window,ThunarFile * directory)4187 thunar_window_view_type_for_directory (ThunarWindow *window,
4188 ThunarFile *directory)
4189 {
4190 GType type = G_TYPE_NONE;
4191 gchar *type_name;
4192
4193 _thunar_return_val_if_fail (THUNAR_IS_WINDOW (window), G_TYPE_NONE);
4194 _thunar_return_val_if_fail (THUNAR_IS_FILE (directory), G_TYPE_NONE);
4195
4196 /* if the directory has a saved view type and directory specific view types are enabled, we use it */
4197 if (window->directory_specific_settings)
4198 {
4199 const gchar *dir_spec_type_name;
4200
4201 dir_spec_type_name = thunar_file_get_metadata_setting (directory, "view-type");
4202 if (dir_spec_type_name != NULL)
4203 type = g_type_from_name (dir_spec_type_name);
4204 }
4205
4206 /* if there is no saved view type for the directory or directory specific view types are not enabled,
4207 * we use the last view type */
4208 if (g_type_is_a (type, G_TYPE_NONE) || g_type_is_a (type, G_TYPE_INVALID))
4209 {
4210 /* determine the last view type */
4211 g_object_get (G_OBJECT (window->preferences), "last-view", &type_name, NULL);
4212 type = g_type_from_name (type_name);
4213 g_free (type_name);
4214 }
4215
4216 /* fallback view type, in case nothing was set */
4217 if (g_type_is_a (type, G_TYPE_NONE) || g_type_is_a (type, G_TYPE_INVALID))
4218 type = THUNAR_TYPE_ICON_VIEW;
4219
4220 return type;
4221 }
4222