1
|
1 /*
|
9
|
2 * GQview
|
|
3 * (C) 2004 John Ellis
|
1
|
4 *
|
|
5 * Author: John Ellis
|
|
6 *
|
9
|
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!
|
1
|
10 */
|
|
11
|
9
|
12
|
1
|
13 #include "gqview.h"
|
9
|
14 #include "img-view.h"
|
|
15
|
|
16 #include "collect.h"
|
|
17 #include "collect-io.h"
|
|
18 #include "dnd.h"
|
|
19 #include "editors.h"
|
|
20 #include "filelist.h"
|
|
21 #include "fullscreen.h"
|
1
|
22 #include "image.h"
|
9
|
23 #include "image-overlay.h"
|
|
24 #include "info.h"
|
|
25 #include "menu.h"
|
|
26 #include "slideshow.h"
|
|
27 #include "utilops.h"
|
|
28 #include "ui_bookmark.h"
|
|
29 #include "ui_fileops.h"
|
|
30 #include "ui_menu.h"
|
|
31
|
1
|
32 #include <gdk/gdkkeysyms.h> /* for keyboard values */
|
|
33
|
9
|
34 #include "icons/view.xpm"
|
|
35
|
|
36
|
|
37 typedef struct _ViewWindow ViewWindow;
|
|
38 struct _ViewWindow
|
|
39 {
|
|
40 GtkWidget *window;
|
|
41 ImageWindow *imd;
|
|
42 FullScreenData *fs;
|
|
43 SlideShowData *ss;
|
|
44
|
|
45 GList *list;
|
|
46 GList *list_pointer;
|
|
47
|
|
48 gint overlay_id;
|
|
49 };
|
|
50
|
|
51
|
|
52 static GList *view_window_list = NULL;
|
|
53
|
|
54
|
|
55 static GtkWidget *view_popup_menu(ViewWindow *vw);
|
|
56 static void view_fullscreen_toggle(ViewWindow *vw, gint force_off);
|
|
57 static void view_overlay_toggle(ViewWindow *vw);
|
|
58
|
|
59 static void view_slideshow_next(ViewWindow *vw);
|
|
60 static void view_slideshow_prev(ViewWindow *vw);
|
|
61 static void view_slideshow_start(ViewWindow *vw);
|
|
62 static void view_slideshow_stop(ViewWindow *vw);
|
|
63
|
|
64 static void view_window_close(ViewWindow *vw);
|
|
65
|
|
66 static void view_window_dnd_init(ViewWindow *vw);
|
|
67
|
|
68
|
|
69 /*
|
|
70 *-----------------------------------------------------------------------------
|
|
71 * misc
|
|
72 *-----------------------------------------------------------------------------
|
|
73 */
|
|
74
|
|
75 static ImageWindow *view_window_active_image(ViewWindow *vw)
|
|
76 {
|
|
77 if (vw->fs) return vw->fs->imd;
|
|
78
|
|
79 return vw->imd;
|
|
80 }
|
|
81
|
|
82 static void view_window_set_list(ViewWindow *vw, GList *list)
|
|
83 {
|
|
84
|
|
85 path_list_free(vw->list);
|
|
86 vw->list = NULL;
|
|
87 vw->list_pointer = NULL;
|
|
88
|
|
89 vw->list = path_list_copy(list);
|
|
90 }
|
|
91
|
|
92 static gint view_window_contains_collection(ViewWindow *vw)
|
|
93 {
|
|
94 CollectionData *cd;
|
|
95 CollectInfo *info;
|
|
96
|
|
97 cd = image_get_collection(view_window_active_image(vw), &info);
|
|
98
|
|
99 return (cd && info);
|
|
100 }
|
|
101
|
|
102 static void view_collection_step(ViewWindow *vw, gint next)
|
|
103 {
|
|
104 ImageWindow *imd = view_window_active_image(vw);
|
|
105 CollectionData *cd;
|
|
106 CollectInfo *info;
|
|
107 CollectInfo *read_ahead_info = NULL;
|
|
108
|
|
109 cd = image_get_collection(imd, &info);
|
|
110
|
|
111 if (!cd || !info) return;
|
|
112
|
|
113 if (next)
|
|
114 {
|
|
115 info = collection_next_by_info(cd, info);
|
|
116 if (enable_read_ahead)
|
|
117 {
|
|
118 read_ahead_info = collection_next_by_info(cd, info);
|
|
119 if (!read_ahead_info) read_ahead_info = collection_prev_by_info(cd, info);
|
|
120 }
|
|
121 }
|
|
122 else
|
|
123 {
|
|
124 info = collection_prev_by_info(cd, info);
|
|
125 if (enable_read_ahead)
|
|
126 {
|
|
127 read_ahead_info = collection_prev_by_info(cd, info);
|
|
128 if (!read_ahead_info) read_ahead_info = collection_next_by_info(cd, info);
|
|
129 }
|
|
130 }
|
|
131
|
|
132 if (info)
|
|
133 {
|
|
134 image_change_from_collection(imd, cd, info, image_zoom_get_default(imd, zoom_mode));
|
|
135
|
|
136 if (read_ahead_info) image_prebuffer_set(imd, read_ahead_info->path);
|
|
137 }
|
|
138
|
|
139 }
|
|
140
|
|
141 static void view_collection_step_to_end(ViewWindow *vw, gint last)
|
|
142 {
|
|
143 ImageWindow *imd = view_window_active_image(vw);
|
|
144 CollectionData *cd;
|
|
145 CollectInfo *info;
|
|
146 CollectInfo *read_ahead_info = NULL;
|
|
147
|
|
148 cd = image_get_collection(imd, &info);
|
|
149
|
|
150 if (!cd || !info) return;
|
|
151
|
|
152 if (last)
|
|
153 {
|
|
154 info = collection_get_last(cd);
|
|
155 if (enable_read_ahead) read_ahead_info = collection_prev_by_info(cd, info);
|
|
156 }
|
|
157 else
|
|
158 {
|
|
159 info = collection_get_first(cd);
|
|
160 if (enable_read_ahead) read_ahead_info = collection_next_by_info(cd, info);
|
|
161 }
|
|
162
|
|
163 if (info)
|
|
164 {
|
|
165 image_change_from_collection(imd, cd, info, image_zoom_get_default(imd, zoom_mode));
|
|
166 if (read_ahead_info) image_prebuffer_set(imd, read_ahead_info->path);
|
|
167 }
|
|
168 }
|
|
169
|
|
170 static void view_list_step(ViewWindow *vw, gint next)
|
|
171 {
|
|
172 ImageWindow *imd = view_window_active_image(vw);
|
|
173 const gchar *path;
|
|
174 GList *work;
|
|
175 GList *work_ahead;
|
|
176
|
|
177 if (!vw->list) return;
|
|
178
|
|
179 path = image_get_path(imd);
|
|
180 if (!path) return;
|
|
181
|
|
182 if (g_list_position(vw->list, vw->list_pointer) >= 0)
|
|
183 {
|
|
184 work = vw->list_pointer;
|
|
185 }
|
|
186 else
|
|
187 {
|
|
188 gint found = FALSE;
|
|
189
|
|
190 work = vw->list;
|
|
191 while (work && !found)
|
|
192 {
|
|
193 gchar *temp;
|
|
194
|
|
195 temp = work->data;
|
|
196
|
|
197 if (strcmp(path, temp) == 0)
|
|
198 {
|
|
199 found = TRUE;
|
|
200 }
|
|
201 else
|
|
202 {
|
|
203 work = work->next;
|
|
204 }
|
|
205 }
|
|
206 }
|
|
207 if (!work) return;
|
|
208
|
|
209 work_ahead = NULL;
|
|
210 if (next)
|
|
211 {
|
|
212 work = work->next;
|
|
213 if (work) work_ahead = work->next;
|
|
214 }
|
|
215 else
|
|
216 {
|
|
217 work = work->prev;
|
|
218 if (work) work_ahead = work->prev;
|
|
219 }
|
|
220 if (!work) return;
|
|
221
|
|
222 vw->list_pointer = work;
|
|
223 path = work->data;
|
|
224 image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
|
|
225
|
|
226 if (enable_read_ahead && work_ahead)
|
|
227 {
|
|
228 const gchar *next_path = work_ahead->data;
|
|
229 image_prebuffer_set(imd, next_path);
|
|
230 }
|
|
231 }
|
|
232
|
|
233 static void view_list_step_to_end(ViewWindow *vw, gint last)
|
|
234 {
|
|
235 ImageWindow *imd = view_window_active_image(vw);
|
|
236 const gchar *path;
|
|
237 GList *work;
|
|
238 GList *work_ahead;
|
|
239
|
|
240 if (!vw->list) return;
|
|
241
|
|
242 if (last)
|
|
243 {
|
|
244 work = g_list_last(vw->list);
|
|
245 work_ahead = work->prev;
|
|
246 }
|
|
247 else
|
|
248 {
|
|
249 work = vw->list;
|
|
250 work_ahead = work->next;
|
|
251 }
|
|
252
|
|
253 vw->list_pointer = work;
|
|
254 path = work->data;
|
|
255 image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
|
|
256
|
|
257 if (enable_read_ahead && work_ahead)
|
|
258 {
|
|
259 const gchar *next_path = work_ahead->data;
|
|
260 image_prebuffer_set(imd, next_path);
|
|
261 }
|
|
262 }
|
|
263
|
|
264 static void view_step_next(ViewWindow *vw)
|
|
265 {
|
|
266 if (vw->ss)
|
|
267 {
|
|
268 view_slideshow_next(vw);
|
|
269 }
|
|
270 else if (vw->list)
|
|
271 {
|
|
272 view_list_step(vw, TRUE);
|
|
273 }
|
|
274 else
|
|
275 {
|
|
276 view_collection_step(vw, TRUE);
|
|
277 }
|
|
278 }
|
|
279
|
|
280 static void view_step_prev(ViewWindow *vw)
|
|
281 {
|
|
282 if (vw->ss)
|
|
283 {
|
|
284 view_slideshow_prev(vw);
|
|
285 }
|
|
286 else if (vw->list)
|
|
287 {
|
|
288 view_list_step(vw, FALSE);
|
|
289 }
|
|
290 else
|
|
291 {
|
|
292 view_collection_step(vw, FALSE);
|
|
293 }
|
|
294 }
|
|
295
|
|
296 static void view_step_to_end(ViewWindow *vw, gint last)
|
|
297 {
|
|
298 if (vw->list)
|
|
299 {
|
|
300 view_list_step_to_end(vw, last);
|
|
301 }
|
|
302 else
|
|
303 {
|
|
304 view_collection_step_to_end(vw, last);
|
|
305 }
|
|
306 }
|
|
307
|
1
|
308 /*
|
|
309 *-----------------------------------------------------------------------------
|
|
310 * view window keyboard
|
|
311 *-----------------------------------------------------------------------------
|
|
312 */
|
|
313
|
9
|
314 static void view_window_menu_pos_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
|
|
315 {
|
|
316 ViewWindow *vw = data;
|
|
317 ImageWindow *imd;
|
|
318
|
|
319 imd = view_window_active_image(vw);
|
|
320 gdk_window_get_origin(imd->image->window, x, y);
|
|
321 popup_menu_position_clamp(menu, x, y, 0);
|
|
322 }
|
|
323
|
1
|
324 static gint view_window_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
|
325 {
|
9
|
326 ViewWindow *vw = data;
|
|
327 ImageWindow *imd;
|
1
|
328 gint stop_signal = FALSE;
|
9
|
329 GtkWidget *menu;
|
1
|
330 gint x = 0;
|
|
331 gint y = 0;
|
|
332
|
9
|
333 imd = view_window_active_image(vw);
|
|
334
|
1
|
335 switch (event->keyval)
|
|
336 {
|
9
|
337 case GDK_Left: case GDK_KP_Left:
|
1
|
338 x -= 1;
|
|
339 stop_signal = TRUE;
|
|
340 break;
|
9
|
341 case GDK_Right: case GDK_KP_Right:
|
1
|
342 x += 1;
|
|
343 stop_signal = TRUE;
|
|
344 break;
|
9
|
345 case GDK_Up: case GDK_KP_Up:
|
1
|
346 y -= 1;
|
|
347 stop_signal = TRUE;
|
|
348 break;
|
9
|
349 case GDK_Down: case GDK_KP_Down:
|
1
|
350 y += 1;
|
|
351 stop_signal = TRUE;
|
|
352 break;
|
9
|
353 }
|
|
354
|
|
355 if ( !(event->state & GDK_CONTROL_MASK) )
|
|
356 switch (event->keyval)
|
|
357 {
|
|
358 case GDK_Page_Up: case GDK_KP_Page_Up:
|
|
359 case GDK_BackSpace:
|
|
360 case 'B': case 'b':
|
|
361 view_step_prev(vw);
|
|
362 stop_signal = TRUE;
|
1
|
363 break;
|
9
|
364 case GDK_Page_Down: case GDK_KP_Page_Down:
|
|
365 case GDK_space:
|
|
366 case 'N': case 'n':
|
|
367 view_step_next(vw);
|
|
368 stop_signal = TRUE;
|
1
|
369 break;
|
9
|
370 case GDK_Home: case GDK_KP_Home:
|
|
371 view_step_to_end(vw, FALSE);
|
|
372 stop_signal = TRUE;
|
1
|
373 break;
|
9
|
374 case GDK_End: case GDK_KP_End:
|
|
375 view_step_to_end(vw, TRUE);
|
1
|
376 stop_signal = TRUE;
|
|
377 break;
|
9
|
378 case '+': case '=': case GDK_KP_Add:
|
|
379 image_zoom_adjust(imd, get_zoom_increment());
|
|
380 break;
|
|
381 case '-': case GDK_KP_Subtract:
|
|
382 image_zoom_adjust(imd, -get_zoom_increment());
|
|
383 break;
|
|
384 case 'X': case 'x': case GDK_KP_Multiply:
|
|
385 image_zoom_set(imd, 0.0);
|
|
386 break;
|
|
387 case 'Z': case 'z': case GDK_KP_Divide: case '1':
|
|
388 image_zoom_set(imd, 1.0);
|
|
389 break;
|
|
390 case '2':
|
|
391 image_zoom_set(imd, 2.0);
|
|
392 break;
|
|
393 case '3':
|
|
394 image_zoom_set(imd, 3.0);
|
|
395 break;
|
|
396 case '4':
|
|
397 image_zoom_set(imd, 4.0);
|
|
398 break;
|
|
399 case '7':
|
|
400 image_zoom_set(imd, -4.0);
|
|
401 break;
|
|
402 case '8':
|
|
403 image_zoom_set(imd, -3.0);
|
|
404 break;
|
|
405 case '9':
|
|
406 image_zoom_set(imd, -2.0);
|
|
407 break;
|
|
408 case 'W': case 'w':
|
|
409 image_zoom_set_fill_geometry(imd, FALSE);
|
|
410 break;
|
|
411 case 'H': case 'h':
|
|
412 image_zoom_set_fill_geometry(imd, TRUE);
|
|
413 break;
|
|
414 case 'R': case 'r':
|
|
415 image_reload(imd);
|
|
416 break;
|
|
417 case 'S': case 's':
|
|
418 if (vw->ss)
|
|
419 view_slideshow_stop(vw);
|
|
420 else
|
|
421 view_slideshow_start(vw);
|
|
422 stop_signal = TRUE;
|
|
423 break;
|
|
424 case 'P': case 'p':
|
|
425 slideshow_pause_toggle(vw->ss);
|
|
426 break;
|
|
427 case 'F': case 'f':
|
|
428 case 'V': case 'v':
|
|
429 view_fullscreen_toggle(vw, FALSE);
|
|
430 stop_signal = TRUE;
|
|
431 break;
|
|
432 case 'I': case 'i':
|
|
433 view_overlay_toggle(vw);
|
|
434 break;
|
|
435 case ']':
|
|
436 image_alter(imd, ALTER_ROTATE_90);
|
|
437 stop_signal = TRUE;
|
|
438 break;
|
|
439 case '[':
|
|
440 image_alter(imd, ALTER_ROTATE_90_CC);
|
|
441 stop_signal = TRUE;
|
|
442 break;
|
|
443 case GDK_Delete: case GDK_KP_Delete:
|
|
444 if (enable_delete_key)
|
|
445 {
|
|
446 file_util_delete(image_get_path(imd), NULL, imd->widget);
|
|
447 stop_signal = TRUE;
|
|
448 }
|
|
449 break;
|
1
|
450 case GDK_Escape:
|
9
|
451 if (vw->fs)
|
|
452 {
|
|
453 view_fullscreen_toggle(vw, TRUE);
|
|
454 }
|
|
455 else
|
|
456 {
|
|
457 gtk_widget_destroy(vw->window);
|
|
458 }
|
|
459 stop_signal = TRUE;
|
|
460 break;
|
|
461 case GDK_Menu:
|
|
462 case GDK_F10:
|
|
463 menu = view_popup_menu(vw);
|
|
464 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, view_window_menu_pos_cb, vw, 0, GDK_CURRENT_TIME);
|
1
|
465 stop_signal = TRUE;
|
|
466 break;
|
|
467 }
|
|
468
|
|
469 if (event->state & GDK_CONTROL_MASK)
|
|
470 {
|
|
471 gint n = -1;
|
|
472 switch (event->keyval)
|
|
473 {
|
|
474 case '1':
|
|
475 n = 0;
|
|
476 break;
|
|
477 case '2':
|
|
478 n = 1;
|
|
479 break;
|
|
480 case '3':
|
|
481 n = 2;
|
|
482 break;
|
|
483 case '4':
|
|
484 n = 3;
|
|
485 break;
|
|
486 case '5':
|
|
487 n = 4;
|
|
488 break;
|
|
489 case '6':
|
|
490 n = 5;
|
|
491 break;
|
|
492 case '7':
|
|
493 n = 6;
|
|
494 break;
|
|
495 case '8':
|
|
496 n = 7;
|
|
497 break;
|
9
|
498 case '9':
|
|
499 n = 8;
|
|
500 break;
|
|
501 case '0':
|
|
502 n = 9;
|
|
503 break;
|
|
504 case 'C': case 'c':
|
|
505 file_util_copy(image_get_path(imd), NULL, NULL, imd->widget);
|
|
506 stop_signal = TRUE;
|
|
507 break;
|
|
508 case 'M': case 'm':
|
|
509 file_util_move(image_get_path(imd), NULL, NULL, imd->widget);
|
|
510 stop_signal = TRUE;
|
|
511 break;
|
|
512 case 'R': case 'r':
|
|
513 file_util_rename(image_get_path(imd), NULL, imd->widget);
|
|
514 stop_signal = TRUE;
|
|
515 break;
|
|
516 case 'D': case 'd':
|
|
517 file_util_delete(image_get_path(imd), NULL, imd->widget);
|
|
518 stop_signal = TRUE;
|
|
519 break;
|
|
520 case 'P': case 'p':
|
|
521 info_window_new(image_get_path(imd), NULL);
|
|
522 stop_signal = TRUE;
|
|
523 break;
|
|
524 case 'W': case 'w':
|
|
525 view_window_close(vw);
|
|
526 break;
|
1
|
527 }
|
|
528 if (n != -1)
|
|
529 {
|
9
|
530 view_fullscreen_toggle(vw, TRUE);
|
|
531 start_editor_from_file(n, image_get_path(imd));
|
1
|
532 }
|
|
533 }
|
9
|
534 else if (event->state & GDK_SHIFT_MASK)
|
1
|
535 {
|
9
|
536 switch (event->keyval)
|
|
537 {
|
|
538 case 'R': case 'r':
|
|
539 image_alter(imd, ALTER_ROTATE_180);
|
|
540 stop_signal = TRUE;
|
|
541 break;
|
|
542 case 'M': case 'm':
|
|
543 image_alter(imd, ALTER_MIRROR);
|
|
544 stop_signal = TRUE;
|
|
545 break;
|
|
546 case 'F': case 'f':
|
|
547 image_alter(imd, ALTER_FLIP);
|
|
548 stop_signal = TRUE;
|
|
549 break;
|
|
550 default:
|
|
551 break;
|
|
552 }
|
1
|
553 x *= 3;
|
|
554 y *= 3;
|
|
555 }
|
|
556
|
|
557 if (x != 0 || y!= 0)
|
|
558 {
|
|
559 keyboard_scroll_calc(&x, &y, event);
|
9
|
560 image_scroll(imd, x, y);
|
1
|
561 }
|
|
562
|
|
563 return stop_signal;
|
|
564 }
|
|
565
|
|
566 /*
|
|
567 *-----------------------------------------------------------------------------
|
|
568 * view window main routines
|
|
569 *-----------------------------------------------------------------------------
|
|
570 */
|
|
571
|
9
|
572 static void button_cb(ImageWindow *imd, gint button, guint32 time,
|
|
573 gdouble x, gdouble y, guint state, gpointer data)
|
|
574 {
|
|
575 ViewWindow *vw = data;
|
|
576 GtkWidget *menu;
|
|
577
|
|
578 switch (button)
|
|
579 {
|
|
580 case 1:
|
|
581 view_step_next(vw);
|
|
582 break;
|
|
583 case 2:
|
|
584 view_step_prev(vw);
|
|
585 break;
|
|
586 case 3:
|
|
587 menu = view_popup_menu(vw);
|
|
588 gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, time);
|
|
589 break;
|
|
590 default:
|
|
591 break;
|
|
592 }
|
|
593 }
|
|
594
|
|
595 static void scroll_cb(ImageWindow *imd, GdkScrollDirection direction, guint32 time,
|
|
596 gdouble x, gdouble y, guint state, gpointer data)
|
1
|
597 {
|
9
|
598 ViewWindow *vw = data;
|
|
599
|
|
600 if (state & GDK_CONTROL_MASK)
|
|
601 {
|
|
602 switch (direction)
|
|
603 {
|
|
604 case GDK_SCROLL_UP:
|
|
605 image_zoom_adjust_at_point(imd, get_zoom_increment(), x, y);
|
|
606 break;
|
|
607 case GDK_SCROLL_DOWN:
|
|
608 image_zoom_adjust_at_point(imd, -get_zoom_increment(), x, y);
|
|
609 break;
|
|
610 default:
|
|
611 break;
|
|
612 }
|
|
613 }
|
|
614 else if ( (state & GDK_SHIFT_MASK) != (mousewheel_scrolls))
|
|
615 {
|
|
616 switch (direction)
|
|
617 {
|
|
618 case GDK_SCROLL_UP:
|
|
619 image_scroll(imd, 0, -MOUSEWHEEL_SCROLL_SIZE);
|
|
620 break;
|
|
621 case GDK_SCROLL_DOWN:
|
|
622 image_scroll(imd, 0, MOUSEWHEEL_SCROLL_SIZE);
|
|
623 break;
|
|
624 case GDK_SCROLL_LEFT:
|
|
625 image_scroll(imd, -MOUSEWHEEL_SCROLL_SIZE, 0);
|
|
626 break;
|
|
627 case GDK_SCROLL_RIGHT:
|
|
628 image_scroll(imd, MOUSEWHEEL_SCROLL_SIZE, 0);
|
|
629 break;
|
|
630 default:
|
|
631 break;
|
|
632 }
|
|
633 }
|
|
634 else
|
|
635 {
|
|
636 switch (direction)
|
|
637 {
|
|
638 case GDK_SCROLL_UP:
|
|
639 view_step_prev(vw);
|
|
640 break;
|
|
641 case GDK_SCROLL_DOWN:
|
|
642 view_step_next(vw);
|
|
643 break;
|
|
644 default:
|
|
645 break;
|
|
646 }
|
|
647 }
|
|
648 }
|
|
649
|
|
650 static void view_image_set_buttons(ViewWindow *vw, ImageWindow *imd)
|
|
651 {
|
|
652 image_set_button_func(imd, button_cb, vw);
|
|
653 image_set_scroll_func(imd, scroll_cb, vw);
|
|
654 }
|
|
655
|
|
656 static void view_fullscreen_stop_func(FullScreenData *fs, gpointer data)
|
|
657 {
|
|
658 ViewWindow *vw = data;
|
|
659
|
|
660 vw->fs = NULL;
|
|
661
|
|
662 if (vw->ss) vw->ss->imd = vw->imd;
|
1
|
663 }
|
|
664
|
9
|
665 static void view_fullscreen_toggle(ViewWindow *vw, gint force_off)
|
4
|
666 {
|
9
|
667 if (force_off && !vw->fs) return;
|
|
668
|
|
669 if (vw->fs)
|
|
670 {
|
|
671 fullscreen_stop(vw->fs);
|
|
672
|
|
673 if (vw->overlay_id != -1) vw->overlay_id = image_overlay_info_enable(vw->imd);
|
|
674 }
|
|
675 else
|
|
676 {
|
|
677 vw->fs = fullscreen_start(vw->window, vw->imd, view_fullscreen_stop_func, vw);
|
|
678
|
|
679 view_image_set_buttons(vw, vw->fs->imd);
|
|
680 g_signal_connect(G_OBJECT(vw->fs->window), "key_press_event",
|
|
681 G_CALLBACK(view_window_key_press_cb), vw);
|
|
682
|
|
683 if (vw->ss) vw->ss->imd = vw->fs->imd;
|
|
684
|
|
685 if (vw->overlay_id != -1)
|
|
686 {
|
|
687 image_overlay_info_disable(vw->imd, vw->overlay_id);
|
|
688 vw->overlay_id = image_overlay_info_enable(vw->fs->imd);
|
|
689 }
|
|
690 }
|
|
691 }
|
|
692
|
|
693 static void view_overlay_toggle(ViewWindow *vw)
|
|
694 {
|
|
695 ImageWindow *imd;
|
|
696
|
|
697 imd = view_window_active_image(vw);
|
|
698
|
|
699 if (vw->overlay_id == -1)
|
|
700 {
|
|
701 vw->overlay_id = image_overlay_info_enable(imd);
|
|
702 }
|
|
703 else
|
|
704 {
|
|
705 image_overlay_info_disable(imd, vw->overlay_id);
|
|
706 vw->overlay_id = -1;
|
|
707 }
|
|
708 }
|
|
709
|
|
710 static void view_slideshow_next(ViewWindow *vw)
|
|
711 {
|
|
712 if (vw->ss) slideshow_next(vw->ss);
|
4
|
713 }
|
|
714
|
9
|
715 static void view_slideshow_prev(ViewWindow *vw)
|
|
716 {
|
|
717 if (vw->ss) slideshow_prev(vw->ss);
|
|
718 }
|
|
719
|
|
720 static void view_slideshow_stop_func(SlideShowData *fs, gpointer data)
|
|
721 {
|
|
722 ViewWindow *vw = data;
|
|
723
|
|
724 vw->ss = NULL;
|
|
725 }
|
|
726
|
|
727 static void view_slideshow_start(ViewWindow *vw)
|
4
|
728 {
|
9
|
729 if (!vw->ss)
|
|
730 {
|
|
731 CollectionData *cd;
|
|
732 CollectInfo *info;
|
|
733
|
|
734 if (vw->list)
|
|
735 {
|
|
736 vw->ss = slideshow_start_from_path_list(view_window_active_image(vw),
|
|
737 path_list_copy(vw->list),
|
|
738 view_slideshow_stop_func, vw);
|
|
739 vw->list_pointer = NULL;
|
|
740 return;
|
|
741 }
|
|
742
|
|
743 cd = image_get_collection(view_window_active_image(vw), &info);
|
|
744 if (cd && info)
|
|
745 {
|
|
746 vw->ss = slideshow_start_from_collection(view_window_active_image(vw), cd,
|
|
747 view_slideshow_stop_func, vw, info);
|
|
748 }
|
|
749 }
|
|
750 }
|
|
751
|
|
752 static void view_slideshow_stop(ViewWindow *vw)
|
|
753 {
|
|
754 if (vw->ss) slideshow_free(vw->ss);
|
|
755 }
|
|
756
|
|
757 static void view_window_close(ViewWindow *vw)
|
|
758 {
|
|
759 view_window_list = g_list_remove(view_window_list, vw);
|
|
760
|
|
761 view_slideshow_stop(vw);
|
|
762 view_fullscreen_toggle(vw, TRUE);
|
|
763 gtk_widget_destroy(vw->window);
|
|
764 path_list_free(vw->list);
|
|
765 g_free(vw);
|
4
|
766 }
|
|
767
|
1
|
768 static gint view_window_delete_cb(GtkWidget *w, GdkEventAny *event, gpointer data)
|
|
769 {
|
9
|
770 ViewWindow *vw = data;
|
|
771
|
|
772 view_window_close(vw);
|
1
|
773 return TRUE;
|
|
774 }
|
|
775
|
9
|
776 static ViewWindow *real_view_window_new(const gchar *path, GList *list, CollectionData *cd, CollectInfo *info)
|
1
|
777 {
|
9
|
778 ViewWindow *vw;
|
1
|
779 GtkAllocation req_size;
|
9
|
780 GdkGeometry geometry;
|
1
|
781 gint w, h;
|
9
|
782
|
|
783 if (!path && !list && (!cd || !info)) return NULL;
|
|
784
|
|
785 vw = g_new0(ViewWindow, 1);
|
|
786 vw->fs = NULL;
|
|
787 vw->ss = NULL;
|
|
788 vw->list = NULL;
|
|
789 vw->list_pointer = NULL;
|
|
790
|
|
791 vw->overlay_id = -1;
|
|
792
|
|
793 vw->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
794
|
|
795 geometry.min_width = 8;
|
|
796 geometry.min_height = 8;
|
|
797 gtk_window_set_geometry_hints(GTK_WINDOW(vw->window), NULL, &geometry, GDK_HINT_MIN_SIZE);
|
1
|
798
|
9
|
799 gtk_window_set_resizable(GTK_WINDOW(vw->window), TRUE);
|
|
800 gtk_window_set_title (GTK_WINDOW(vw->window), "GQview");
|
|
801 gtk_window_set_wmclass(GTK_WINDOW(vw->window), "view", "GQview");
|
|
802 gtk_container_set_border_width(GTK_CONTAINER(vw->window), 0);
|
|
803
|
|
804 window_set_icon(vw->window, (const gchar **)view_xpm, NULL);
|
|
805
|
|
806 vw->imd = image_new(FALSE);
|
|
807
|
|
808 if (black_window_background) image_background_set_black(vw->imd, TRUE);
|
|
809
|
|
810 image_attach_window(vw->imd, vw->window, NULL, "GQview", TRUE);
|
|
811
|
|
812 image_auto_refresh(vw->imd, 0);
|
|
813 image_top_window_set_sync(vw->imd, TRUE);
|
|
814
|
|
815 gtk_container_add(GTK_CONTAINER(vw->window), vw->imd->widget);
|
|
816 gtk_widget_show(vw->imd->widget);
|
|
817
|
|
818 view_window_dnd_init(vw);
|
1
|
819
|
9
|
820 view_image_set_buttons(vw, vw->imd);
|
1
|
821
|
9
|
822 g_signal_connect(G_OBJECT(vw->window), "delete_event",
|
|
823 G_CALLBACK(view_window_delete_cb), vw);
|
|
824 g_signal_connect(G_OBJECT(vw->window), "key_press_event",
|
|
825 G_CALLBACK(view_window_key_press_cb), vw);
|
|
826 if (cd && info)
|
|
827 {
|
|
828 image_change_from_collection(vw->imd, cd, info, image_zoom_get_default(NULL, zoom_mode));
|
|
829 if (enable_read_ahead)
|
|
830 {
|
|
831 CollectInfo * r_info = collection_next_by_info(cd, info);
|
|
832 if (!r_info) r_info = collection_prev_by_info(cd, info);
|
|
833 if (r_info) image_prebuffer_set(vw->imd, r_info->path);
|
|
834 }
|
|
835 }
|
|
836 else if (list)
|
|
837 {
|
|
838 view_window_set_list(vw, list);
|
|
839 vw->list_pointer = vw->list;
|
|
840 image_change_path(vw->imd, (gchar *)vw->list->data, image_zoom_get_default(NULL, zoom_mode));
|
1
|
841
|
9
|
842 if (enable_read_ahead)
|
|
843 {
|
|
844 GList *work = vw->list->next;
|
|
845 if (work) image_prebuffer_set(vw->imd, (gchar *)work->data);
|
|
846 }
|
|
847 }
|
|
848 else
|
|
849 {
|
|
850 image_change_path(vw->imd, path, image_zoom_get_default(NULL, zoom_mode));
|
|
851 }
|
1
|
852
|
9
|
853 if (image_zoom_get(vw->imd) == 0.0)
|
|
854 {
|
|
855 w = vw->imd->image_width;
|
|
856 h = vw->imd->image_height;
|
|
857 }
|
|
858 else
|
|
859 {
|
|
860 w = vw->imd->width;
|
|
861 h = vw->imd->height;
|
|
862 }
|
1
|
863 if (limit_window_size)
|
|
864 {
|
|
865 gint mw = gdk_screen_width() * max_window_size / 100;
|
|
866 gint mh = gdk_screen_height() * max_window_size / 100;
|
|
867
|
|
868 if (w > mw) w = mw;
|
|
869 if (h > mh) h = mh;
|
|
870 }
|
|
871
|
9
|
872 gtk_window_set_default_size(GTK_WINDOW(vw->window), w, h);
|
1
|
873 req_size.x = req_size.y = 0;
|
|
874 req_size.width = w;
|
|
875 req_size.height = h;
|
9
|
876 gtk_widget_size_allocate(GTK_WIDGET(vw->window), &req_size);
|
|
877
|
|
878 gtk_widget_set_size_request(vw->imd->image, w, h);
|
|
879
|
|
880 gtk_widget_show(vw->window);
|
|
881
|
|
882 view_window_list = g_list_append(view_window_list, vw);
|
|
883
|
|
884 return vw;
|
|
885 }
|
|
886
|
|
887 static void view_window_collection_unref_cb(GtkWidget *widget, gpointer data)
|
|
888 {
|
|
889 CollectionData *cd = data;
|
|
890
|
|
891 collection_unref(cd);
|
|
892 }
|
|
893
|
|
894 void view_window_new(const gchar *path)
|
|
895 {
|
|
896 if (file_extension_match(path, ".gqv"))
|
|
897 {
|
|
898 ViewWindow *vw;
|
|
899 CollectionData *cd;
|
|
900 CollectInfo *info;
|
|
901
|
|
902 cd = collection_new(path);
|
|
903 if (collection_load(cd, path, FALSE))
|
|
904 {
|
|
905 info = collection_get_first(cd);
|
|
906 }
|
|
907 else
|
|
908 {
|
|
909 collection_unref(cd);
|
|
910 cd = NULL;
|
|
911 info = NULL;
|
|
912 }
|
|
913 vw = real_view_window_new(NULL, NULL, cd, info);
|
|
914 if (vw && cd)
|
|
915 {
|
|
916 g_signal_connect(G_OBJECT(vw->window), "destroy",
|
|
917 G_CALLBACK(view_window_collection_unref_cb), cd);
|
|
918 }
|
|
919 }
|
|
920 else if (isdir(path))
|
|
921 {
|
|
922 GList *list = NULL;
|
1
|
923
|
9
|
924 if (path_list(path, &list, NULL))
|
|
925 {
|
|
926 list = path_list_sort(list);
|
|
927 list = path_list_filter(list, FALSE);
|
|
928 }
|
|
929 real_view_window_new(NULL, list, NULL, NULL);
|
|
930 path_list_free(list);
|
|
931 }
|
|
932 else
|
|
933 {
|
|
934 real_view_window_new(path, NULL, NULL, NULL);
|
|
935 }
|
|
936 }
|
|
937
|
|
938 void view_window_new_from_list(GList *list)
|
|
939 {
|
|
940 real_view_window_new(NULL, list, NULL, NULL);
|
|
941 }
|
|
942
|
|
943 void view_window_new_from_collection(CollectionData *cd, CollectInfo *info)
|
|
944 {
|
|
945 real_view_window_new(NULL, NULL, cd, info);
|
|
946 }
|
|
947
|
|
948 /*
|
|
949 *-----------------------------------------------------------------------------
|
|
950 * public
|
|
951 *-----------------------------------------------------------------------------
|
|
952 */
|
|
953
|
|
954 void view_window_colors_update(void)
|
|
955 {
|
|
956 GList *work;
|
1
|
957
|
9
|
958 work = view_window_list;
|
|
959 while (work)
|
|
960 {
|
|
961 ViewWindow *vw = work->data;
|
|
962 work = work->next;
|
|
963
|
|
964 image_background_set_black(vw->imd, black_window_background);
|
|
965 }
|
|
966 }
|
|
967
|
|
968 gint view_window_find_image(ImageWindow *imd, gint *index, gint *total)
|
|
969 {
|
|
970 GList *work;
|
|
971
|
|
972 work = view_window_list;
|
|
973 while (work)
|
|
974 {
|
|
975 ViewWindow *vw = work->data;
|
|
976 work = work->next;
|
|
977
|
|
978 if (vw->imd == imd ||
|
|
979 (vw->fs && vw->fs->imd == imd))
|
|
980 {
|
|
981 if (vw->ss)
|
|
982 {
|
|
983 gint n;
|
|
984 n = g_list_length(vw->ss->list_done);
|
|
985 if (index) *index = n - 1;
|
|
986 if (total) *total = n + g_list_length(vw->ss->list);
|
|
987 }
|
|
988 else
|
|
989 {
|
|
990 if (index) *index = g_list_position(vw->list, vw->list_pointer);
|
|
991 if (total) *total = g_list_length(vw->list);
|
|
992 }
|
|
993 return TRUE;
|
|
994 }
|
|
995 }
|
|
996
|
|
997 return FALSE;
|
1
|
998 }
|
|
999
|
|
1000 /*
|
|
1001 *-----------------------------------------------------------------------------
|
|
1002 * view window menu routines and callbacks
|
|
1003 *-----------------------------------------------------------------------------
|
|
1004 */
|
|
1005
|
9
|
1006 static void view_new_window_cb(GtkWidget *widget, gpointer data)
|
1
|
1007 {
|
9
|
1008 ViewWindow *vw = data;
|
|
1009 CollectionData *cd;
|
|
1010 CollectInfo *info;
|
|
1011
|
|
1012 cd = image_get_collection(vw->imd, &info);
|
|
1013
|
|
1014 if (cd && info)
|
|
1015 {
|
|
1016 view_window_new_from_collection(cd, info);
|
|
1017 }
|
|
1018 else
|
|
1019 {
|
|
1020 view_window_new(image_get_path(vw->imd));
|
|
1021 }
|
1
|
1022 }
|
|
1023
|
9
|
1024 static void view_edit_cb(GtkWidget *widget, gpointer data)
|
1
|
1025 {
|
9
|
1026 ViewWindow *vw;
|
|
1027 gint n;
|
|
1028
|
|
1029 vw = submenu_item_get_data(widget);
|
|
1030 n = GPOINTER_TO_INT(data);
|
|
1031 if (!vw) return;
|
|
1032
|
|
1033 view_fullscreen_toggle(vw, TRUE);
|
|
1034 start_editor_from_file(n, image_get_path(vw->imd));
|
1
|
1035 }
|
|
1036
|
9
|
1037 static void view_alter_cb(GtkWidget *widget, gpointer data)
|
|
1038 {
|
|
1039 ViewWindow *vw;
|
|
1040 AlterType type;
|
|
1041
|
|
1042 vw = submenu_item_get_data(widget);
|
|
1043 type = GPOINTER_TO_INT(data);
|
|
1044
|
|
1045 if (!vw) return;
|
|
1046 image_alter(vw->imd, type);
|
|
1047 }
|
|
1048
|
|
1049 static void view_info_cb(GtkWidget *widget, gpointer data)
|
3
|
1050 {
|
9
|
1051 ViewWindow *vw = data;
|
|
1052 ImageWindow *imd;
|
|
1053
|
|
1054 imd = view_window_active_image(vw);
|
|
1055 info_window_new(image_get_path(imd), NULL);
|
|
1056 }
|
|
1057
|
|
1058 static void view_wallpaper_cb(GtkWidget *widget, gpointer data)
|
|
1059 {
|
|
1060 ViewWindow *vw = data;
|
|
1061 ImageWindow *imd;
|
|
1062
|
|
1063 imd = view_window_active_image(vw);
|
|
1064 image_to_root_window(imd, (image_zoom_get(imd) == 0.0));
|
3
|
1065 }
|
|
1066
|
1
|
1067 static void view_zoom_in_cb(GtkWidget *widget, gpointer data)
|
|
1068 {
|
9
|
1069 ViewWindow *vw = data;
|
|
1070
|
|
1071 image_zoom_adjust(view_window_active_image(vw), get_zoom_increment());
|
1
|
1072 }
|
|
1073
|
|
1074 static void view_zoom_out_cb(GtkWidget *widget, gpointer data)
|
|
1075 {
|
9
|
1076 ViewWindow *vw = data;
|
|
1077
|
|
1078 image_zoom_adjust(view_window_active_image(vw), -get_zoom_increment());
|
1
|
1079 }
|
|
1080
|
|
1081 static void view_zoom_1_1_cb(GtkWidget *widget, gpointer data)
|
|
1082 {
|
9
|
1083 ViewWindow *vw = data;
|
|
1084
|
|
1085 image_zoom_set(view_window_active_image(vw), 1.0);
|
1
|
1086 }
|
|
1087
|
|
1088 static void view_zoom_fit_cb(GtkWidget *widget, gpointer data)
|
|
1089 {
|
9
|
1090 ViewWindow *vw = data;
|
|
1091
|
|
1092 image_zoom_set(view_window_active_image(vw), 0.0);
|
1
|
1093 }
|
|
1094
|
|
1095 static void view_copy_cb(GtkWidget *widget, gpointer data)
|
|
1096 {
|
9
|
1097 ViewWindow *vw = data;
|
|
1098 ImageWindow *imd;
|
|
1099
|
|
1100 imd = view_window_active_image(vw);
|
|
1101 file_util_copy(image_get_path(imd), NULL, NULL, imd->widget);
|
1
|
1102 }
|
|
1103
|
|
1104 static void view_move_cb(GtkWidget *widget, gpointer data)
|
|
1105 {
|
9
|
1106 ViewWindow *vw = data;
|
|
1107 ImageWindow *imd;
|
|
1108
|
|
1109 imd = view_window_active_image(vw);
|
|
1110 file_util_move(image_get_path(imd), NULL, NULL, imd->widget);
|
1
|
1111 }
|
|
1112
|
|
1113 static void view_rename_cb(GtkWidget *widget, gpointer data)
|
|
1114 {
|
9
|
1115 ViewWindow *vw = data;
|
|
1116 ImageWindow *imd;
|
|
1117
|
|
1118 imd = view_window_active_image(vw);
|
|
1119 file_util_rename(image_get_path(imd), NULL, imd->widget);
|
1
|
1120 }
|
|
1121
|
|
1122 static void view_delete_cb(GtkWidget *widget, gpointer data)
|
|
1123 {
|
9
|
1124 ViewWindow *vw = data;
|
|
1125 ImageWindow *imd;
|
|
1126
|
|
1127 imd = view_window_active_image(vw);
|
|
1128 file_util_delete(image_get_path(imd), NULL, imd->widget);
|
|
1129 }
|
|
1130
|
|
1131 static void view_fullscreen_cb(GtkWidget *widget, gpointer data)
|
|
1132 {
|
|
1133 ViewWindow *vw = data;
|
|
1134
|
|
1135 view_fullscreen_toggle(vw, FALSE);
|
|
1136 }
|
|
1137
|
|
1138 static void view_slideshow_start_cb(GtkWidget *widget, gpointer data)
|
|
1139 {
|
|
1140 ViewWindow *vw = data;
|
|
1141
|
|
1142 view_slideshow_start(vw);
|
|
1143 }
|
|
1144
|
|
1145 static void view_slideshow_stop_cb(GtkWidget *widget, gpointer data)
|
|
1146 {
|
|
1147 ViewWindow *vw = data;
|
|
1148
|
|
1149 view_slideshow_stop(vw);
|
|
1150 }
|
|
1151
|
|
1152 static void view_slideshow_pause_cb(GtkWidget *widget, gpointer data)
|
|
1153 {
|
|
1154 ViewWindow *vw = data;
|
|
1155
|
|
1156 slideshow_pause_toggle(vw->ss);
|
1
|
1157 }
|
|
1158
|
|
1159 static void view_close_cb(GtkWidget *widget, gpointer data)
|
|
1160 {
|
9
|
1161 ViewWindow *vw = data;
|
|
1162
|
|
1163 view_window_close(vw);
|
|
1164 }
|
|
1165
|
|
1166 static GtkWidget *view_popup_menu(ViewWindow *vw)
|
|
1167 {
|
|
1168 GtkWidget *menu;
|
|
1169 GtkWidget *item;
|
|
1170
|
|
1171 menu = popup_menu_short_lived();
|
|
1172
|
|
1173 menu_item_add_stock(menu, _("Zoom _in"), GTK_STOCK_ZOOM_IN, G_CALLBACK(view_zoom_in_cb), vw);
|
|
1174 menu_item_add_stock(menu, _("Zoom _out"), GTK_STOCK_ZOOM_OUT, G_CALLBACK(view_zoom_out_cb), vw);
|
|
1175 menu_item_add_stock(menu, _("Zoom _1:1"), GTK_STOCK_ZOOM_100, G_CALLBACK(view_zoom_1_1_cb), vw);
|
|
1176 menu_item_add_stock(menu, _("Fit image to _window"), GTK_STOCK_ZOOM_FIT, G_CALLBACK(view_zoom_fit_cb), vw);
|
|
1177 menu_item_add_divider(menu);
|
|
1178
|
|
1179 item = submenu_add_edit(menu, NULL, G_CALLBACK(view_edit_cb), vw);
|
|
1180 menu_item_add_divider(item);
|
|
1181 menu_item_add(item, _("Set as _wallpaper"), G_CALLBACK(view_wallpaper_cb), vw);
|
|
1182
|
|
1183 submenu_add_alter(menu, G_CALLBACK(view_alter_cb), vw);
|
|
1184
|
|
1185 menu_item_add_stock(menu, _("_Properties"), GTK_STOCK_PROPERTIES, G_CALLBACK(view_info_cb), vw);
|
|
1186
|
|
1187 menu_item_add_stock(menu, _("View in _new window"), GTK_STOCK_NEW, G_CALLBACK(view_new_window_cb), vw);
|
|
1188
|
|
1189 menu_item_add_divider(menu);
|
|
1190 menu_item_add_stock(menu, _("_Copy..."), GTK_STOCK_COPY, G_CALLBACK(view_copy_cb), vw);
|
|
1191 menu_item_add(menu, _("_Move..."), G_CALLBACK(view_move_cb), vw);
|
|
1192 menu_item_add(menu, _("_Rename..."), G_CALLBACK(view_rename_cb), vw);
|
|
1193 menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(view_delete_cb), vw);
|
|
1194
|
|
1195 menu_item_add_divider(menu);
|
|
1196
|
|
1197 if (vw->ss)
|
|
1198 {
|
|
1199 menu_item_add(menu, _("_Stop slideshow"), G_CALLBACK(view_slideshow_stop_cb), vw);
|
|
1200 if (slideshow_paused(vw->ss))
|
|
1201 {
|
|
1202 item = menu_item_add(menu, _("Continue slides_how"),
|
|
1203 G_CALLBACK(view_slideshow_pause_cb), vw);
|
|
1204 }
|
|
1205 else
|
|
1206 {
|
|
1207 item = menu_item_add(menu, _("Pause slides_how"),
|
|
1208 G_CALLBACK(view_slideshow_pause_cb), vw);
|
|
1209 }
|
|
1210 }
|
|
1211 else
|
|
1212 {
|
|
1213 item = menu_item_add(menu, _("_Start slideshow"), G_CALLBACK(view_slideshow_start_cb), vw);
|
|
1214 gtk_widget_set_sensitive(item, (vw->list != NULL) || view_window_contains_collection(vw));
|
|
1215 item = menu_item_add(menu, _("Pause slides_how"), G_CALLBACK(view_slideshow_pause_cb), vw);
|
|
1216 gtk_widget_set_sensitive(item, FALSE);
|
|
1217 }
|
|
1218
|
|
1219 if (vw->fs)
|
|
1220 {
|
|
1221 menu_item_add(menu, _("Exit _full screen"), G_CALLBACK(view_fullscreen_cb), vw);
|
|
1222 }
|
|
1223 else
|
|
1224 {
|
|
1225 menu_item_add(menu, _("_Full screen"), G_CALLBACK(view_fullscreen_cb), vw);
|
|
1226 }
|
|
1227
|
|
1228 menu_item_add_divider(menu);
|
|
1229 menu_item_add_stock(menu, _("C_lose window"), GTK_STOCK_CLOSE, G_CALLBACK(view_close_cb), vw);
|
|
1230
|
|
1231 return menu;
|
|
1232 }
|
|
1233
|
|
1234 /*
|
|
1235 *-------------------------------------------------------------------
|
|
1236 * dnd confirm dir
|
|
1237 *-------------------------------------------------------------------
|
|
1238 */
|
|
1239
|
|
1240 typedef struct {
|
|
1241 ViewWindow *vw;
|
|
1242 GList *list;
|
|
1243 } CViewConfirmD;
|
|
1244
|
|
1245 static void view_dir_list_cancel(GtkWidget *widget, gpointer data)
|
|
1246 {
|
|
1247 /* do nothing */
|
|
1248 }
|
|
1249
|
|
1250 static void view_dir_list_do(ViewWindow *vw, GList *list, gint skip, gint recurse)
|
|
1251 {
|
|
1252 GList *work;
|
|
1253
|
|
1254 view_window_set_list(vw, NULL);
|
|
1255
|
|
1256 work = list;
|
|
1257 while (work)
|
|
1258 {
|
|
1259 gchar *path = work->data;
|
|
1260 work = work->next;
|
|
1261
|
|
1262 if (isdir(path))
|
|
1263 {
|
|
1264 if (!skip)
|
|
1265 {
|
|
1266 GList *list = NULL;
|
|
1267
|
|
1268 if (recurse)
|
|
1269 {
|
|
1270 list = path_list_recursive(path);
|
|
1271 }
|
|
1272 else
|
|
1273 {
|
|
1274 path_list(path, &list, NULL);
|
|
1275 list = path_list_sort(list);
|
|
1276 list = path_list_filter(list, FALSE);
|
|
1277 }
|
|
1278 if (list) vw->list = g_list_concat(vw->list, list);
|
|
1279 }
|
|
1280 }
|
|
1281 else
|
|
1282 {
|
|
1283 /* FIXME: no filtering here */
|
|
1284 vw->list = g_list_append(vw->list, g_strdup(path));
|
|
1285 }
|
|
1286 }
|
|
1287
|
|
1288 if (vw->list)
|
|
1289 {
|
|
1290 gchar *path;
|
|
1291
|
|
1292 vw->list_pointer = vw->list;
|
|
1293 path = vw->list->data;
|
|
1294 image_change_path(vw->imd, path, image_zoom_get_default(vw->imd, zoom_mode));
|
|
1295
|
|
1296 work = vw->list->next;
|
|
1297 if (enable_read_ahead && work)
|
|
1298 {
|
|
1299 path = work->data;
|
|
1300 image_prebuffer_set(vw->imd, path);
|
|
1301 }
|
|
1302 }
|
|
1303 else
|
|
1304 {
|
|
1305 image_change_path(vw->imd, NULL, image_zoom_get_default(vw->imd, zoom_mode));
|
|
1306 }
|
|
1307 }
|
|
1308
|
|
1309 static void view_dir_list_add(GtkWidget *widget, gpointer data)
|
|
1310 {
|
|
1311 CViewConfirmD *d = data;
|
|
1312 view_dir_list_do(d->vw, d->list, FALSE, FALSE);
|
|
1313 }
|
|
1314
|
|
1315 static void view_dir_list_recurse(GtkWidget *widget, gpointer data)
|
|
1316 {
|
|
1317 CViewConfirmD *d = data;
|
|
1318 view_dir_list_do(d->vw, d->list, FALSE, TRUE);
|
|
1319 }
|
|
1320
|
|
1321 static void view_dir_list_skip(GtkWidget *widget, gpointer data)
|
|
1322 {
|
|
1323 CViewConfirmD *d = data;
|
|
1324 view_dir_list_do(d->vw, d->list, TRUE, FALSE);
|
|
1325 }
|
|
1326
|
|
1327 static void view_dir_list_destroy(GtkWidget *widget, gpointer data)
|
|
1328 {
|
|
1329 CViewConfirmD *d = data;
|
|
1330 path_list_free(d->list);
|
|
1331 g_free(d);
|
|
1332 }
|
|
1333
|
|
1334 static GtkWidget *view_confirm_dir_list(ViewWindow *vw, GList *list)
|
|
1335 {
|
|
1336 GtkWidget *menu;
|
|
1337 CViewConfirmD *d;
|
|
1338
|
|
1339 d = g_new(CViewConfirmD, 1);
|
|
1340 d->vw = vw;
|
|
1341 d->list = list;
|
|
1342
|
|
1343 menu = popup_menu_short_lived();
|
|
1344 g_signal_connect(G_OBJECT(menu), "destroy",
|
|
1345 G_CALLBACK(view_dir_list_destroy), d);
|
|
1346
|
|
1347 menu_item_add_stock(menu, _("Dropped list includes folders."), GTK_STOCK_DND_MULTIPLE, NULL, NULL);
|
|
1348 menu_item_add_divider(menu);
|
|
1349 menu_item_add_stock(menu, _("_Add contents"), GTK_STOCK_OK, G_CALLBACK(view_dir_list_add), d);
|
|
1350 menu_item_add_stock(menu, _("Add contents _recursive"), GTK_STOCK_ADD, G_CALLBACK(view_dir_list_recurse), d);
|
|
1351 menu_item_add_stock(menu, _("_Skip folders"), GTK_STOCK_REMOVE, G_CALLBACK(view_dir_list_skip), d);
|
|
1352 menu_item_add_divider(menu);
|
|
1353 menu_item_add_stock(menu, _("Cancel"), GTK_STOCK_CANCEL, G_CALLBACK(view_dir_list_cancel), d);
|
|
1354
|
|
1355 return menu;
|
1
|
1356 }
|
|
1357
|
9
|
1358 /*
|
|
1359 *-----------------------------------------------------------------------------
|
|
1360 * image drag and drop routines
|
|
1361 *-----------------------------------------------------------------------------
|
|
1362 */
|
|
1363
|
|
1364 static void view_window_get_dnd_data(GtkWidget *widget, GdkDragContext *context,
|
|
1365 gint x, gint y,
|
|
1366 GtkSelectionData *selection_data, guint info,
|
|
1367 guint time, gpointer data)
|
1
|
1368 {
|
9
|
1369 ViewWindow *vw = data;
|
|
1370 ImageWindow *imd;
|
|
1371
|
|
1372 if (gtk_drag_get_source_widget(context) == vw->imd->image) return;
|
|
1373
|
|
1374 imd = vw->imd;
|
|
1375
|
|
1376 if (info == TARGET_URI_LIST || info == TARGET_APP_COLLECTION_MEMBER)
|
|
1377 {
|
|
1378 CollectionData *source;
|
|
1379 GList *list;
|
|
1380 GList *info_list;
|
|
1381
|
|
1382 if (info == TARGET_URI_LIST)
|
|
1383 {
|
|
1384 GList *work;
|
|
1385
|
|
1386 list = uri_list_from_text(selection_data->data, TRUE);
|
|
1387
|
|
1388 work = list;
|
|
1389 while (work)
|
|
1390 {
|
|
1391 if (isdir((gchar *)work->data))
|
|
1392 {
|
|
1393 GtkWidget *menu;
|
|
1394 menu = view_confirm_dir_list(vw, list);
|
|
1395 gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, time);
|
|
1396 return;
|
|
1397 }
|
|
1398 work = work->next;
|
|
1399 }
|
|
1400
|
|
1401 list = path_list_filter(list, FALSE);
|
|
1402
|
|
1403 source = NULL;
|
|
1404 info_list = NULL;
|
|
1405 }
|
|
1406 else
|
|
1407 {
|
|
1408 source = collection_from_dnd_data((gchar *)selection_data->data, &list, &info_list);
|
|
1409 }
|
|
1410
|
|
1411 if (list)
|
|
1412 {
|
|
1413 gchar *path;
|
|
1414
|
|
1415 path = list->data;
|
|
1416 if (isfile(path))
|
|
1417 {
|
|
1418 view_slideshow_stop(vw);
|
|
1419 view_window_set_list(vw, NULL);
|
1
|
1420
|
9
|
1421 if (source && info_list)
|
|
1422 {
|
|
1423 image_change_from_collection(imd, source, info_list->data, image_zoom_get_default(imd, zoom_mode));
|
|
1424 }
|
|
1425 else
|
|
1426 {
|
|
1427 if (list->next)
|
|
1428 {
|
|
1429 vw->list = list;
|
|
1430 list = NULL;
|
|
1431
|
|
1432 vw->list_pointer = vw->list;
|
|
1433 }
|
|
1434 image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
|
|
1435 }
|
|
1436 }
|
|
1437 }
|
|
1438 path_list_free(list);
|
|
1439 g_list_free(info_list);
|
|
1440 }
|
|
1441 }
|
|
1442
|
|
1443 static void view_window_set_dnd_data(GtkWidget *widget, GdkDragContext *context,
|
|
1444 GtkSelectionData *selection_data, guint info,
|
|
1445 guint time, gpointer data)
|
|
1446 {
|
|
1447 ViewWindow *vw = data;
|
|
1448 const gchar *path;
|
|
1449
|
|
1450 path = image_get_path(vw->imd);
|
1
|
1451
|
9
|
1452 if (path)
|
|
1453 {
|
|
1454 gchar *text = NULL;
|
|
1455 gint len;
|
|
1456 gint plain_text;
|
|
1457 GList *list;
|
1
|
1458
|
9
|
1459 switch (info)
|
|
1460 {
|
|
1461 case TARGET_URI_LIST:
|
|
1462 plain_text = FALSE;
|
|
1463 break;
|
|
1464 case TARGET_TEXT_PLAIN:
|
|
1465 default:
|
|
1466 plain_text = TRUE;
|
|
1467 break;
|
|
1468 }
|
|
1469 list = g_list_append(NULL, (gchar *)path);
|
|
1470 text = uri_text_from_list(list, &len, plain_text);
|
|
1471 g_list_free(list);
|
|
1472 if (text)
|
|
1473 {
|
|
1474 gtk_selection_data_set (selection_data, selection_data->target,
|
|
1475 8, text, len);
|
|
1476 g_free(text);
|
|
1477 }
|
|
1478 }
|
|
1479 else
|
|
1480 {
|
|
1481 gtk_selection_data_set (selection_data, selection_data->target,
|
|
1482 8, NULL, 0);
|
|
1483 }
|
1
|
1484 }
|
|
1485
|
9
|
1486 static void view_window_dnd_init(ViewWindow *vw)
|
|
1487 {
|
|
1488 ImageWindow *imd;
|
1
|
1489
|
9
|
1490 imd = vw->imd;
|
|
1491
|
|
1492 gtk_drag_source_set(imd->image, GDK_BUTTON2_MASK,
|
|
1493 dnd_file_drag_types, dnd_file_drag_types_count,
|
|
1494 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
|
|
1495 g_signal_connect(G_OBJECT(imd->image), "drag_data_get",
|
|
1496 G_CALLBACK(view_window_set_dnd_data), vw);
|
|
1497
|
|
1498 gtk_drag_dest_set(imd->image,
|
|
1499 GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
|
|
1500 dnd_file_drop_types, dnd_file_drop_types_count,
|
|
1501 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
|
|
1502 g_signal_connect(G_OBJECT(imd->image), "drag_data_received",
|
|
1503 G_CALLBACK(view_window_get_dnd_data), vw);
|
|
1504 }
|
|
1505
|
|
1506 /*
|
|
1507 *-----------------------------------------------------------------------------
|
|
1508 * maintenance (for rename, move, remove)
|
|
1509 *-----------------------------------------------------------------------------
|
|
1510 */
|
|
1511
|
|
1512 static void view_real_removed(ViewWindow *vw, const gchar *path, GList *ignore_list)
|
|
1513 {
|
|
1514 ImageWindow *imd;
|
|
1515 const gchar *image_path;
|
|
1516
|
|
1517 imd = view_window_active_image(vw);
|
|
1518 image_path = image_get_path(imd);
|
|
1519
|
|
1520 if (image_path && strcmp(image_path, path) == 0)
|
|
1521 {
|
|
1522 if (vw->list)
|
|
1523 {
|
|
1524 view_list_step(vw, TRUE);
|
|
1525 if (image_get_path(imd) == image_path)
|
|
1526 {
|
|
1527 view_list_step(vw, FALSE);
|
|
1528 }
|
|
1529 }
|
|
1530 else if (view_window_contains_collection(vw))
|
|
1531 {
|
|
1532 view_collection_step(vw, TRUE);
|
|
1533 if (image_get_path(imd) == image_path)
|
|
1534 {
|
|
1535 view_collection_step(vw, FALSE);
|
|
1536 }
|
|
1537 }
|
|
1538 if (image_get_path(imd) == image_path)
|
|
1539 {
|
|
1540 image_change_path(imd, NULL, image_zoom_get_default(imd, zoom_mode));
|
|
1541 }
|
|
1542 }
|
|
1543
|
|
1544 if (vw->list)
|
|
1545 {
|
|
1546 GList *work;
|
|
1547 GList *old;
|
|
1548
|
|
1549 old = vw->list_pointer;
|
|
1550
|
|
1551 work = vw->list;
|
|
1552 while (work)
|
|
1553 {
|
|
1554 gchar *chk_path;
|
|
1555 GList *chk_link;
|
|
1556
|
|
1557 chk_path = work->data;
|
|
1558 chk_link = work;
|
|
1559 work = work->next;
|
|
1560
|
|
1561 if (strcmp(chk_path, path) == 0)
|
|
1562 {
|
|
1563 if (vw->list_pointer == chk_link)
|
|
1564 {
|
|
1565 vw->list_pointer = (chk_link->next) ? chk_link->next : chk_link->prev;
|
|
1566 }
|
|
1567 vw->list = g_list_remove(vw->list, chk_path);
|
|
1568 g_free(chk_path);
|
|
1569 }
|
|
1570 }
|
|
1571
|
|
1572 /* handles stepping correctly when same image is in the list more than once */
|
|
1573 if (old && old != vw->list_pointer)
|
|
1574 {
|
|
1575 gchar *path;
|
|
1576
|
|
1577 if (vw->list_pointer)
|
|
1578 {
|
|
1579 path = vw->list_pointer->data;
|
|
1580 }
|
|
1581 else
|
|
1582 {
|
|
1583 path = NULL;
|
|
1584 }
|
|
1585
|
|
1586 image_change_path(imd, path, image_zoom_get_default(imd, zoom_mode));
|
|
1587 }
|
|
1588 }
|
|
1589
|
|
1590 if (vw->overlay_id != -1) image_overlay_update(imd, vw->overlay_id);
|
|
1591 }
|
|
1592
|
|
1593 static void view_real_moved(ViewWindow *vw, const gchar *source, const gchar *dest)
|
|
1594 {
|
|
1595 ImageWindow *imd;
|
|
1596 const gchar *image_path;
|
|
1597
|
|
1598 imd = view_window_active_image(vw);
|
|
1599 image_path = image_get_path(imd);
|
|
1600
|
|
1601 if (image_path && strcmp(image_path, source) == 0)
|
|
1602 {
|
|
1603 image_set_path(imd, dest);
|
|
1604 }
|
|
1605
|
|
1606 if (vw->list)
|
|
1607 {
|
|
1608 GList *work;
|
|
1609 work = vw->list;
|
|
1610 while (work)
|
|
1611 {
|
|
1612 gchar *chk_path;
|
|
1613
|
|
1614 chk_path = work->data;
|
|
1615
|
|
1616 if (strcmp(chk_path, source) == 0)
|
|
1617 {
|
|
1618 work->data = g_strdup(dest);
|
|
1619 g_free(chk_path);
|
|
1620 }
|
|
1621
|
|
1622 work = work->next;
|
|
1623 }
|
|
1624 }
|
|
1625 }
|
|
1626
|
|
1627 void view_window_maint_removed(const gchar *path, GList *ignore_list)
|
|
1628 {
|
|
1629 GList *work = view_window_list;
|
|
1630 while (work)
|
|
1631 {
|
|
1632 ViewWindow *vw = work->data;
|
|
1633 work = work->next;
|
|
1634
|
|
1635 view_real_removed(vw, path, ignore_list);
|
|
1636 }
|
|
1637 }
|
|
1638
|
|
1639 void view_window_maint_moved(const gchar *source, const gchar *dest)
|
|
1640 {
|
|
1641 GList *work = view_window_list;
|
|
1642 while (work)
|
|
1643 {
|
|
1644 ViewWindow *vw = work->data;
|
|
1645 work = work->next;
|
|
1646
|
|
1647 view_real_moved(vw, source, dest);
|
|
1648 }
|
|
1649 }
|
|
1650
|