~ubuntu-branches/ubuntu/utopic/pcmanfm/utopic-proposed

« back to all changes in this revision

Viewing changes to src/main-win.c

  • Committer: Package Import Robot
  • Author(s): Andriy Grytsenko
  • Date: 2014-02-25 04:07:51 UTC
  • mfrom: (1.2.6)
  • Revision ID: package-import@ubuntu.com-20140225040751-oo835klpwl58mcy4
Tags: 1.2.0-1
* Bump Standards-Version to actual one (fixes lintian warning, see QA page).
* Adding files NEWS to pcmanfm documentation.
* Bump Standards-Version to 3.9.5.
* Updating watch file to support XZ tarball format and non-numeric versions.
* Merging upstream version 1.2.0. (Closes: #656298, #731549)
* Use single docs directory for all packages.
* Raising version of libfm required to >= 1.2.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *      main-win.c
3
3
 *
4
4
 *      Copyright 2009 - 2012 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5
 
 *      Copyright 2012 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
 
5
 *      Copyright 2012-2014 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
6
6
 *
7
7
 *      This program is free software; you can redistribute it and/or modify
8
8
 *      it under the terms of the GNU General Public License as published by
37
37
#include "main-win.h"
38
38
#include "pref.h"
39
39
#include "tab-page.h"
 
40
#include "connect-server.h"
40
41
 
41
42
#include "gseal-gtk-compat.h"
42
43
 
54
55
static gboolean on_focus_in(GtkWidget* w, GdkEventFocus* evt);
55
56
static gboolean on_key_press_event(GtkWidget* w, GdkEventKey* evt);
56
57
static gboolean on_button_press_event(GtkWidget* w, GdkEventButton* evt);
 
58
static gboolean on_scroll_event(GtkWidget* w, GdkEventScroll* evt);
57
59
static void on_unrealize(GtkWidget* widget);
58
60
 
59
61
static void bounce_action(GtkAction* act, FmMainWin* win);
62
64
static void on_new_tab(GtkAction* act, FmMainWin* win);
63
65
static void on_close_tab(GtkAction* act, FmMainWin* win);
64
66
static void on_close_win(GtkAction* act, FmMainWin* win);
 
67
static void on_open(GtkAction* act, FmMainWin* win);
65
68
 
 
69
static void on_link(GtkAction* act, FmMainWin* win);
66
70
static void on_copy_to(GtkAction* act, FmMainWin* win);
67
71
static void on_move_to(GtkAction* act, FmMainWin* win);
68
72
static void on_rename(GtkAction* act, FmMainWin* win);
69
 
 
 
73
static void on_trash(GtkAction* act, FmMainWin* win);
 
74
static void on_del(GtkAction* act, FmMainWin* win);
 
75
static void on_copy_path(GtkAction* act, FmMainWin* win);
70
76
static void on_preference(GtkAction* act, FmMainWin* win);
71
77
 
72
78
static void on_add_bookmark(GtkAction* act, FmMainWin* win);
81
87
static void on_go_computer(GtkAction* act, FmMainWin* win);
82
88
static void on_go_network(GtkAction* act, FmMainWin* win);
83
89
static void on_go_apps(GtkAction* act, FmMainWin* win);
 
90
static void on_go_connect(GtkAction* act, FmMainWin* win);
84
91
static void on_reload(GtkAction* act, FmMainWin* win);
 
92
#if FM_CHECK_VERSION(1, 0, 2)
 
93
static void on_filter(GtkAction* act, FmMainWin* win);
 
94
#endif
85
95
static void on_show_hidden(GtkToggleAction* act, FmMainWin* win);
 
96
#if FM_CHECK_VERSION(1, 2, 0)
 
97
static void on_mingle_dirs(GtkToggleAction* act, FmMainWin* win);
 
98
#endif
 
99
#if FM_CHECK_VERSION(1, 0, 2)
 
100
static void on_sort_ignore_case(GtkToggleAction* act, FmMainWin* win);
 
101
#endif
 
102
static void on_save_per_folder(GtkToggleAction* act, FmMainWin* win);
86
103
static void on_show_side_pane(GtkToggleAction* act, FmMainWin* win);
 
104
static void on_dual_pane(GtkToggleAction* act, FmMainWin* win);
 
105
static void on_show_toolbar(GtkToggleAction *action, FmMainWin *win);
 
106
static void on_toolbar_new_win(GtkToggleAction *act, FmMainWin *win);
 
107
static void on_toolbar_new_tab(GtkToggleAction *act, FmMainWin *win);
 
108
static void on_toolbar_nav(GtkToggleAction *act, FmMainWin *win);
 
109
static void on_toolbar_home(GtkToggleAction *act, FmMainWin *win);
 
110
static void on_show_status(GtkToggleAction *action, FmMainWin *win);
87
111
static void on_change_mode(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win);
88
112
static void on_sort_by(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win);
89
113
static void on_sort_type(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win);
91
115
static void on_about(GtkAction* act, FmMainWin* win);
92
116
static void on_key_nav_list(GtkAction* act, FmMainWin* win);
93
117
static void on_open_in_terminal(GtkAction* act, FmMainWin* win);
94
 
static void on_open_as_root(GtkAction* act, FmMainWin* win);
 
118
/*static void on_open_as_root(GtkAction* act, FmMainWin* win);*/
95
119
#if FM_CHECK_VERSION(1, 0, 2)
96
120
static void on_search(GtkAction* act, FmMainWin* win);
97
121
#endif
 
122
#if FM_CHECK_VERSION(1, 2, 0)
 
123
static void on_launch(GtkAction* act, FmMainWin* win);
 
124
#endif
98
125
static void on_fullscreen(GtkToggleAction* act, FmMainWin* win);
99
126
 
100
127
static void on_location(GtkAction* act, FmMainWin* win);
101
128
 
 
129
static void on_size_increment(GtkAction *act, FmMainWin *win);
 
130
static void on_size_decrement(GtkAction *act, FmMainWin *win);
 
131
static void on_size_default(GtkAction *act, FmMainWin *win);
 
132
 
102
133
static void on_notebook_switch_page(GtkNotebook* nb, gpointer* page, guint num, FmMainWin* win);
103
134
static void on_notebook_page_added(GtkNotebook* nb, GtkWidget* page, guint num, FmMainWin* win);
104
135
static void on_notebook_page_removed(GtkNotebook* nb, GtkWidget* page, guint num, FmMainWin* win);
105
136
 
106
 
static void on_folder_view_clicked(FmFolderView* fv, FmFolderViewClickType type, FmFileInfo* fi, FmMainWin* win);
107
 
 
108
137
#include "main-win-ui.c" /* ui xml definitions and actions */
109
138
 
110
139
static GSList* all_wins = NULL;
111
 
static GtkDialog* about_dlg = NULL;
 
140
static GtkAboutDialog* about_dlg = NULL;
112
141
static GtkWidget* key_nav_list_dlg = NULL;
113
142
 
 
143
static GQuark main_win_qdata;
 
144
 
114
145
static void fm_main_win_class_init(FmMainWinClass *klass)
115
146
{
116
147
    GObjectClass *g_object_class = G_OBJECT_CLASS(klass);
128
159
    widget_class->focus_in_event = on_focus_in;
129
160
    widget_class->key_press_event = on_key_press_event;
130
161
    widget_class->button_press_event = on_button_press_event;
 
162
    widget_class->scroll_event = on_scroll_event;
131
163
    widget_class->unrealize = on_unrealize;
132
164
 
133
165
    fm_main_win_parent_class = (GtkWindowClass*)g_type_class_peek(GTK_TYPE_WINDOW);
 
166
 
 
167
    main_win_qdata = g_quark_from_static_string("FmMainWin::data");
134
168
}
135
169
 
136
170
static gboolean idle_focus_view(gpointer user_data)
148
182
static void on_location_activate(GtkEntry* entry, FmMainWin* win)
149
183
{
150
184
    FmPath* path = fm_path_entry_get_path(FM_PATH_ENTRY(entry));
 
185
 
 
186
    /* bug #3615243 seems to be thread-related issue, let ref the path now */
 
187
    fm_path_ref(path);
151
188
    fm_main_win_chdir(win, path);
 
189
    fm_path_unref(path);
 
190
    if (app_config->pathbar_mode_buttons)
 
191
    {
 
192
        /* recover from Ctrl+L mode change */
 
193
        gtk_widget_hide(GTK_WIDGET(win->location));
 
194
        gtk_widget_hide(gtk_ui_manager_get_widget(win->ui, "/toolbar/Go"));
 
195
        gtk_widget_show(GTK_WIDGET(win->path_bar));
 
196
    }
152
197
 
153
198
    /* FIXME: due to bug #650114 in GTK+, GtkEntry still call a
154
199
     * idle function for GtkEntryCompletion even if the completion
166
211
     * priority than GtkEntry's idle function (They use G_PRIORITY_HIGH).
167
212
     */
168
213
    if(win->idle_handler == 0)
169
 
        win->idle_handler = g_idle_add_full(G_PRIORITY_LOW, idle_focus_view, win, NULL);
 
214
        win->idle_handler = gdk_threads_add_idle_full(G_PRIORITY_LOW, idle_focus_view, win, NULL);
 
215
}
 
216
 
 
217
static void on_path_bar_chdir(FmPathBar *bar, FmPath *path, FmMainWin *win)
 
218
{
 
219
    fm_main_win_chdir(win, path);
 
220
}
 
221
 
 
222
static void on_path_bar_mode(GtkRadioAction *act, GtkRadioAction *cur, FmMainWin *win)
 
223
{
 
224
    int mode = gtk_radio_action_get_current_value(cur);
 
225
 
 
226
    if (app_config->pathbar_mode_buttons != mode)
 
227
    {
 
228
        app_config->pathbar_mode_buttons = mode;
 
229
        pcmanfm_save_config(FALSE);
 
230
    }
 
231
    gtk_widget_set_visible(GTK_WIDGET(win->location), mode == 0);
 
232
    gtk_widget_set_visible(gtk_ui_manager_get_widget(win->ui, "/toolbar/Go"), mode == 0);
 
233
    gtk_widget_set_visible(GTK_WIDGET(win->path_bar), mode);
170
234
}
171
235
 
172
236
static void update_sort_menu(FmMainWin* win)
173
237
{
174
238
    GtkAction* act;
175
239
    FmFolderView* fv = win->folder_view;
176
 
    FmFolderModelViewCol by = fm_folder_view_get_sort_by(fv);
 
240
    GtkSortType type;
177
241
#if FM_CHECK_VERSION(1, 0, 2)
 
242
    FmFolderModelCol by;
 
243
    FmSortMode mode;
 
244
 
 
245
    if (win->in_update)
 
246
        return;
 
247
    win->in_update = TRUE;
 
248
    /* we have to update this any time */
 
249
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/SavePerFolder");
 
250
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), win->current_page->own_config);
 
251
    win->in_update = FALSE;
178
252
    if(fv == NULL || fm_folder_view_get_model(fv) == NULL)
179
253
        /* since 1.0.2 libfm have sorting only in FmFolderModel therefore
180
254
           if there is no model then we cannot get last sorting from it */
181
255
        return;
 
256
    if(!fm_folder_model_get_sort(fm_folder_view_get_model(fv), &by, &mode))
 
257
        return;
 
258
    type = FM_SORT_IS_ASCENDING(mode) ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING;
 
259
    /* we don't handle extended modes in radio actions so do that here */
 
260
    if(mode != win->current_page->sort_type)
 
261
    {
 
262
        win->current_page->sort_type = mode;
 
263
        if (win->current_page->own_config)
 
264
        {
 
265
            fm_app_config_save_config_for_path(fm_folder_view_get_cwd(fv),
 
266
                                               mode, by, -1,
 
267
                                               win->current_page->show_hidden,
 
268
                                               NULL);
 
269
        }
 
270
        else
 
271
        {
 
272
            app_config->sort_type = mode;
 
273
            pcmanfm_save_config(FALSE);
 
274
        }
 
275
    }
 
276
#else
 
277
    FmFolderModelViewCol by = fm_folder_view_get_sort_by(fv);
 
278
 
 
279
    type = fm_folder_view_get_sort_type(fv);
182
280
#endif
 
281
    win->in_update = TRUE;
183
282
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Sort/Asc");
184
 
    gtk_radio_action_set_current_value(GTK_RADIO_ACTION(act), fm_folder_view_get_sort_type(fv));
 
283
    gtk_radio_action_set_current_value(GTK_RADIO_ACTION(act), type);
185
284
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Sort/ByName");
186
285
#if FM_CHECK_VERSION(1, 0, 2)
187
286
    if(by == FM_FOLDER_MODEL_COL_DEFAULT)
188
287
        by = FM_FOLDER_MODEL_COL_NAME;
189
288
#endif
190
289
    gtk_radio_action_set_current_value(GTK_RADIO_ACTION(act), by);
 
290
#if FM_CHECK_VERSION(1, 0, 2)
 
291
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Sort/SortIgnoreCase");
 
292
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act),
 
293
                                 (mode & FM_SORT_CASE_SENSITIVE) == 0);
 
294
#endif
 
295
#if FM_CHECK_VERSION(1, 2, 0)
 
296
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Sort/MingleDirs");
 
297
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act),
 
