168
194
g_signal_handlers_disconnect_by_func(page->folder, on_folder_unmount, page);
169
195
g_object_unref(page->folder);
170
196
page->folder = NULL;
197
#if FM_CHECK_VERSION(1, 2, 0)
198
if (page->want_focus)
199
fm_path_unref(page->want_focus);
200
page->want_focus = NULL;
205
/* workaround on FmStandardView: it should forward focus-in events but doesn't do */
206
static void on_folder_view_add(GtkContainer *container, GtkWidget *child, FmTabPage *page)
208
g_signal_connect(child, "focus-in-event",
209
G_CALLBACK(on_folder_view_focus_in), page);
212
static void on_folder_view_remove(GtkContainer *container, GtkWidget *child, FmTabPage *page)
214
g_signal_handlers_disconnect_by_func(child, on_folder_view_focus_in, page);
217
static void _connect_focus_in(FmFolderView *folder_view, FmTabPage *page)
221
g_signal_connect(folder_view, "focus-in-event",
222
G_CALLBACK(on_folder_view_focus_in), page);
223
g_signal_connect(folder_view, "add",
224
G_CALLBACK(on_folder_view_add), page);
225
g_signal_connect(folder_view, "remove",
226
G_CALLBACK(on_folder_view_remove), page);
227
children = gtk_container_get_children(GTK_CONTAINER(folder_view));
228
for (l = children; l; l = l->next)
229
g_signal_connect(l->data, "focus-in-event",
230
G_CALLBACK(on_folder_view_focus_in), page);
231
g_list_free(children);
234
static void _disconnect_focus_in(FmFolderView *folder_view, FmTabPage *page)
238
g_signal_handlers_disconnect_by_func(folder_view, on_folder_view_focus_in, page);
239
g_signal_handlers_disconnect_by_func(folder_view, on_folder_view_add, page);
240
g_signal_handlers_disconnect_by_func(folder_view, on_folder_view_remove, page);
241
children = gtk_container_get_children(GTK_CONTAINER(folder_view));
242
for (l = children; l; l = l->next)
243
g_signal_handlers_disconnect_by_func(l->data, on_folder_view_focus_in, page);
244
g_list_free(children);
247
#if FM_CHECK_VERSION(1, 2, 0)
248
static void on_home_path_changed(FmAppConfig *cfg, FmSidePane *sp)
250
if (cfg->home_path && cfg->home_path[0])
251
fm_side_pane_set_home_dir(sp, cfg->home_path);
253
fm_side_pane_set_home_dir(sp, fm_get_home_dir());
174
257
#if GTK_CHECK_VERSION(3, 0, 0)
175
258
void fm_tab_page_destroy(GtkWidget *object)
189
273
if(page->folder_view)
275
/* tab page may be inactive now and there is a chance it does not contain
276
own view therefore we have to destroy own folder view widget manually */
277
GtkWidget *fv = GTK_WIDGET(page->folder_view);
278
GtkWidget *parent = gtk_widget_get_parent(fv);
283
panes = gtk_container_get_children(GTK_CONTAINER(page->views));
284
for (l = panes; l; l = l->next)
285
if ((GtkWidget*)l->data == fv)
288
gtk_container_remove(GTK_CONTAINER(parent), fv);
191
292
g_signal_handlers_disconnect_by_func(page->folder_view, on_folder_view_sel_changed, page);
293
#if FM_CHECK_VERSION(1, 2, 0)
294
g_signal_handlers_disconnect_by_func(page->folder_view, on_folder_view_columns_changed, page);
296
#if FM_CHECK_VERSION(1, 2, 0)
297
g_signal_handlers_disconnect_by_func(app_config, on_home_path_changed, page->side_pane);
299
_disconnect_focus_in(page->folder_view, page);
300
g_object_unref(page->folder_view);
192
301
page->folder_view = NULL;
303
#if FM_CHECK_VERSION(1, 0, 2)
304
g_strfreev(page->columns);
305
page->columns = NULL;
307
if(page->update_scroll_id)
309
g_source_remove(page->update_scroll_id);
310
page->update_scroll_id = 0;
312
#if FM_CHECK_VERSION(1, 2, 0)
313
fm_side_pane_set_popup_updater(page->side_pane, NULL, NULL);
317
g_object_unref(page->dd);
195
321
#if GTK_CHECK_VERSION(3, 0, 0)
196
322
if(GTK_WIDGET_CLASS(fm_tab_page_parent_class)->destroy)
214
340
static void on_folder_view_sel_changed(FmFolderView* fv, gint n_sel, FmTabPage* page)
216
342
char* msg = page->status_text[FM_STATUS_TEXT_SELECTED_FILES];
348
str = g_string_sized_new(64);
221
349
/* FIXME: display total size of all selected files. */
222
350
if(n_sel == 1) /* only one file is selected */
224
352
FmFileInfoList* files = fm_folder_view_dup_selected_files(fv);
225
353
FmFileInfo* fi = fm_file_info_list_peek_head(files);
226
354
const char* size_str = fm_file_info_get_disp_size(fi);
355
#if FM_CHECK_VERSION(1, 2, 0)
229
msg = g_strdup_printf("\"%s\" (%s) %s",
360
g_string_printf(str, "\"%s\" (%s) %s",
230
361
fm_file_info_get_disp_name(fi),
231
362
size_str ? size_str : "",
232
363
fm_file_info_get_desc(fi));
236
msg = g_strdup_printf("\"%s\" %s",
367
g_string_printf(str, "\"%s\" %s",
237
368
fm_file_info_get_disp_name(fi),
238
369
fm_file_info_get_desc(fi));
371
#if FM_CHECK_VERSION(1, 2, 0)
372
/* ---- statusbar plugins support ---- */
374
for (l = _tab_page_modules; l; l = l->next)
376
FmTabPageStatusInit *module = l->data;
377
char *message = module->sel_message(files, n_sel);
378
if (message && message[0])
380
g_string_append_c(str, ' ');
381
g_string_append(str, message);
240
386
fm_file_info_list_unref(files);
244
msg = g_strdup_printf(ngettext("%d item selected", "%d items selected", n_sel), n_sel);
390
FmFileInfoList* files;
395
g_string_printf(str, ngettext("%d item selected", "%d items selected", n_sel), n_sel);
396
/* don't count if too many files are selected, that isn't lightweight */
400
files = fm_folder_view_dup_selected_files(fv);
401
for (l = fm_file_info_list_peek_head_link(files); l; l = l->next)
403
if (fm_file_info_is_dir(l->data))
405
/* if we got a directory then we cannot tell it's size
406
unless we do deep count but we cannot afford it */
410
sum += fm_file_info_get_size(l->data);
414
fm_file_size_to_str(size_str, sizeof(size_str), sum,
416
g_string_append_printf(str, " (%s)", size_str);
418
#if FM_CHECK_VERSION(1, 2, 0)
419
/* ---- statusbar plugins support ---- */
421
for (l = _tab_page_modules; l; l = l->next)
423
FmTabPageStatusInit *module = l->data;
424
char *message = module->sel_message(files, n_sel);
425
if (message && message[0])
427
g_string_append_c(str, ' ');
428
g_string_append(str, message);
433
fm_file_info_list_unref(files);
435
/* FIXME: can we show some more info on selection?
436
that isn't lightweight if a lot of files are selected */
438
msg = g_string_free(str, FALSE);
251
444
(guint)FM_STATUS_TEXT_SELECTED_FILES, msg);
447
#if FM_CHECK_VERSION(1, 2, 0)
448
static void on_folder_view_columns_changed(FmFolderView *fv, FmTabPage *page)
450
GSList *columns = fm_folder_view_get_columns(fv), *l;
456
i = g_slist_length(columns);
457
cols = g_new(char *, i+1);
458
for (i = 0, l = columns; l; i++, l = l->next)
460
FmFolderViewColumnInfo *info = l->data;
463
cols[i] = g_strdup_printf("%s:%d",
464
fm_folder_model_col_get_name(info->col_id),
467
cols[i] = g_strdup(fm_folder_model_col_get_name(info->col_id));
469
g_slist_free(columns);
470
cols[i] = NULL; /* terminate the list */
471
if (page->own_config)
473
g_strfreev(page->columns);
474
page->columns = cols;
475
fm_app_config_save_config_for_path(fm_folder_view_get_cwd(fv),
476
page->sort_type, page->sort_by, -1,
477
page->show_hidden, cols);
481
g_strfreev(app_config->columns);
482
app_config->columns = cols;
483
pcmanfm_save_config(FALSE);
488
static gboolean on_folder_view_focus_in(GtkWidget *widget, GdkEvent *event, FmTabPage *page)
490
g_signal_emit(page, signals[GOT_FOCUS], 0);
254
494
static FmJobErrorAction on_folder_error(FmFolder* folder, GError* err, FmJobErrorSeverity severity, FmTabPage* page)
256
496
GtkWindow* win = GTK_WINDOW(GET_MAIN_WIN(page));
329
594
fm_folder_view_set_model(fv, NULL);
597
static gboolean update_scroll(gpointer data)
599
FmTabPage* page = data;
600
GtkScrolledWindow* scroll = GTK_SCROLLED_WINDOW(page->folder_view);
601
#if !FM_CHECK_VERSION(1, 0, 2)
602
const FmNavHistoryItem* item;
604
item = fm_nav_history_get_cur(page->nav_history);
605
/* scroll to recorded position */
606
gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(scroll), item->scroll_pos);
608
gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(scroll),
609
fm_nav_history_get_scroll_pos(page->nav_history));
611
#if FM_CHECK_VERSION(1, 2, 0)
612
if (page->want_focus)
614
fm_folder_view_select_file_path(page->folder_view, page->want_focus);
615
fm_folder_view_scroll_to_path(page->folder_view, page->want_focus, TRUE);
616
fm_path_unref(page->want_focus);
617
page->want_focus = NULL;
620
page->update_scroll_id = 0;
332
624
static void on_folder_finish_loading(FmFolder* folder, FmTabPage* page)
334
626
FmFolderView* fv = page->folder_view;
335
const FmNavHistoryItem* item;
336
GtkScrolledWindow* scroll = GTK_SCROLLED_WINDOW(fv);
338
628
/* Note: most of the time, we delay the creation of the
339
629
* folder model and do it after the whole folder is loaded.
345
635
if(fm_folder_view_get_model(fv) == NULL)
347
637
/* create a model for the folder and set it to the view */
348
FmFolderModel* model = fm_folder_model_new(folder, app_config->show_hidden);
638
FmFolderModel* model = fm_folder_model_new(folder, page->show_hidden);
349
639
fm_folder_view_set_model(fv, model);
350
640
#if FM_CHECK_VERSION(1, 0, 2)
641
if (page->filter_pattern)
643
fm_folder_model_add_filter(model, fm_tab_page_path_filter, page);
644
fm_folder_model_apply_filters(model);
351
646
/* since 1.0.2 sorting should be applied on model instead of view */
352
fm_folder_model_set_sort(model, app_config->sort_by,
353
(app_config->sort_type == GTK_SORT_ASCENDING) ?
354
FM_SORT_ASCENDING : FM_SORT_DESCENDING);
647
fm_folder_model_set_sort(model, page->sort_by, page->sort_type);
356
649
g_object_unref(model);
358
651
fm_folder_query_filesystem_info(folder); /* FIXME: is this needed? */
360
653
// fm_path_entry_set_path(entry, path);
361
/* scroll to recorded position */
362
item = fm_nav_history_get_cur(page->nav_history);
363
gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(scroll), item->scroll_pos);
654
/* delaying scrolling since drawing folder view is delayed */
655
if(!page->update_scroll_id)
656
page->update_scroll_id = gdk_threads_add_timeout(20, update_scroll, page);
365
658
/* update status bar */
366
659
/* update status text */
377
670
static void on_folder_unmount(FmFolder* folder, FmTabPage* page)
379
gtk_widget_destroy(GTK_WIDGET(page));
672
if (app_config->close_on_unmount)
673
gtk_widget_destroy(GTK_WIDGET(page));
675
#if FM_CHECK_VERSION(1, 2, 0)
676
if (app_config->home_path && app_config->home_path[0])
678
FmPath *path = fm_path_new_for_str(app_config->home_path);
680
fm_tab_page_chdir(page, path);
685
fm_tab_page_chdir(page, fm_path_get_home());
382
688
static void on_folder_removed(FmFolder* folder, FmTabPage* page)
384
gtk_widget_destroy(GTK_WIDGET(page));
690
if (app_config->close_on_unmount)
691
gtk_widget_destroy(GTK_WIDGET(page));
693
#if FM_CHECK_VERSION(1, 2, 0)
694
if (app_config->home_path && app_config->home_path[0])
696
FmPath *path = fm_path_new_for_str(app_config->home_path);
698
fm_tab_page_chdir(page, path);
703
fm_tab_page_chdir(page, fm_path_get_home());
387
706
static void on_folder_fs_info(FmFolder* folder, FmTabPage* page)
430
749
static void on_open_in_new_tab(GtkAction* act, FmMainWin* win)
432
FmPathList* sels = fm_folder_view_dup_selected_file_paths(win->folder_view);
752
FmFileInfoList* sels;
434
for( l = fm_path_list_peek_head_link(sels); l; l=l->next )
755
g_object_get(act, "action-group", &act_grp, NULL);
756
sels = g_object_get_qdata(act_grp, popup_qdata);
757
g_object_unref(act_grp);
758
for( l = fm_file_info_list_peek_head_link(sels); l; l=l->next )
436
FmPath* path = (FmPath*)l->data;
437
fm_main_win_add_tab(win, path);
760
FmFileInfo* fi = (FmFileInfo*)l->data;
761
fm_main_win_add_tab(win, fm_file_info_get_path(fi));
439
fm_path_list_unref(sels);
442
765
static void on_open_in_new_win(GtkAction* act, FmMainWin* win)
444
FmPathList* sels = fm_folder_view_dup_selected_file_paths(win->folder_view);
768
FmFileInfoList* sels;
446
for( l = fm_path_list_peek_head_link(sels); l; l=l->next )
771
g_object_get(act, "action-group", &act_grp, NULL);
772
sels = g_object_get_qdata(act_grp, popup_qdata);
773
g_object_unref(act_grp);
774
for( l = fm_file_info_list_peek_head_link(sels); l; l=l->next )
448
FmPath* path = (FmPath*)l->data;
449
fm_main_win_add_win(win, path);
776
FmFileInfo* fi = (FmFileInfo*)l->data;
777
fm_main_win_add_win(win, fm_file_info_get_path(fi));
451
fm_path_list_unref(sels);
454
781
static void on_open_folder_in_terminal(GtkAction* act, FmMainWin* win)
456
FmFileInfoList* files = fm_folder_view_dup_selected_files(win->folder_view);
784
FmFileInfoList* files;
787
g_object_get(act, "action-group", &act_grp, NULL);
788
files = g_object_get_qdata(act_grp, popup_qdata);
789
g_object_unref(act_grp);
458
790
for(l=fm_file_info_list_peek_head_link(files);l;l=l->next)
460
792
FmFileInfo* fi = (FmFileInfo*)l->data;
461
if(fm_file_info_is_dir(fi) /*&& !fm_file_info_is_virtual(fi)*/)
462
pcmanfm_open_folder_in_terminal(GTK_WINDOW(win), fm_file_info_get_path(fi));
793
pcmanfm_open_folder_in_terminal(GTK_WINDOW(win), fm_file_info_get_path(fi));
464
fm_file_info_list_unref(files);
467
797
/* folder view popups */
836
#if FM_CHECK_VERSION(1, 2, 0)
837
void _update_sidepane_popup(FmSidePane* sp, GtkUIManager* ui,
838
GtkActionGroup* act_grp,
839
FmFileInfo* file, gpointer user_data)
841
FmMainWin *win = GET_MAIN_WIN(user_data); /* user_data is FmTabPage */
842
FmFileInfoList* files;
844
/* bookmark may contain not a directory */
845
if (G_UNLIKELY(!file || !fm_file_info_is_dir(file)))
847
/* well, it should be FmMainWin but let safeguard it */
848
if (G_UNLIKELY(!IS_FM_MAIN_WIN(win)))
850
files = fm_file_info_list_new();
851
fm_file_info_list_push_tail(files, file);
852
g_object_set_qdata_full(G_OBJECT(act_grp), popup_qdata, files,
853
(GDestroyNotify)fm_file_info_list_unref);
854
gtk_action_group_set_translation_domain(act_grp, NULL);
855
gtk_action_group_add_actions(act_grp, folder_menu_actions,
856
G_N_ELEMENTS(folder_menu_actions), win);
857
/* we use the same XML for simplicity */
858
gtk_ui_manager_add_ui_from_string(ui, folder_menu_xml, -1, NULL);
859
if (!fm_file_info_is_native(file))
860
gtk_action_set_visible(gtk_action_group_get_action(act_grp, "Term"), FALSE);
864
static gboolean on_drag_motion(FmTabLabel *label, GdkDragContext *drag_context,
865
gint x, gint y, guint time, FmTabPage *page)
868
GdkDragAction action = 0;
869
FmFileInfo *file_info = NULL;
871
/* if change_tab_on_drop is set then we should ignore it and drop file
872
using classic behavior - drop after it unfolded, so not drop on label */
873
if (!app_config->change_tab_on_drop && page->folder_view)
874
file_info = fm_folder_view_get_cwd_info(page->folder_view);
875
fm_dnd_dest_set_dest_file(page->dd, file_info);
876
if (file_info == NULL)
877
return FALSE; /* not in drop zone */
878
target = fm_dnd_dest_find_target(page->dd, drag_context);
879
if (target != GDK_NONE && fm_dnd_dest_is_target_supported(page->dd, target))
880
action = fm_dnd_dest_get_default_action(page->dd, drag_context, target);
882
return FALSE; /* cannot drop on that destination */
883
gdk_drag_status(drag_context, action, time);
498
887
static void fm_tab_page_init(FmTabPage *page)
500
889
GtkPaned* paned = GTK_PANED(page);
501
890
FmTabLabel* tab_label;
502
891
FmFolderView* folder_view;
503
892
GList* focus_chain = NULL;
893
AtkObject *atk_widget, *atk_label;
894
AtkRelation *relation;
504
895
FmSidePaneMode mode = app_config->side_pane_mode;
506
897
page->side_pane = fm_side_pane_new();
507
898
fm_side_pane_set_mode(page->side_pane, (mode & FM_SP_MODE_MASK));
899
#if FM_CHECK_VERSION(1, 2, 0)
900
fm_side_pane_set_popup_updater(page->side_pane, _update_sidepane_popup, page);
901
if (app_config->home_path && app_config->home_path[0])
902
fm_side_pane_set_home_dir(page->side_pane, app_config->home_path);
903
g_signal_connect(app_config, "changed::home_path",
904
G_CALLBACK(on_home_path_changed), page->side_pane);
508
906
/* TODO: add a close button to side pane */
509
907
gtk_paned_add1(paned, GTK_WIDGET(page->side_pane));
510
908
focus_chain = g_list_prepend(focus_chain, page->side_pane);
910
/* setup initial view mode for the tab from configuration */
911
page->view_mode = app_config->view_mode;
512
913
/* handlers below will be used when FmMainWin detects new page added */
513
914
folder_view = (FmFolderView*)fm_standard_view_new(app_config->view_mode,
514
915
update_files_popup,
515
916
open_folder_func);
516
page->folder_view = folder_view;
517
#if !FM_CHECK_VERSION(1, 0, 2)
518
/* since 1.0.2 sorting should be applied on model instead */
519
fm_folder_view_sort(folder_view, app_config->sort_type, app_config->sort_by);
917
/* FIXME: it is inefficient to set view mode to default one then change
918
it per-folder but it will be default in most cases but might it be
919
even more inefficient to add an object property for the mode and set
920
it in fm_tab_page_init() from the property? let make it later */
921
page->folder_view = g_object_ref_sink(folder_view);
521
922
fm_folder_view_set_selection_mode(folder_view, GTK_SELECTION_MULTIPLE);
522
923
page->nav_history = fm_nav_history_new();
523
gtk_paned_add2(paned, GTK_WIDGET(page->folder_view));
524
focus_chain = g_list_prepend(focus_chain, page->folder_view);
924
page->views = GTK_BOX(gtk_hbox_new(TRUE, 4));
925
gtk_box_pack_start(page->views, GTK_WIDGET(folder_view), TRUE, TRUE, 0);
926
gtk_paned_add2(paned, GTK_WIDGET(page->views));
927
focus_chain = g_list_prepend(focus_chain, page->views);
526
929
/* We need this to change tab order to focus folder view before left pane. */
527
930
gtk_container_set_focus_chain(GTK_CONTAINER(page), focus_chain);
540
943
page->tab_label = tab_label;
542
g_signal_connect(page->folder_view, "sel-changed",
945
atk_widget = gtk_widget_get_accessible(GTK_WIDGET(folder_view));
946
atk_label = gtk_widget_get_accessible(GTK_WIDGET(tab_label));
947
relation = atk_relation_new(&atk_widget, 1, ATK_RELATION_LABEL_FOR);
948
atk_relation_set_add(atk_object_ref_relation_set(atk_label), relation);
949
g_object_unref(relation);
951
g_signal_connect(folder_view, "sel-changed",
543
952
G_CALLBACK(on_folder_view_sel_changed), page);
953
#if FM_CHECK_VERSION(1, 2, 0)
954
g_signal_connect(folder_view, "columns-changed",
955
G_CALLBACK(on_folder_view_columns_changed), page);
957
_connect_focus_in(folder_view, page);
545
959
g_signal_connect(page->folder_view, "chdir",
546
960
G_CALLBACK(on_folder_view_chdir), page);
568
985
static void fm_tab_page_chdir_without_history(FmTabPage* page, FmPath* path)
570
987
char* disp_name = fm_path_display_basename(path);
989
FmStandardViewMode view_mode;
990
gboolean show_hidden;
991
char **columns; /* unused with libfm < 1.0.2 */
992
#if FM_CHECK_VERSION(1, 2, 0)
993
FmPath *prev_path = NULL;
996
#if FM_CHECK_VERSION(1, 0, 2)
997
if (page->filter_pattern && page->filter_pattern[0])
999
/* include pattern into page title */
1000
char *text = g_strdup_printf("%s [%s]", disp_name, page->filter_pattern);
571
1005
fm_tab_label_set_text(page->tab_label, disp_name);
572
1006
g_free(disp_name);
574
char * disp_path = fm_path_display_name(path, FALSE);
1008
#if FM_CHECK_VERSION(1, 2, 0)
1009
if (app_config->focus_previous && page->folder)
1011
prev_path = fm_folder_get_path(page->folder);
1012
if (fm_path_equal(fm_path_get_parent(prev_path), path))
1013
fm_path_ref(prev_path);
1019
disp_path = fm_path_display_name(path, FALSE);
575
1020
fm_tab_label_set_tooltip_text(FM_TAB_LABEL(page->tab_label), disp_path);
576
1021
g_free(disp_path);
597
1060
on_folder_start_loading(page->folder, page);
1062
/* change view and sort modes according to new path */
1063
fm_standard_view_set_mode(FM_STANDARD_VIEW(page->folder_view), view_mode);
1064
#if FM_CHECK_VERSION(1, 0, 2)
1065
/* update columns from config */
1068
guint i, n = g_strv_length(columns);
1069
FmFolderViewColumnInfo *infos = g_new(FmFolderViewColumnInfo, n);
1070
GSList *infos_list = NULL;
1072
for (i = 0; i < n; i++)
1074
char *name = g_strdup(columns[i]), *delim;
1076
#if FM_CHECK_VERSION(1, 2, 0)
1079
delim = strchr(name, ':');
1083
#if FM_CHECK_VERSION(1, 2, 0)
1084
infos[i].width = atoi(delim);
1087
infos[i].col_id = fm_folder_model_get_col_by_name(name);
1089
infos_list = g_slist_append(infos_list, &infos[i]);
1091
#if FM_CHECK_VERSION(1, 2, 0)
1092
g_signal_handlers_block_by_func(page->folder_view,
1093
on_folder_view_columns_changed, page);
1095
fm_folder_view_set_columns(page->folder_view, infos_list);
1096
#if FM_CHECK_VERSION(1, 2, 0)
1097
g_signal_handlers_unblock_by_func(page->folder_view,
1098
on_folder_view_columns_changed, page);
1100
g_slist_free(infos_list);
1102
if (page->own_config)
1103
page->columns = g_strdupv(columns);
1106
/* since 1.0.2 sorting should be applied on model instead */
1107
fm_folder_view_sort(page->folder_view, page->sort_type, page->sort_by);
599
1110
fm_side_pane_chdir(page->side_pane, path);
601
1112
/* tell the world that our current working directory is changed */
667
1194
if(fm_nav_history_can_back(page->nav_history))
1196
#if !FM_CHECK_VERSION(1, 0, 2)
669
1197
const FmNavHistoryItem* item;
670
1199
GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(page->folder_view));
671
1200
int scroll_pos = gtk_adjustment_get_value(vadjustment);
1201
#if FM_CHECK_VERSION(1, 0, 2)
1202
guint index = fm_nav_history_get_cur_index(page->nav_history);
1203
FmPath *path = fm_nav_history_go_to(page->nav_history, index + 1, scroll_pos);
1204
fm_tab_page_chdir_without_history(page, path);
672
1206
fm_nav_history_back(page->nav_history, scroll_pos);
673
1207
item = fm_nav_history_get_cur(page->nav_history);
674
1208
fm_tab_page_chdir_without_history(page, item->path);
1213
#if FM_CHECK_VERSION(1, 0, 2)
1214
void fm_tab_page_history(FmTabPage* page, guint history_item)
1216
GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(page->folder_view));
1217
int scroll_pos = gtk_adjustment_get_value(vadjustment);
1218
FmPath *path = fm_nav_history_go_to(page->nav_history, history_item, scroll_pos);
1219
fm_tab_page_chdir_without_history(page, path);
678
1222
void fm_tab_page_history(FmTabPage* page, GList* history_item_link)
680
1224
const FmNavHistoryItem* item = (FmNavHistoryItem*)history_item_link->data;
699
1244
void fm_tab_page_reload(FmTabPage* page)
701
1246
FmFolder* folder = fm_folder_view_get_folder(page->folder_view);
1250
GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(page->folder_view));
1251
int scroll_pos = gtk_adjustment_get_value(vadjustment);
1252
/* save the scroll position before reload */
1253
#if FM_CHECK_VERSION(1, 0, 2)
1254
int idx = fm_nav_history_get_cur_index(page->nav_history);
1255
fm_nav_history_go_to(page->nav_history, idx, scroll_pos);
1257
FmNavHistoryItem* item = (FmNavHistoryItem*)fm_nav_history_get_cur(page->nav_history);
1258
/* NOTE: ignoring const modifier due to invalid pre-1.0.2 design */
1259
item->scroll_pos = scroll_pos;
703
1261
fm_folder_reload(folder);
1266
* fm_tab_page_take_view_back
1267
* @page: the page instance
1269
* If folder view that is bound to page isn't present in the container,
1270
* then moves it from the container where it is currently, to the @page.
1271
* This API should be called only in single-pane mode, for two-pane use
1272
* fm_tab_page_set_passive_view() instead.
1274
* Returns: %TRUE if folder was not in @page and moved successfully.
1276
gboolean fm_tab_page_take_view_back(FmTabPage *page)
1279
GtkWidget *folder_view = GTK_WIDGET(page->folder_view);
1281
gtk_widget_set_state(folder_view, GTK_STATE_NORMAL);
1282
panes = gtk_container_get_children(GTK_CONTAINER(page->views));
1283
for (l = panes; l; l = l->next)
1284
if ((GtkWidget*)l->data == folder_view)
1289
/* we already keep the reference, no need to do it again */
1290
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(folder_view)),
1292
gtk_box_pack_start(page->views, folder_view, TRUE, TRUE, 0);
1297
* fm_tab_page_set_passive_view
1298
* @page: the page instance
1299
* @view: the folder view to add
1300
* @on_right: %TRUE if @view should be moved to right pane
1302
* If folder @view isn't already in designed place then moves it from the
1303
* container where it is currently, to the @page. If @on_right is %TRUE
1304
* then attempts to move into right pane. If @on_right is %FALSE then
1305
* attempts to move into left pane.
1307
* Also if folder view that is bound to @page isn't presented in the
1308
* container, then moves it from the container where it is currently, to
1309
* the @page on the side opposite to @view.
1311
* See also: fm_tab_page_take_view_back().
1313
* Returns: %TRUE if @view was moved successfully.
1315
gboolean fm_tab_page_set_passive_view(FmTabPage *page, FmFolderView *view,
1320
g_return_val_if_fail(page != NULL && view != NULL, FALSE);
1321
if (!fm_tab_page_take_view_back(page))
1323
#if !FM_CHECK_VERSION(1, 2, 0)
1324
/* workaround on ExoIconView bug - it doesn't follow state change
1325
so we re-add the folder view into our container to force change */
1326
GtkWidget *fv = GTK_WIDGET(page->folder_view);
1328
/* we already keep the reference, no need to do it again */
1329
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(fv)), fv);
1330
gtk_box_pack_start(page->views, fv, TRUE, TRUE, 0);
1333
pane = GTK_WIDGET(view);
1334
gtk_widget_set_state(pane, GTK_STATE_ACTIVE);
1336
/* gtk_widget_reparent() is buggy so we do it manually */
1337
if (gtk_widget_get_parent(pane))
1338
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(pane)), pane);
1339
gtk_box_pack_start(page->views, pane, TRUE, TRUE, 0);
1340
g_object_unref(view);
1342
gtk_box_reorder_child(page->views, pane, 0);
1347
* fm_tab_page_get_passive_view
1348
* @page: the page instance
1350
* Checks if the @page contains some folder view that was added via call
1351
* to fm_tab_page_set_passive_view() and was not moved out yet.
1353
* Returns: (transfer none): the folder view or %NULL.
1355
FmFolderView *fm_tab_page_get_passive_view(FmTabPage *page)
1360
panes = gtk_container_get_children(GTK_CONTAINER(page->views));
1361
for (l = panes; l; l = l->next)
1362
if ((FmFolderView*)l->data != page->folder_view)
1364
view = l ? l->data : NULL;
1369
#if FM_CHECK_VERSION(1, 0, 2)
1371
* fm_tab_page_set_filter_pattern
1372
* @page: the page instance
1373
* @pattern: (allow-none): new pattern
1375
* Changes filter for the folder view in the @page. If @pattern is %NULL
1376
* then folder contents will be not filtered anymore.
1378
void fm_tab_page_set_filter_pattern(FmTabPage *page, const char *pattern)
1380
FmFolderModel *model = NULL;
1383
/* validate pattern */
1384
if (pattern && pattern[0] == '\0')
1386
if (page->folder_view != NULL)
1387
model = fm_folder_view_get_model(page->folder_view);
1388
if (page->filter_pattern == NULL && pattern == NULL)
1389
return; /* nothing to change */
1390
/* if we have model then update filter chain in it */
1393
if (page->filter_pattern == NULL && pattern)
1394
fm_folder_model_add_filter(model, fm_tab_page_path_filter, page);
1395
else if (page->filter_pattern && pattern == NULL)
1396
fm_folder_model_remove_filter(model, fm_tab_page_path_filter, page);
1398
/* update page own data */
1399
g_free(page->filter_pattern);
1402
char *casefold = g_utf8_casefold(pattern, -1);
1403
page->filter_pattern = g_utf8_normalize(casefold, -1, G_NORMALIZE_ALL);
1407
page->filter_pattern = NULL;
1408
/* apply changes if needed */
1410
fm_folder_model_apply_filters(model);
1411
/* update tab page title */
1412
disp_name = fm_path_display_basename(fm_folder_view_get_cwd(page->folder_view));
1413
if (page->filter_pattern)
1415
/* include pattern into page title */
1416
char *text = g_strdup_printf("%s [%s]", disp_name, page->filter_pattern);
1420
fm_tab_label_set_text(page->tab_label, disp_name);