comparison src/layout.c @ 9:d907d608745f

Sync to GQview 1.5.9 release. ######## DO NOT BASE ENHANCEMENTS OR TRANSLATION UPDATES ON CODE IN THIS CVS! This CVS is never up to date with current development and is provided solely for reference purposes, please use the latest official release package when making any changes or translation updates. ########
author gqview
date Sat, 26 Feb 2005 00:13:35 +0000
parents
children 17acca639a86
comparison
equal deleted inserted replaced
8:e0d0593d519e 9:d907d608745f
1 /*
2 * GQview
3 * (C) 2004 John Ellis
4 *
5 * Author: John Ellis
6 *
7 * This software is released under the GNU General Public License (GNU GPL).
8 * Please read the included file COPYING for more information.
9 * This software comes with no warranty of any kind, use at your own risk!
10 */
11
12 #include "gqview.h"
13 #include "layout.h"
14
15 #include "image.h"
16 #include "layout_config.h"
17 #include "layout_image.h"
18 #include "layout_util.h"
19 #include "menu.h"
20 #include "pixbuf_util.h"
21 #include "view_dir_list.h"
22 #include "view_dir_tree.h"
23 #include "view_file_list.h"
24 #include "view_file_icon.h"
25 #include "ui_bookmark.h"
26 #include "ui_fileops.h"
27 #include "ui_menu.h"
28 #include "ui_misc.h"
29 #include "ui_tabcomp.h"
30
31 #include "icons/tools.xpm"
32
33 #define MAINWINDOW_DEF_WIDTH 620
34 #define MAINWINDOW_DEF_HEIGHT 400
35
36 #define MAIN_WINDOW_DIV_HPOS -1
37 #define MAIN_WINDOW_DIV_VPOS 200
38
39 #define TOOLWINDOW_DEF_WIDTH 260
40 #define TOOLWINDOW_DEF_HEIGHT 450
41 #define PROGRESS_WIDTH 150
42 #define ZOOM_LABEL_WIDTH 64
43
44 #define PANE_DIVIDER_SIZE 10
45
46
47 GList *layout_window_list = NULL;
48
49
50 static void layout_list_scroll_to_subpart(LayoutWindow *lw, const gchar *needle);
51
52
53 /*
54 *-----------------------------------------------------------------------------
55 * misc
56 *-----------------------------------------------------------------------------
57 */
58
59 gint layout_valid(LayoutWindow **lw)
60 {
61 if (*lw == NULL)
62 {
63 if (layout_window_list) *lw = layout_window_list->data;
64 return (*lw != NULL);
65 }
66
67 return (g_list_find(layout_window_list, *lw) != NULL);
68 }
69
70 LayoutWindow *layout_find_by_image(ImageWindow *imd)
71 {
72 GList *work;
73
74 work = layout_window_list;
75 while (work)
76 {
77 LayoutWindow *lw = work->data;
78 work = work->next;
79
80 if (lw->image == imd) return lw;
81 }
82
83 return NULL;
84 }
85
86 /*
87 *-----------------------------------------------------------------------------
88 * menu, toolbar, and dir view
89 *-----------------------------------------------------------------------------
90 */
91
92 static void layout_path_entry_changed_cb(GtkWidget *widget, gpointer data)
93 {
94 LayoutWindow *lw = data;
95 gchar *buf;
96
97 if (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) < 0) return;
98
99 buf = g_strdup(gtk_entry_get_text(GTK_ENTRY(lw->path_entry)));
100 if (!buf || (lw->path && strcmp(buf, lw->path) == 0))
101 {
102 g_free(buf);
103 return;
104 }
105
106 layout_set_path(lw, buf);
107
108 g_free(buf);
109 }
110
111 static void layout_path_entry_tab_cb(const gchar *path, gpointer data)
112 {
113 LayoutWindow *lw = data;
114 gchar *buf;
115 gchar *base;
116
117 buf = g_strdup(path);
118 parse_out_relatives(buf);
119 base = remove_level_from_path(buf);
120
121 if (isdir(buf))
122 {
123 if ((!lw->path || strcmp(lw->path, buf) != 0) && layout_set_path(lw, buf))
124 {
125 gint pos = -1;
126 /* put the '/' back, if we are in tab completion for a dir and result was path change */
127 gtk_editable_insert_text(GTK_EDITABLE(lw->path_entry), "/", -1, &pos);
128 gtk_editable_set_position(GTK_EDITABLE(lw->path_entry),
129 strlen(gtk_entry_get_text(GTK_ENTRY(lw->path_entry))));
130 }
131 }
132 else if (lw->path && strcmp(lw->path, base) == 0)
133 {
134 layout_list_scroll_to_subpart(lw, filename_from_path(buf));
135 }
136
137 g_free(base);
138 g_free(buf);
139 }
140
141 static void layout_path_entry_cb(const gchar *path, gpointer data)
142 {
143 LayoutWindow *lw = data;
144 gchar *buf;
145
146 buf = g_strdup(path);
147 parse_out_relatives(buf);
148
149 layout_set_path(lw, buf);
150
151 g_free(buf);
152 }
153
154 static void layout_vdlist_select_cb(ViewDirList *vdl, const gchar *path, gpointer data)
155 {
156 LayoutWindow *lw = data;
157
158 layout_set_path(lw, path);
159 }
160
161 static void layout_vdtree_select_cb(ViewDirTree *vdt, const gchar *path, gpointer data)
162 {
163 LayoutWindow *lw = data;
164
165 layout_set_path(lw, path);
166 }
167
168 static GtkWidget *layout_tool_setup(LayoutWindow *lw)
169 {
170 GtkWidget *box;
171 GtkWidget *menu_bar;
172 GtkWidget *tabcomp;
173 #if 0
174 GtkWidget *popwin;
175 #endif
176
177 box = gtk_vbox_new(FALSE, 0);
178
179 menu_bar = layout_actions_menu_bar(lw);
180 gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, FALSE, 0);
181 gtk_widget_show(menu_bar);
182
183 lw->toolbar = layout_button_bar(lw);
184 gtk_box_pack_start(GTK_BOX(box), lw->toolbar, FALSE, FALSE, 0);
185 if (!lw->toolbar_hidden) gtk_widget_show(lw->toolbar);
186
187 tabcomp = tab_completion_new_with_history(&lw->path_entry, NULL, "path_list", -1,
188 layout_path_entry_cb, lw);
189 tab_completion_add_tab_func(lw->path_entry, layout_path_entry_tab_cb, lw);
190 gtk_box_pack_start(GTK_BOX(box), tabcomp, FALSE, FALSE, 0);
191 gtk_widget_show(tabcomp);
192
193 #if 0
194 popwin = gtk_widget_get_toplevel(GTK_COMBO(tabcomp)->list);
195 #endif
196 g_signal_connect(G_OBJECT(lw->path_entry->parent), "changed",
197 G_CALLBACK(layout_path_entry_changed_cb), lw);
198
199 if (lw->tree_view)
200 {
201 lw->vdt = vdtree_new(lw->path, TRUE);
202 vdtree_set_layout(lw->vdt, lw);
203 vdtree_set_select_func(lw->vdt, layout_vdtree_select_cb, lw);
204
205 lw->dir_view = lw->vdt->widget;
206 }
207 else
208 {
209 lw->vdl = vdlist_new(lw->path);
210 vdlist_set_layout(lw->vdl, lw);
211 vdlist_set_select_func(lw->vdl, layout_vdlist_select_cb, lw);
212
213 lw->dir_view = lw->vdl->widget;
214 }
215
216 gtk_box_pack_start(GTK_BOX(box), lw->dir_view, TRUE, TRUE, 0);
217 gtk_widget_show(lw->dir_view);
218
219 gtk_widget_show(box);
220
221 return box;
222 }
223
224 /*
225 *-----------------------------------------------------------------------------
226 * sort button (and menu)
227 *-----------------------------------------------------------------------------
228 */
229
230 static void layout_sort_menu_cb(GtkWidget *widget, gpointer data)
231 {
232 LayoutWindow *lw;
233 SortType type;
234
235 lw = submenu_item_get_data(widget);
236 if (!lw) return;
237
238 type = (SortType)GPOINTER_TO_INT(data);
239
240 layout_sort_set(lw, type, lw->sort_ascend);
241 }
242
243 static void layout_sort_menu_ascend_cb(GtkWidget *widget, gpointer data)
244 {
245 LayoutWindow *lw = data;
246
247 layout_sort_set(lw, lw->sort_method, !lw->sort_ascend);
248 }
249
250 static void layout_sort_menu_hide_cb(GtkWidget *widget, gpointer data)
251 {
252 /* destroy the menu */
253 gtk_widget_unref(GTK_WIDGET(widget));
254 }
255
256 static void layout_sort_button_press_cb(GtkWidget *widget, gpointer data)
257 {
258 LayoutWindow *lw = data;
259 GtkWidget *menu;
260 GdkEvent *event;
261 guint32 etime;
262
263 menu = submenu_add_sort(NULL, G_CALLBACK(layout_sort_menu_cb), lw, FALSE, FALSE, TRUE, lw->sort_method);
264
265 /* apparently the menu is never sunk, even on a popup */
266 g_object_ref(G_OBJECT(menu));
267 gtk_object_sink(GTK_OBJECT(menu));
268
269 /* ascending option */
270 menu_item_add_divider(menu);
271 menu_item_add_check(menu, _("Ascending"), lw->sort_ascend, G_CALLBACK(layout_sort_menu_ascend_cb), lw);
272
273 g_signal_connect(G_OBJECT(menu), "selection_done",
274 G_CALLBACK(layout_sort_menu_hide_cb), NULL);
275
276 event = gtk_get_current_event();
277 if (event)
278 {
279 etime = gdk_event_get_time(event);
280 gdk_event_free(event);
281 }
282 else
283 {
284 etime = 0;
285 }
286
287 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, etime);
288 }
289
290 static GtkWidget *layout_sort_button(LayoutWindow *lw)
291 {
292 GtkWidget *button;
293
294 button = gtk_button_new_with_label(sort_type_get_text(lw->sort_method));
295 g_signal_connect(G_OBJECT(button), "clicked",
296 G_CALLBACK(layout_sort_button_press_cb), lw);
297 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
298
299 return button;
300 }
301
302 /*
303 *-----------------------------------------------------------------------------
304 * status bar
305 *-----------------------------------------------------------------------------
306 */
307
308 void layout_status_update_progress(LayoutWindow *lw, gdouble val, const gchar *text)
309 {
310 if (!layout_valid(&lw)) return;
311 if (!lw->info_progress_bar) return;
312
313 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(lw->info_progress_bar), val);
314 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(lw->info_progress_bar), (text) ? text : " ");
315 }
316
317 void layout_status_update_info(LayoutWindow *lw, const gchar *text)
318 {
319 gchar *buf = NULL;
320
321 if (!layout_valid(&lw)) return;
322
323 if (!text)
324 {
325 gint n;
326 gint64 n_bytes = 0;
327 gint s;
328 gint64 s_bytes = 0;
329 const gchar *ss;
330 gchar *b;
331 gchar *sb;
332
333 if (layout_image_slideshow_active(lw))
334 {
335 if (!layout_image_slideshow_paused(lw))
336 {
337 ss = _(" Slideshow");
338 }
339 else
340 {
341 ss = _(" Paused");
342 }
343 }
344 else
345 {
346 ss = "";
347 }
348
349 n = layout_list_count(lw, &n_bytes);
350 s = layout_selection_count(lw, &s_bytes);
351
352 layout_bars_new_selection(lw, s);
353
354 if (s > 0)
355 {
356 b = text_from_size_abrev(n_bytes);
357 sb = text_from_size_abrev(s_bytes);
358 buf = g_strdup_printf(_("%s, %d files (%s, %d)%s"), b, n, sb, s, ss);
359 g_free(b);
360 g_free(sb);
361 }
362 else if (n > 0)
363 {
364 b = text_from_size_abrev(n_bytes);
365 buf = g_strdup_printf(_("%s, %d files%s"), b, n, ss);
366 g_free(b);
367 }
368 else
369 {
370 buf = g_strdup_printf(_("%d files%s"), n, ss);
371 }
372
373 text = buf;
374
375 layout_image_overlay_update(lw);
376 }
377
378 gtk_label_set_text(GTK_LABEL(lw->info_status), text);
379 g_free(buf);
380 }
381
382 void layout_status_update_image(LayoutWindow *lw)
383 {
384 gchar *text;
385 gchar *b;
386
387 if (!layout_valid(&lw) || !lw->image) return;
388
389 text = image_zoom_get_as_text(lw->image);
390 gtk_label_set_text(GTK_LABEL(lw->info_zoom), text);
391 g_free(text);
392
393 b = text_from_size(lw->image->size);
394
395 if (lw->image->unknown)
396 {
397 if (image_get_path(lw->image) && !access_file(image_get_path(lw->image), R_OK))
398 {
399 text = g_strdup_printf(_("(no read permission) %s bytes"), b);
400 }
401 else
402 {
403 text = g_strdup_printf(_("( ? x ? ) %s bytes"), b);
404 }
405 }
406 else
407 {
408 text = g_strdup_printf(_("( %d x %d ) %s bytes"),
409 lw->image->image_width, lw->image->image_height, b);
410 }
411
412 gtk_label_set_text(GTK_LABEL(lw->info_details), text);
413
414 g_free(b);
415 g_free(text);
416 }
417
418 void layout_status_update_all(LayoutWindow *lw)
419 {
420 layout_status_update_progress(lw, 0.0, NULL);
421 layout_status_update_info(lw, NULL);
422 layout_status_update_image(lw);
423 }
424
425 static GtkWidget *layout_status_label(gchar *text, GtkWidget *box, gint start, gint size, gint expand)
426 {
427 GtkWidget *label;
428 GtkWidget *frame;
429
430 frame = gtk_frame_new(NULL);
431 if (size) gtk_widget_set_size_request(frame, size, -1);
432 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
433 if (start)
434 {
435 gtk_box_pack_start(GTK_BOX(box), frame, expand, expand, 0);
436 }
437 else
438 {
439 gtk_box_pack_end(GTK_BOX(box), frame, expand, expand, 0);
440 }
441 gtk_widget_show(frame);
442
443 label = gtk_label_new(text ? text : "");
444 gtk_container_add(GTK_CONTAINER(frame), label);
445 gtk_widget_show(label);
446
447 return label;
448 }
449
450 static void layout_status_setup(LayoutWindow *lw, GtkWidget *box, gint small_format)
451 {
452 GtkWidget *hbox;
453
454 if (lw->info_box) return;
455
456 if (small_format)
457 {
458 lw->info_box = gtk_vbox_new(FALSE, 0);
459 }
460 else
461 {
462 lw->info_box = gtk_hbox_new(FALSE, 0);
463 }
464 gtk_box_pack_end(GTK_BOX(box), lw->info_box, FALSE, FALSE, 0);
465 gtk_widget_show(lw->info_box);
466
467 if (small_format)
468 {
469 hbox = gtk_hbox_new(FALSE, 0);
470 gtk_box_pack_start(GTK_BOX(lw->info_box), hbox, FALSE, FALSE, 0);
471 gtk_widget_show(hbox);
472 }
473 else
474 {
475 hbox = lw->info_box;
476 }
477 lw->info_progress_bar = gtk_progress_bar_new();
478 gtk_widget_set_size_request(lw->info_progress_bar, PROGRESS_WIDTH, -1);
479 gtk_box_pack_start(GTK_BOX(hbox), lw->info_progress_bar, FALSE, FALSE, 0);
480 gtk_widget_show(lw->info_progress_bar);
481
482 lw->info_sort = layout_sort_button(lw);
483 gtk_box_pack_start(GTK_BOX(hbox), lw->info_sort, FALSE, FALSE, 0);
484 gtk_widget_show(lw->info_sort);
485
486 lw->info_status = layout_status_label(NULL, lw->info_box, TRUE, 0, (!small_format));
487
488 if (small_format)
489 {
490 hbox = gtk_hbox_new(FALSE, 0);
491 gtk_box_pack_start(GTK_BOX(lw->info_box), hbox, FALSE, FALSE, 0);
492 gtk_widget_show(hbox);
493 }
494 else
495 {
496 hbox = lw->info_box;
497 }
498 lw->info_details = layout_status_label(NULL, hbox, TRUE, 0, TRUE);
499 lw->info_zoom = layout_status_label(NULL, hbox, FALSE, ZOOM_LABEL_WIDTH, FALSE);
500 }
501
502 /*
503 *-----------------------------------------------------------------------------
504 * views
505 *-----------------------------------------------------------------------------
506 */
507
508 static GtkWidget *layout_tools_new(LayoutWindow *lw)
509 {
510 lw->dir_view = layout_tool_setup(lw);
511 return lw->dir_view;
512 }
513
514 static void layout_list_status_cb(ViewFileList *vfl, gpointer data)
515 {
516 LayoutWindow *lw = data;
517
518 layout_status_update_info(lw, NULL);
519 }
520
521 static void layout_list_thumb_cb(ViewFileList *vfl, gdouble val, const gchar *text, gpointer data)
522 {
523 LayoutWindow *lw = data;
524
525 layout_status_update_progress(lw, val, text);
526 }
527
528 static void layout_icon_status_cb(ViewFileIcon *vfi, gpointer data)
529 {
530 LayoutWindow *lw = data;
531
532 layout_status_update_info(lw, NULL);
533 }
534
535 static void layout_icon_thumb_cb(ViewFileIcon *vfi, gdouble val, const gchar *text, gpointer data)
536 {
537 LayoutWindow *lw = data;
538
539 layout_status_update_progress(lw, val, text);
540 }
541
542 static GtkWidget *layout_list_new(LayoutWindow *lw)
543 {
544 if (lw->icon_view)
545 {
546 lw->vfi = vficon_new(NULL);
547 vficon_set_layout(lw->vfi, lw);
548
549 vficon_set_status_func(lw->vfi, layout_icon_status_cb, lw);
550 vficon_set_thumb_status_func(lw->vfi, layout_icon_thumb_cb, lw);
551
552 return lw->vfi->widget;
553 }
554
555 lw->vfl = vflist_new(NULL, lw->thumbs_enabled);
556 vflist_set_layout(lw->vfl, lw);
557
558 vflist_set_status_func(lw->vfl, layout_list_status_cb, lw);
559 vflist_set_thumb_status_func(lw->vfl, layout_list_thumb_cb, lw);
560
561 return lw->vfl->widget;
562 }
563
564 static void layout_list_sync_thumb(LayoutWindow *lw)
565 {
566 if (lw->vfl) vflist_thumb_set(lw->vfl, lw->thumbs_enabled);
567 }
568
569 static void layout_list_scroll_to_subpart(LayoutWindow *lw, const gchar *needle)
570 {
571 if (!lw) return;
572 #if 0
573 if (lw->vfl) vflist_scroll_to_subpart(lw->vfl, needle);
574 if (lw->vfi) vficon_scroll_to_subpart(lw->vfi, needle);
575 #endif
576 }
577
578 GList *layout_list(LayoutWindow *lw)
579 {
580 if (!layout_valid(&lw)) return NULL;
581
582 if (lw->vfl) return vflist_get_list(lw->vfl);
583 if (lw->vfi) return vficon_get_list(lw->vfi);
584
585 return NULL;
586 }
587
588 gint layout_list_count(LayoutWindow *lw, gint64 *bytes)
589 {
590 if (!layout_valid(&lw)) return 0;
591
592 if (lw->vfl) return vflist_count(lw->vfl, bytes);
593 if (lw->vfi) return vficon_count(lw->vfi, bytes);
594
595 return 0;
596 }
597
598 const gchar *layout_list_get_path(LayoutWindow *lw, gint index)
599 {
600 if (!layout_valid(&lw)) return NULL;
601
602 if (lw->vfl) return vflist_index_get_path(lw->vfl, index);
603 if (lw->vfi) return vficon_index_get_path(lw->vfi, index);
604
605 return NULL;
606 }
607
608 gint layout_list_get_index(LayoutWindow *lw, const gchar *path)
609 {
610 if (!layout_valid(&lw)) return -1;
611
612 if (lw->vfl) return vflist_index_by_path(lw->vfl, path);
613 if (lw->vfi) return vficon_index_by_path(lw->vfi, path);
614
615 return -1;
616 }
617
618 void layout_list_sync_path(LayoutWindow *lw, const gchar *path)
619 {
620 if (!layout_valid(&lw)) return;
621
622 if (lw->vfl) vflist_select_by_path(lw->vfl, path);
623 if (lw->vfi) vficon_select_by_path(lw->vfi, path);
624 }
625
626 static void layout_list_sync_sort(LayoutWindow *lw)
627 {
628 if (!layout_valid(&lw)) return;
629
630 if (lw->vfl) vflist_sort_set(lw->vfl, lw->sort_method, lw->sort_ascend);
631 if (lw->vfi) vficon_sort_set(lw->vfi, lw->sort_method, lw->sort_ascend);
632 }
633
634 GList *layout_selection_list(LayoutWindow *lw)
635 {
636 if (!layout_valid(&lw)) return NULL;
637
638 if (layout_image_get_collection(lw, NULL))
639 {
640 const gchar *path;
641
642 path = layout_image_get_path(lw);
643 if (path) return g_list_append(NULL, g_strdup(path));
644 return NULL;
645 }
646
647 if (lw->vfl) return vflist_selection_get_list(lw->vfl);
648 if (lw->vfi) return vficon_selection_get_list(lw->vfi);
649
650 return NULL;
651 }
652
653 GList *layout_selection_list_by_index(LayoutWindow *lw)
654 {
655 if (!layout_valid(&lw)) return NULL;
656
657 if (lw->vfl) return vflist_selection_get_list_by_index(lw->vfl);
658 if (lw->vfi) return vficon_selection_get_list_by_index(lw->vfi);
659
660 return NULL;
661 }
662
663 gint layout_selection_count(LayoutWindow *lw, gint64 *bytes)
664 {
665 if (!layout_valid(&lw)) return 0;
666
667 if (lw->vfl) return vflist_selection_count(lw->vfl, bytes);
668 if (lw->vfi) return vficon_selection_count(lw->vfi, bytes);
669
670 return 0;
671 }
672
673 void layout_select_all(LayoutWindow *lw)
674 {
675 if (!layout_valid(&lw)) return;
676
677 if (lw->vfl) vflist_select_all(lw->vfl);
678 if (lw->vfi) vficon_select_all(lw->vfi);
679 }
680
681 void layout_select_none(LayoutWindow *lw)
682 {
683 if (!layout_valid(&lw)) return;
684
685 if (lw->vfl) vflist_select_none(lw->vfl);
686 if (lw->vfi) vficon_select_none(lw->vfi);
687 }
688
689 /*
690 *-----------------------------------------------------------------------------
691 * access
692 *-----------------------------------------------------------------------------
693 */
694
695 const gchar *layout_get_path(LayoutWindow *lw)
696 {
697 if (!layout_valid(&lw)) return NULL;
698 return lw->path;
699 }
700
701 static void layout_sync_path(LayoutWindow *lw)
702 {
703 if (!lw->path) return;
704
705 lw->last_time = filetime(lw->path);
706
707 gtk_entry_set_text(GTK_ENTRY(lw->path_entry), lw->path);
708 if (lw->vdl) vdlist_set_path(lw->vdl, lw->path);
709 if (lw->vdt) vdtree_set_path(lw->vdt, lw->path);
710
711 if (lw->vfl) vflist_set_path(lw->vfl, lw->path);
712 if (lw->vfi) vficon_set_path(lw->vfi, lw->path);
713 }
714
715 gint layout_set_path(LayoutWindow *lw, const gchar *path)
716 {
717 gint have_file = FALSE;
718
719 if (!layout_valid(&lw)) return FALSE;
720
721 if (!path || !isname(path)) return FALSE;
722 if (lw->path && path && strcmp(path, lw->path) == 0)
723 {
724 return TRUE;
725 }
726
727 if (isdir(path))
728 {
729 g_free(lw->path);
730 lw->path = g_strdup(path);
731 }
732 else
733 {
734 gchar *base;
735
736 base = remove_level_from_path(path);
737 if (lw->path && strcmp(lw->path, base) == 0)
738 {
739 g_free(base);
740 }
741 else if (isdir(base))
742 {
743 g_free(lw->path);
744 lw->path = base;
745 }
746 else
747 {
748 g_free(base);
749 return FALSE;
750 }
751 if (isfile(path)) have_file = TRUE;
752 }
753
754 if (lw->path_entry) tab_completion_append_to_history(lw->path_entry, lw->path);
755 layout_sync_path(lw);
756
757 if (have_file)
758 {
759 gint row;
760
761 row = layout_list_get_index(lw, path);
762 if (row >= 0)
763 {
764 layout_image_set_index(lw, row);
765 }
766 else
767 {
768 layout_image_set_path(lw, path);
769 }
770 }
771 else if (!lazy_image_sync)
772 {
773 layout_image_set_index(lw, 0);
774 }
775
776 return TRUE;
777 }
778
779 static void layout_refresh_lists(LayoutWindow *lw)
780 {
781 if (lw->path) lw->last_time = filetime(lw->path);
782
783 if (lw->vdl) vdlist_refresh(lw->vdl);
784 if (lw->vdt) vdtree_refresh(lw->vdt);
785
786 if (lw->vfl) vflist_refresh(lw->vfl);
787 if (lw->vfi) vficon_refresh(lw->vfi);
788 }
789
790 static void layout_refresh_by_time(LayoutWindow *lw)
791 {
792 layout_refresh_lists(lw);
793
794 if (lw->image && filetime(layout_image_get_path(lw)) >= lw->last_time)
795 {
796 layout_image_refresh(lw);
797 }
798 }
799
800 void layout_refresh(LayoutWindow *lw)
801 {
802 if (!layout_valid(&lw)) return;
803
804 if (debug) printf("layout refresh\n");
805
806 layout_refresh_lists(lw);
807
808 if (lw->image) layout_image_refresh(lw);
809 }
810
811 static gint layout_check_for_update_cb(gpointer data)
812 {
813 LayoutWindow *lw = data;
814
815 if (!update_on_time_change) return TRUE;
816
817 if (lw->path)
818 {
819 time_t new_time;
820
821 new_time = filetime(lw->path);
822
823 if (new_time > 0 && new_time > lw->last_time)
824 {
825 if (debug) printf("layout path time changed, refreshing...\n");
826 layout_refresh_by_time(lw);
827 }
828 }
829
830 return TRUE;
831 }
832
833 void layout_thumb_set(LayoutWindow *lw, gint enable)
834 {
835 if (!layout_valid(&lw)) return;
836
837 if (lw->thumbs_enabled == enable) return;
838
839 lw->thumbs_enabled = enable;
840
841 layout_util_sync_thumb(lw);
842 layout_list_sync_thumb(lw);
843 }
844
845 gint layout_thumb_get(LayoutWindow *lw)
846 {
847 if (!layout_valid(&lw)) return FALSE;
848
849 return lw->thumbs_enabled;
850 }
851
852 void layout_sort_set(LayoutWindow *lw, SortType type, gint ascend)
853 {
854 if (!layout_valid(&lw)) return;
855 if (lw->sort_method == type && lw->sort_ascend == ascend) return;
856
857 lw->sort_method = type;
858 lw->sort_ascend = ascend;
859
860 if (lw->info_sort) gtk_label_set_text(GTK_LABEL(GTK_BIN(lw->info_sort)->child),
861 sort_type_get_text(type));
862 layout_list_sync_sort(lw);
863 }
864
865 gint layout_sort_get(LayoutWindow *lw, SortType *type, gint *ascend)
866 {
867 if (!layout_valid(&lw)) return FALSE;
868
869 if (type) *type = lw->sort_method;
870 if (ascend) *ascend = lw->sort_ascend;
871
872 return TRUE;
873 }
874
875 gint layout_geometry_get(LayoutWindow *lw, gint *x, gint *y, gint *w, gint *h)
876 {
877 if (!layout_valid(&lw)) return FALSE;
878
879 gdk_window_get_root_origin(lw->window->window, x, y);
880 gdk_drawable_get_size(lw->window->window, w, h);
881
882 return TRUE;
883 }
884
885 gint layout_geometry_get_dividers(LayoutWindow *lw, gint *h, gint *v)
886 {
887 if (!layout_valid(&lw)) return FALSE;
888
889 if (lw->h_pane && GTK_PANED(lw->h_pane)->child1->allocation.x >= 0)
890 {
891 *h = GTK_PANED(lw->h_pane)->child1->allocation.width;
892 }
893 else if (h != &lw->div_h)
894 {
895 *h = lw->div_h;
896 }
897
898 if (lw->v_pane && GTK_PANED(lw->v_pane)->child1->allocation.x >= 0)
899 {
900 *v = GTK_PANED(lw->v_pane)->child1->allocation.height;
901 }
902 else if (v != &lw->div_v)
903 {
904 *v = lw->div_v;
905 }
906
907 return TRUE;
908 }
909
910 void layout_views_set(LayoutWindow *lw, gint tree, gint icons)
911 {
912 if (!layout_valid(&lw)) return;
913
914 if (lw->tree_view == tree && lw->icon_view == icons) return;
915
916 lw->tree_view = tree;
917 lw->icon_view = icons;
918
919 layout_style_set(lw, -1, NULL);
920 }
921
922 gint layout_views_get(LayoutWindow *lw, gint *tree, gint *icons)
923 {
924 if (!layout_valid(&lw)) return FALSE;
925
926 *tree = lw->tree_view;
927 *icons = lw->icon_view;
928
929 return TRUE;
930 }
931
932 /*
933 *-----------------------------------------------------------------------------
934 * location utils
935 *-----------------------------------------------------------------------------
936 */
937
938 static gint layout_location_single(LayoutLocation l)
939 {
940 return (l == LAYOUT_LEFT ||
941 l == LAYOUT_RIGHT ||
942 l == LAYOUT_TOP ||
943 l == LAYOUT_BOTTOM);
944 }
945
946 static gint layout_location_vertical(LayoutLocation l)
947 {
948 return (l & LAYOUT_TOP ||
949 l & LAYOUT_BOTTOM);
950 }
951
952 static gint layout_location_first(LayoutLocation l)
953 {
954 return (l & LAYOUT_TOP ||
955 l & LAYOUT_LEFT);
956 }
957
958 static LayoutLocation layout_grid_compass(LayoutWindow *lw)
959 {
960 if (layout_location_single(lw->dir_location)) return lw->dir_location;
961 if (layout_location_single(lw->file_location)) return lw->file_location;
962 return lw->image_location;
963 }
964
965 static void layout_location_compute(LayoutLocation l1, LayoutLocation l2,
966 GtkWidget *s1, GtkWidget *s2,
967 GtkWidget **d1, GtkWidget **d2)
968 {
969 LayoutLocation l;
970
971 l = l1 & l2; /* get common compass direction */
972 l = l1 - l; /* remove it */
973
974 if (layout_location_first(l))
975 {
976 *d1 = s1;
977 *d2 = s2;
978 }
979 else
980 {
981 *d1 = s2;
982 *d2 = s1;
983 }
984 }
985
986 /*
987 *-----------------------------------------------------------------------------
988 * tools window (for floating/hidden)
989 *-----------------------------------------------------------------------------
990 */
991
992 gint layout_geometry_get_tools(LayoutWindow *lw, gint *x, gint *y, gint *w, gint *h, gint *divider_pos)
993 {
994 if (!layout_valid(&lw)) return FALSE;
995
996 if (!lw->tools || !GTK_WIDGET_VISIBLE(lw->tools))
997 {
998 /* use the stored values (sort of breaks success return value) */
999
1000 *divider_pos = lw->div_float;
1001
1002 return FALSE;
1003 }
1004
1005 gdk_window_get_root_origin(lw->tools->window, x, y);
1006 gdk_drawable_get_size(lw->tools->window, w, h);
1007
1008 if (GTK_IS_VPANED(lw->tools_pane))
1009 {
1010 *divider_pos = GTK_PANED(lw->tools_pane)->child1->allocation.height;
1011 }
1012 else
1013 {
1014 *divider_pos = GTK_PANED(lw->tools_pane)->child1->allocation.width;
1015 }
1016
1017 return TRUE;
1018 }
1019
1020 static void layout_tools_geometry_sync(LayoutWindow *lw)
1021 {
1022 layout_geometry_get_tools(lw, &float_window_x, &float_window_x,
1023 &float_window_w, &float_window_h, &lw->div_float);
1024 }
1025
1026 static void layout_tools_hide(LayoutWindow *lw, gint hide)
1027 {
1028 if (!lw->tools) return;
1029
1030 if (hide)
1031 {
1032 if (GTK_WIDGET_VISIBLE(lw->tools))
1033 {
1034 layout_tools_geometry_sync(lw);
1035 gtk_widget_hide(lw->tools);
1036 }
1037 }
1038 else
1039 {
1040 if (!GTK_WIDGET_VISIBLE(lw->tools))
1041 {
1042 gtk_widget_show(lw->tools);
1043 if (lw->vfi) vficon_refresh(lw->vfi);
1044 }
1045 }
1046
1047 lw->tools_hidden = hide;
1048 }
1049
1050 static gint layout_tools_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data)
1051 {
1052 LayoutWindow *lw = data;
1053
1054 layout_tools_float_toggle(lw);
1055
1056 return TRUE;
1057 }
1058
1059 static void layout_tools_setup(LayoutWindow *lw, GtkWidget *tools, GtkWidget *files)
1060 {
1061 GtkWidget *vbox;
1062 GtkWidget *w1, *w2;
1063 gint vertical;
1064 gint new_window = FALSE;
1065
1066 vertical = (layout_location_single(lw->image_location) && !layout_location_vertical(lw->image_location)) ||
1067 (!layout_location_single(lw->image_location) && layout_location_vertical(layout_grid_compass(lw)));
1068 #if 0
1069 layout_location_compute(lw->dir_location, lw->file_location,
1070 tools, files, &w1, &w2);
1071 #endif
1072 /* for now, tools/dir are always first in order */
1073 w1 = tools;
1074 w2 = files;
1075
1076 if (!lw->tools)
1077 {
1078 GdkGeometry geometry;
1079 GdkWindowHints hints;
1080
1081 lw->tools = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1082 g_signal_connect(G_OBJECT(lw->tools), "delete_event",
1083 G_CALLBACK(layout_tools_delete_cb), lw);
1084 layout_keyboard_init(lw, lw->tools);
1085
1086 if (save_window_positions)
1087 {
1088 hints = GDK_HINT_USER_POS | GDK_HINT_USER_SIZE;
1089 }
1090 else
1091 {
1092 hints = 0;
1093 }
1094
1095 geometry.min_width = 32;
1096 geometry.min_height = 32;
1097 geometry.base_width = TOOLWINDOW_DEF_WIDTH;
1098 geometry.base_height = TOOLWINDOW_DEF_HEIGHT;
1099 gtk_window_set_geometry_hints(GTK_WINDOW(lw->tools), NULL, &geometry,
1100 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | hints);
1101
1102
1103 gtk_window_set_resizable(GTK_WINDOW(lw->tools), TRUE);
1104 gtk_window_set_title(GTK_WINDOW(lw->tools), _("GQview Tools"));
1105 gtk_window_set_wmclass(GTK_WINDOW(lw->tools), "tools", "GQview");
1106 gtk_container_set_border_width(GTK_CONTAINER(lw->tools), 0);
1107
1108 window_set_icon(lw->tools, (const gchar **)tools_xpm, NULL);
1109
1110 new_window = TRUE;
1111 }
1112 else
1113 {
1114 layout_tools_geometry_sync(lw);
1115 /* dump the contents */
1116 gtk_widget_destroy(GTK_BIN(lw->tools)->child);
1117 }
1118
1119 layout_actions_add_window(lw, lw->tools);
1120
1121 vbox = gtk_vbox_new(FALSE, 0);
1122 gtk_container_add(GTK_CONTAINER(lw->tools), vbox);
1123 gtk_widget_show(vbox);
1124
1125 layout_status_setup(lw, vbox, TRUE);
1126
1127 if (vertical)
1128 {
1129 lw->tools_pane = gtk_vpaned_new();
1130 }
1131 else
1132 {
1133 lw->tools_pane = gtk_hpaned_new();
1134 }
1135 gtk_box_pack_start(GTK_BOX(vbox), lw->tools_pane, TRUE, TRUE, 0);
1136 gtk_widget_show(lw->tools_pane);
1137
1138 gtk_paned_pack1(GTK_PANED(lw->tools_pane), w1, FALSE, TRUE);
1139 gtk_paned_pack2(GTK_PANED(lw->tools_pane), w2, TRUE, TRUE);
1140
1141 gtk_widget_show(tools);
1142 gtk_widget_show(files);
1143
1144 if (new_window)
1145 {
1146 if (save_window_positions)
1147 {
1148 gtk_window_set_default_size(GTK_WINDOW(lw->tools), float_window_w, float_window_h);
1149 gtk_window_move(GTK_WINDOW(lw->tools), float_window_x, float_window_y);
1150 }
1151 else
1152 {
1153 if (vertical)
1154 {
1155 gtk_window_set_default_size(GTK_WINDOW(lw->tools),
1156 TOOLWINDOW_DEF_WIDTH, TOOLWINDOW_DEF_HEIGHT);
1157 }
1158 else
1159 {
1160 gtk_window_set_default_size(GTK_WINDOW(lw->tools),
1161 TOOLWINDOW_DEF_HEIGHT, TOOLWINDOW_DEF_WIDTH);
1162 }
1163 }
1164 }
1165
1166 if (!save_window_positions)
1167 {
1168 if (vertical)
1169 {
1170 lw->div_float = MAIN_WINDOW_DIV_VPOS;
1171 }
1172 else
1173 {
1174 lw->div_float = MAIN_WINDOW_DIV_HPOS;
1175 }
1176 }
1177
1178 gtk_paned_set_position(GTK_PANED(lw->tools_pane), lw->div_float);
1179 }
1180
1181 /*
1182 *-----------------------------------------------------------------------------
1183 * glue (layout arrangement)
1184 *-----------------------------------------------------------------------------
1185 */
1186
1187 static void layout_grid_compute(LayoutWindow *lw,
1188 GtkWidget *image, GtkWidget *tools, GtkWidget *files,
1189 GtkWidget **w1, GtkWidget **w2, GtkWidget **w3)
1190 {
1191 /* heh, this was fun */
1192
1193 if (layout_location_single(lw->dir_location))
1194 {
1195 if (layout_location_first(lw->dir_location))
1196 {
1197 *w1 = tools;
1198 layout_location_compute(lw->file_location, lw->image_location, files, image, w2, w3);
1199 }
1200 else
1201 {
1202 *w3 = tools;
1203 layout_location_compute(lw->file_location, lw->image_location, files, image, w1, w2);
1204 }
1205 }
1206 else if (layout_location_single(lw->file_location))
1207 {
1208 if (layout_location_first(lw->file_location))
1209 {
1210 *w1 = files;
1211 layout_location_compute(lw->dir_location, lw->image_location, tools, image, w2, w3);
1212 }
1213 else
1214 {
1215 *w3 = files;
1216 layout_location_compute(lw->dir_location, lw->image_location, tools, image, w1, w2);
1217 }
1218 }
1219 else
1220 {
1221 /* image */
1222 if (layout_location_first(lw->image_location))
1223 {
1224 *w1 = image;
1225 layout_location_compute(lw->file_location, lw->dir_location, files, tools, w2, w3);
1226 }
1227 else
1228 {
1229 *w3 = image;
1230 layout_location_compute(lw->file_location, lw->dir_location, files, tools, w1, w2);
1231 }
1232 }
1233 }
1234
1235 static void layout_grid_setup(LayoutWindow *lw)
1236 {
1237 gint priority_location;
1238 GtkWidget *h;
1239 GtkWidget *v;
1240 GtkWidget *w1, *w2, *w3;
1241
1242 GtkWidget *image;
1243 GtkWidget *tools;
1244 GtkWidget *files;
1245
1246 layout_actions_setup(lw);
1247 layout_actions_add_window(lw, lw->window);
1248
1249 lw->group_box = gtk_vbox_new(FALSE, 0);
1250 gtk_box_pack_start(GTK_BOX(lw->main_box), lw->group_box, TRUE, TRUE, 0);
1251 gtk_widget_show(lw->group_box);
1252
1253 priority_location = layout_grid_compass(lw);
1254
1255 image = layout_image_new(lw, NULL);
1256 tools = layout_tools_new(lw);
1257 files = layout_list_new(lw);
1258
1259 image = layout_bars_prepare(lw, image);
1260
1261 if (lw->tools_float || lw->tools_hidden)
1262 {
1263 gtk_box_pack_start(GTK_BOX(lw->group_box), image, TRUE, TRUE, 0);
1264 gtk_widget_show(image);
1265
1266 layout_tools_setup(lw, tools, files);
1267
1268 gtk_widget_grab_focus(lw->image->widget);
1269
1270 return;
1271 }
1272 else if (lw->tools)
1273 {
1274 layout_tools_geometry_sync(lw);
1275 gtk_widget_destroy(lw->tools);
1276 lw->tools = NULL;
1277 lw->tools_pane = NULL;
1278 }
1279
1280 layout_status_setup(lw, lw->group_box, FALSE);
1281
1282 layout_grid_compute(lw, image, tools, files, &w1, &w2, &w3);
1283
1284 v = lw->v_pane = gtk_vpaned_new();
1285
1286 h = lw->h_pane = gtk_hpaned_new();
1287
1288 if (!layout_location_vertical(priority_location))
1289 {
1290 GtkWidget *tmp;
1291
1292 tmp = v;
1293 v = h;
1294 h = tmp;
1295 }
1296
1297 gtk_box_pack_start(GTK_BOX(lw->group_box), v, TRUE, TRUE, 0);
1298
1299 if (!layout_location_first(priority_location))
1300 {
1301 gtk_paned_pack1(GTK_PANED(v), h, FALSE, TRUE);
1302 gtk_paned_pack2(GTK_PANED(v), w3, TRUE, TRUE);
1303
1304 gtk_paned_pack1(GTK_PANED(h), w1, FALSE, TRUE);
1305 gtk_paned_pack2(GTK_PANED(h), w2, TRUE, TRUE);
1306 }
1307 else
1308 {
1309 gtk_paned_pack1(GTK_PANED(v), w1, FALSE, TRUE);
1310 gtk_paned_pack2(GTK_PANED(v), h, TRUE, TRUE);
1311
1312 gtk_paned_pack1(GTK_PANED(h), w2, FALSE, TRUE);
1313 gtk_paned_pack2(GTK_PANED(h), w3, TRUE, TRUE);
1314 }
1315
1316 gtk_widget_show(image);
1317 gtk_widget_show(tools);
1318 gtk_widget_show(files);
1319
1320 gtk_widget_show(v);
1321 gtk_widget_show(h);
1322
1323 /* fix to have image pane visible when it is left and priority widget */
1324 if (lw->div_h == -1 &&
1325 w1 == image &&
1326 !layout_location_vertical(priority_location) &&
1327 layout_location_first(priority_location))
1328 {
1329 gtk_widget_set_size_request(image, 200, -1);
1330 }
1331
1332 gtk_paned_set_position(GTK_PANED(lw->h_pane), lw->div_h);
1333 gtk_paned_set_position(GTK_PANED(lw->v_pane), lw->div_v);
1334
1335 gtk_widget_grab_focus(lw->image->widget);
1336 }
1337
1338 void layout_style_set(LayoutWindow *lw, gint style, const gchar *order)
1339 {
1340 gchar *path;
1341 ImageWindow *old_image;
1342
1343 if (!layout_valid(&lw)) return;
1344
1345 if (style != -1)
1346 {
1347 LayoutLocation d, f, i;
1348
1349 layout_config_parse(style, order, &d, &f, &i);
1350
1351 if (lw->dir_location == d &&
1352 lw->file_location == f &&
1353 lw->image_location == i) return;
1354
1355 lw->dir_location = d;
1356 lw->file_location = f;
1357 lw->image_location = i;
1358 }
1359
1360 /* remember state */
1361
1362 layout_image_slideshow_stop(lw);
1363 layout_image_full_screen_stop(lw);
1364
1365 path = lw->path;
1366 lw->path = NULL;
1367 old_image = lw->image;
1368 lw->image = NULL;
1369 lw->utility_box = NULL;
1370
1371 layout_geometry_get_dividers(lw, &lw->div_h, &lw->div_v);
1372
1373 /* clear it all */
1374
1375 gtk_widget_hide(old_image->widget);
1376 gtk_widget_ref(old_image->widget);
1377 gtk_container_remove(GTK_CONTAINER(old_image->widget->parent), old_image->widget);
1378
1379 lw->h_pane = NULL;
1380 lw->v_pane = NULL;
1381
1382 lw->toolbar = NULL;
1383 lw->thumb_button = NULL;
1384 lw->path_entry = NULL;
1385 lw->dir_view = NULL;
1386 lw->vdl = NULL;
1387 lw->vdt = NULL;
1388
1389 lw->file_view = NULL;
1390 lw->vfl = NULL;
1391 lw->vfi = NULL;
1392
1393 lw->info_box = NULL;
1394 lw->info_progress_bar = NULL;
1395 lw->info_sort = NULL;
1396 lw->info_status = NULL;
1397 lw->info_details = NULL;
1398 lw->info_zoom = NULL;
1399
1400 #if 0
1401 if (lw->menu_fact) g_object_unref(G_OBJECT(lw->menu_fact));
1402 lw->menu_fact = NULL;
1403 #endif
1404 if (lw->ui_manager) g_object_unref(lw->ui_manager);
1405 lw->ui_manager = NULL;
1406 lw->action_group = NULL;
1407
1408 gtk_container_remove(GTK_CONTAINER(lw->main_box), lw->group_box);
1409 lw->group_box = NULL;
1410
1411 /* re-fill */
1412
1413 layout_grid_setup(lw);
1414 layout_tools_hide(lw, lw->tools_hidden);
1415
1416 layout_list_sync_sort(lw);
1417 layout_util_sync(lw);
1418 layout_status_update_all(lw);
1419
1420 /* sync */
1421
1422 if (image_get_path(old_image))
1423 {
1424 layout_set_path(lw, image_get_path(old_image));
1425 }
1426 else
1427 {
1428 layout_set_path(lw, path);
1429 }
1430 image_change_from_image(lw->image, old_image);
1431 image_top_window_set_sync(lw->image, (lw->tools_float || lw->tools_hidden));
1432
1433 /* clean up */
1434
1435 gtk_widget_unref(old_image->widget);
1436 g_free(path);
1437 }
1438
1439 void layout_styles_update(void)
1440 {
1441 GList *work;
1442
1443 work = layout_window_list;
1444 while (work)
1445 {
1446 LayoutWindow *lw = work->data;
1447 work = work->next;
1448
1449 layout_style_set(lw, layout_style, layout_order);
1450 }
1451 }
1452
1453 void layout_colors_update(void)
1454 {
1455 GList *work;
1456
1457 work = layout_window_list;
1458 while (work)
1459 {
1460 LayoutWindow *lw = work->data;
1461 work = work->next;
1462
1463 if (lw->image) image_background_set_black(lw->image, black_window_background);
1464 }
1465 }
1466
1467 void layout_tools_float_toggle(LayoutWindow *lw)
1468 {
1469 gint popped;
1470
1471 if (!lw) return;
1472
1473 if (!lw->tools_hidden)
1474 {
1475 popped = !lw->tools_float;
1476 }
1477 else
1478 {
1479 popped = TRUE;
1480 }
1481
1482 if (lw->tools_float == popped)
1483 {
1484 if (popped && lw->tools_hidden)
1485 {
1486 layout_tools_float_set(lw, popped, FALSE);
1487 }
1488 }
1489 else
1490 {
1491 if (lw->tools_float)
1492 {
1493 layout_tools_float_set(lw, FALSE, FALSE);
1494 }
1495 else
1496 {
1497 layout_tools_float_set(lw, TRUE, FALSE);
1498 }
1499 }
1500 }
1501
1502 void layout_tools_hide_toggle(LayoutWindow *lw)
1503 {
1504 if (!lw) return;
1505
1506 layout_tools_float_set(lw, lw->tools_float, !lw->tools_hidden);
1507 }
1508
1509 void layout_tools_float_set(LayoutWindow *lw, gint popped, gint hidden)
1510 {
1511 if (!layout_valid(&lw)) return;
1512
1513 if (lw->tools_float == popped && lw->tools_hidden == hidden) return;
1514
1515 if (lw->tools_float == popped && lw->tools_float && lw->tools)
1516 {
1517 layout_tools_hide(lw, hidden);
1518 return;
1519 }
1520
1521 lw->tools_float = popped;
1522 lw->tools_hidden = hidden;
1523
1524 layout_style_set(lw, -1, NULL);
1525 }
1526
1527 gint layout_tools_float_get(LayoutWindow *lw, gint *popped, gint *hidden)
1528 {
1529 if (!layout_valid(&lw)) return FALSE;
1530
1531 *popped = lw->tools_float;
1532 *hidden = lw->tools_hidden;
1533
1534 return TRUE;
1535 }
1536
1537 void layout_toolbar_toggle(LayoutWindow *lw)
1538 {
1539 if (!layout_valid(&lw)) return;
1540 if (!lw->toolbar) return;
1541
1542 lw->toolbar_hidden = !lw->toolbar_hidden;
1543
1544 if (lw->toolbar_hidden)
1545 {
1546 if (GTK_WIDGET_VISIBLE(lw->toolbar)) gtk_widget_hide(lw->toolbar);
1547 }
1548 else
1549 {
1550 if (!GTK_WIDGET_VISIBLE(lw->toolbar)) gtk_widget_show(lw->toolbar);
1551 }
1552 }
1553
1554 gint layout_toolbar_hidden(LayoutWindow *lw)
1555 {
1556 if (!layout_valid(&lw)) return TRUE;
1557
1558 return lw->toolbar_hidden;
1559 }
1560
1561 /*
1562 *-----------------------------------------------------------------------------
1563 * base
1564 *-----------------------------------------------------------------------------
1565 */
1566
1567 void layout_close(LayoutWindow *lw)
1568 {
1569 if (layout_window_list && layout_window_list->next)
1570 {
1571 layout_free(lw);
1572 }
1573 else
1574 {
1575 exit_gqview();
1576 }
1577 }
1578
1579 void layout_free(LayoutWindow *lw)
1580 {
1581 if (!lw) return;
1582
1583 layout_window_list = g_list_remove(layout_window_list, lw);
1584
1585 if (lw->last_time_id != -1)
1586 {
1587 g_source_remove(lw->last_time_id);
1588 }
1589
1590 layout_bars_close(lw);
1591
1592 #if 0
1593 if (lw->menu_fact) g_object_unref(G_OBJECT(lw->menu_fact));
1594 #endif
1595 if (lw->tooltips) g_object_unref(G_OBJECT(lw->tooltips));
1596 gtk_widget_destroy(lw->window);
1597
1598 g_free(lw->path);
1599
1600 g_free(lw);
1601 }
1602
1603 static gint layout_delete_cb(GtkWidget *widget, GdkEventAny *event, gpointer data)
1604 {
1605 LayoutWindow *lw = data;
1606
1607 layout_close(lw);
1608 return TRUE;
1609 }
1610
1611 LayoutWindow *layout_new(const gchar *path, gint popped, gint hidden)
1612 {
1613 LayoutWindow *lw;
1614 GdkGeometry geometry;
1615 GdkWindowHints hints;
1616
1617 lw = g_new0(LayoutWindow, 1);
1618
1619 lw->thumbs_enabled = thumbnails_enabled;
1620 lw->sort_method = SORT_NAME;
1621 lw->sort_ascend = TRUE;
1622
1623 lw->tools_float = popped;
1624 lw->tools_hidden = hidden;
1625
1626 lw->toolbar_hidden = toolbar_hidden;
1627
1628 lw->utility_box = NULL;
1629 lw->bar_sort = NULL;
1630 lw->bar_sort_enabled = FALSE;
1631 lw->bar_exif = NULL;
1632 lw->bar_exif_enabled = FALSE;
1633 lw->bar_exif_size = -1;
1634 lw->bar_exif_advanced = FALSE;
1635
1636 lw->full_screen_overlay_id = -1;
1637 lw->full_screen_overlay_on = FALSE;
1638
1639 /* default layout */
1640
1641 layout_config_parse(layout_style, layout_order,
1642 &lw->dir_location, &lw->file_location, &lw->image_location);
1643 lw->tree_view = layout_view_tree;
1644 lw->icon_view = layout_view_icons;
1645
1646 /* divider positions */
1647
1648 if (save_window_positions)
1649 {
1650 lw->div_h = window_hdivider_pos;
1651 lw->div_v = window_vdivider_pos;
1652 lw->div_float = float_window_divider;
1653 }
1654 else
1655 {
1656 lw->div_h = MAIN_WINDOW_DIV_HPOS;
1657 lw->div_v = MAIN_WINDOW_DIV_VPOS;
1658 lw->div_float = MAIN_WINDOW_DIV_VPOS;
1659 }
1660
1661 /* window */
1662
1663 lw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1664 gtk_window_set_resizable(GTK_WINDOW(lw->window), TRUE);
1665
1666 gtk_window_set_title(GTK_WINDOW(lw->window), "GQview");
1667 gtk_window_set_wmclass(GTK_WINDOW(lw->window), "gqview", "GQview");
1668 gtk_container_set_border_width(GTK_CONTAINER(lw->window), 0);
1669
1670 window_set_icon(lw->window, NULL, NULL);
1671
1672 if (save_window_positions)
1673 {
1674 hints = GDK_HINT_USER_POS | GDK_HINT_USER_SIZE;
1675 }
1676 else
1677 {
1678 hints = 0;
1679 }
1680
1681 geometry.min_width = 32;
1682 geometry.min_height = 32;
1683 geometry.base_width = MAINWINDOW_DEF_WIDTH;
1684 geometry.base_height = MAINWINDOW_DEF_HEIGHT;
1685 gtk_window_set_geometry_hints(GTK_WINDOW(lw->window), NULL, &geometry,
1686 GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | hints);
1687
1688 if (save_window_positions)
1689 {
1690 gtk_window_set_default_size(GTK_WINDOW(lw->window), main_window_w, main_window_h);
1691 if (!layout_window_list)
1692 {
1693 gtk_window_move(GTK_WINDOW(lw->window), main_window_x, main_window_y);
1694 if (main_window_maximized) gtk_window_maximize(GTK_WINDOW(lw->window));
1695 }
1696 }
1697 else
1698 {
1699 gtk_window_set_default_size(GTK_WINDOW(lw->window), MAINWINDOW_DEF_WIDTH, MAINWINDOW_DEF_HEIGHT);
1700 }
1701
1702 g_signal_connect(G_OBJECT(lw->window), "delete_event",
1703 G_CALLBACK(layout_delete_cb), lw);
1704
1705 layout_keyboard_init(lw, lw->window);
1706
1707 #if 0
1708 gtk_widget_realize(lw->window);
1709 #endif
1710
1711 lw->tooltips = gtk_tooltips_new();
1712 g_object_ref(G_OBJECT(lw->tooltips));
1713 gtk_object_sink(GTK_OBJECT(lw->tooltips));
1714
1715 lw->main_box = gtk_vbox_new(FALSE, 0);
1716 gtk_container_add(GTK_CONTAINER(lw->window), lw->main_box);
1717 gtk_widget_show(lw->main_box);
1718
1719 layout_grid_setup(lw);
1720 image_top_window_set_sync(lw->image, (lw->tools_float || lw->tools_hidden));
1721
1722 layout_util_sync(lw);
1723 layout_status_update_all(lw);
1724
1725 if (path)
1726 {
1727 layout_set_path(lw, path);
1728 }
1729 else
1730 {
1731 GdkPixbuf *pixbuf;
1732
1733 pixbuf = pixbuf_inline(PIXBUF_INLINE_LOGO);
1734 image_change_pixbuf(lw->image, pixbuf, 1.0);
1735 gdk_pixbuf_unref(pixbuf);
1736 }
1737
1738 /* set up the time stat timeout */
1739 lw->last_time = 0;
1740 lw->last_time_id = g_timeout_add(5000, layout_check_for_update_cb, lw);
1741
1742 gtk_widget_show(lw->window);
1743 layout_tools_hide(lw, lw->tools_hidden);
1744
1745 layout_window_list = g_list_append(layout_window_list, lw);
1746
1747 return lw;
1748 }
1749
1750 /*
1751 *-----------------------------------------------------------------------------
1752 * maintenance (for rename, move, remove)
1753 *-----------------------------------------------------------------------------
1754 */
1755
1756 static void layout_real_time_update(LayoutWindow *lw)
1757 {
1758 /* this resets the last time stamp of path so that a refresh does not occur
1759 * from an internal file operation.
1760 */
1761
1762 if (lw->path) lw->last_time = filetime(lw->path);
1763 }
1764
1765 static void layout_real_renamed(LayoutWindow *lw, const gchar *source, const gchar *dest)
1766 {
1767 gint update = FALSE;
1768
1769 if (lw->image) layout_image_maint_renamed(lw, source, dest);
1770
1771 if (lw->vfl) update |= vflist_maint_renamed(lw->vfl, source, dest);
1772 if (lw->vfi) update |= vficon_maint_renamed(lw->vfi, source, dest);
1773
1774 if (update) layout_real_time_update(lw);
1775 }
1776
1777 static void layout_real_removed(LayoutWindow *lw, const gchar *path, GList *ignore_list)
1778 {
1779 gint update = FALSE;
1780
1781 if (lw->image) layout_image_maint_removed(lw, path);
1782
1783 if (lw->vfl) update |= vflist_maint_removed(lw->vfl, path, ignore_list);
1784 if (lw->vfi) update |= vficon_maint_removed(lw->vfi, path, ignore_list);
1785
1786 if (update) layout_real_time_update(lw);
1787 }
1788
1789 static void layout_real_moved(LayoutWindow *lw, const gchar *source, const gchar *dest, GList *ignore_list)
1790 {
1791 gint update = FALSE;
1792
1793 if (lw->image) layout_image_maint_moved(lw, source, dest);
1794
1795 if (lw->vfl) update |= vflist_maint_moved(lw->vfl, source, dest, ignore_list);
1796 if (lw->vfi) update |= vficon_maint_moved(lw->vfi, source, dest, ignore_list);
1797
1798 if (update) layout_real_time_update(lw);
1799 }
1800
1801 void layout_maint_renamed(const gchar *source, const gchar *dest)
1802 {
1803 GList *work = layout_window_list;
1804 while (work)
1805 {
1806 LayoutWindow *lw = work->data;
1807 work = work->next;
1808
1809 layout_real_renamed(lw, source, dest);
1810 }
1811 }
1812
1813 void layout_maint_removed(const gchar *path, GList *ignore_list)
1814 {
1815 GList *work = layout_window_list;
1816 while (work)
1817 {
1818 LayoutWindow *lw = work->data;
1819 work = work->next;
1820
1821 layout_real_removed(lw, path, ignore_list);
1822 }
1823 }
1824
1825 void layout_maint_moved(const gchar *source, const gchar *dest, GList *ignore_list)
1826 {
1827 GList *work = layout_window_list;
1828 while (work)
1829 {
1830 LayoutWindow *lw = work->data;
1831 work = work->next;
1832
1833 layout_real_moved(lw, source, dest, ignore_list);
1834 }
1835 }