298
                                 (mode & FM_SORT_NO_FOLDER_FIRST) != 0);
 
299
#endif
 
300
    win->in_update = FALSE;
191
301
}
192
302
 
193
303
static void update_view_menu(FmMainWin* win)
194
304
{
195
305
    GtkAction* act;
196
306
    FmFolderView* fv = win->folder_view;
 
307
 
197
308
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/ShowHidden");
 
309
    if (win->in_update)
 
310
        return;
 
311
    win->in_update = TRUE;
198
312
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), fm_folder_view_get_show_hidden(fv));
199
 
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/IconView");
200
 
    gtk_radio_action_set_current_value(GTK_RADIO_ACTION(act),
 
313
    gtk_radio_action_set_current_value(win->first_view_mode,
201
314
                                       fm_standard_view_get_mode(FM_STANDARD_VIEW(fv)));
 
315
    win->in_update = FALSE;
 
316
}
 
317
 
 
318
static void update_file_menu(FmMainWin* win, FmPath *path)
 
319
{
 
320
    GtkAction *act;
 
321
    /* FmFolderView *fv = win->folder_view; */
 
322
 
 
323
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ToolMenu/Term");
 
324
    gtk_action_set_sensitive(act, path && fm_path_is_native(path));
 
325
#if FM_CHECK_VERSION(1, 2, 0)
 
326
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ToolMenu/Launch");
 
327
    gtk_action_set_sensitive(act, path && fm_path_is_native(path));
 
328
#endif
 
329
    act = gtk_ui_manager_get_action(win->ui, "/menubar/GoMenu/Up");
 
330
    gtk_action_set_sensitive(act, path && fm_path_get_parent(path));
202
331
}
203
332
 
204
333
static void on_folder_view_sort_changed(FmFolderView* fv, FmMainWin* win)
215
344
 
216
345
    if(fv != win->folder_view)
217
346
        return;
 
347
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/Open");
 
348
    gtk_action_set_sensitive(act, has_selected);
218
349
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/Cut");
219
350
    gtk_action_set_sensitive(act, has_selected);
220
351
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/Copy");
221
352
    gtk_action_set_sensitive(act, has_selected);
 
353
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/ToTrash");
 
354
    gtk_action_set_sensitive(act, has_selected);
222
355
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/Del");
223
356
    gtk_action_set_sensitive(act, has_selected);
 
357
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/CopyPath");
 
358
    gtk_action_set_sensitive(act, has_selected);
224
359
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/Rename");
 
360
    gtk_action_set_sensitive(act, n_sel == 1); /* can rename only single file */
 
361
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/Link");
225
362
    gtk_action_set_sensitive(act, has_selected);
226
363
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/CopyTo");
227
364
    gtk_action_set_sensitive(act, has_selected);
228
365
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/MoveTo");
229
366
    gtk_action_set_sensitive(act, has_selected);
 
367
    act = gtk_ui_manager_get_action(win->ui, "/menubar/EditMenu/FileProp");
 
368
    gtk_action_set_sensitive(act, has_selected);
230
369
}
231
370
 
232
371
static gboolean on_view_key_press_event(FmFolderView* fv, GdkEventKey* evt, FmMainWin* win)
242
381
 
243
382
static void on_bookmark(GtkMenuItem* mi, FmMainWin* win)
244
383
{
245
 
    FmPath* path = (FmPath*)g_object_get_data(G_OBJECT(mi), "path");
 
384
    FmPath* path = (FmPath*)g_object_get_qdata(G_OBJECT(mi), main_win_qdata);
246
385
    switch(app_config->bm_open_method)
247
386
    {
248
387
    case FM_OPEN_IN_CURRENT_TAB: /* current tab */
259
398
 
260
399
static void create_bookmarks_menu(FmMainWin* win)
261
400
{
262
 
    GList* l;
 
401
    const GList *list, *l;
263
402
    GtkWidget* mi;
264
403
    int i = 0;
265
404
 
266
 
    for(l=win->bookmarks->items;l;l=l->next)
 
405
#if FM_CHECK_VERSION(1, 0, 2)
 
406
    list = fm_bookmarks_get_all(win->bookmarks);
 
407
#else
 
408
    list = fm_bookmarks_list_all(win->bookmarks);
 
409
#endif
 
410
    for(l=list;l;l=l->next)
267
411
    {
268
412
        FmBookmarkItem* item = (FmBookmarkItem*)l->data;
269
413
        mi = gtk_image_menu_item_new_with_label(item->name);
270
414
        gtk_widget_show(mi);
271
 
        g_object_set_data_full(G_OBJECT(mi), "path", fm_path_ref(item->path), (GDestroyNotify)fm_path_unref);
 
415
        g_object_set_qdata_full(G_OBJECT(mi), main_win_qdata,
 
416
                                fm_path_ref(item->path), (GDestroyNotify)fm_path_unref);
272
417
        g_signal_connect(mi, "activate", G_CALLBACK(on_bookmark), win);
273
418
        gtk_menu_shell_insert(win->bookmarks_menu, mi, i);
274
419
        ++i;
275
420
    }
 
421
#if FM_CHECK_VERSION(1, 0, 2)
 
422
    g_list_free_full((GList*)list, (GDestroyNotify)fm_bookmark_item_unref);
 
423
#endif
276
424
    if(i > 0)
277
425
    {
278
426
        mi = gtk_separator_menu_item_new();
289
437
    for(l = mis;l;l=l->next)
290
438
    {
291
439
        GtkWidget* item = (GtkWidget*)l->data;
292
 
        if( g_object_get_data(G_OBJECT(item), "path") )
 
440
        if( g_object_get_qdata(G_OBJECT(item), main_win_qdata) )
293
441
        {
294
442
            g_signal_handlers_disconnect_by_func(item, on_bookmark, win);
295
443
            gtk_widget_destroy(item);
316
464
    create_bookmarks_menu(win);
317
465
}
318
466
 
 
467
static void _update_hist_buttons(FmMainWin* win);
 
468
 
319
469
static void on_history_item(GtkMenuItem* mi, FmMainWin* win)
320
470
{
321
471
    FmTabPage* page = win->current_page;
322
 
    GList* l = g_object_get_data(G_OBJECT(mi), "path");
 
472
#if FM_CHECK_VERSION(1, 0, 2)
 
473
    guint l = GPOINTER_TO_UINT(g_object_get_qdata(G_OBJECT(mi), main_win_qdata));
 
474
#else
 
475
    GList* l = g_object_get_qdata(G_OBJECT(mi), main_win_qdata);
 
476
#endif
323
477
    fm_tab_page_history(page, l);
 
478
    /* update folder popup */
 
479
    fm_folder_view_set_active(win->folder_view, FALSE);
 
480
    fm_folder_view_add_popup(win->folder_view, GTK_WINDOW(win), NULL);
 
481
    _update_hist_buttons(win);
324
482
}
325
483
 
326
484
static void disconnect_history_item(GtkWidget* mi, gpointer win)
337
495
    gtk_container_foreach(GTK_CONTAINER(menu), disconnect_history_item, win);
338
496
}
339
497
 
 
498
#if FM_CHECK_VERSION(1, 2, 0)
 
499
static void on_show_history_menu(FmMenuToolItem* btn, FmMainWin* win)
 
500
#else
340
501
static void on_show_history_menu(GtkMenuToolButton* btn, FmMainWin* win)
 
502
#endif
341
503
{
 
504
#if FM_CHECK_VERSION(1, 2, 0)
 
505
    GtkMenuShell* menu = (GtkMenuShell*)fm_menu_tool_item_get_menu(btn);
 
506
#else
342
507
    GtkMenuShell* menu = (GtkMenuShell*)gtk_menu_tool_button_get_menu(btn);
 
508
#endif
 
509
#if FM_CHECK_VERSION(1, 0, 2)
 
510
    guint i, cur = fm_nav_history_get_cur_index(win->nav_history);
 
511
    FmPath* path;
 
512
#else
343
513
    const GList* l;
344
514
    const GList* cur = fm_nav_history_get_cur_link(win->nav_history);
 
515
#endif
345
516
 
346
517
    /* delete old items */
347
518
    gtk_container_foreach(GTK_CONTAINER(menu), (GtkCallback)gtk_widget_destroy, NULL);
348
519
 
 
520
#if FM_CHECK_VERSION(1, 0, 2)
 
521
    for (i = 0; (path = fm_nav_history_get_nth_path(win->nav_history, i)); i++)
 
522
    {
 
523
#else
349
524
    for(l = fm_nav_history_list(win->nav_history); l; l=l->next)
350
525
    {
351
526
        const FmNavHistoryItem* item = (FmNavHistoryItem*)l->data;
352
527
        FmPath* path = item->path;
 
528
#endif
353
529
        char* str = fm_path_display_name(path, TRUE);
354
530
        GtkWidget* mi;
 
531
#if FM_CHECK_VERSION(1, 0, 2)
 
532
        if (i == cur)
 
533
#else
355
534
        if( l == cur )
 
535
#endif
356
536
        {
357
537
            mi = gtk_check_menu_item_new_with_label(str);
358
538
            gtk_check_menu_item_set_draw_as_radio(GTK_CHECK_MENU_ITEM(mi), TRUE);
362
542
            mi = gtk_menu_item_new_with_label(str);
363
543
        g_free(str);
364
544
 
365
 
        /* FIXME: need to avoid cast from const GList */
366
 
        g_object_set_data_full(G_OBJECT(mi), "path", (gpointer)l, NULL);
 
545
#if FM_CHECK_VERSION(1, 0, 2)
 
546
        g_object_set_qdata(G_OBJECT(mi), main_win_qdata, GUINT_TO_POINTER(i));
 
547
#else
 
548
        g_object_set_qdata_full(G_OBJECT(mi), main_win_qdata, (gpointer)l, NULL);
 
549
#endif
367
550
        g_signal_connect(mi, "activate", G_CALLBACK(on_history_item), win);
368
551
        gtk_menu_shell_append(menu, mi);
369
552
    }
399
582
        return;
400
583
 
401
584
    if(button == 2) /* middle click */
 
585
    {
 
586
        FmPath *prev_path = NULL;
 
587
 
 
588
        if (win->folder_view)
 
589
            prev_path = fm_folder_view_get_cwd(win->folder_view);
402
590
        fm_main_win_add_tab(win, path);
 
591
        /* the side pane activates row itself so let reset it back */
 
592
        if (prev_path)
 
593
            fm_side_pane_chdir(sp, prev_path);
 
594
    }
403
595
    else
404
596
        fm_main_win_chdir(win, path);
405
597
 
411
603
/* This callback is only connected to side pane of current active tab page. */
412
604
static void on_side_pane_mode_changed(FmSidePane* sp, FmMainWin* win)
413
605
{
414
 
#if 0
415
 
    GList* children;
416
 
    GList* child;
417
 
#endif
418
606
    FmSidePaneMode mode;
419
607
 
420
608
    if(sp != win->side_pane)
421
609
        return;
422
610
 
423
 
#if 0
424
 
    children = gtk_container_get_children(GTK_CONTAINER(win->notebook));
425
 
#endif
426
611
    mode = fm_side_pane_get_mode(sp);
427
 
#if 0
428
 
    /* set the side pane mode to all other tab pages */
429
 
    for(child = children; child; child = child->next)
430
 
    {
431
 
        FmTabPage* page = FM_TAB_PAGE(child->data);
432
 
        if(page != win->current_page)
433
 
            fm_side_pane_set_mode(fm_tab_page_get_side_pane(page), mode);
434
 
    }
435
 
    g_list_free(children);
436
 
#endif
437
612
 
438
613
    /* update menu */
439
 
    gtk_radio_action_set_current_value(GTK_RADIO_ACTION(gtk_ui_manager_get_action(win->ui,
440
 
                                           "/menubar/ViewMenu/SidePane/Places")),
441
 
                                       mode);
 
614
    gtk_radio_action_set_current_value(win->first_side_pane_mode, mode);
442
615
 
443
616
    if(mode != (app_config->side_pane_mode & FM_SP_MODE_MASK))
444
617
    {
448
621
    }
449
622
}
450
623
 
 
624
static void on_always_show_tabs_changed(FmAppConfig *cfg, FmMainWin *win)
 
625
{
 
626
    /* it will affect only the case when window has exactly 1 tab,
 
627
       all other cases will be handled when tab is added or removed */
 
628
    if (gtk_notebook_get_n_pages(win->notebook) == 1)
 
629
        gtk_notebook_set_show_tabs(win->notebook, app_config->always_show_tabs);
 
630
}
 
631
 
 
632
static void on_toolsbar_changed(FmAppConfig *cfg, FmMainWin *win)
 
633
{
 
634
    GtkAction* act;
 
635
    GtkWidget *toolitem;
 
636
    int n;
 
637
    gboolean active;
 
638
 
 
639
    if (win->in_update)
 
640
        return;
 
641
    win->in_update = TRUE; /* avoid recursion */
 
642
    active = cfg->tb.visible;
 
643
    gtk_widget_set_visible(GTK_WIDGET(win->toolbar), active);
 
644
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarNewWin");
 
645
    gtk_action_set_sensitive(act, active);
 
646
    if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(act)) != app_config->tb.new_win)
 
647
        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.new_win);
 
648
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarNewTab");
 
649
    gtk_action_set_sensitive(act, active);
 
650
    if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(act)) != app_config->tb.new_tab)
 
651
        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.new_tab);
 
652
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarNav");
 
653
    gtk_action_set_sensitive(act, active);
 
654
    if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(act)) != app_config->tb.nav)
 
