Mercurial > geeqie
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 } |