655
        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.nav);
 
656
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarHome");
 
657
    gtk_action_set_sensitive(act, active);
 
658
    if (gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(act)) != app_config->tb.home)
 
659
        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.home);
 
660
    if (active) /* it it's hidden no reason to update its children */
 
661
    {
 
662
        toolitem = gtk_ui_manager_get_widget(win->ui, "/toolbar/New");
 
663
        gtk_widget_set_visible(toolitem, cfg->tb.new_win);
 
664
        toolitem = gtk_ui_manager_get_widget(win->ui, "/toolbar/NewTab");
 
665
        gtk_widget_set_visible(toolitem, cfg->tb.new_tab);
 
666
        active = cfg->tb.nav;
 
667
        toolitem = gtk_ui_manager_get_widget(win->ui, "/toolbar/Next");
 
668
        gtk_widget_set_visible(toolitem, active);
 
669
        n = gtk_toolbar_get_item_index(win->toolbar, GTK_TOOL_ITEM(toolitem));
 
670
        toolitem = GTK_WIDGET(gtk_toolbar_get_nth_item(win->toolbar, n-1));
 
671
        gtk_widget_set_visible(toolitem, active); /* Hist */
 
672
#if FM_CHECK_VERSION(1, 2, 0)
 
673
        toolitem = GTK_WIDGET(gtk_toolbar_get_nth_item(win->toolbar, n-2));
 
674
        gtk_widget_set_visible(toolitem, active); /* Prev */
 
675
#endif
 
676
        toolitem = GTK_WIDGET(gtk_toolbar_get_nth_item(win->toolbar, n+1));
 
677
        gtk_widget_set_visible(toolitem, active); /* Up */
 
678
        toolitem = gtk_ui_manager_get_widget(win->ui, "/toolbar/Home");
 
679
        gtk_widget_set_visible(toolitem, cfg->tb.home);
 
680
    }
 
681
    win->in_update = FALSE;
 
682
}
 
683
 
 
684
static void on_statusbar_changed(FmAppConfig *cfg, FmMainWin *win)
 
685
{
 
686
    gtk_widget_set_visible(GTK_WIDGET(win->statusbar), cfg->show_statusbar);
 
687
    update_statusbar(win);
 
688
}
 
689
 
 
690
static gboolean settings_hack_done = FALSE;
 
691
static gint old_gtk_timeout_expand = 0;
 
692
 
 
693
static void on_change_tab_on_drop_changed(FmAppConfig *cfg, gpointer _unused)
 
694
{
 
695
    if (app_config->change_tab_on_drop)
 
696
        g_object_set(gtk_settings_get_default(), "gtk-timeout-expand",
 
697
                     old_gtk_timeout_expand, NULL);
 
698
    else
 
699
        g_object_set(gtk_settings_get_default(), "gtk-timeout-expand", 600000, NULL);
 
700
}
 
701
 
 
702
static void _do_settings_hack(void)
 
703
{
 
704
    GtkSettings *settings;
 
705
 
 
706
    if (settings_hack_done)
 
707
        return;
 
708
    settings_hack_done = TRUE;
 
709
    settings = gtk_settings_get_default();
 
710
    g_object_get(settings, "gtk-timeout-expand", &old_gtk_timeout_expand, NULL);
 
711
    if (!app_config->change_tab_on_drop)
 
712
        /* dirty hack to override crazy GtkNotebook which unfolds tab
 
713
           each time it sees some drag comes to the tab label */
 
714
        g_object_set(settings, "gtk-timeout-expand", 600000, NULL);
 
715
    g_signal_connect(app_config, "changed::change_tab_on_drop",
 
716
                     G_CALLBACK(on_change_tab_on_drop_changed), NULL);
 
717
}
 
718
 
451
719
static void fm_main_win_init(FmMainWin *win)
452
720
{
453
721
    GtkBox *vbox;
454
722
    GtkWidget *menubar;
 
723
    GtkBox *pathbox;
455
724
    GtkToolItem *toolitem;
456
725
    GtkUIManager* ui;
457
726
    GtkActionGroup* act_grp;
458
727
    GtkAction* act;
459
728
    GtkAccelGroup* accel_grp;
 
729
    AtkObject *atk_obj, *atk_view;
 
730
    AtkRelation *relation;
 
731
#if FM_CHECK_VERSION(1, 2, 0)
 
732
    GtkRadioAction *mode_action;
 
733
    GSList *radio_group;
 
734
    GString *str, *xml;
 
735
    static char accel_str[] = "<Ctrl>1";
 
736
    int i;
 
737
    gboolean is_first;
 
738
#endif
460
739
    GtkShadowType shadow_type;
461
740
 
462
741
    pcmanfm_ref();
480
759
    gtk_action_group_add_actions(act_grp, main_win_actions, G_N_ELEMENTS(main_win_actions), win);
481
760
    gtk_action_group_add_toggle_actions(act_grp, main_win_toggle_actions,
482
761
                                        G_N_ELEMENTS(main_win_toggle_actions), win);
 
762
#if FM_CHECK_VERSION(1, 2, 0)
 
763
    /* generate list of modes dynamically from FmStandardView widget data */
 
764
    radio_group = NULL;
 
765
    is_first = TRUE;
 
766
    str = g_string_new("ViewMode:");
 
767
    xml = g_string_new("<menubar><menu action='ViewMenu'><menu action='FolderView'><placeholder name='ViewModes'>");
 
768
    accel_str[6] = '1';
 
769
    for(i = 0; i < fm_standard_view_get_n_modes(); i++)
 
770
    {
 
771
        if(fm_standard_view_get_mode_label(i))
 
772
        {
 
773
            g_string_append(str, fm_standard_view_mode_to_str(i));
 
774
            mode_action = gtk_radio_action_new(str->str,
 
775
                                               fm_standard_view_get_mode_label(i),
 
776
                                               fm_standard_view_get_mode_tooltip(i),
 
777
                                               fm_standard_view_get_mode_icon(i),
 
778
                                               i);
 
779
            gtk_radio_action_set_group(mode_action, radio_group);
 
780
            radio_group = gtk_radio_action_get_group(mode_action);
 
781
            gtk_action_group_add_action_with_accel(act_grp,
 
782
                                                   GTK_ACTION(mode_action),
 
783
                                                   accel_str);
 
784
            if (is_first) /* work on first one only */
 
785
            {
 
786
                win->first_view_mode = mode_action;
 
787
                g_signal_connect(mode_action, "changed", G_CALLBACK(on_change_mode), win);
 
788
            }
 
789
            is_first = FALSE;
 
790
            g_object_unref(mode_action);
 
791
            g_string_append_printf(xml, "<menuitem action='%s'/>", str->str);
 
792
            accel_str[6]++; /* <Ctrl>2 and so on */
 
793
            g_string_truncate(str, 9); /* reset it to just "ViewMode:" */
 
794
        }
 
795
    }
 
796
    g_string_append(xml, "</placeholder></menu>"); /* it will be continued below */
 
797
#else
483
798
    gtk_action_group_add_radio_actions(act_grp, main_win_mode_actions,
484
799
                                       G_N_ELEMENTS(main_win_mode_actions),
485
800
                                       app_config->view_mode,
486
801
                                       G_CALLBACK(on_change_mode), win);
 
802
#endif
487
803
    gtk_action_group_add_radio_actions(act_grp, main_win_sort_type_actions,
488
804
                                       G_N_ELEMENTS(main_win_sort_type_actions),
 
805
#if FM_CHECK_VERSION(1, 0, 2)
 
806
                                       FM_SORT_IS_ASCENDING(app_config->sort_type) ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING,
 
807
#else
489
808
                                       app_config->sort_type,
 
809
#endif
490
810
                                       G_CALLBACK(on_sort_type), win);
491
811
    gtk_action_group_add_radio_actions(act_grp, main_win_sort_by_actions,
492
812
                                       G_N_ELEMENTS(main_win_sort_by_actions),
493
813
                                       app_config->sort_by,
494
814
                                       G_CALLBACK(on_sort_by), win);
 
815
#if FM_CHECK_VERSION(1, 2, 0)
 
816
    /* generate list of modes dynamically from FmSidePane widget data */
 
817
    radio_group = NULL;
 
818
    is_first = TRUE;
 
819
    g_string_assign(str, "SidePaneMode:");
 
820
    g_string_append(xml, "<menu action='SidePane'><placeholder name='SidePaneModes'>");
 
821
    accel_str[6] = '6';
 
822
    for(i = 1; i <= fm_side_pane_get_n_modes(); i++)
 
823
    {
 
824
        if(fm_side_pane_get_mode_label(i))
 
825
        {
 
826
            g_string_append(str, fm_side_pane_get_mode_name(i));
 
827
            mode_action = gtk_radio_action_new(str->str,
 
828
                                               fm_side_pane_get_mode_label(i),
 
829
                                               fm_side_pane_get_mode_tooltip(i),
 
830
                                               NULL,
 
831
                                               i);
 
832
            gtk_radio_action_set_group(mode_action, radio_group);
 
833
            radio_group = gtk_radio_action_get_group(mode_action);
 
834
            gtk_action_group_add_action_with_accel(act_grp,
 
835
                                                   GTK_ACTION(mode_action),
 
836
                                                   accel_str);
 
837
            if (is_first) /* work on first one only */
 
838
            {
 
839
                win->first_side_pane_mode = mode_action;
 
840
                g_signal_connect(mode_action, "changed", G_CALLBACK(on_side_pane_mode), win);
 
841
            }
 
842
            is_first = FALSE;
 
843
            g_object_unref(mode_action);
 
844
            g_string_append_printf(xml, "<menuitem action='%s'/>", str->str);
 
845
            accel_str[6]++; /* <Ctrl>7 and so on */
 
846
            g_string_truncate(str, 13); /* reset it to just "SidePaneMode:" */
 
847
        }
 
848
    }
 
849
    gtk_radio_action_set_current_value(win->first_side_pane_mode,
 
850
                                       (app_config->side_pane_mode & FM_SP_MODE_MASK));
 
851
    g_string_append(xml, "</placeholder></menu></menu></menubar>");
 
852
    g_string_free(str, TRUE);
 
853
#else
495
854
    gtk_action_group_add_radio_actions(act_grp, main_win_side_bar_mode_actions,
496
855
                                       G_N_ELEMENTS(main_win_side_bar_mode_actions),
497
856
                                       (app_config->side_pane_mode & FM_SP_MODE_MASK),
498
857
                                       G_CALLBACK(on_side_pane_mode), win);
 
858
#endif
 
859
    gtk_action_group_add_radio_actions(act_grp, main_win_path_bar_mode_actions,
 
860
                                       G_N_ELEMENTS(main_win_path_bar_mode_actions),
 
861
                                       0, G_CALLBACK(on_path_bar_mode), win);
499
862
 
500
863
    accel_grp = gtk_ui_manager_get_accel_group(ui);
501
864
    gtk_window_add_accel_group(GTK_WINDOW(win), accel_grp);
502
865
 
503
866
    gtk_ui_manager_insert_action_group(ui, act_grp, 0);
504
867
    gtk_ui_manager_add_ui_from_string(ui, main_menu_xml, -1, NULL);
 
868
#if FM_CHECK_VERSION(1, 2, 0)
 
869
    /* add ui generated above */
 
870
    gtk_ui_manager_add_ui_from_string(ui, xml->str, xml->len, NULL);
 
871
    g_string_free(xml, TRUE);
 
872
#else
 
873
    act = gtk_ui_manager_get_action(ui, "/menubar/ViewMenu/FolderView/IconView");
 
874
    win->first_view_mode = GTK_RADIO_ACTION(act);
 
875
    act = gtk_ui_manager_get_action(ui, "/menubar/ViewMenu/SidePane/Places");
 
876
    win->first_side_pane_mode = GTK_RADIO_ACTION(act);
 
877
#endif
 
878
#if !FM_CHECK_VERSION(1, 0, 2)
505
879
    act = gtk_ui_manager_get_action(ui, "/menubar/ViewMenu/ShowHidden");
506
 
#if !FM_CHECK_VERSION(1, 0, 2)
507
880
    /* we cannot keep it in sync without callback from folder view which
508
881
       is available only in 1.0.2 so just hide it */
509
882
    gtk_action_set_visible(act, FALSE);
512
885
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act),
513
886
                                 (app_config->side_pane_mode & FM_SP_HIDE) == 0);
514
887
 
 
888
#if FM_CHECK_VERSION(1, 2, 0)
 
889
    /* disable "Find Files" button if module isn't available */
 
890
    if (!fm_module_is_in_use("vfs", "search"))
 
891
    {
 
892
        act = gtk_ui_manager_get_action(ui, "/menubar/ToolMenu/Search");
 
893
        gtk_action_set_sensitive(act, FALSE);
 
894
    }
 
895
    /* disable "Applications" button if module isn't available */
 
896
    if (!fm_module_is_in_use("vfs", "menu"))
 
897
    {
 
898
        act = gtk_ui_manager_get_action(ui, "/menubar/GoMenu/Apps");
 
899
        gtk_action_set_sensitive(act, FALSE);
 
900
    }
 
901
#endif
 
902
 
515
903
    menubar = gtk_ui_manager_get_widget(ui, "/menubar");
516
904
    win->toolbar = GTK_TOOLBAR(gtk_ui_manager_get_widget(ui, "/toolbar"));
517
905
    /* FIXME: should make these optional */
518
906
    gtk_toolbar_set_icon_size(win->toolbar, GTK_ICON_SIZE_SMALL_TOOLBAR);
519
907
    gtk_toolbar_set_style(win->toolbar, GTK_TOOLBAR_ICONS);
520
908
 
 
909
#if FM_CHECK_VERSION(1, 2, 0)
 
910
    /* create history button after 'Prev' and add a popup menu to it */
 
911
    toolitem = fm_menu_tool_item_new();
 
912
    gtk_toolbar_insert(win->toolbar, toolitem, 3);
 
913
#else
521
914
    /* create 'Prev' button manually and add a popup menu to it */
522
915
    toolitem = (GtkToolItem*)g_object_new(GTK_TYPE_MENU_TOOL_BUTTON, NULL);
523
916
    gtk_toolbar_insert(win->toolbar, toolitem, 1);
524
917
    act = gtk_ui_manager_get_action(ui, "/menubar/GoMenu/Prev");
525
918
    gtk_activatable_set_related_action(GTK_ACTIVATABLE(toolitem), act);
 
919
#endif
526
920
 
527
921
    /* set up history menu */
528
922
    win->history_menu = gtk_menu_new();
 
923
#if FM_CHECK_VERSION(1, 2, 0)
 
924
    fm_menu_tool_item_set_menu(FM_MENU_TOOL_ITEM(toolitem), win->history_menu);
 
925
    gtk_tool_item_set_tooltip_text(toolitem, _("Show history of visited folders"));
 
926
#else
529
927
    gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolitem), win->history_menu);
 
928
    gtk_menu_tool_button_set_arrow_tooltip_text(GTK_MENU_TOOL_BUTTON(toolitem),
 
929
                                                _("Show history of visited folders"));
 
930
#endif
530
931
    g_signal_connect(toolitem, "show-menu", G_CALLBACK(on_show_history_menu), win);
 
932
    atk_obj = gtk_widget_get_accessible(GTK_WIDGET(toolitem));
 
933
    if (atk_obj)
 
934
        atk_object_set_name(atk_obj, _("History"));
531
935
 
532
936
    gtk_box_pack_start( vbox, menubar, FALSE, TRUE, 0 );
533
937
    gtk_box_pack_start( vbox, GTK_WIDGET(win->toolbar), FALSE, TRUE, 0 );
540
944
    g_signal_connect(win->location, "activate", G_CALLBACK(on_location_activate), win);
541
945
    if(geteuid() == 0) /* if we're using root, Give the user some warnings */
542
946
    {
543
 
        GtkWidget* warning = gtk_image_new_from_stock(GTK_STOCK_DIALOG_AUTHENTICATION, GTK_ICON_SIZE_SMALL_TOOLBAR);
 
947
        GtkWidget* warning = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
544
948
        gtk_widget_set_tooltip_markup(warning, _("You are in super user mode"));
545
949
 
546
950
        toolitem = gtk_tool_item_new();
550
954
        gtk_toolbar_insert(win->toolbar, toolitem, 0);
551
955
    }
552
956
 
 
957
    win->path_bar = fm_path_bar_new();
 
958
    g_signal_connect(win->path_bar, "chdir", G_CALLBACK(on_path_bar_chdir), win);
 
959
    pathbox = (GtkBox*)gtk_hbox_new(FALSE, 0);
 
960
    gtk_box_pack_start(pathbox, GTK_WIDGET(win->location), TRUE, TRUE, 0);
 
961
    gtk_box_pack_start(pathbox, GTK_WIDGET(win->path_bar), TRUE, TRUE, 0);
 
962
 
553
963
    toolitem = (GtkToolItem*)gtk_tool_item_new();
554
 
    gtk_container_add(GTK_CONTAINER(toolitem), GTK_WIDGET(win->location));
 
964
    gtk_container_add(GTK_CONTAINER(toolitem), GTK_WIDGET(pathbox));
555
965
    gtk_tool_item_set_expand(toolitem, TRUE);
556
966
    gtk_toolbar_insert(win->toolbar, toolitem, gtk_toolbar_get_n_items(win->toolbar) - 1);
 
967
    g_signal_connect(app_config, "changed::toolsbar",
 
968
                     G_CALLBACK(on_toolsbar_changed), win);
557
969
 
558
970
    /* notebook - it contains both side pane and folder view(s) */
559
971
    win->notebook = (GtkNotebook*)gtk_notebook_new();
560
972
    gtk_notebook_set_scrollable(win->notebook, TRUE);
561
973
    gtk_container_set_border_width(GTK_CONTAINER(win->notebook), 0);
562
974
    gtk_notebook_set_show_border(win->notebook, FALSE);
 
975
    _do_settings_hack(); /* do it after GtkNotebook initialized */
563
976
 
564
977
    /* We need to use connect_after here.
565
978
     * GtkNotebook handles the real page switching stuff in default
571
984
    g_signal_connect(win->notebook, "page-removed", G_CALLBACK(on_notebook_page_removed), win);
572
985
 
573
986
    gtk_box_pack_start(vbox, GTK_WIDGET(win->notebook), TRUE, TRUE, 0);
 
987
    g_signal_connect(app_config, "changed::always_show_tabs",
 
988
                     G_CALLBACK(on_always_show_tabs_changed), win);
574
989
 
575
990
    /* status bar */
576
991
    win->statusbar = (GtkStatusbar*)gtk_statusbar_new();
584
999
    gtk_box_pack_start( vbox, GTK_WIDGET(win->statusbar), FALSE, TRUE, 0 );
585
1000
    win->statusbar_ctx = gtk_statusbar_get_context_id(win->statusbar, "status");
586
1001
    win->statusbar_ctx2 = gtk_statusbar_get_context_id(win->statusbar, "status2");
 
1002
    g_signal_connect(app_config, "changed::statusbar",
 
1003
                     G_CALLBACK(on_statusbar_changed), win);
587
1004
 
588
1005
    g_object_unref(act_grp);
589
1006
    win->ui = ui;
590
1007
 
 
1008
    /* accessibility: setup relation for Go button and location entry */
 
1009
    atk_obj = gtk_widget_get_accessible(GTK_WIDGET(win->location));
 
1010
    relation = atk_relation_new(&atk_obj, 1, ATK_RELATION_LABEL_FOR);
 
1011
    /* use atk_view for button temporarily */
 
1012
    atk_view = gtk_widget_get_accessible(gtk_ui_manager_get_widget(ui, "/toolbar/Go"));
 
1013
    atk_relation_set_add(atk_object_ref_relation_set(atk_view), relation);
 
1014
    g_object_unref(relation);
 
1015
    /* setup relations with view */
 
1016
    atk_view = gtk_widget_get_accessible(GTK_WIDGET(win->notebook));
 
1017
    relation = atk_relation_new(&atk_obj, 1, ATK_RELATION_CONTROLLED_BY);
 
1018
    atk_relation_set_add(atk_object_ref_relation_set(atk_view), relation);
 
1019
    g_object_unref(relation);
 
1020
    atk_obj = gtk_widget_get_accessible(GTK_WIDGET(win->statusbar));
 
1021
    relation = atk_relation_new(&atk_obj, 1, ATK_RELATION_DESCRIBED_BY);
 
1022
    atk_relation_set_add(atk_object_ref_relation_set(atk_view), relation);
 
1023
    g_object_unref(relation);
 
1024
 
591
1025
    gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(vbox));
592
1026
}
593
1027
 
617
1051
        g_signal_handlers_disconnect_by_func(win->notebook, on_notebook_switch_page, win);
618
1052
        g_signal_handlers_disconnect_by_func(win->notebook, on_notebook_page_added, win);
619
1053
        g_signal_handlers_disconnect_by_func(win->notebook, on_notebook_page_removed, win);
 
1054
        g_signal_handlers_disconnect_by_func(app_config, on_toolsbar_changed, win);
 
1055
        g_signal_handlers_disconnect_by_func(app_config, on_statusbar_changed, win);
 
1056
        g_signal_handlers_disconnect_by_func(app_config, on_always_show_tabs_changed, win);
620
1057
 
621
1058
        gtk_window_group_remove_window(win->win_group, GTK_WINDOW(win));
622
1059
        g_object_unref(win->win_group);
663
1100
static void on_unrealize(GtkWidget* widget)
664
1101
{
665
1102
    int w, h;
 
1103
    FmMainWin *win = FM_MAIN_WIN(widget);
666
1104
 
667
1105
    gtk_window_get_size(GTK_WINDOW(widget), &w, &h);
668
 
    if(!FM_MAIN_WIN(widget)->fullscreen &&
 
1106
    if(!win->fullscreen && !win->maximized &&
669
1107
       (w != app_config->win_width || h != app_config->win_height))
670
1108
    {
671
1109
        app_config->win_width = w;
672
1110
        app_config->win_height = h;
673
1111
        pcmanfm_save_config(FALSE);
674
1112
    }
 
1113
    if (win->maximized != app_config->maximized)
 
1114
    {
 
1115
        app_config->maximized = win->maximized;
 
1116
        pcmanfm_save_config(FALSE);
 
1117
    }
675
1118
    (*GTK_WIDGET_CLASS(fm_main_win_parent_class)->unrealize)(widget);
676
1119
}
677
1120
 
678
 
static void on_about_response(GtkDialog* dlg, gint response, GtkDialog **dlgptr)
 
1121
static void on_about_response(GtkDialog* dlg, gint response, GtkAboutDialog **dlgptr)
679
1122
{
680
1123
    g_signal_handlers_disconnect_by_func(dlg, on_about_response, dlgptr);
681
1124
    *dlgptr = NULL;
688
1131
    if(!about_dlg)
689
1132
    {
690
1133
        GtkBuilder* builder = gtk_builder_new();
 
1134
        GString *comments = g_string_new(_("Lightweight file manager\n"));
 
1135
 
691
1136
        gtk_builder_add_from_file(builder, PACKAGE_UI_DIR "/about.ui", NULL);
692
 
        about_dlg = GTK_DIALOG(gtk_builder_get_object(builder, "dlg"));
 
1137
        about_dlg = GTK_ABOUT_DIALOG(gtk_builder_get_object(builder, "dlg"));
 
1138
#if FM_CHECK_VERSION(1, 2, 0)
 
1139
        g_string_append_printf(comments, _("using LibFM ver. %s\n"), fm_version());
 
1140
#endif
 
1141
        g_string_append(comments, _("\nDeveloped by Hon Jen Yee (PCMan)"));
 
1142
        gtk_about_dialog_set_comments(about_dlg, comments->str);
 
1143
        g_string_free(comments, TRUE);
693
1144
        g_object_unref(builder);
694
1145
        g_signal_connect(about_dlg, "response", G_CALLBACK(on_about_response), (gpointer)&about_dlg);
695
1146
        pcmanfm_ref();
712
1163
        key_nav_list_dlg = gtk_message_dialog_new(NULL, 0,
713
1164
                                                  GTK_MESSAGE_INFO,
714
1165
                                                  GTK_BUTTONS_OK,
715
 
                                                  _("Keyboard navigation"));
 
1166
                                                  _("Keyboard Navigation"));
716
1167
        gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(key_nav_list_dlg),
717
1168
                         _("Tab: cycle focus Folder View -> Side Pane -> Tools Bar\n"
718
1169
                           "Shift+Tab: cycle focus Tools Bar -> Side Pane -> Folder View\n"
720
1171
                           "F8: focus divider between Side pane and Folder view\n"
721
1172
                           "F10: activate main menu\n"
722
1173
                           "Ctrl+L or Alt+D: jump focus to Path Bar"));
723
 
        gtk_window_set_title(GTK_WINDOW(key_nav_list_dlg), _("Keyboard navigation"));
 
1174
        gtk_window_set_title(GTK_WINDOW(key_nav_list_dlg), _("Keyboard Navigation"));
724
1175
        g_signal_connect(key_nav_list_dlg, "response", G_CALLBACK(on_key_nav_list_response), (gpointer)&key_nav_list_dlg);
725
1176
    }
726
1177
    gtk_window_present(GTK_WINDOW(key_nav_list_dlg));
728
1179
 
729
1180
static void on_open_in_terminal(GtkAction* act, FmMainWin* win)
730
1181
{
 
1182
    FmPath *path;
 
1183
#if FM_CHECK_VERSION(1, 0, 2)
 
1184
    path = fm_nav_history_get_nth_path(win->nav_history,
 
1185
                                fm_nav_history_get_cur_index(win->nav_history));
 
1186
    if (path)
 
1187
#else
731
1188
    const FmNavHistoryItem* item = fm_nav_history_get_cur(win->nav_history);
732
 
    if(item && item->path)
733
 
        pcmanfm_open_folder_in_terminal(GTK_WINDOW(win), item->path);
734
 
}
735
 
 
736
 
static const char* su_cmd_subst(char opt, gpointer user_data)
737
 
{
738
 
    return user_data;
739
 
}
740
 
 
741
 
static FmAppCommandParseOption su_cmd_opts[] =
742
 
{
743
 
    { 's', su_cmd_subst },
744
 
    { 0, NULL }
745
 
};
746
 
 
747
 
static void on_open_as_root(GtkAction* act, FmMainWin* win)
748
 
{
749
 
    GAppInfo* app;
750
 
    char* cmd;
751
 
    if(!app_config->su_cmd)
752
 
    {
753
 
        fm_show_error(GTK_WINDOW(win), NULL, _("Switch user command is not set."));
754
 
        fm_edit_preference(GTK_WINDOW(win), PREF_ADVANCED);
755
 
        return;
756
 
    }
757
 
    /* FIXME: need to rename to pcmanfm when we reach stable release. */
758
 
    if(fm_app_command_parse(app_config->su_cmd, su_cmd_opts, &cmd, "pcmanfm %U") == 0)
759
 
    {
760
 
        /* no %s found so just append to it */
761
 
        g_free(cmd);
762
 
        cmd = g_strconcat(app_config->su_cmd, " pcmanfm %U", NULL);
763
 
    }
764
 
    app = g_app_info_create_from_commandline(cmd, NULL, 0, NULL);
765
 
    g_free(cmd);
766
 
    if(app)
767
 
    {
768
 
        FmPath* cwd = fm_tab_page_get_cwd(win->current_page);
769
 
        GError* err = NULL;
770
 
        GdkAppLaunchContext* ctx = gdk_app_launch_context_new();
771
 
        char* uri = fm_path_to_uri(cwd);
772
 
        GList* uris = g_list_prepend(NULL, uri);
773
 
        gdk_app_launch_context_set_screen(ctx, gtk_widget_get_screen(GTK_WIDGET(win)));
774
 
        gdk_app_launch_context_set_timestamp(ctx, gtk_get_current_event_time());
775
 
        if(!g_app_info_launch_uris(app, uris, G_APP_LAUNCH_CONTEXT(ctx), &err))
776
 
        {
777
 
            fm_show_error(GTK_WINDOW(win), NULL, err->message);
778
 
            g_error_free(err);
779
 
            fm_edit_preference(GTK_WINDOW(win), PREF_ADVANCED);
780
 
        }
781
 
        g_list_free(uris);
782
 
        g_free(uri);
783
 
        g_object_unref(ctx);
784
 
        g_object_unref(app);
785
 
    }
 
1189
    if(item && (path = item->path))
 
1190
#endif
 
1191
        pcmanfm_open_folder_in_terminal(GTK_WINDOW(win), path);
786
1192
}
787
1193
 
788
1194
#if FM_CHECK_VERSION(1, 0, 2)
796
1202
}
797
1203
#endif
798
1204
 
 
1205
#if FM_CHECK_VERSION(1, 2, 0)
 
1206
static void on_launch(GtkAction* act, FmMainWin* win)
 
1207
{
 
1208
    char *cmd, *cwd, *def;
 
1209
 
 
1210
    cmd = fm_get_user_input(GTK_WINDOW(win), _("Run a command"),
 
1211
                            _("Enter a command to run:"), NULL);
 
1212
    if (cmd == NULL || cmd[0] == '\0') /* cancelled or empty */
 
1213
        return;
 
1214
    cwd = fm_path_to_str(fm_tab_page_get_cwd(win->current_page));
 
1215
    def = g_get_current_dir();
 
1216
    if (chdir(cwd) != 0) /* error */
 
1217
    {
 
1218
        fm_show_error(GTK_WINDOW(win), _("Current folder is inaccessible"), NULL);
 
1219
    }
 
1220
    else /* run and return back */
 
1221
    {
 
1222
        fm_launch_command_simple(GTK_WINDOW(win), NULL, 0, cmd, NULL);
 
1223
        /* return back */
 
1224
        if(chdir(def) != 0)
 
1225
            g_warning("on_launch(): chdir() failed");
 
1226
    }
 
1227
    g_free(cmd);
 
1228
    g_free(cwd);
 
1229
    g_free(def);
 
1230
}
 
1231
#endif
 
1232
 
799
1233
static void on_show_hidden(GtkToggleAction* act, FmMainWin* win)
800
1234
{
801
1235
    FmTabPage* page = win->current_page;
835
1269
static void on_change_mode(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win)
836
1270
{
837
1271
    int mode = gtk_radio_action_get_current_value(cur);
 
1272
    if (win->in_update)
 
1273
        return;
838
1274
    fm_standard_view_set_mode(FM_STANDARD_VIEW(win->folder_view), mode);
 
1275
    if (win->current_page->own_config)
 
1276
        fm_app_config_save_config_for_path(fm_folder_view_get_cwd(win->folder_view),
 
1277
                                           win->current_page->sort_type,
 
1278
                                           win->current_page->sort_by, mode,
 
1279
                                           win->current_page->show_hidden, NULL);
 
1280
    else
 
1281
        win->current_page->view_mode = mode;
839
1282
}
840
1283
 
841
1284
static void on_sort_by(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win)
842
1285
{
843
1286
    int val = gtk_radio_action_get_current_value(cur);
844
 
    fm_folder_view_sort(win->folder_view, -1, val);
845
 
    if(val != app_config->sort_by)
846
 
    {
847
 
        app_config->sort_by = val;
848
 
        pcmanfm_save_config(FALSE);
 
1287
    FmFolderView *fv = win->folder_view;
 
1288
#if FM_CHECK_VERSION(1, 0, 2)
 
1289
    FmFolderModel *model = fm_folder_view_get_model(fv);
 
1290
 
 
1291
    if (model)
 
1292
        fm_folder_model_set_sort(model, val, FM_SORT_DEFAULT);
 
1293
#else
 
1294
    fm_folder_view_sort(fv, -1, val);
 
1295
#endif
 
1296
    if(val != (int)win->current_page->sort_by)
 
1297
    {
 
1298
        win->current_page->sort_by = val;
 
1299
        if (win->current_page->own_config)
 
1300
        {
 
1301
            fm_app_config_save_config_for_path(fm_folder_view_get_cwd(fv),
 
1302
                                               win->current_page->sort_type,
 
1303
                                               val, -1,
 
1304
                                               win->current_page->show_hidden,
 
1305
                                               NULL);
 
1306
        }
 
1307
        else
 
1308
        {
 
1309
            app_config->sort_by = val;
 
1310
            pcmanfm_save_config(FALSE);
 
1311
        }
 
1312
    }
 
1313
}
 
1314
 
 
1315
#if FM_CHECK_VERSION(1, 0, 2)
 
1316
static inline void update_sort_type_for_page(FmTabPage *page, FmFolderView *fv, FmSortMode mode)
 
1317
#else
 
1318
static inline void update_sort_type_for_page(FmTabPage *page, FmFolderView *fv, guint mode)
 
1319
#endif
 
1320
{
 
1321
    if(mode != page->sort_type)
 
1322
    {
 
1323
        page->sort_type = mode;
 
1324
        if (page->own_config)
 
1325
        {
 
1326
            fm_app_config_save_config_for_path(fm_folder_view_get_cwd(fv), mode,
 
1327
                                               page->sort_by, -1,
 
1328
                                               page->show_hidden, NULL);
 
1329
        }
 
1330
        else
 
1331
        {
 
1332
            app_config->sort_type = mode;
 
1333
            pcmanfm_save_config(FALSE);
 
1334
        }
849
1335
    }
850
1336
}
851
1337
 
852
1338
static void on_sort_type(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win)
853
1339
{
854
1340
    guint val = gtk_radio_action_get_current_value(cur);
 
1341
    FmFolderView *fv = win->folder_view;
 
1342
#if FM_CHECK_VERSION(1, 0, 2)
 
1343
    FmFolderModel *model = fm_folder_view_get_model(fv);
 
1344
    FmSortMode mode;
 
1345
 
 
1346
    if (model)
 
1347
    {
 
1348
        fm_folder_model_get_sort(model, NULL, &mode);
 
1349
        mode &= ~FM_SORT_ORDER_MASK;
 
1350
        mode |= (val == GTK_SORT_ASCENDING) ? FM_SORT_ASCENDING : FM_SORT_DESCENDING;
 
1351
        fm_folder_model_set_sort(model, -1, mode);
 
1352
        update_sort_type_for_page(win->current_page, fv, mode);
 
1353
    }
 
1354
#else
855
1355
    fm_folder_view_sort(win->folder_view, val, -1);
856
 
    if(val != app_config->sort_type)
857
 
    {
858
 
        app_config->sort_type = val;
859
 
        pcmanfm_save_config(FALSE);
 
1356
    update_sort_type_for_page(win->current_page, fv, val);
 
1357
#endif
 
1358
}
 
1359
 
 
1360
#if FM_CHECK_VERSION(1, 2, 0)
 
1361
static void on_mingle_dirs(GtkToggleAction* act, FmMainWin* win)
 
1362
{
 
1363
    FmFolderView *fv = win->folder_view;
 
1364
    FmFolderModel *model = fm_folder_view_get_model(fv);
 
1365
    FmSortMode mode;
 
1366
    gboolean active;
 
1367
 
 
1368
    if (model)
 
1369
    {
 
1370
        fm_folder_model_get_sort(model, NULL, &mode);
 
1371
        active = gtk_toggle_action_get_active(act);
 
1372
        mode &= ~FM_SORT_NO_FOLDER_FIRST;
 
1373
        if (active)
 
1374
            mode |= FM_SORT_NO_FOLDER_FIRST;
 
1375
        fm_folder_model_set_sort(model, -1, mode);
 
1376
        update_sort_type_for_page(win->current_page, fv, mode);
 
1377
    }
 
1378
}
 
1379
#endif
 
1380
 
 
1381
#if FM_CHECK_VERSION(1, 0, 2)
 
1382
static void on_sort_ignore_case(GtkToggleAction* act, FmMainWin* win)
 
1383
{
 
1384
    FmFolderView *fv = win->folder_view;
 
1385
    FmFolderModel *model = fm_folder_view_get_model(fv);
 
1386
    FmSortMode mode;
 
1387
    gboolean active;
 
1388
 
 
1389
    if (model)
 
1390
    {
 
1391
        fm_folder_model_get_sort(model, NULL, &mode);
 
1392
        active = gtk_toggle_action_get_active(act);
 
1393
        mode &= ~FM_SORT_CASE_SENSITIVE;
 
1394
        if (!active)
 
1395
            mode |= FM_SORT_CASE_SENSITIVE;
 
1396
        fm_folder_model_set_sort(model, -1, mode);
 
1397
        update_sort_type_for_page(win->current_page, fv, mode);
 
1398
    }
 
1399
}
 
1400
#endif
 
1401
 
 
1402
static void on_save_per_folder(GtkToggleAction* act, FmMainWin* win)
 
1403
{
 
1404
    gboolean active = gtk_toggle_action_get_active(act);
 
1405
    FmTabPage *page = win->current_page;
 
1406
    FmFolderView *fv = win->folder_view;
 
1407
 
 
1408
    if (active)
 
1409
    {
 
1410
        if (page->own_config) /* not changed */
 
1411
            return;
 
1412
        page->own_config = TRUE;
 
1413
#if FM_CHECK_VERSION(1, 0, 2)
 
1414
        page->columns = g_strdupv(app_config->columns);
 
1415
#endif
 
1416
        fm_app_config_save_config_for_path(fm_folder_view_get_cwd(fv),
 
1417
                                           page->sort_type, page->sort_by,
 
1418
                                           fm_standard_view_get_mode(FM_STANDARD_VIEW(fv)),
 
1419
#if FM_CHECK_VERSION(1, 0, 2)
 
1420
                                           page->show_hidden, page->columns);
 
1421
#else
 
1422
                                           page->show_hidden, NULL);
 
1423
#endif
 
1424
    }
 
1425
    else if (page->own_config) /* attribute removed */
 
1426
    {
 
1427
        page->own_config = FALSE;
 
1428
#if FM_CHECK_VERSION(1, 0, 2)
 
1429
        g_strfreev(page->columns);
 
1430
        page->columns = NULL;
 
1431
#endif
 
1432
        fm_app_config_clear_config_for_path(fm_folder_view_get_cwd(fv));
860
1433
    }
861
1434
}
862
1435
 
863
1436
static void on_side_pane_mode(GtkRadioAction* act, GtkRadioAction *cur, FmMainWin* win)
864
1437
{
865
1438
    FmTabPage* cur_page = win->current_page;
866
 
    FmSidePane* sp = fm_tab_page_get_side_pane(cur_page);
 
1439
    FmSidePane* sp;
 
1440
 
 
1441
    if (cur_page == NULL) /* it can be NULL if we are in FmMainWin setup */
 
1442
        return;
 
1443
    sp = fm_tab_page_get_side_pane(cur_page);
867
1444
    int val = gtk_radio_action_get_current_value(cur);
868
1445
    fm_side_pane_set_mode(sp, val);
869
1446
}
888
1465
{
889
1466
    FmPath* path = fm_tab_page_get_cwd(win->current_page);
890
1467
    fm_main_win_add_tab(win, path);
 
1468
    /* FR #1967725: focus location bar for newly created tab */
 
1469
    gtk_window_set_focus(GTK_WINDOW(win), GTK_WIDGET(win->location));
 
1470
    if (win->idle_handler)
 
1471
    {
 
1472
        /* it will steal focus so cancel it */
 
1473
        g_source_remove(win->idle_handler);
 
1474
        win->idle_handler = 0;
 
1475
    }
891
1476
}
892
1477
 
893
1478
static void on_close_win(GtkAction* act, FmMainWin* win)
905
1490
 
906
1491
static void on_go(GtkAction* act, FmMainWin* win)
907
1492
{
908
 
    fm_main_win_chdir_by_name(win, gtk_entry_get_text(GTK_ENTRY(win->location)));
 
1493
    /* fm_main_win_chdir_by_name(win, gtk_entry_get_text(GTK_ENTRY(win->location))); */
 
1494
    g_signal_emit_by_name(win->location, "activate");
909
1495
}
910
1496
 
911
1497
static void _update_hist_buttons(FmMainWin* win)
914
1500
    FmNavHistory *nh = fm_tab_page_get_history(win->current_page);
915
1501
 
916
1502
    act = gtk_ui_manager_get_action(win->ui, "/menubar/GoMenu/Next");
 
1503
#if FM_CHECK_VERSION(1, 0, 2)
 
1504
    gtk_action_set_sensitive(act, fm_nav_history_get_cur_index(nh) > 0);
 
1505
#else
917
1506
    gtk_action_set_sensitive(act, fm_nav_history_can_forward(nh));
 
1507
#endif
918
1508
    act = gtk_ui_manager_get_action(win->ui, "/menubar/GoMenu/Prev");
919
1509
    gtk_action_set_sensitive(act, fm_nav_history_can_back(nh));
 
1510
    update_file_menu(win, fm_tab_page_get_cwd(win->current_page));
920
1511
}
921
1512
 
922
1513
static void on_go_back(GtkAction* act, FmMainWin* win)
923
1514
{
924
1515
    fm_tab_page_back(win->current_page);
 
1516
    /* update folder popup */
 
1517
    fm_folder_view_set_active(win->folder_view, FALSE);
 
1518
    fm_folder_view_add_popup(win->folder_view, GTK_WINDOW(win), NULL);
925
1519
    _update_hist_buttons(win);
926
1520
}
927
1521
 
928
1522
static void on_go_forward(GtkAction* act, FmMainWin* win)
929
1523
{
930
1524
    fm_tab_page_forward(win->current_page);
 
1525
    /* update folder popup */
 
1526
    fm_folder_view_set_active(win->folder_view, FALSE);
 
1527
    fm_folder_view_add_popup(win->folder_view, GTK_WINDOW(win), NULL);
931
1528
    _update_hist_buttons(win);
932
1529
}
933
1530
 
940
1537
 
941
1538
static void on_go_home(GtkAction* act, FmMainWin* win)
942
1539
{
943
 
    fm_main_win_chdir( win, fm_path_get_home());
 
1540
#if FM_CHECK_VERSION(1, 2, 0)
 
1541
    if (app_config->home_path && app_config->home_path[0])
 
1542
        fm_main_win_chdir_by_name(win, app_config->home_path);
 
1543
    else
 
1544
#endif
 
1545
        fm_main_win_chdir( win, fm_path_get_home());
944
1546
}
945
1547
 
946
1548
static void on_go_desktop(GtkAction* act, FmMainWin* win)
968
1570
    fm_main_win_chdir(win, fm_path_get_apps_menu());
969
1571
}
970
1572
 
 
1573
static void on_go_connect(GtkAction* act, FmMainWin* win)
 
1574
{
 
1575
    open_connect_dialog(GTK_WINDOW(win));
 
1576
}
 
1577
 
971
1578
void fm_main_win_chdir_by_name(FmMainWin* win, const char* path_str)
972
1579
{
973
1580
    FmPath* path = fm_path_new_for_str(path_str);
981
1588
     * trigger on_side_pane_chdir() callback. So we need to block it here. */
982
1589
    g_signal_handlers_block_by_func(win->side_pane, on_side_pane_chdir, win);
983
1590
    fm_tab_page_chdir(win->current_page, path);
 
1591
    /* update folder popup */
 
1592
    fm_folder_view_set_active(win->folder_view, FALSE);
 
1593
    fm_folder_view_add_popup(win->folder_view, GTK_WINDOW(win), NULL);
984
1594
    g_signal_handlers_unblock_by_func(win->side_pane, on_side_pane_chdir, win);
985
1595
    _update_hist_buttons(win);
 
1596
    update_view_menu(win);
 
1597
    update_file_menu(win, path);
986
1598
}
987
1599
 
988
1600
#if 0
1008
1620
{
1009
1621
    FmTabPage* page = win->current_page;
1010
1622
    const char* text;
 
1623
    if (!app_config->show_statusbar)
 
1624
        return; /* don't waste time on it */
1011
1625
    gtk_statusbar_pop(win->statusbar, win->statusbar_ctx);
1012
1626
    text = fm_tab_page_get_status_text(page, FM_STATUS_TEXT_NORMAL);
1013
1627
    if(text)
1052
1666
    return ret;
1053
1667
}
1054
1668
 
 
1669
static gboolean on_window_state_event(GtkWidget *widget, GdkEventWindowState *evt, FmMainWin *win)
 
1670
{
 
1671
    if (evt->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
 
1672
        win->fullscreen = ((evt->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0);
 
1673
    if (evt->changed_mask & GDK_WINDOW_STATE_MAXIMIZED)
 
1674
        win->maximized = ((evt->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0);
 
1675
    return FALSE;
 
1676
}
 
1677
 
1055
1678
FmMainWin* fm_main_win_add_win(FmMainWin* win, FmPath* path)
1056
1679
{
 
1680
    GtkAction *act;
 
1681
 
1057
1682
    win = fm_main_win_new();
1058
1683
    gtk_window_set_default_size(GTK_WINDOW(win),
1059
1684
                                app_config->win_width,
1060
1685
                                app_config->win_height);
 
1686
    if (app_config->maximized)
 
1687
        gtk_window_maximize(GTK_WINDOW(win));
1061
1688
    gtk_widget_show_all(GTK_WIDGET(win));
 
1689
    g_signal_connect(win, "window-state-event", G_CALLBACK(on_window_state_event), win);
1062
1690
    /* create new tab */
1063
1691
    fm_main_win_add_tab(win, path);
1064
1692
    gtk_window_present(GTK_WINDOW(win));
 
1693
    /* set toolbar visibility and menu toggleables from config */
 
1694
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ShowToolbar");
 
1695
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.visible);
 
1696
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarNewWin");
 
1697
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.new_win);
 
1698
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarNewTab");
 
1699
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.new_tab);
 
1700
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarNav");
 
1701
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.nav);
 
1702
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/Toolbar/ToolbarHome");
 
1703
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->tb.home);
 
1704
    /* the same for statusbar */
 
1705
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/ShowStatus");
 
1706
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), app_config->show_statusbar);
 
1707
    gtk_widget_set_visible(GTK_WIDGET(win->statusbar), app_config->show_statusbar);
 
1708
    /* the same for path bar mode */
 
1709
    gtk_widget_hide(GTK_WIDGET(win->path_bar));
 
1710
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/PathMode/PathEntry");
 
1711
    gtk_radio_action_set_current_value(GTK_RADIO_ACTION(act), app_config->pathbar_mode_buttons);
1065
1712
    return win;
1066
1713
}
1067
1714
 
 
1715
static void on_open(GtkAction* act, FmMainWin* win)
 
1716
{
 
1717
    FmFileInfoList *files = fm_folder_view_dup_selected_files(win->folder_view);
 
1718
    if(files)
 
1719
    {
 
1720
        GList* l = fm_file_info_list_peek_head_link(files);
 
1721
        if (g_list_length(l) > 0)
 
1722
            fm_launch_files_simple(GTK_WINDOW(win), NULL, l, pcmanfm_open_folder, NULL);
 
1723
        fm_file_info_list_unref(files);
 
1724
    }
 
1725
}
 
1726
 
 
1727
static void on_link(GtkAction *act, FmMainWin *win)
 
1728
{
 
1729
    FmPathList *files = fm_folder_view_dup_selected_file_paths(win->folder_view);
 
1730
    if (files)
 
1731
    {
 
1732
        FmPath *dest = fm_select_folder(GTK_WINDOW(win), NULL);
 
1733
        if (dest)
 
1734
        {
 
1735
            fm_link_files(GTK_WINDOW(win), files, dest);
 
1736
            fm_path_unref(dest);
 
1737
        }
 
1738
        fm_path_list_unref(files);
 
1739
    }
 
1740
}
 
1741
 
1068
1742
static void on_copy_to(GtkAction* act, FmMainWin* win)
1069
1743
{
1070
1744
    FmPathList* files = fm_folder_view_dup_selected_file_paths(win->folder_view);
1096
1770
    }
1097
1771
}
1098
1772
 
 
1773
static void on_trash(GtkAction* act, FmMainWin* win)
 
1774
{
 
1775
    FmPathList* files = fm_folder_view_dup_selected_file_paths(win->folder_view);
 
1776
    if(files)
 
1777
    {
 
1778
        fm_trash_files(GTK_WINDOW(win), files);
 
1779
        fm_path_list_unref(files);
 
1780
    }
 
1781
}
 
1782
 
 
1783
static void on_del(GtkAction* act, FmMainWin* win)
 
1784
{
 
1785
    FmPathList* files = fm_folder_view_dup_selected_file_paths(win->folder_view);
 
1786
    if(files)
 
1787
    {
 
1788
        fm_delete_files(GTK_WINDOW(win), files);
 
1789
        fm_path_list_unref(files);
 
1790
    }
 
1791
}
 
1792
 
 
1793
static void on_copy_path(GtkAction* action, FmMainWin* win)
 
1794
{
 
1795
    GdkDisplay *dpy = gtk_widget_get_display(GTK_WIDGET(win));
 
1796
    GtkClipboard *clipboard = gtk_clipboard_get_for_display(dpy, GDK_SELECTION_CLIPBOARD);
 
1797
    GString *str = g_string_sized_new(128);
 
1798
    FmPathList *files = fm_folder_view_dup_selected_file_paths(win->folder_view);
 
1799
    GList *fl;
 
1800
 
 
1801
    for (fl = fm_path_list_peek_head_link(files); fl; fl = fl->next)
 
1802
    {
 
1803
        char *path = fm_path_to_str(fl->data);
 
1804
        if (str->len > 0)
 
1805
            g_string_append_c(str, '\n');
 
1806
        g_string_append(str, path);
 
1807
        g_free(path);
 
1808
    }
 
1809
    gtk_clipboard_set_text(clipboard, str->str, str->len);
 
1810
    g_string_free(str, TRUE);
 
1811
}
 
1812
 
1099
1813
static void on_preference(GtkAction* act, FmMainWin* win)
1100
1814
{
1101
1815
    fm_edit_preference(GTK_WINDOW(win), 0);
1119
1833
    }
1120
1834
}
1121
1835
 
 
1836
static void on_show_toolbar(GtkToggleAction *action, FmMainWin *win)
 
1837
{
 
1838
    gboolean active = gtk_toggle_action_get_active(action);
 
1839
 
 
1840
    app_config->tb.visible = active;
 
1841
    fm_config_emit_changed(fm_config, "toolsbar");
 
1842
    pcmanfm_save_config(FALSE);
 
1843
}
 
1844
 
 
1845
/* toolbar items: NewWin NewTab Prev (Hist) Next Up Home (Location) Go */
 
1846
static void on_toolbar_new_win(GtkToggleAction *act, FmMainWin *win)
 
1847
{
 
1848
    gboolean active = gtk_toggle_action_get_active(act);
 
1849
 
 
1850
    app_config->tb.new_win = active;
 
1851
    fm_config_emit_changed(fm_config, "toolsbar");
 
1852
    pcmanfm_save_config(FALSE);
 
1853
}
 
1854
 
 
1855
static void on_toolbar_new_tab(GtkToggleAction *act, FmMainWin *win)
 
1856
{
 
1857
    gboolean active = gtk_toggle_action_get_active(act);
 
1858
 
 
1859
    app_config->tb.new_tab = active;
 
1860
    fm_config_emit_changed(fm_config, "toolsbar");
 
1861
    pcmanfm_save_config(FALSE);
 
1862
}
 
1863
 
 
1864
static void on_toolbar_nav(GtkToggleAction *act, FmMainWin *win)
 
1865
{
 
1866
    gboolean active = gtk_toggle_action_get_active(act);
 
1867
 
 
1868
    app_config->tb.nav = active;
 
1869
    fm_config_emit_changed(fm_config, "toolsbar");
 
1870
    pcmanfm_save_config(FALSE);
 
1871
}
 
1872
 
 
1873
static void on_toolbar_home(GtkToggleAction *act, FmMainWin *win)
 
1874
{
 
1875
    gboolean active = gtk_toggle_action_get_active(act);
 
1876
 
 
1877
    app_config->tb.home = active;
 
1878
    fm_config_emit_changed(fm_config, "toolsbar");
 
1879
    pcmanfm_save_config(FALSE);
 
1880
}
 
1881
 
1122
1882
static void on_location(GtkAction* act, FmMainWin* win)
1123
1883
{
1124
1884
    gtk_widget_grab_focus(GTK_WIDGET(win->location));
 
1885
    if (app_config->pathbar_mode_buttons)
 
1886
    {
 
1887
        gtk_widget_show(GTK_WIDGET(win->location));
 
1888
        gtk_widget_show(gtk_ui_manager_get_widget(win->ui, "/toolbar/Go"));
 
1889
        gtk_widget_hide(GTK_WIDGET(win->path_bar));
 
1890
    }
1125
1891
}
1126
1892
 
1127
1893
static void bounce_action(GtkAction* act, FmMainWin* win)
1128
1894
{
 
1895
    GtkWindow *window = GTK_WINDOW(win);
 
1896
    GtkWidget *current_focus;
 
1897
 
1129
1898
    g_debug("bouncing action %s to popup", gtk_action_get_name(act));
1130
 
    fm_folder_view_bounce_action(act, FM_FOLDER_VIEW(win->folder_view));
 
1899
    /* save current focus */
 
1900
    current_focus = gtk_window_get_focus(window);
 
1901
    /* bug #3615003: if folder view does not have the focus, action will not work */
 
1902
    gtk_window_set_focus(window, GTK_WIDGET(win->folder_view));
 
1903
    fm_folder_view_bounce_action(act, win->folder_view);
 
1904
    /* restore focus back */
 
1905
    gtk_window_set_focus(window, current_focus);
 
1906
}
 
1907
 
 
1908
static guint icon_sizes[] =
 
1909
{
 
1910
    8,
 
1911
    10,
 
1912
    12,
 
1913
    16,
 
1914
    20,
 
1915
    24,
 
1916
    32, /* 30 would be better */
 
1917
    40, /* 38 */
 
1918
    48,
 
1919
    64, /* 60 */
 
1920
    80, /* 76 */
 
1921
    96,
 
1922
    128, /* 120 */
 
1923
    160, /* 152 */
 
1924
    192,
 
1925
    224,
 
1926
    256
 
1927
};
 
1928
 
 
1929
static void on_size_decrement(GtkAction *act, FmMainWin *win)
 
1930
{
 
1931
    FmStandardViewMode mode;
 
1932
    guint size, i;
 
1933
 
 
1934
    if (win->folder_view == NULL)
 
1935
        return;
 
1936
    mode = fm_standard_view_get_mode(FM_STANDARD_VIEW(win->folder_view));
 
1937
    switch (mode)
 
1938
    {
 
1939
    case FM_FV_ICON_VIEW:
 
1940
        size = fm_config->big_icon_size;
 
1941
        if (size < 24)
 
1942
            return;
 
1943
        break;
 
1944
    case FM_FV_COMPACT_VIEW:
 
1945
    case FM_FV_LIST_VIEW:
 
1946
        size = fm_config->small_icon_size;
 
1947
        if (size < 10)
 
1948
            return;
 
1949
        break;
 
1950
    case FM_FV_THUMBNAIL_VIEW:
 
1951
        size = fm_config->thumbnail_size;
 
1952
        if (size < 80)
 
1953
            return;
 
1954
        break;
 
1955
    default:
 
1956
        return;
 
1957
    }
 
1958
    for (i = G_N_ELEMENTS(icon_sizes); i > 0; )
 
1959
    {
 
1960
        i--;
 
1961
        if (icon_sizes[i] < size)
 
1962
            break;
 
1963
    }
 
1964
    switch (mode)
 
1965
    {
 
1966
    case FM_FV_ICON_VIEW:
 
1967
        fm_config->big_icon_size = icon_sizes[i];
 
1968
        fm_config_emit_changed(fm_config, "big_icon_size");
 
1969
        break;
 
1970
    case FM_FV_COMPACT_VIEW:
 
1971
    case FM_FV_LIST_VIEW:
 
1972
        fm_config->small_icon_size = icon_sizes[i];
 
1973
        fm_config_emit_changed(fm_config, "small_icon_size");
 
1974
        break;
 
1975
    case FM_FV_THUMBNAIL_VIEW:
 
1976
        fm_config->thumbnail_size = icon_sizes[i];
 
1977
        fm_config_emit_changed(fm_config, "thumbnail_size");
 
1978
    }
 
1979
    pcmanfm_save_config(FALSE);
 
1980
}
 
1981
 
 
1982
static void on_size_increment(GtkAction *act, FmMainWin *win)
 
1983
{
 
1984
    FmStandardViewMode mode;
 
1985
    guint size, i;
 
1986
 
 
1987
    if (win->folder_view == NULL)
 
1988
        return;
 
1989
    mode = fm_standard_view_get_mode(FM_STANDARD_VIEW(win->folder_view));
 
1990
    switch (mode)
 
1991
    {
 
1992
    case FM_FV_ICON_VIEW:
 
1993
        size = fm_config->big_icon_size;
 
1994
        if (size > 80)
 
1995
            return;
 
1996
        break;
 
1997
    case FM_FV_COMPACT_VIEW:
 
1998
    case FM_FV_LIST_VIEW:
 
1999
        size = fm_config->small_icon_size;
 
2000
        if (size > 40)
 
2001
            return;
 
2002
        break;
 
2003
    case FM_FV_THUMBNAIL_VIEW:
 
2004
        size = fm_config->thumbnail_size;
 
2005
        if (size > 224)
 
2006
            return;
 
2007
        break;
 
2008
    default:
 
2009
        return;
 
2010
    }
 
2011
    for (i = 1; i < G_N_ELEMENTS(icon_sizes); i++)
 
2012
    {
 
2013
        if (icon_sizes[i] > size)
 
2014
            break;
 
2015
    }
 
2016
    switch (mode)
 
2017
    {
 
2018
    case FM_FV_ICON_VIEW:
 
2019
        fm_config->big_icon_size = icon_sizes[i];
 
2020
        fm_config_emit_changed(fm_config, "big_icon_size");
 
2021
        break;
 
2022
    case FM_FV_COMPACT_VIEW:
 
2023
    case FM_FV_LIST_VIEW:
 
2024
        fm_config->small_icon_size = icon_sizes[i];
 
2025
        fm_config_emit_changed(fm_config, "small_icon_size");
 
2026
        break;
 
2027
    case FM_FV_THUMBNAIL_VIEW:
 
2028
        fm_config->thumbnail_size = icon_sizes[i];
 
2029
        fm_config_emit_changed(fm_config, "thumbnail_size");
 
2030
    }
 
2031
    pcmanfm_save_config(FALSE);
 
2032
}
 
2033
 
 
2034
static void on_size_default(GtkAction *act, FmMainWin *win)
 
2035
{
 
2036
    FmStandardViewMode mode;
 
2037
 
 
2038
    if (win->folder_view == NULL)
 
2039
        return;
 
2040
    mode = fm_standard_view_get_mode(FM_STANDARD_VIEW(win->folder_view));
 
2041
    switch (mode)
 
2042
    {
 
2043
    case FM_FV_ICON_VIEW:
 
2044
        if (fm_config->big_icon_size == 48)
 
2045
            return;
 
2046
        fm_config->big_icon_size = 48;
 
2047
        fm_config_emit_changed(fm_config, "big_icon_size");
 
2048
        break;
 
2049
    case FM_FV_COMPACT_VIEW:
 
2050
    case FM_FV_LIST_VIEW:
 
2051
        if (fm_config->small_icon_size == 20)
 
2052
            return;
 
2053
        fm_config->small_icon_size = 20;
 
2054
        fm_config_emit_changed(fm_config, "small_icon_size");
 
2055
        break;
 
2056
    case FM_FV_THUMBNAIL_VIEW:
 
2057
        if (fm_config->thumbnail_size == 128)
 
2058
            return;
 
2059
        fm_config->thumbnail_size = 128;
 
2060
        fm_config_emit_changed(fm_config, "thumbnail_size");
 
2061
        break;
 
2062
    default:
 
2063
        return;
 
2064
    }
 
2065
    pcmanfm_save_config(FALSE);
1131
2066
}
1132
2067
 
1133
2068
/* This callback is only connected to folder view of current active tab page. */
1155
2090
{
1156
2091
    if(page != win->current_page)
1157
2092
        return;
 
2093
    if (!app_config->show_statusbar)
 
2094
        return;
1158
2095
 
1159
2096
    switch(type)
1160
2097
    {
1187
2124
        return;
1188
2125
 
1189
2126
    fm_path_entry_set_path(win->location, path);
 
2127
    fm_path_bar_set_path(win->path_bar, path);
1190
2128
    gtk_window_set_title(GTK_WINDOW(win), fm_tab_page_get_title(page));
1191
2129
}
1192
2130
 
 
2131
static void on_tab_page_got_focus(FmTabPage* page, FmMainWin* win)
 
2132
{
 
2133
    int n = gtk_notebook_page_num(win->notebook, GTK_WIDGET(page));
 
2134
    /* sometimes views receive focus while they are in rendering process
 
2135
       therefore click on tab will not always work as expected because it
 
2136
       is reset in this callback, the trick is if notebook is in update
 
2137
       process then focus change is pending (see on_notebook_switch_page()
 
2138
       for details) therefore we can check that and do nothing */
 
2139
    if (n >= 0 && win->idle_handler == 0) /* don't change page if it is pending */
 
2140
        gtk_notebook_set_current_page(win->notebook, n);
 
2141
}
 
2142
 
1193
2143
#if FM_CHECK_VERSION(1, 0, 2)
1194
2144
static void on_folder_view_filter_changed(FmFolderView* fv, FmMainWin* win)
1195
2145
{
1196
2146
    GtkAction* act;
1197
2147
    gboolean active;
1198
2148
 
 
2149
    if (fv != win->folder_view)
 
2150
        return;
 
2151
 
1199
2152
    active = fm_folder_view_get_show_hidden(fv);
1200
2153
 
1201
2154
    act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/ShowHidden");
1202
2155
    gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), active);
1203
 
    if(active != app_config->show_hidden)
 
2156
    if(active != win->current_page->show_hidden)
1204
2157
    {
1205
 
        app_config->show_hidden = active;
1206
 
        pcmanfm_save_config(FALSE);
 
2158
        win->current_page->show_hidden = active;
 
2159
        if (win->current_page->own_config)
 
2160
        {
 
2161
            fm_app_config_save_config_for_path(fm_folder_view_get_cwd(fv),
 
2162
                                               win->current_page->sort_type,
 
2163
                                               win->current_page->sort_by, -1,
 
2164
                                               active, NULL);
 
2165
        }
 
2166
        else
 
2167
        {
 
2168
            app_config->show_hidden = active;
 
2169
            pcmanfm_save_config(FALSE);
 
2170
        }
1207
2171
    }
1208
2172
}
1209
2173
#endif
1210
2174
 
 
2175
static inline FmTabPage *_find_tab_page(FmMainWin *win, FmFolderView *fv)
 
2176
{
 
2177
    FmTabPage *page;
 
2178
    gint n;
 
2179
 
 
2180
    for (n = gtk_notebook_get_n_pages(win->notebook); n > 0; )
 
2181
    {
 
2182
        page = FM_TAB_PAGE(gtk_notebook_get_nth_page(win->notebook, --n));
 
2183
        if (fv == fm_tab_page_get_folder_view(page))
 
2184
            return page;
 
2185
    }
 
2186
    return NULL;
 
2187
}
 
2188
 
1211
2189
static void on_notebook_switch_page(GtkNotebook* nb, gpointer* new_page, guint num, FmMainWin* win)
1212
2190
{
1213
2191
    GtkWidget* sw_page = gtk_notebook_get_nth_page(nb, num);
1214
2192
    FmTabPage* page;
 
2193
    FmFolderView *old_view = NULL, *passive_view = NULL;
1215
2194
 
1216
2195
    g_return_if_fail(FM_IS_TAB_PAGE(sw_page));
1217
2196
    page = (FmTabPage*)sw_page;
1218
2197
    /* deactivate gestures from old view first */
1219
2198
    if(win->folder_view)
 
2199
    {
1220
2200
        fm_folder_view_set_active(win->folder_view, FALSE);
 
2201
        g_object_unref(win->folder_view);
 
2202
    }
 
2203
 
 
2204
    /* remember old views for checks below */
 
2205
    if (win->current_page)
 
2206
    {
 
2207
        passive_view = fm_tab_page_get_passive_view(win->current_page);
 
2208
        old_view = fm_tab_page_get_folder_view(win->current_page);
 
2209
    }
1221
2210
 
1222
2211
    /* connect to the new active page */
1223
2212
    win->current_page = page;
1224
2213
    win->folder_view = fm_tab_page_get_folder_view(page);
 
2214
    if(win->folder_view)
 
2215
        g_object_ref(win->folder_view);
1225
2216
    win->nav_history = fm_tab_page_get_history(page);
1226
2217
    win->side_pane = fm_tab_page_get_side_pane(page);
1227
2218
 
 
2219
    /* set active and passive panes */
 
2220
    if (win->enable_passive_view && passive_view)
 
2221
    {
 
2222
        FmTabPage *psv_page;
 
2223
 
 
2224
        if (win->folder_view == passive_view)
 
2225
        {
 
2226
            /* we moved to other pane so we have to set passive_view_on_right */
 
2227
            win->passive_view_on_right = win->passive_view_on_right ? FALSE : TRUE;
 
2228
            passive_view = old_view;
 
2229
        }
 
2230
        /* now set it */
 
2231
        fm_tab_page_set_passive_view(page, passive_view, win->passive_view_on_right);
 
2232
        /* FIXME: log errors */
 
2233
        /* ok, passive view was just changed, we have to update the button */
 
2234
        psv_page = _find_tab_page(win, passive_view);
 
2235
        if (psv_page)
 
2236
            gtk_widget_set_state(GTK_WIDGET(psv_page->tab_label), GTK_STATE_SELECTED);
 
2237
    }
 
2238
    else
 
2239
    {
 
2240
        /* FIXME: log errors */
 
2241
        fm_tab_page_take_view_back(page);
 
2242
    }
 
2243
 
1228
2244
    /* reactivate gestures */
1229
2245
    fm_folder_view_set_active(win->folder_view, TRUE);
1230
2246
    g_debug("reactivated gestures to page %u", num);
1250
2266
    }
1251
2267
 
1252
2268
    fm_path_entry_set_path(win->location, fm_tab_page_get_cwd(page));
 
2269
    fm_path_bar_set_path(win->path_bar, fm_tab_page_get_cwd(page));
1253
2270
    gtk_window_set_title((GtkWindow*)win, fm_tab_page_get_title(page));
1254
2271
 
1255
2272
    update_sort_menu(win);
1256
2273
    update_view_menu(win);
 
2274
    update_file_menu(win, fm_tab_page_get_cwd(page));
1257
2275
    update_statusbar(win);
1258
2276
 
1259
 
    /* FIXME: this does not work sometimes due to limitation of GtkNotebook.
1260
 
     * So weird. After page switching with mouse button, GTK+ always tries
1261
 
     * to focus the left pane, instead of the folder_view we specified. */
1262
 
    gtk_widget_grab_focus(GTK_WIDGET(win->folder_view));
 
2277
    if(win->idle_handler == 0)
 
2278
        win->idle_handler = gdk_threads_add_idle_full(G_PRIORITY_LOW,
 
2279
                                                      idle_focus_view, win, NULL);
1263
2280
}
1264
2281
 
1265
2282
static void on_notebook_page_added(GtkNotebook* nb, GtkWidget* page, guint num, FmMainWin* win)
1272
2289
                     G_CALLBACK(on_tab_page_chdir), win);
1273
2290
    g_signal_connect(tab_page, "status",
1274
2291
                     G_CALLBACK(on_tab_page_status_text), win);
 
2292
    g_signal_connect(tab_page, "got-focus",
 
2293
                     G_CALLBACK(on_tab_page_got_focus), win);
 
2294
    /* FIXME: remove direct access */
1275
2295
    g_signal_connect(tab_page->folder_view, "sort-changed",
1276
2296
                     G_CALLBACK(on_folder_view_sort_changed), win);
1277
2297
    g_signal_connect(tab_page->folder_view, "sel-changed",
1305
2325
{
1306
2326
    FmTabPage* tab_page = FM_TAB_PAGE(page);
1307
2327
    FmFolderView* folder_view = fm_tab_page_get_folder_view(tab_page);
 
2328
    GtkAction* act;
1308
2329
 
1309
 
    g_debug("FmMainWin: removed page %u; %u pages left", num,
1310
 
            gtk_notebook_get_n_pages(nb));
 
2330
    g_debug("FmMainWin[%p]: removed page %u[%p](view=%p); %u pages left", win,
 
2331
            num, page, folder_view, gtk_notebook_get_n_pages(nb));
1311
2332
    /* disconnect from previous active page */
1312
2333
    g_signal_handlers_disconnect_by_func(tab_page,
1313
2334
                                         on_tab_page_splitter_pos_changed, win);
1315
2336
                                         on_tab_page_chdir, win);
1316
2337
    g_signal_handlers_disconnect_by_func(tab_page,
1317
2338
                                         on_tab_page_status_text, win);
 
2339
    g_signal_handlers_disconnect_by_func(tab_page,
 
2340
                                         on_tab_page_got_focus, win);
1318
2341
    if(folder_view)
1319
2342
    {
1320
2343
        g_signal_handlers_disconnect_by_func(folder_view,
1321
2344
                                             on_view_key_press_event, win);
1322
 
        g_signal_handlers_disconnect_by_func(tab_page->folder_view,
 
2345
        g_signal_handlers_disconnect_by_func(folder_view,
1323
2346
                                             on_folder_view_sort_changed, win);
1324
 
        g_signal_handlers_disconnect_by_func(tab_page->folder_view,
 
2347
        g_signal_handlers_disconnect_by_func(folder_view,
1325
2348
                                             on_folder_view_sel_changed, win);
1326
2349
#if FM_CHECK_VERSION(1, 0, 2)
1327
 
        g_signal_handlers_disconnect_by_func(tab_page->folder_view,
 
2350
        g_signal_handlers_disconnect_by_func(folder_view,
1328
2351
                                             on_folder_view_filter_changed, win);
1329
2352
#endif
1330
 
        g_signal_handlers_disconnect_by_func(tab_page->folder_view,
 
2353
        g_signal_handlers_disconnect_by_func(folder_view,
1331
2354
                                             on_folder_view_clicked, win);
 
2355
        /* update menu if passive pane was removed */
 
2356
        if (win->current_page && win->enable_passive_view &&
 
2357
            fm_tab_page_get_passive_view(win->current_page) == folder_view)
 
2358
        {
 
2359
            win->enable_passive_view = FALSE;
 
2360
            act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/DualPane");
 
2361
            gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(act), FALSE);
 
2362
        }
1332
2363
    }
1333
2364
    g_signal_handlers_disconnect_by_func(tab_page->side_pane,
1334
2365
                                         on_side_pane_mode_changed, win);
1338
2369
    if(tab_page == win->current_page)
1339
2370
    {
1340
2371
        win->current_page = NULL;
 
2372
        if (win->folder_view)
 
2373
            g_object_unref(win->folder_view);
1341
2374
        win->folder_view = NULL;
1342
2375
        win->nav_history = NULL;
1343
2376
        win->side_pane = NULL;
1448
2481
            gtk_widget_grab_focus(GTK_WIDGET(win->folder_view));
1449
2482
            fm_path_entry_set_path(win->location,
1450
2483
                                   fm_tab_page_get_cwd(win->current_page));
 
2484
            fm_path_bar_set_path(win->path_bar,
 
2485
                                 fm_tab_page_get_cwd(win->current_page));
1451
2486
            return TRUE;
1452
2487
        }
1453
2488
    }
1458
2493
{
1459
2494
    FmMainWin* win = FM_MAIN_WIN(w);
1460
2495
    GtkAction* act;
 
2496
 
1461
2497
    if(evt->button == 8) /* back */
1462
2498
    {
1463
2499
        act = gtk_ui_manager_get_action(win->ui, "/Prev2");
1474
2510
        return FALSE;
1475
2511
}
1476
2512
 
 
2513
static gboolean on_scroll_event(GtkWidget* w, GdkEventScroll* evt)
 
2514
{
 
2515
    FmMainWin* win = FM_MAIN_WIN(w);
 
2516
    GtkAction* act;
 
2517
    int modifier = evt->state & gtk_accelerator_get_default_mod_mask();
 
2518
 
 
2519
    /* g_debug("on_scroll_event:%d", evt->direction); */
 
2520
    if (modifier != GDK_CONTROL_MASK) ;
 
2521
    else if(evt->direction == GDK_SCROLL_UP)
 
2522
    {
 
2523
        act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/SizeBigger");
 
2524
        gtk_action_activate(act);
 
2525
        return TRUE;
 
2526
    }
 
2527
    else if(evt->direction == GDK_SCROLL_DOWN)
 
2528
    {
 
2529
        act = gtk_ui_manager_get_action(win->ui, "/menubar/ViewMenu/SizeSmaller");
 
2530
        gtk_action_activate(act);
 
2531
        return TRUE;
 
2532
    }
 
2533
    if(GTK_WIDGET_CLASS(fm_main_win_parent_class)->scroll_event)
 
2534
        return GTK_WIDGET_CLASS(fm_main_win_parent_class)->scroll_event(w, evt);
 
2535
    else
 
2536
        return FALSE;
 
2537
}
 
2538
 
1477
2539
static void on_reload(GtkAction* act, FmMainWin* win)
1478
2540
{
1479
2541
    FmTabPage* page = win->current_page;
1480
2542
    fm_tab_page_reload(page);
1481
2543
}
1482
2544
 
 
2545
#if FM_CHECK_VERSION(1, 0, 2)
 
2546
static void on_filter(GtkAction* act, FmMainWin* win)
 
2547
{
 
2548
    FmTabPage *page = win->current_page;
 
2549
    const char *old_filter = page->filter_pattern ? page->filter_pattern : "*";
 
2550
    char *new_filter;
 
2551
 
 
2552
    new_filter = fm_get_user_input(GTK_WINDOW(win), _("Select filter"),
 
2553
                                   _("Choose a new shell pattern to show files:"),
 
2554
                                   old_filter);
 
2555
    if (!new_filter) /* cancelled */
 
2556
        return;
 
2557
    if (strcmp(new_filter, "*"))
 
2558
        fm_tab_page_set_filter_pattern(page, new_filter);
 
2559
    else
 
2560
        fm_tab_page_set_filter_pattern(page, NULL);
 
2561
    g_free(new_filter);
 
2562
    gtk_window_set_title(GTK_WINDOW(win), fm_tab_page_get_title(page));
 
2563
}
 
2564
#endif
 
2565
 
1483
2566
static void on_show_side_pane(GtkToggleAction* act, FmMainWin* win)
1484
2567
{
1485
2568
    gboolean active;
1495
2578
        app_config->side_pane_mode |= FM_SP_HIDE;
1496
2579
        gtk_widget_hide(GTK_WIDGET(win->side_pane));
1497
2580
    }
 
2581
    /* FIXME: propagate the event to other windows? */
 
2582
    pcmanfm_save_config(FALSE);
 
2583
}
 
2584
 
 
2585
static void on_dual_pane(GtkToggleAction* act, FmMainWin* win)
 
2586
{
 
2587
    gboolean active;
 
2588
    int num;
 
2589
    FmFolderView *fv;
 
2590
    GtkWidget *page;
 
2591
 
 
2592
    active = gtk_toggle_action_get_active(act);
 
2593
    /* g_debug("on_dual_pane: %d", active); */
 
2594
    if (active && !win->enable_passive_view)
 
2595
    {
 
2596
        num = gtk_notebook_get_n_pages(win->notebook);
 
2597
        if (num < 2) /* single page yet */
 
2598
        {
 
2599
            win->passive_view_on_right = FALSE;
 
2600
            num = fm_main_win_add_tab(win, fm_tab_page_get_cwd(win->current_page));
 
2601
            g_debug("on_dual_pane: added duplicate of the single page");
 
2602
            page = gtk_notebook_get_nth_page(win->notebook, 0);
 
2603
        }
 
2604
        else if (gtk_notebook_get_current_page(win->notebook) < num - 1)
 
2605
        {
 
2606
            /* there is a page on right */
 
2607
            win->passive_view_on_right = TRUE;
 
2608
            num = gtk_notebook_get_current_page(win->notebook) + 1;
 
2609
            g_debug("on_dual_pane: adding passive page %d to right pane", num);
 
2610
            page = gtk_notebook_get_nth_page(win->notebook, num);
 
2611
        }
 
2612
        else
 
2613
        {
 
2614
            /* it is the most right page */
 
2615
            win->passive_view_on_right = FALSE;
 
2616
            g_debug("on_dual_pane: adding passive page %d to left pane", num - 2);
 
2617
            page = gtk_notebook_get_nth_page(win->notebook, num - 2);
 
2618
        }
 
2619
        fv = fm_tab_page_get_folder_view(FM_TAB_PAGE(page));
 
2620
        fm_tab_page_set_passive_view(win->current_page, fv,
 
2621
                                     win->passive_view_on_right);
 
2622
        /* ok, passive view was just changed, we have to update the button */
 
2623
        gtk_widget_set_state(GTK_WIDGET(FM_TAB_PAGE(page)->tab_label), GTK_STATE_SELECTED);
 
2624
        win->enable_passive_view = TRUE;
 
2625
    }
 
2626
    else if (!active && win->enable_passive_view)
 
2627
    {
 
2628
        /* take passive pane back to the tab page */
 
2629
        fv = fm_tab_page_get_passive_view(win->current_page);
 
2630
        if (fv)
 
2631
        {
 
2632
            FmTabPage *tp = _find_tab_page(win, fv);
 
2633
            if (tp)
 
2634
            {
 
2635
                fm_tab_page_take_view_back(tp);
 
2636
                gtk_widget_set_state(GTK_WIDGET(FM_TAB_PAGE(tp)->tab_label), GTK_STATE_ACTIVE);
 
2637
            }
 
2638
        }
 
2639
        win->enable_passive_view = FALSE;
 
2640
    }
 
2641
}
 
2642
 
 
2643
static void on_show_status(GtkToggleAction *action, FmMainWin *win)
 
2644
{
 
2645
    gboolean active;
 
2646
 
 
2647
    active = gtk_toggle_action_get_active(action);
 
2648
    if (active != app_config->show_statusbar)
 
2649
    {
 
2650
        app_config->show_statusbar = active;
 
2651
        fm_config_emit_changed(fm_config, "statusbar");
 
2652
        pcmanfm_save_config(FALSE);
 
2653
    }
1498
2654
}