Mercurial > geeqie
annotate src/view_file_icon.c @ 111:3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
* view_file_icon.c: Fix odd crash when removing files, it seems the
high priority idle sync is no longer called before the treeview tries
to redraw itself, so fix the cleanup of removed pointers so that they
are always valid or NULL (I wonder if the priorities used by
GtkTreeView have changed in newer versions of GTK?).
* view_file_list.c: Fix progress bar warning when files are removed
before thumbnail generation is finished.
author | gqview |
---|---|
date | Wed, 15 Nov 2006 07:19:16 +0000 |
parents | 9d5c75b5ec28 |
children | 55166d93498d |
rev | line source |
---|---|
9 | 1 /* |
2 * GQview | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
3 * (C) 2006 John Ellis |
9 | 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 "view_file_icon.h" | |
14 | |
15 #include "cellrenderericon.h" | |
16 #include "collect.h" | |
17 #include "collect-io.h" | |
18 #include "collect-table.h" | |
19 #include "dnd.h" | |
20 #include "editors.h" | |
21 #include "img-view.h" | |
22 #include "info.h" | |
23 #include "filelist.h" | |
24 #include "layout.h" | |
25 #include "layout_image.h" | |
26 #include "menu.h" | |
27 #include "thumb.h" | |
28 #include "utilops.h" | |
29 #include "ui_bookmark.h" | |
30 #include "ui_fileops.h" | |
31 #include "ui_menu.h" | |
32 #include "ui_tree_edit.h" | |
33 | |
34 | |
35 #include <gdk/gdkkeysyms.h> /* for keyboard values */ | |
36 | |
37 /* between these, the icon width is increased by thumb_max_width / 2 */ | |
38 #define THUMB_MIN_ICON_WIDTH 128 | |
39 #define THUMB_MAX_ICON_WIDTH 150 | |
40 | |
41 #define VFICON_MAX_COLUMNS 32 | |
42 #define THUMB_BORDER_PADDING 2 | |
43 | |
44 #define VFICON_TIP_DELAY 500 | |
45 | |
46 #define ICON_DATA(x) ((IconData *)x) | |
47 #define FILE_DATA(x) ((FileData *)x) | |
48 | |
49 | |
50 enum { | |
51 FILE_COLUMN_POINTER = 0, | |
52 FILE_COLUMN_COUNT | |
53 }; | |
54 | |
55 typedef enum { | |
56 SELECTION_NONE = 0, | |
57 SELECTION_SELECTED = 1 << 0, | |
58 SELECTION_PRELIGHT = 1 << 1, | |
59 SELECTION_FOCUS = 1 << 2 | |
60 } SelectionType; | |
61 | |
62 typedef struct _IconData IconData; | |
63 struct _IconData | |
64 { | |
65 FileData fd; | |
66 SelectionType selected; | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
67 gint row; |
9 | 68 }; |
69 | |
70 | |
71 static gint iconlist_read(const gchar *path, GList **list) | |
72 { | |
73 GList *temp; | |
74 GList *work; | |
75 | |
76 if (!filelist_read(path, &temp, NULL)) return FALSE; | |
77 | |
78 work = temp; | |
79 while (work) | |
80 { | |
81 FileData *fd; | |
82 IconData *id; | |
83 | |
84 fd = work->data; | |
85 id = g_new0(IconData, 1); | |
86 | |
87 memcpy(id, fd, sizeof(FileData)); | |
88 id->selected = SELECTION_NONE; | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
89 id->row = -1; |
9 | 90 |
91 work->data = id; | |
92 g_free(fd); | |
93 | |
94 work = work->next; | |
95 } | |
96 | |
97 *list = temp; | |
98 | |
99 return TRUE; | |
100 } | |
101 | |
102 static void iconlist_free(GList *list) | |
103 { | |
104 filelist_free(list); | |
105 } | |
106 | |
107 | |
108 static void vficon_toggle_filenames(ViewFileIcon *vfi); | |
109 static void vficon_selection_remove(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter); | |
110 static void vficon_move_focus(ViewFileIcon *vfi, gint row, gint col, gint relative); | |
111 static void vficon_set_focus(ViewFileIcon *vfi, FileData *fd); | |
112 static void vficon_thumb_update(ViewFileIcon *vfi); | |
113 static void vficon_populate_at_new_size(ViewFileIcon *vfi, gint w, gint h, gint force); | |
114 | |
115 | |
116 /* | |
117 *----------------------------------------------------------------------------- | |
118 * pop-up menu | |
119 *----------------------------------------------------------------------------- | |
120 */ | |
121 | |
122 static GList *vficon_pop_menu_file_list(ViewFileIcon *vfi) | |
123 { | |
124 if (!vfi->click_fd) return NULL; | |
125 | |
126 if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) | |
127 { | |
128 return vficon_selection_get_list(vfi); | |
129 } | |
130 | |
131 return g_list_append(NULL, g_strdup(vfi->click_fd->path)); | |
132 } | |
133 | |
134 static void vficon_pop_menu_edit_cb(GtkWidget *widget, gpointer data) | |
135 { | |
136 ViewFileIcon *vfi; | |
137 gint n; | |
138 GList *list; | |
139 | |
140 vfi = submenu_item_get_data(widget); | |
141 n = GPOINTER_TO_INT(data); | |
142 | |
143 if (!vfi) return; | |
144 | |
145 list = vficon_pop_menu_file_list(vfi); | |
146 start_editor_from_path_list(n, list); | |
147 path_list_free(list); | |
148 } | |
149 | |
150 static void vficon_pop_menu_info_cb(GtkWidget *widget, gpointer data) | |
151 { | |
152 ViewFileIcon *vfi = data; | |
153 | |
154 info_window_new(NULL, vficon_pop_menu_file_list(vfi)); | |
155 } | |
156 | |
157 static void vficon_pop_menu_view_cb(GtkWidget *widget, gpointer data) | |
158 { | |
159 ViewFileIcon *vfi = data; | |
160 | |
161 if (!vfi->click_fd) return; | |
162 | |
163 if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) | |
164 { | |
165 GList *list; | |
166 | |
167 list = vficon_selection_get_list(vfi); | |
168 view_window_new_from_list(list); | |
169 path_list_free(list); | |
170 } | |
171 else | |
172 { | |
173 view_window_new(vfi->click_fd->path); | |
174 } | |
175 } | |
176 | |
177 static void vficon_pop_menu_copy_cb(GtkWidget *widget, gpointer data) | |
178 { | |
179 ViewFileIcon *vfi = data; | |
180 | |
181 file_util_copy(NULL, vficon_pop_menu_file_list(vfi), NULL, vfi->listview); | |
182 } | |
183 | |
184 static void vficon_pop_menu_move_cb(GtkWidget *widget, gpointer data) | |
185 { | |
186 ViewFileIcon *vfi = data; | |
187 | |
188 file_util_move(NULL, vficon_pop_menu_file_list(vfi), NULL, vfi->listview); | |
189 } | |
190 | |
191 static void vficon_pop_menu_rename_cb(GtkWidget *widget, gpointer data) | |
192 { | |
193 ViewFileIcon *vfi = data; | |
194 | |
195 file_util_rename(NULL, vficon_pop_menu_file_list(vfi), vfi->listview); | |
196 } | |
197 | |
198 static void vficon_pop_menu_delete_cb(GtkWidget *widget, gpointer data) | |
199 { | |
200 ViewFileIcon *vfi = data; | |
201 | |
202 file_util_delete(NULL, vficon_pop_menu_file_list(vfi), vfi->listview); | |
203 } | |
204 | |
205 static void vficon_pop_menu_sort_cb(GtkWidget *widget, gpointer data) | |
206 { | |
207 ViewFileIcon *vfi; | |
208 SortType type; | |
209 | |
210 vfi = submenu_item_get_data(widget); | |
211 if (!vfi) return; | |
212 | |
213 type = (SortType)GPOINTER_TO_INT(data); | |
214 | |
215 if (vfi->layout) | |
216 { | |
217 layout_sort_set(vfi->layout, type, vfi->sort_ascend); | |
218 } | |
219 else | |
220 { | |
221 vficon_sort_set(vfi, type, vfi->sort_ascend); | |
222 } | |
223 } | |
224 | |
225 static void vficon_pop_menu_sort_ascend_cb(GtkWidget *widget, gpointer data) | |
226 { | |
227 ViewFileIcon *vfi = data; | |
228 | |
229 if (vfi->layout) | |
230 { | |
231 layout_sort_set(vfi->layout, vfi->sort_method, !vfi->sort_ascend); | |
232 } | |
233 else | |
234 { | |
235 vficon_sort_set(vfi, vfi->sort_method, !vfi->sort_ascend); | |
236 } | |
237 } | |
238 | |
239 static void vficon_pop_menu_list_cb(GtkWidget *widget, gpointer data) | |
240 { | |
241 ViewFileIcon *vfi = data; | |
242 | |
243 if (vfi->layout) layout_views_set(vfi->layout, vfi->layout->tree_view, FALSE); | |
244 } | |
245 | |
246 static void vficon_pop_menu_show_names_cb(GtkWidget *widget, gpointer data) | |
247 { | |
248 ViewFileIcon *vfi = data; | |
249 | |
250 vficon_toggle_filenames(vfi); | |
251 } | |
252 | |
253 static void vficon_pop_menu_refresh_cb(GtkWidget *widget, gpointer data) | |
254 { | |
255 ViewFileIcon *vfi = data; | |
256 | |
257 vficon_refresh(vfi); | |
258 } | |
259 | |
260 static void vficon_popup_destroy_cb(GtkWidget *widget, gpointer data) | |
261 { | |
262 ViewFileIcon *vfi = data; | |
263 vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL); | |
264 vfi->click_fd = NULL; | |
265 vfi->popup = NULL; | |
266 } | |
267 | |
268 static GtkWidget *vficon_pop_menu(ViewFileIcon *vfi, gint active) | |
269 { | |
270 GtkWidget *menu; | |
271 GtkWidget *item; | |
272 GtkWidget *submenu; | |
273 | |
274 menu = popup_menu_short_lived(); | |
275 | |
276 g_signal_connect(G_OBJECT(menu), "destroy", | |
277 G_CALLBACK(vficon_popup_destroy_cb), vfi); | |
278 | |
279 submenu_add_edit(menu, &item, G_CALLBACK(vficon_pop_menu_edit_cb), vfi); | |
280 gtk_widget_set_sensitive(item, active); | |
281 | |
282 item = menu_item_add_stock(menu, _("_Properties"), GTK_STOCK_PROPERTIES, G_CALLBACK(vficon_pop_menu_info_cb), vfi); | |
283 gtk_widget_set_sensitive(item, active); | |
284 | |
285 item = menu_item_add_stock(menu, _("View in _new window"), GTK_STOCK_NEW, G_CALLBACK(vficon_pop_menu_view_cb), vfi); | |
286 gtk_widget_set_sensitive(item, active); | |
287 | |
288 menu_item_add_divider(menu); | |
289 item = menu_item_add_stock(menu, _("_Copy..."), GTK_STOCK_COPY, G_CALLBACK(vficon_pop_menu_copy_cb), vfi); | |
290 gtk_widget_set_sensitive(item, active); | |
291 item = menu_item_add(menu, _("_Move..."), G_CALLBACK(vficon_pop_menu_move_cb), vfi); | |
292 gtk_widget_set_sensitive(item, active); | |
293 item = menu_item_add(menu, _("_Rename..."), G_CALLBACK(vficon_pop_menu_rename_cb), vfi); | |
294 gtk_widget_set_sensitive(item, active); | |
295 item = menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(vficon_pop_menu_delete_cb), vfi); | |
296 gtk_widget_set_sensitive(item, active); | |
297 | |
298 menu_item_add_divider(menu); | |
299 | |
300 submenu = submenu_add_sort(NULL, G_CALLBACK(vficon_pop_menu_sort_cb), vfi, | |
301 FALSE, FALSE, TRUE, vfi->sort_method); | |
302 menu_item_add_divider(submenu); | |
303 menu_item_add_check(submenu, _("Ascending"), vfi->sort_ascend, | |
304 G_CALLBACK(vficon_pop_menu_sort_ascend_cb), vfi); | |
305 | |
306 item = menu_item_add(menu, _("_Sort"), NULL, NULL); | |
307 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); | |
308 | |
309 menu_item_add_check(menu, _("View as _icons"), TRUE, | |
310 G_CALLBACK(vficon_pop_menu_list_cb), vfi); | |
311 menu_item_add_check(menu, _("Show filename _text"), vfi->show_text, | |
312 G_CALLBACK(vficon_pop_menu_show_names_cb), vfi); | |
313 menu_item_add_stock(menu, _("Re_fresh"), GTK_STOCK_REFRESH, G_CALLBACK(vficon_pop_menu_refresh_cb), vfi); | |
314 | |
315 return menu; | |
316 } | |
317 | |
318 /* | |
319 *------------------------------------------------------------------- | |
320 * signals | |
321 *------------------------------------------------------------------- | |
322 */ | |
323 | |
324 static void vficon_send_update(ViewFileIcon *vfi) | |
325 { | |
326 if (vfi->func_status) vfi->func_status(vfi, vfi->data_status); | |
327 } | |
328 | |
329 static void vficon_send_layout_select(ViewFileIcon *vfi, FileData *fd) | |
330 { | |
331 const gchar *read_ahead_path = NULL; | |
332 | |
333 if (!vfi->layout || !fd) return; | |
334 | |
335 if (enable_read_ahead) | |
336 { | |
337 FileData *fd_n; | |
338 gint row; | |
339 | |
340 row = g_list_index(vfi->list, fd); | |
341 if (row > vficon_index_by_path(vfi, layout_image_get_path(vfi->layout)) && | |
342 row + 1 < vficon_count(vfi, NULL)) | |
343 { | |
344 fd_n = vficon_index_get_data(vfi, row + 1); | |
345 } | |
346 else if (row > 0) | |
347 { | |
348 fd_n = vficon_index_get_data(vfi, row - 1); | |
349 } | |
350 else | |
351 { | |
352 fd_n = NULL; | |
353 } | |
354 if (fd_n) read_ahead_path = fd_n->path; | |
355 } | |
356 | |
357 layout_image_set_with_ahead(vfi->layout, fd->path, read_ahead_path); | |
358 } | |
359 | |
360 static void vficon_toggle_filenames(ViewFileIcon *vfi) | |
361 { | |
362 vfi->show_text = !vfi->show_text; | |
363 show_icon_names = vfi->show_text; | |
364 | |
365 vficon_populate_at_new_size(vfi, vfi->listview->allocation.width, vfi->listview->allocation.height, TRUE); | |
366 } | |
367 | |
368 static gint vficon_get_icon_width(ViewFileIcon *vfi) | |
369 { | |
370 gint width; | |
371 | |
372 if (!vfi->show_text) return thumb_max_width; | |
373 | |
374 width = thumb_max_width + thumb_max_width / 2; | |
375 if (width < THUMB_MIN_ICON_WIDTH) width = THUMB_MIN_ICON_WIDTH; | |
376 if (width > THUMB_MAX_ICON_WIDTH) width = thumb_max_width; | |
377 | |
378 return width; | |
379 } | |
380 | |
381 /* | |
382 *------------------------------------------------------------------- | |
383 * misc utils | |
384 *------------------------------------------------------------------- | |
385 */ | |
386 | |
387 static gint vficon_find_position(ViewFileIcon *vfi, FileData *fd, gint *row, gint *col) | |
388 { | |
389 gint n; | |
390 | |
391 n = g_list_index(vfi->list, fd); | |
392 | |
393 if (n < 0) return FALSE; | |
394 | |
395 *row = n / vfi->columns; | |
396 *col = n - (*row * vfi->columns); | |
397 | |
398 return TRUE; | |
399 } | |
400 | |
401 static gint vficon_find_iter(ViewFileIcon *vfi, FileData *fd, GtkTreeIter *iter, gint *column) | |
402 { | |
403 GtkTreeModel *store; | |
404 gint row, col; | |
405 | |
406 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
407 if (!vficon_find_position(vfi, fd, &row, &col)) return FALSE; | |
408 if (!gtk_tree_model_iter_nth_child(store, iter, NULL, row)) return FALSE; | |
409 if (column) *column = col; | |
410 | |
411 return TRUE; | |
412 } | |
413 | |
414 static FileData *vficon_find_data(ViewFileIcon *vfi, gint row, gint col, GtkTreeIter *iter) | |
415 { | |
416 GtkTreeModel *store; | |
417 GtkTreeIter p; | |
418 | |
419 if (row < 0 || col < 0) return NULL; | |
420 | |
421 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
422 if (gtk_tree_model_iter_nth_child(store, &p, NULL, row)) | |
423 { | |
424 GList *list; | |
425 | |
426 gtk_tree_model_get(store, &p, FILE_COLUMN_POINTER, &list, -1); | |
427 if (!list) return NULL; | |
428 | |
429 if (iter) *iter = p; | |
430 | |
431 return g_list_nth_data(list, col); | |
432 } | |
433 | |
434 return NULL; | |
435 } | |
436 | |
437 static FileData *vficon_find_data_by_coord(ViewFileIcon *vfi, gint x, gint y, GtkTreeIter *iter) | |
438 { | |
439 GtkTreePath *tpath; | |
440 GtkTreeViewColumn *column; | |
441 | |
442 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfi->listview), x, y, | |
443 &tpath, &column, NULL, NULL)) | |
444 { | |
445 GtkTreeModel *store; | |
446 GtkTreeIter row; | |
447 GList *list; | |
448 gint n; | |
449 | |
450 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
451 gtk_tree_model_get_iter(store, &row, tpath); | |
452 gtk_tree_path_free(tpath); | |
453 | |
454 gtk_tree_model_get(store, &row, FILE_COLUMN_POINTER, &list, -1); | |
455 | |
456 n = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(column), "column_number")); | |
457 if (list) | |
458 { | |
459 if (iter) *iter = row; | |
460 return g_list_nth_data(list, n); | |
461 } | |
462 } | |
463 | |
464 return NULL; | |
465 } | |
466 | |
467 /* | |
468 *------------------------------------------------------------------- | |
469 * tooltip type window | |
470 *------------------------------------------------------------------- | |
471 */ | |
472 | |
473 static void tip_show(ViewFileIcon *vfi) | |
474 { | |
475 GtkWidget *label; | |
476 gint x, y; | |
477 | |
478 if (vfi->tip_window) return; | |
479 | |
480 gdk_window_get_pointer(gtk_tree_view_get_bin_window(GTK_TREE_VIEW(vfi->listview)), &x, &y, NULL); | |
481 | |
482 vfi->tip_fd = vficon_find_data_by_coord(vfi, x, y, NULL); | |
483 if (!vfi->tip_fd) return; | |
484 | |
485 vfi->tip_window = gtk_window_new(GTK_WINDOW_POPUP); | |
486 gtk_window_set_resizable(GTK_WINDOW(vfi->tip_window), FALSE); | |
487 gtk_container_set_border_width(GTK_CONTAINER(vfi->tip_window), 2); | |
488 | |
489 label = gtk_label_new(vfi->tip_fd->name); | |
490 | |
491 g_object_set_data(G_OBJECT(vfi->tip_window), "tip_label", label); | |
492 gtk_container_add(GTK_CONTAINER(vfi->tip_window), label); | |
493 gtk_widget_show(label); | |
494 | |
495 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
496 | |
497 if (!GTK_WIDGET_REALIZED(vfi->tip_window)) gtk_widget_realize(vfi->tip_window); | |
498 gtk_window_move(GTK_WINDOW(vfi->tip_window), x + 16, y + 16); | |
499 gtk_widget_show(vfi->tip_window); | |
500 } | |
501 | |
502 static void tip_hide(ViewFileIcon *vfi) | |
503 { | |
504 if (vfi->tip_window) gtk_widget_destroy(vfi->tip_window); | |
505 vfi->tip_window = NULL; | |
506 } | |
507 | |
508 static gint tip_schedule_cb(gpointer data) | |
509 { | |
510 ViewFileIcon *vfi = data; | |
511 GtkWidget *window; | |
512 | |
513 if (vfi->tip_delay_id == -1) return FALSE; | |
514 | |
515 window = gtk_widget_get_toplevel(vfi->listview); | |
516 | |
517 if (GTK_WIDGET_SENSITIVE(window) && | |
518 GTK_WINDOW(window)->has_focus) | |
519 { | |
520 tip_show(vfi); | |
521 } | |
522 | |
523 vfi->tip_delay_id = -1; | |
524 return FALSE; | |
525 } | |
526 | |
527 static void tip_schedule(ViewFileIcon *vfi) | |
528 { | |
529 tip_hide(vfi); | |
530 | |
531 if (vfi->tip_delay_id != -1) | |
532 { | |
533 g_source_remove(vfi->tip_delay_id); | |
534 vfi->tip_delay_id = -1; | |
535 } | |
536 | |
537 if (!vfi->show_text) | |
538 { | |
539 vfi->tip_delay_id = g_timeout_add(VFICON_TIP_DELAY, tip_schedule_cb, vfi); | |
540 } | |
541 } | |
542 | |
543 static void tip_unschedule(ViewFileIcon *vfi) | |
544 { | |
545 tip_hide(vfi); | |
546 | |
547 if (vfi->tip_delay_id != -1) g_source_remove(vfi->tip_delay_id); | |
548 vfi->tip_delay_id = -1; | |
549 } | |
550 | |
551 static void tip_update(ViewFileIcon *vfi, FileData *fd) | |
552 { | |
553 if (vfi->tip_window) | |
554 { | |
555 gint x, y; | |
556 | |
557 gdk_window_get_pointer(NULL, &x, &y, NULL); | |
558 gtk_window_move(GTK_WINDOW(vfi->tip_window), x + 16, y + 16); | |
559 | |
560 if (fd != vfi->tip_fd) | |
561 { | |
562 GtkWidget *label; | |
563 | |
564 vfi->tip_fd = fd; | |
565 | |
566 if (!vfi->tip_fd) | |
567 { | |
568 tip_hide(vfi); | |
569 tip_schedule(vfi); | |
570 return; | |
571 } | |
572 | |
573 label = g_object_get_data(G_OBJECT(vfi->tip_window), "tip_label"); | |
574 gtk_label_set_text(GTK_LABEL(label), vfi->tip_fd->name); | |
575 } | |
576 } | |
577 else | |
578 { | |
579 tip_schedule(vfi); | |
580 } | |
581 } | |
582 | |
583 /* | |
584 *------------------------------------------------------------------- | |
585 * dnd | |
586 *------------------------------------------------------------------- | |
587 */ | |
588 | |
589 static void vficon_dnd_get(GtkWidget *widget, GdkDragContext *context, | |
590 GtkSelectionData *selection_data, guint info, | |
591 guint time, gpointer data) | |
592 { | |
593 ViewFileIcon *vfi = data; | |
594 GList *list = NULL; | |
595 gchar *uri_text = NULL; | |
596 gint total; | |
597 | |
598 if (!vfi->click_fd) return; | |
599 | |
600 if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) | |
601 { | |
602 list = vficon_selection_get_list(vfi); | |
603 } | |
604 else | |
605 { | |
606 const gchar *path = vfi->click_fd->path; | |
607 | |
608 list = g_list_append(NULL, g_strdup(path)); | |
609 } | |
610 | |
611 if (!list) return; | |
612 uri_text = uri_text_from_list(list, &total, (info == TARGET_TEXT_PLAIN)); | |
613 path_list_free(list); | |
614 | |
615 if (debug) printf(uri_text); | |
616 | |
617 gtk_selection_data_set(selection_data, selection_data->target, | |
64
04ff0df3ad2f
Mon Aug 15 17:13:57 2005 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
618 8, (guchar *)uri_text, total); |
9 | 619 g_free(uri_text); |
620 } | |
621 | |
622 static void vficon_dnd_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
623 { | |
624 ViewFileIcon *vfi = data; | |
625 | |
626 tip_unschedule(vfi); | |
627 | |
628 if (vfi->click_fd && vfi->click_fd->pixbuf) | |
629 { | |
630 gint items; | |
631 | |
632 if (ICON_DATA(vfi->click_fd)->selected & SELECTION_SELECTED) | |
633 items = g_list_length(vfi->selection); | |
634 else | |
635 items = 1; | |
636 | |
637 dnd_set_drag_icon(widget, context, vfi->click_fd->pixbuf, items); | |
638 } | |
639 } | |
640 | |
641 static void vficon_dnd_end(GtkWidget *widget, GdkDragContext *context, gpointer data) | |
642 { | |
643 ViewFileIcon *vfi = data; | |
644 | |
645 vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL); | |
646 | |
647 if (context->action == GDK_ACTION_MOVE) | |
648 { | |
649 vficon_refresh(vfi); | |
650 } | |
651 | |
652 tip_unschedule(vfi); | |
653 } | |
654 | |
655 static void vficon_dnd_init(ViewFileIcon *vfi) | |
656 { | |
657 gtk_drag_source_set(vfi->listview, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK, | |
658 dnd_file_drag_types, dnd_file_drag_types_count, | |
659 GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK); | |
660 g_signal_connect(G_OBJECT(vfi->listview), "drag_data_get", | |
661 G_CALLBACK(vficon_dnd_get), vfi); | |
662 g_signal_connect(G_OBJECT(vfi->listview), "drag_begin", | |
663 G_CALLBACK(vficon_dnd_begin), vfi); | |
664 g_signal_connect(G_OBJECT(vfi->listview), "drag_end", | |
665 G_CALLBACK(vficon_dnd_end), vfi); | |
666 } | |
667 | |
668 /* | |
669 *------------------------------------------------------------------- | |
670 * cell updates | |
671 *------------------------------------------------------------------- | |
672 */ | |
673 | |
674 static void vficon_selection_set(ViewFileIcon *vfi, FileData *fd, SelectionType value, GtkTreeIter *iter) | |
675 { | |
676 IconData *id; | |
677 GtkTreeModel *store; | |
678 GList *list; | |
679 | |
680 if (!fd) return; | |
681 | |
682 id = ICON_DATA(fd); | |
683 | |
684 if (id->selected == value) return; | |
685 id->selected = value; | |
686 | |
687 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
688 if (iter) | |
689 { | |
690 gtk_tree_model_get(store, iter, FILE_COLUMN_POINTER, &list, -1); | |
691 if (list) gtk_list_store_set(GTK_LIST_STORE(store), iter, FILE_COLUMN_POINTER, list, -1); | |
692 } | |
693 else | |
694 { | |
695 GtkTreeIter row; | |
696 | |
697 if (vficon_find_iter(vfi, fd, &row, NULL)) | |
698 { | |
699 gtk_tree_model_get(store, &row, FILE_COLUMN_POINTER, &list, -1); | |
700 if (list) gtk_list_store_set(GTK_LIST_STORE(store), &row, FILE_COLUMN_POINTER, list, -1); | |
701 } | |
702 } | |
703 } | |
704 | |
705 static void vficon_selection_add(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter) | |
706 { | |
707 if (!fd) return; | |
708 | |
709 vficon_selection_set(vfi, fd, ICON_DATA(fd)->selected | mask, iter); | |
710 } | |
711 | |
712 static void vficon_selection_remove(ViewFileIcon *vfi, FileData *fd, SelectionType mask, GtkTreeIter *iter) | |
713 { | |
714 if (!fd) return; | |
715 | |
716 vficon_selection_set(vfi, fd, ICON_DATA(fd)->selected & ~mask, iter); | |
717 } | |
718 | |
719 /* | |
720 *------------------------------------------------------------------- | |
721 * selections | |
722 *------------------------------------------------------------------- | |
723 */ | |
724 | |
725 static void vficon_verify_selections(ViewFileIcon *vfi) | |
726 { | |
727 GList *work; | |
728 | |
729 work = vfi->selection; | |
730 while (work) | |
731 { | |
732 FileData *fd = work->data; | |
733 work = work->next; | |
734 if (!g_list_find(vfi->list, fd)) | |
735 { | |
736 vfi->selection = g_list_remove(vfi->selection, fd); | |
737 } | |
738 } | |
739 } | |
740 | |
741 void vficon_select_all(ViewFileIcon *vfi) | |
742 { | |
743 GList *work; | |
744 | |
745 g_list_free(vfi->selection); | |
746 vfi->selection = NULL; | |
747 | |
748 work = vfi->list; | |
749 while (work) | |
750 { | |
751 vfi->selection = g_list_append(vfi->selection, work->data); | |
752 vficon_selection_add(vfi, work->data, SELECTION_SELECTED, NULL); | |
753 work = work->next; | |
754 } | |
755 | |
756 vficon_send_update(vfi); | |
757 } | |
758 | |
759 void vficon_select_none(ViewFileIcon *vfi) | |
760 { | |
761 GList *work; | |
762 | |
763 work = vfi->selection; | |
764 while (work) | |
765 { | |
766 vficon_selection_remove(vfi, work->data, SELECTION_SELECTED, NULL); | |
767 work = work->next; | |
768 } | |
769 | |
770 g_list_free(vfi->selection); | |
771 vfi->selection = NULL; | |
772 | |
773 vficon_send_update(vfi); | |
774 } | |
775 | |
776 static void vficon_select(ViewFileIcon *vfi, FileData *fd) | |
777 { | |
778 vfi->prev_selection = fd; | |
779 | |
780 if (!fd || ICON_DATA(fd)->selected & SELECTION_SELECTED) return; | |
781 | |
782 vfi->selection = g_list_append(vfi->selection, fd); | |
783 vficon_selection_add(vfi, fd, SELECTION_SELECTED, NULL); | |
784 | |
785 vficon_send_update(vfi); | |
786 } | |
787 | |
788 static void vficon_unselect(ViewFileIcon *vfi, FileData *fd) | |
789 { | |
790 vfi->prev_selection = fd; | |
791 | |
792 if (!fd || !(ICON_DATA(fd)->selected & SELECTION_SELECTED) ) return; | |
793 | |
794 vfi->selection = g_list_remove(vfi->selection, fd); | |
795 vficon_selection_remove(vfi, fd, SELECTION_SELECTED, NULL); | |
796 | |
797 vficon_send_update(vfi); | |
798 } | |
799 | |
800 static void vficon_select_util(ViewFileIcon *vfi, FileData *fd, gint select) | |
801 { | |
802 if (select) | |
803 { | |
804 vficon_select(vfi, fd); | |
805 } | |
806 else | |
807 { | |
808 vficon_unselect(vfi, fd); | |
809 } | |
810 } | |
811 | |
812 static void vficon_select_region_util(ViewFileIcon *vfi, FileData *start, FileData *end, gint select) | |
813 { | |
814 gint row1, col1; | |
815 gint row2, col2; | |
816 gint t; | |
817 gint i, j; | |
818 | |
819 if (!vficon_find_position(vfi, start, &row1, &col1) || | |
820 !vficon_find_position(vfi, end, &row2, &col2) ) return; | |
821 | |
822 vfi->prev_selection = end; | |
823 | |
824 if (!collection_rectangular_selection) | |
825 { | |
826 GList *work; | |
827 FileData *fd; | |
828 | |
829 if (g_list_index(vfi->list, start) > g_list_index(vfi->list, end)) | |
830 { | |
831 fd = start; | |
832 start = end; | |
833 end = fd; | |
834 } | |
835 | |
836 work = g_list_find(vfi->list, start); | |
837 while (work) | |
838 { | |
839 fd = work->data; | |
840 vficon_select_util(vfi, fd, select); | |
841 | |
842 if (work->data != end) | |
843 work = work->next; | |
844 else | |
845 work = NULL; | |
846 } | |
847 return; | |
848 } | |
849 | |
850 if (row2 < row1) | |
851 { | |
852 t = row1; | |
853 row1 = row2; | |
854 row2 = t; | |
855 } | |
856 if (col2 < col1) | |
857 { | |
858 t = col1; | |
859 col1 = col2; | |
860 col2 = t; | |
861 } | |
862 | |
863 if (debug) printf("table: %d x %d to %d x %d\n", row1, col1, row2, col2); | |
864 | |
865 for (i = row1; i <= row2; i++) | |
866 { | |
867 for (j = col1; j <= col2; j++) | |
868 { | |
869 FileData *fd = vficon_find_data(vfi, i, j, NULL); | |
870 if (fd) vficon_select_util(vfi, fd, select); | |
871 } | |
872 } | |
873 } | |
874 | |
875 gint vficon_index_is_selected(ViewFileIcon *vfi, gint row) | |
876 { | |
877 FileData *fd = g_list_nth_data(vfi->list, row); | |
878 | |
879 if (!fd) return FALSE; | |
880 | |
881 return (ICON_DATA(fd)->selected & SELECTION_SELECTED); | |
882 } | |
883 | |
884 gint vficon_selection_count(ViewFileIcon *vfi, gint64 *bytes) | |
885 { | |
886 if (bytes) | |
887 { | |
888 gint64 b = 0; | |
889 GList *work; | |
890 | |
891 work = vfi->selection; | |
892 while (work) | |
893 { | |
894 FileData *fd = work->data; | |
895 b += fd->size; | |
896 | |
897 work = work->next; | |
898 } | |
899 | |
900 *bytes = b; | |
901 } | |
902 | |
903 return g_list_length(vfi->selection); | |
904 } | |
905 | |
906 GList *vficon_selection_get_list(ViewFileIcon *vfi) | |
907 { | |
908 GList *list = NULL; | |
909 GList *work; | |
910 | |
911 work = vfi->selection; | |
912 while (work) | |
913 { | |
914 FileData *fd = work->data; | |
915 | |
916 list = g_list_prepend(list, g_strdup(fd->path)); | |
917 | |
918 work = work->next; | |
919 } | |
920 | |
921 list = g_list_reverse(list); | |
922 | |
923 return list; | |
924 } | |
925 | |
926 GList *vficon_selection_get_list_by_index(ViewFileIcon *vfi) | |
927 { | |
928 GList *list = NULL; | |
929 GList *work; | |
930 | |
931 work = vfi->selection; | |
932 while (work) | |
933 { | |
934 list = g_list_prepend(list, GINT_TO_POINTER(g_list_index(vfi->list, work->data))); | |
935 work = work->next; | |
936 } | |
937 | |
938 return g_list_reverse(list); | |
939 } | |
940 | |
941 void vficon_select_by_path(ViewFileIcon *vfi, const gchar *path) | |
942 { | |
943 FileData *fd; | |
944 GList *work; | |
945 | |
946 if (!path) return; | |
947 | |
948 fd = NULL; | |
949 work = vfi->list; | |
950 while (work && !fd) | |
951 { | |
952 FileData *chk = work->data; | |
953 work = work->next; | |
954 if (strcmp(chk->path, path) == 0) fd = chk; | |
955 } | |
956 | |
957 if (!fd) return; | |
958 | |
959 if (!(ICON_DATA(fd)->selected & SELECTION_SELECTED)) | |
960 { | |
961 vficon_select_none(vfi); | |
962 vficon_select(vfi, fd); | |
963 } | |
964 | |
965 vficon_set_focus(vfi, fd); | |
966 } | |
967 | |
968 /* | |
969 *------------------------------------------------------------------- | |
970 * focus | |
971 *------------------------------------------------------------------- | |
972 */ | |
973 | |
974 static void vficon_move_focus(ViewFileIcon *vfi, gint row, gint col, gint relative) | |
975 { | |
976 gint new_row; | |
977 gint new_col; | |
978 | |
979 if (relative) | |
980 { | |
981 new_row = vfi->focus_row; | |
982 new_col = vfi->focus_column; | |
983 | |
984 new_row += row; | |
985 if (new_row < 0) new_row = 0; | |
986 if (new_row >= vfi->rows) new_row = vfi->rows - 1; | |
987 | |
988 while(col != 0) | |
989 { | |
990 if (col < 0) | |
991 { | |
992 new_col--; | |
993 col++; | |
994 } | |
995 else | |
996 { | |
997 new_col++; | |
998 col--; | |
999 } | |
1000 | |
1001 if (new_col < 0) | |
1002 { | |
1003 if (new_row > 0) | |
1004 { | |
1005 new_row--; | |
1006 new_col = vfi->columns - 1; | |
1007 } | |
1008 else | |
1009 { | |
1010 new_col = 0; | |
1011 } | |
1012 } | |
1013 if (new_col >= vfi->columns) | |
1014 { | |
1015 if (new_row < vfi->rows - 1) | |
1016 { | |
1017 new_row++; | |
1018 new_col = 0; | |
1019 } | |
1020 else | |
1021 { | |
1022 new_col = vfi->columns - 1; | |
1023 } | |
1024 } | |
1025 } | |
1026 } | |
1027 else | |
1028 { | |
1029 new_row = row; | |
1030 new_col = col; | |
1031 | |
1032 if (new_row >= vfi->rows) | |
1033 { | |
1034 if (vfi->rows > 0) | |
1035 new_row = vfi->rows - 1; | |
1036 else | |
1037 new_row = 0; | |
1038 new_col = vfi->columns - 1; | |
1039 } | |
1040 if (new_col >= vfi->columns) new_col = vfi->columns - 1; | |
1041 } | |
1042 | |
1043 if (new_row == vfi->rows - 1) | |
1044 { | |
1045 gint l; | |
1046 | |
1047 /* if we moved beyond the last image, go to the last image */ | |
1048 | |
1049 l = g_list_length(vfi->list); | |
1050 if (vfi->rows > 1) l -= (vfi->rows - 1) * vfi->columns; | |
1051 if (new_col >= l) new_col = l - 1; | |
1052 } | |
1053 | |
1054 vficon_set_focus(vfi, vficon_find_data(vfi, new_row, new_col, NULL)); | |
1055 } | |
1056 | |
1057 static void vficon_set_focus(ViewFileIcon *vfi, FileData *fd) | |
1058 { | |
1059 GtkTreeIter iter; | |
1060 gint row, col; | |
1061 | |
1062 if (g_list_find(vfi->list, vfi->focus_fd)) | |
1063 { | |
1064 if (fd == vfi->focus_fd) | |
1065 { | |
1066 /* ensure focus row col are correct */ | |
1067 vficon_find_position(vfi, vfi->focus_fd, &vfi->focus_row, &vfi->focus_column); | |
1068 return; | |
1069 } | |
1070 vficon_selection_remove(vfi, vfi->focus_fd, SELECTION_FOCUS, NULL); | |
1071 } | |
1072 | |
1073 if (!vficon_find_position(vfi, fd, &row, &col)) | |
1074 { | |
1075 vfi->focus_fd = NULL; | |
1076 vfi->focus_row = -1; | |
1077 vfi->focus_column = -1; | |
1078 return; | |
1079 } | |
1080 | |
1081 vfi->focus_fd = fd; | |
1082 vfi->focus_row = row; | |
1083 vfi->focus_column = col; | |
1084 vficon_selection_add(vfi, vfi->focus_fd, SELECTION_FOCUS, NULL); | |
1085 | |
1086 if (vficon_find_iter(vfi, vfi->focus_fd, &iter, NULL)) | |
1087 { | |
1088 GtkTreePath *tpath; | |
1089 GtkTreeViewColumn *column; | |
1090 GtkTreeModel *store; | |
1091 | |
1092 tree_view_row_make_visible(GTK_TREE_VIEW(vfi->listview), &iter, FALSE); | |
1093 | |
1094 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1095 tpath = gtk_tree_model_get_path(store, &iter); | |
1096 /* focus is set to an extra column with 0 width to hide focus, we draw it ourself */ | |
1097 column = gtk_tree_view_get_column(GTK_TREE_VIEW(vfi->listview), VFICON_MAX_COLUMNS); | |
1098 gtk_tree_view_set_cursor(GTK_TREE_VIEW(vfi->listview), tpath, column, FALSE); | |
1099 gtk_tree_path_free(tpath); | |
1100 } | |
1101 } | |
1102 | |
1103 static void vficon_update_focus(ViewFileIcon *vfi) | |
1104 { | |
1105 gint new_row = 0; | |
1106 gint new_col = 0; | |
1107 | |
1108 if (vfi->focus_fd && vficon_find_position(vfi, vfi->focus_fd, &new_row, &new_col)) | |
1109 { | |
1110 /* first find the old focus, if it exists and is valid */ | |
1111 } | |
1112 else | |
1113 { | |
1114 /* (try to) stay where we were */ | |
1115 new_row = vfi->focus_row; | |
1116 new_col = vfi->focus_column; | |
1117 } | |
1118 | |
1119 vficon_move_focus(vfi, new_row, new_col, FALSE); | |
1120 } | |
1121 | |
1122 /* used to figure the page up/down distances */ | |
1123 static gint page_height(ViewFileIcon *vfi) | |
1124 { | |
1125 GtkAdjustment *adj; | |
1126 gint page_size; | |
1127 gint row_height; | |
1128 gint ret; | |
1129 | |
1130 adj = gtk_tree_view_get_vadjustment(GTK_TREE_VIEW(vfi->listview)); | |
1131 page_size = (gint)adj->page_increment; | |
1132 | |
1133 row_height = thumb_max_height + THUMB_BORDER_PADDING * 2; | |
1134 if (vfi->show_text) row_height += thumb_max_height / 3; | |
1135 | |
1136 ret = page_size / row_height; | |
1137 if (ret < 1) ret = 1; | |
1138 | |
1139 return ret; | |
1140 } | |
1141 | |
1142 /* | |
1143 *------------------------------------------------------------------- | |
1144 * keyboard | |
1145 *------------------------------------------------------------------- | |
1146 */ | |
1147 | |
1148 static void vfi_menu_position_cb(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) | |
1149 { | |
1150 ViewFileIcon *vfi = data; | |
1151 GtkTreeModel *store; | |
1152 GtkTreeIter iter; | |
1153 gint column; | |
1154 GtkTreePath *tpath; | |
1155 gint cw, ch; | |
1156 | |
1157 if (!vficon_find_iter(vfi, vfi->click_fd, &iter, &column)) return; | |
1158 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1159 tpath = gtk_tree_model_get_path(store, &iter); | |
1160 tree_view_get_cell_clamped(GTK_TREE_VIEW(vfi->listview), tpath, column, FALSE, x, y, &cw, &ch); | |
1161 gtk_tree_path_free(tpath); | |
1162 *y += ch; | |
1163 popup_menu_position_clamp(menu, x, y, 0); | |
1164 } | |
1165 | |
1166 static gint vficon_press_key_cb(GtkWidget *widget, GdkEventKey *event, gpointer data) | |
1167 { | |
1168 ViewFileIcon *vfi = data; | |
1169 gint focus_row = 0; | |
1170 gint focus_col = 0; | |
1171 FileData *fd; | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1172 gint stop_signal; |
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1173 |
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1174 stop_signal = TRUE; |
9 | 1175 switch (event->keyval) |
1176 { | |
1177 case GDK_Left: case GDK_KP_Left: | |
1178 focus_col = -1; | |
1179 break; | |
1180 case GDK_Right: case GDK_KP_Right: | |
1181 focus_col = 1; | |
1182 break; | |
1183 case GDK_Up: case GDK_KP_Up: | |
1184 focus_row = -1; | |
1185 break; | |
1186 case GDK_Down: case GDK_KP_Down: | |
1187 focus_row = 1; | |
1188 break; | |
1189 case GDK_Page_Up: case GDK_KP_Page_Up: | |
1190 focus_row = -page_height(vfi); | |
1191 break; | |
1192 case GDK_Page_Down: case GDK_KP_Page_Down: | |
1193 focus_row = page_height(vfi); | |
1194 break; | |
1195 case GDK_Home: case GDK_KP_Home: | |
1196 focus_row = -vfi->focus_row; | |
1197 focus_col = -vfi->focus_column; | |
1198 break; | |
1199 case GDK_End: case GDK_KP_End: | |
1200 focus_row = vfi->rows - 1 - vfi->focus_row; | |
1201 focus_col = vfi->columns - 1 - vfi->focus_column; | |
1202 break; | |
1203 case GDK_space: | |
1204 fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL); | |
1205 if (fd) | |
1206 { | |
1207 vfi->click_fd = fd; | |
1208 if (event->state & GDK_CONTROL_MASK) | |
1209 { | |
1210 gint selected; | |
1211 | |
1212 selected = ICON_DATA(fd)->selected & SELECTION_SELECTED; | |
1213 if (selected) | |
1214 { | |
1215 vficon_unselect(vfi, fd); | |
1216 } | |
1217 else | |
1218 { | |
1219 vficon_select(vfi, fd); | |
1220 vficon_send_layout_select(vfi, fd); | |
1221 } | |
1222 } | |
1223 else | |
1224 { | |
1225 vficon_select_none(vfi); | |
1226 vficon_select(vfi, fd); | |
1227 vficon_send_layout_select(vfi, fd); | |
1228 } | |
1229 } | |
1230 break; | |
1231 case GDK_Menu: | |
1232 fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL); | |
1233 vfi->click_fd = fd; | |
1234 | |
1235 vficon_selection_add(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL); | |
1236 tip_unschedule(vfi); | |
1237 | |
1238 vfi->popup = vficon_pop_menu(vfi, (fd != NULL)); | |
1239 gtk_menu_popup(GTK_MENU(vfi->popup), NULL, NULL, vfi_menu_position_cb, vfi, 0, GDK_CURRENT_TIME); | |
1240 break; | |
1241 default: | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1242 stop_signal = FALSE; |
9 | 1243 break; |
1244 } | |
1245 | |
1246 if (focus_row != 0 || focus_col != 0) | |
1247 { | |
1248 FileData *new_fd; | |
1249 FileData *old_fd; | |
1250 | |
1251 old_fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL); | |
1252 vficon_move_focus(vfi, focus_row, focus_col, TRUE); | |
1253 new_fd = vficon_find_data(vfi, vfi->focus_row, vfi->focus_column, NULL); | |
1254 | |
1255 if (new_fd != old_fd) | |
1256 { | |
1257 if (event->state & GDK_SHIFT_MASK) | |
1258 { | |
1259 if (!collection_rectangular_selection) | |
1260 { | |
1261 vficon_select_region_util(vfi, old_fd, new_fd, FALSE); | |
1262 } | |
1263 else | |
1264 { | |
1265 vficon_select_region_util(vfi, vfi->click_fd, old_fd, FALSE); | |
1266 } | |
1267 vficon_select_region_util(vfi, vfi->click_fd, new_fd, TRUE); | |
1268 vficon_send_layout_select(vfi, new_fd); | |
1269 } | |
1270 else if (event->state & GDK_CONTROL_MASK) | |
1271 { | |
1272 vfi->click_fd = new_fd; | |
1273 } | |
1274 else | |
1275 { | |
1276 vfi->click_fd = new_fd; | |
1277 vficon_select_none(vfi); | |
1278 vficon_select(vfi, new_fd); | |
1279 vficon_send_layout_select(vfi, new_fd); | |
1280 } | |
1281 } | |
1282 } | |
1283 | |
1284 if (stop_signal) | |
1285 { | |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1286 #if 0 |
9 | 1287 g_signal_stop_emission_by_name(GTK_OBJECT(widget), "key_press_event"); |
85
9d5c75b5ec28
Fri Oct 20 09:20:10 2006 John Ellis <johne@verizon.net>
gqview
parents:
64
diff
changeset
|
1288 #endif |
9 | 1289 tip_unschedule(vfi); |
1290 } | |
1291 | |
1292 return stop_signal; | |
1293 } | |
1294 | |
1295 /* | |
1296 *------------------------------------------------------------------- | |
1297 * mouse | |
1298 *------------------------------------------------------------------- | |
1299 */ | |
1300 | |
1301 static gint vficon_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1302 { | |
1303 ViewFileIcon *vfi = data; | |
1304 FileData *fd; | |
1305 | |
1306 fd = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, NULL); | |
1307 tip_update(vfi, fd); | |
1308 | |
1309 return FALSE; | |
1310 } | |
1311 | |
1312 static gint vficon_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1313 { | |
1314 ViewFileIcon *vfi = data; | |
1315 GtkTreeIter iter; | |
1316 FileData *fd; | |
1317 | |
1318 tip_unschedule(vfi); | |
1319 | |
1320 fd = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, &iter); | |
1321 | |
1322 vfi->click_fd = fd; | |
1323 vficon_selection_add(vfi, vfi->click_fd, SELECTION_PRELIGHT, &iter); | |
1324 | |
1325 switch (bevent->button) | |
1326 { | |
1327 case 1: | |
1328 if (!GTK_WIDGET_HAS_FOCUS(vfi->listview)) | |
1329 { | |
1330 gtk_widget_grab_focus(vfi->listview); | |
1331 } | |
1332 #if 0 | |
1333 if (bevent->type == GDK_2BUTTON_PRESS && | |
1334 vfi->layout) | |
1335 { | |
1336 vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, &iter); | |
1337 layout_image_full_screen_start(vfi->layout); | |
1338 } | |
1339 #endif | |
1340 break; | |
1341 case 3: | |
1342 vfi->popup = vficon_pop_menu(vfi, (fd != NULL)); | |
1343 gtk_menu_popup(GTK_MENU(vfi->popup), NULL, NULL, NULL, NULL, bevent->button, bevent->time); | |
1344 break; | |
1345 default: | |
1346 break; | |
1347 } | |
1348 | |
1349 return TRUE; | |
1350 } | |
1351 | |
1352 static gint vficon_release_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data) | |
1353 { | |
1354 ViewFileIcon *vfi = data; | |
1355 GtkTreeIter iter; | |
1356 FileData *fd = NULL; | |
1357 gint was_selected = FALSE; | |
1358 | |
1359 tip_schedule(vfi); | |
1360 | |
1361 if ((gint)bevent->x != 0 || (gint) bevent->y != 0) | |
1362 { | |
1363 fd = vficon_find_data_by_coord(vfi, (gint)bevent->x, (gint)bevent->y, &iter); | |
1364 } | |
1365 | |
1366 if (vfi->click_fd) | |
1367 { | |
1368 vficon_selection_remove(vfi, vfi->click_fd, SELECTION_PRELIGHT, NULL); | |
1369 } | |
1370 | |
1371 if (fd) was_selected = (ICON_DATA(fd)->selected & SELECTION_SELECTED); | |
1372 | |
1373 if (bevent->button == 1 && | |
1374 fd && vfi->click_fd == fd) | |
1375 { | |
1376 vficon_set_focus(vfi, fd); | |
1377 | |
1378 if (bevent->state & GDK_CONTROL_MASK) | |
1379 { | |
1380 gint select; | |
1381 | |
1382 select = !(ICON_DATA(fd)->selected & SELECTION_SELECTED); | |
1383 if ((bevent->state & GDK_SHIFT_MASK) && vfi->prev_selection) | |
1384 { | |
1385 vficon_select_region_util(vfi, vfi->prev_selection, fd, select); | |
1386 } | |
1387 else | |
1388 { | |
1389 vficon_select_util(vfi, fd, select); | |
1390 } | |
1391 } | |
1392 else | |
1393 { | |
1394 vficon_select_none(vfi); | |
1395 | |
1396 if ((bevent->state & GDK_SHIFT_MASK) && | |
1397 vfi->prev_selection) | |
1398 { | |
1399 vficon_select_region_util(vfi, vfi->prev_selection, fd, TRUE); | |
1400 } | |
1401 else | |
1402 { | |
1403 vficon_select_util(vfi, fd, TRUE); | |
1404 was_selected = FALSE; | |
1405 } | |
1406 } | |
1407 } | |
1408 else if (bevent->button == 2 && | |
1409 fd && vfi->click_fd == fd) | |
1410 { | |
1411 vficon_select_util(vfi, fd, !(ICON_DATA(fd)->selected & SELECTION_SELECTED)); | |
1412 } | |
1413 | |
1414 if (fd && !was_selected && | |
1415 (ICON_DATA(fd)->selected & SELECTION_SELECTED)) | |
1416 { | |
1417 vficon_send_layout_select(vfi, fd); | |
1418 } | |
1419 | |
1420 return TRUE; | |
1421 } | |
1422 | |
1423 static gint vficon_leave_cb(GtkWidget *widget, GdkEventCrossing *event, gpointer data) | |
1424 { | |
1425 ViewFileIcon *vfi = data; | |
1426 | |
1427 tip_unschedule(vfi); | |
1428 return FALSE; | |
1429 } | |
1430 | |
1431 /* | |
1432 *------------------------------------------------------------------- | |
1433 * population | |
1434 *------------------------------------------------------------------- | |
1435 */ | |
1436 | |
1437 static gboolean vficon_destroy_node_cb(GtkTreeModel *store, GtkTreePath *tpath, GtkTreeIter *iter, gpointer data) | |
1438 { | |
1439 GList *list; | |
1440 | |
1441 gtk_tree_model_get(store, iter, FILE_COLUMN_POINTER, &list, -1); | |
1442 g_list_free(list); | |
1443 | |
1444 return FALSE; | |
1445 } | |
1446 | |
1447 static void vficon_clear_store(ViewFileIcon *vfi) | |
1448 { | |
1449 GtkTreeModel *store; | |
1450 | |
1451 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1452 gtk_tree_model_foreach(store, vficon_destroy_node_cb, NULL); | |
1453 | |
1454 gtk_list_store_clear(GTK_LIST_STORE(store)); | |
1455 } | |
1456 | |
1457 static void vficon_set_thumb(ViewFileIcon *vfi, FileData *fd, GdkPixbuf *pb) | |
1458 { | |
1459 GtkTreeModel *store; | |
1460 GtkTreeIter iter; | |
1461 GList *list; | |
1462 | |
1463 if (!vficon_find_iter(vfi, fd, &iter, NULL)) return; | |
1464 | |
1465 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1466 | |
1467 if (pb) g_object_ref(pb); | |
1468 if (fd->pixbuf) g_object_unref(fd->pixbuf); | |
1469 fd->pixbuf = pb; | |
1470 | |
1471 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
1472 gtk_list_store_set(GTK_LIST_STORE(store), &iter, FILE_COLUMN_POINTER, list, -1); | |
1473 } | |
1474 | |
1475 static GList *vficon_add_row(ViewFileIcon *vfi, GtkTreeIter *iter) | |
1476 { | |
1477 GtkListStore *store; | |
1478 GList *list = NULL; | |
1479 gint i; | |
1480 | |
1481 for (i = 0; i < vfi->columns; i++) list = g_list_prepend(list, NULL); | |
1482 | |
1483 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview))); | |
1484 gtk_list_store_append(store, iter); | |
1485 gtk_list_store_set(store, iter, FILE_COLUMN_POINTER, list, -1); | |
1486 | |
1487 return list; | |
1488 } | |
1489 | |
1490 static void vficon_populate(ViewFileIcon *vfi, gint resize, gint keep_position) | |
1491 { | |
1492 GtkTreeModel *store; | |
1493 GtkTreePath *tpath; | |
1494 gint row; | |
1495 GList *work; | |
1496 FileData *visible_fd = NULL; | |
1497 | |
1498 vficon_verify_selections(vfi); | |
1499 | |
1500 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1501 | |
1502 if (keep_position && GTK_WIDGET_REALIZED(vfi->listview) && | |
1503 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfi->listview), 0, 0, &tpath, NULL, NULL, NULL)) | |
1504 { | |
1505 GtkTreeIter iter; | |
1506 GList *list; | |
1507 | |
1508 gtk_tree_model_get_iter(store, &iter, tpath); | |
1509 gtk_tree_path_free(tpath); | |
1510 | |
1511 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
1512 if (list) visible_fd = list->data; | |
1513 } | |
1514 | |
1515 vficon_clear_store(vfi); | |
1516 | |
1517 if (resize) | |
1518 { | |
1519 gint i; | |
1520 gint thumb_width; | |
1521 | |
1522 thumb_width = vficon_get_icon_width(vfi); | |
1523 | |
1524 for (i = 0; i < VFICON_MAX_COLUMNS; i++) | |
1525 { | |
1526 GtkTreeViewColumn *column; | |
1527 GtkCellRenderer *cell; | |
1528 GList *list; | |
1529 | |
1530 column = gtk_tree_view_get_column(GTK_TREE_VIEW(vfi->listview), i); | |
1531 gtk_tree_view_column_set_visible(column, (i < vfi->columns)); | |
1532 gtk_tree_view_column_set_fixed_width(column, thumb_width + (THUMB_BORDER_PADDING * 6)); | |
1533 | |
1534 list = gtk_tree_view_column_get_cell_renderers(column); | |
1535 cell = (list) ? list->data : NULL; | |
1536 g_list_free(list); | |
1537 | |
1538 if (cell && GQV_IS_CELL_RENDERER_ICON(cell)) | |
1539 { | |
1540 g_object_set(G_OBJECT(cell), "fixed_width", thumb_width, | |
1541 "fixed_height", thumb_max_height, | |
1542 "show_text", vfi->show_text, NULL); | |
1543 } | |
1544 } | |
1545 if (GTK_WIDGET_REALIZED(vfi->listview)) gtk_tree_view_columns_autosize(GTK_TREE_VIEW(vfi->listview)); | |
1546 } | |
1547 | |
1548 row = -1; | |
1549 work = vfi->list; | |
1550 while (work) | |
1551 { | |
1552 GList *list; | |
1553 GtkTreeIter iter; | |
1554 | |
1555 row++; | |
1556 | |
1557 list = vficon_add_row(vfi, &iter); | |
1558 while (work && list) | |
1559 { | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1560 FileData *fd; |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1561 |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1562 fd = work->data; |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1563 ICON_DATA(fd)->row = row; |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1564 |
9 | 1565 list->data = work->data; |
1566 list = list->next; | |
1567 work = work->next; | |
1568 } | |
1569 } | |
1570 | |
1571 if (visible_fd && | |
1572 gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfi->listview), 0, 0, &tpath, NULL, NULL, NULL)) | |
1573 { | |
1574 GtkTreeIter iter; | |
1575 GList *list; | |
1576 | |
1577 gtk_tree_model_get_iter(store, &iter, tpath); | |
1578 gtk_tree_path_free(tpath); | |
1579 | |
1580 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
1581 if (g_list_find(list, visible_fd) == NULL && | |
1582 vficon_find_iter(vfi, visible_fd, &iter, NULL)) | |
1583 { | |
1584 tree_view_row_make_visible(GTK_TREE_VIEW(vfi->listview), &iter, FALSE); | |
1585 } | |
1586 } | |
1587 | |
1588 vfi->rows = row + 1; | |
1589 | |
1590 vficon_send_update(vfi); | |
1591 vficon_thumb_update(vfi); | |
1592 } | |
1593 | |
1594 static void vficon_populate_at_new_size(ViewFileIcon *vfi, gint w, gint h, gint force) | |
1595 { | |
1596 gint new_cols; | |
1597 gint thumb_width; | |
1598 | |
1599 thumb_width = vficon_get_icon_width(vfi); | |
1600 | |
1601 new_cols = w / (thumb_width + (THUMB_BORDER_PADDING * 6)); | |
1602 if (new_cols < 1) new_cols = 1; | |
1603 | |
1604 if (!force && new_cols == vfi->columns) return; | |
1605 | |
1606 vfi->columns = new_cols; | |
1607 | |
1608 vficon_populate(vfi, TRUE, TRUE); | |
1609 | |
1610 if (debug) printf("col tab pop cols=%d rows=%d\n", vfi->columns, vfi->rows); | |
1611 } | |
1612 | |
1613 static void vficon_sync(ViewFileIcon *vfi) | |
1614 { | |
1615 GtkTreeModel *store; | |
1616 GtkTreeIter iter; | |
1617 GList *work; | |
1618 gint r, c; | |
1619 | |
1620 if (vfi->rows == 0) return; | |
1621 | |
1622 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1623 | |
1624 r = -1; | |
1625 c = 0; | |
1626 | |
1627 work = vfi->list; | |
1628 while (work) | |
1629 { | |
1630 GList *list; | |
1631 r++; | |
1632 c = 0; | |
1633 if (gtk_tree_model_iter_nth_child(store, &iter, NULL, r)) | |
1634 { | |
1635 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
1636 gtk_list_store_set(GTK_LIST_STORE(store), &iter, FILE_COLUMN_POINTER, list, -1); | |
1637 } | |
1638 else | |
1639 { | |
1640 list = vficon_add_row(vfi, &iter); | |
1641 } | |
1642 | |
1643 while (list) | |
1644 { | |
1645 FileData *fd; | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1646 |
9 | 1647 if (work) |
1648 { | |
1649 fd = work->data; | |
1650 work = work->next; | |
1651 c++; | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1652 |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1653 ICON_DATA(fd)->row = r; |
9 | 1654 } |
1655 else | |
1656 { | |
1657 fd = NULL; | |
1658 } | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1659 |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1660 list->data = fd; |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
1661 list = list->next; |
9 | 1662 } |
1663 } | |
1664 | |
1665 r++; | |
1666 while (gtk_tree_model_iter_nth_child(store, &iter, NULL, r)) | |
1667 { | |
1668 GList *list; | |
1669 | |
1670 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
1671 gtk_list_store_remove(GTK_LIST_STORE(store), &iter); | |
1672 g_list_free(list); | |
1673 } | |
1674 | |
1675 vfi->rows = r; | |
1676 | |
1677 vficon_update_focus(vfi); | |
1678 } | |
1679 | |
1680 static gint vficon_sync_idle_cb(gpointer data) | |
1681 { | |
1682 ViewFileIcon *vfi = data; | |
1683 | |
1684 if (vfi->sync_idle_id == -1) return FALSE; | |
1685 vfi->sync_idle_id = -1; | |
1686 | |
1687 vficon_sync(vfi); | |
1688 return FALSE; | |
1689 } | |
1690 | |
1691 static void vficon_sync_idle(ViewFileIcon *vfi) | |
1692 { | |
1693 if (vfi->sync_idle_id == -1) | |
1694 { | |
1695 /* high priority, the view needs to be resynced before a redraw | |
1696 * may contain invalid pointers at this time | |
1697 */ | |
1698 vfi->sync_idle_id = g_idle_add_full(G_PRIORITY_HIGH, vficon_sync_idle_cb, vfi, NULL); | |
1699 } | |
1700 } | |
1701 | |
1702 static void vficon_sized_cb(GtkWidget *widget, GtkAllocation *allocation, gpointer data) | |
1703 { | |
1704 ViewFileIcon *vfi = data; | |
1705 | |
1706 vficon_populate_at_new_size(vfi, allocation->width, allocation->height, FALSE); | |
1707 } | |
1708 | |
1709 /* | |
1710 *----------------------------------------------------------------------------- | |
1711 * misc | |
1712 *----------------------------------------------------------------------------- | |
1713 */ | |
1714 | |
1715 void vficon_sort_set(ViewFileIcon *vfi, SortType type, gint ascend) | |
1716 { | |
1717 if (vfi->sort_method == type && vfi->sort_ascend == ascend) return; | |
1718 | |
1719 vfi->sort_method = type; | |
1720 vfi->sort_ascend = ascend; | |
1721 | |
1722 if (!vfi->list) return; | |
1723 | |
1724 vfi->list = filelist_sort(vfi->list, vfi->sort_method, vfi->sort_ascend); | |
1725 vficon_sync(vfi); | |
1726 } | |
1727 | |
1728 /* | |
1729 *----------------------------------------------------------------------------- | |
1730 * thumb updates | |
1731 *----------------------------------------------------------------------------- | |
1732 */ | |
1733 | |
1734 static gint vficon_thumb_next(ViewFileIcon *vfi); | |
1735 | |
1736 static void vficon_thumb_status(ViewFileIcon *vfi, gdouble val, const gchar *text) | |
1737 { | |
1738 if (vfi->func_thumb_status) | |
1739 { | |
1740 vfi->func_thumb_status(vfi, val, text, vfi->data_thumb_status); | |
1741 } | |
1742 } | |
1743 | |
1744 static void vficon_thumb_cleanup(ViewFileIcon *vfi) | |
1745 { | |
1746 vficon_thumb_status(vfi, 0.0, NULL); | |
1747 | |
1748 g_list_free(vfi->thumbs_list); | |
1749 vfi->thumbs_list = NULL; | |
1750 vfi->thumbs_count = 0; | |
1751 vfi->thumbs_running = FALSE; | |
1752 | |
1753 thumb_loader_free(vfi->thumbs_loader); | |
1754 vfi->thumbs_loader = NULL; | |
1755 | |
1756 vfi->thumbs_fd = NULL; | |
1757 } | |
1758 | |
1759 static void vficon_thumb_stop(ViewFileIcon *vfi) | |
1760 { | |
1761 if (vfi->thumbs_running) vficon_thumb_cleanup(vfi); | |
1762 } | |
1763 | |
1764 static void vficon_thumb_do(ViewFileIcon *vfi, ThumbLoader *tl, FileData *fd) | |
1765 { | |
1766 GdkPixbuf *pixbuf; | |
1767 | |
1768 if (!fd) return; | |
1769 | |
1770 pixbuf = thumb_loader_get_pixbuf(tl, TRUE); | |
1771 vficon_set_thumb(vfi, fd, pixbuf); | |
1772 g_object_unref(pixbuf); | |
1773 | |
1774 vficon_thumb_status(vfi, (gdouble)(vfi->thumbs_count) / g_list_length(vfi->list), _("Loading thumbs...")); | |
1775 } | |
1776 | |
1777 static void vficon_thumb_error_cb(ThumbLoader *tl, gpointer data) | |
1778 { | |
1779 ViewFileIcon *vfi = data; | |
1780 | |
1781 if (vfi->thumbs_fd && vfi->thumbs_loader == tl) | |
1782 { | |
1783 vficon_thumb_do(vfi, tl, vfi->thumbs_fd); | |
1784 } | |
1785 | |
1786 while (vficon_thumb_next(vfi)); | |
1787 } | |
1788 | |
1789 static void vficon_thumb_done_cb(ThumbLoader *tl, gpointer data) | |
1790 { | |
1791 ViewFileIcon *vfi = data; | |
1792 | |
1793 if (vfi->thumbs_fd && vfi->thumbs_loader == tl) | |
1794 { | |
1795 vficon_thumb_do(vfi, tl, vfi->thumbs_fd); | |
1796 } | |
1797 | |
1798 while (vficon_thumb_next(vfi)); | |
1799 } | |
1800 | |
1801 static gint vficon_thumb_next(ViewFileIcon *vfi) | |
1802 { | |
1803 GtkTreePath *tpath; | |
1804 FileData *fd = NULL; | |
1805 | |
1806 if (!GTK_WIDGET_REALIZED(vfi->listview)) | |
1807 { | |
1808 vficon_thumb_status(vfi, 0.0, NULL); | |
1809 return FALSE; | |
1810 } | |
1811 | |
1812 if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(vfi->listview), 0, 0, &tpath, NULL, NULL, NULL)) | |
1813 { | |
1814 GtkTreeModel *store; | |
1815 GtkTreeIter iter; | |
1816 gint valid = TRUE; | |
1817 | |
1818 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
1819 gtk_tree_model_get_iter(store, &iter, tpath); | |
1820 gtk_tree_path_free(tpath); | |
1821 | |
1822 while (!fd && valid && tree_view_row_get_visibility(GTK_TREE_VIEW(vfi->listview), &iter, FALSE) == 0) | |
1823 { | |
1824 GList *list; | |
1825 | |
1826 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
1827 | |
1828 while (!fd && list) | |
1829 { | |
1830 FileData *tfd = list->data; | |
1831 if (tfd && !tfd->pixbuf) fd = tfd; | |
1832 list = list->next; | |
1833 } | |
1834 | |
1835 valid = gtk_tree_model_iter_next(store, &iter); | |
1836 } | |
1837 } | |
1838 | |
1839 /* then find first undone */ | |
1840 | |
1841 if (!fd) | |
1842 { | |
1843 GList *work = vfi->list; | |
1844 while (work && !fd) | |
1845 { | |
1846 FileData *fd_p = work->data; | |
1847 work = work->next; | |
1848 | |
1849 if (!fd_p->pixbuf) fd = fd_p; | |
1850 } | |
1851 } | |
1852 | |
1853 if (!fd) | |
1854 { | |
1855 /* done */ | |
1856 vficon_thumb_cleanup(vfi); | |
1857 return FALSE; | |
1858 } | |
1859 | |
1860 vfi->thumbs_count++; | |
1861 | |
1862 vfi->thumbs_fd = fd; | |
1863 | |
1864 thumb_loader_free(vfi->thumbs_loader); | |
1865 | |
1866 vfi->thumbs_loader = thumb_loader_new(thumb_max_width, thumb_max_height); | |
1867 thumb_loader_set_callbacks(vfi->thumbs_loader, | |
1868 vficon_thumb_done_cb, | |
1869 vficon_thumb_error_cb, | |
1870 NULL, | |
1871 vfi); | |
1872 | |
1873 if (!thumb_loader_start(vfi->thumbs_loader, fd->path)) | |
1874 { | |
1875 /* set icon to unknown, continue */ | |
1876 if (debug) printf("thumb loader start failed %s\n", vfi->thumbs_loader->path); | |
1877 vficon_thumb_do(vfi, vfi->thumbs_loader, fd); | |
1878 | |
1879 return TRUE; | |
1880 } | |
1881 | |
1882 return FALSE; | |
1883 } | |
1884 | |
1885 static void vficon_thumb_update(ViewFileIcon *vfi) | |
1886 { | |
1887 vficon_thumb_stop(vfi); | |
1888 | |
1889 vficon_thumb_status(vfi, 0.0, _("Loading thumbs...")); | |
1890 vfi->thumbs_running = TRUE; | |
1891 | |
1892 while (vficon_thumb_next(vfi)); | |
1893 } | |
1894 | |
1895 /* | |
1896 *----------------------------------------------------------------------------- | |
1897 * row stuff | |
1898 *----------------------------------------------------------------------------- | |
1899 */ | |
1900 | |
1901 FileData *vficon_index_get_data(ViewFileIcon *vfi, gint row) | |
1902 { | |
1903 return FILE_DATA(g_list_nth_data(vfi->list, row)); | |
1904 } | |
1905 | |
1906 gchar *vficon_index_get_path(ViewFileIcon *vfi, gint row) | |
1907 { | |
1908 FileData *fd; | |
1909 | |
1910 fd = g_list_nth_data(vfi->list, row); | |
1911 | |
1912 return (fd ? fd->path : NULL); | |
1913 } | |
1914 | |
1915 gint vficon_index_by_path(ViewFileIcon *vfi, const gchar *path) | |
1916 { | |
1917 gint p = 0; | |
1918 GList *work; | |
1919 | |
1920 if (!path) return -1; | |
1921 | |
1922 work = vfi->list; | |
1923 while (work) | |
1924 { | |
1925 FileData *fd = work->data; | |
1926 if (strcmp(path, fd->path) == 0) return p; | |
1927 work = work->next; | |
1928 p++; | |
1929 } | |
1930 | |
1931 return -1; | |
1932 } | |
1933 | |
1934 gint vficon_count(ViewFileIcon *vfi, gint64 *bytes) | |
1935 { | |
1936 if (bytes) | |
1937 { | |
1938 gint64 b = 0; | |
1939 GList *work; | |
1940 | |
1941 work = vfi->list; | |
1942 while (work) | |
1943 { | |
1944 FileData *fd = work->data; | |
1945 work = work->next; | |
1946 b += fd->size; | |
1947 } | |
1948 | |
1949 *bytes = b; | |
1950 } | |
1951 | |
1952 return g_list_length(vfi->list); | |
1953 } | |
1954 | |
1955 GList *vficon_get_list(ViewFileIcon *vfi) | |
1956 { | |
1957 GList *list = NULL; | |
1958 GList *work; | |
1959 | |
1960 work = vfi->list; | |
1961 while (work) | |
1962 { | |
1963 FileData *fd = work->data; | |
1964 work = work->next; | |
1965 | |
1966 list = g_list_prepend(list, g_strdup(fd->path)); | |
1967 } | |
1968 | |
1969 return g_list_reverse(list); | |
1970 } | |
1971 | |
1972 /* | |
1973 *----------------------------------------------------------------------------- | |
1974 * | |
1975 *----------------------------------------------------------------------------- | |
1976 */ | |
1977 | |
1978 static gint vficon_refresh_real(ViewFileIcon *vfi, gint keep_position) | |
1979 { | |
1980 gint ret = TRUE; | |
1981 GList *old_list; | |
1982 GList *work; | |
1983 FileData *focus_fd; | |
1984 | |
1985 focus_fd = vfi->focus_fd; | |
1986 | |
1987 old_list = vfi->list; | |
1988 vfi->list = NULL; | |
1989 | |
1990 if (vfi->path) | |
1991 { | |
1992 ret = iconlist_read(vfi->path, &vfi->list); | |
1993 } | |
1994 | |
1995 /* check for same files from old_list */ | |
1996 work = old_list; | |
1997 while (work) | |
1998 { | |
1999 FileData *fd; | |
2000 GList *needle; | |
2001 | |
2002 fd = work->data; | |
2003 needle = vfi->list; | |
2004 while (needle) | |
2005 { | |
2006 FileData *fdn = needle->data; | |
2007 if (strcmp(fd->name, fdn->name) == 0) | |
2008 { | |
2009 /* swap, to retain old thumb, selection */ | |
2010 needle->data = fd; | |
2011 work->data = fdn; | |
2012 needle = NULL; | |
2013 | |
2014 if (fd->date != fdn->date || fd->size != fdn->size) | |
2015 { | |
2016 /* file changed, update */ | |
2017 fd->date = fdn->date; | |
2018 fd->size = fdn->size; | |
2019 vficon_set_thumb(vfi, fd, NULL); | |
2020 } | |
2021 } | |
2022 else | |
2023 { | |
2024 needle = needle->next; | |
2025 } | |
2026 } | |
2027 | |
2028 work = work->next; | |
2029 } | |
2030 | |
2031 vfi->list = filelist_sort(vfi->list, vfi->sort_method, vfi->sort_ascend); | |
2032 | |
2033 work = old_list; | |
2034 while (work) | |
2035 { | |
2036 FileData *fd = work->data; | |
2037 work = work->next; | |
2038 | |
2039 if (fd == vfi->prev_selection) vfi->prev_selection = NULL; | |
2040 if (fd == vfi->click_fd) vfi->click_fd = NULL; | |
2041 } | |
2042 | |
2043 vficon_populate(vfi, TRUE, keep_position); | |
2044 | |
2045 /* attempt to keep focus on same icon when refreshing */ | |
2046 if (focus_fd && g_list_find(vfi->list, focus_fd)) | |
2047 { | |
2048 vficon_set_focus(vfi, focus_fd); | |
2049 } | |
2050 | |
2051 iconlist_free(old_list); | |
2052 | |
2053 return ret; | |
2054 } | |
2055 | |
2056 gint vficon_refresh(ViewFileIcon *vfi) | |
2057 { | |
2058 return vficon_refresh_real(vfi, TRUE); | |
2059 } | |
2060 | |
2061 /* | |
2062 *----------------------------------------------------------------------------- | |
2063 * draw, etc. | |
2064 *----------------------------------------------------------------------------- | |
2065 */ | |
2066 | |
2067 typedef struct _ColumnData ColumnData; | |
2068 struct _ColumnData | |
2069 { | |
2070 ViewFileIcon *vfi; | |
2071 gint number; | |
2072 }; | |
2073 | |
2074 static void vficon_cell_data_cb(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, | |
2075 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) | |
2076 { | |
2077 ColumnData *cd = data; | |
2078 ViewFileIcon *vfi; | |
2079 GtkStyle *style; | |
2080 GList *list; | |
2081 FileData *fd; | |
2082 GdkColor color_fg; | |
2083 GdkColor color_bg; | |
2084 | |
2085 vfi = cd->vfi; | |
2086 | |
2087 gtk_tree_model_get(tree_model, iter, FILE_COLUMN_POINTER, &list, -1); | |
2088 fd = g_list_nth_data(list, cd->number); | |
2089 | |
2090 style = gtk_widget_get_style(vfi->listview); | |
2091 if (fd && ICON_DATA(fd)->selected & SELECTION_SELECTED) | |
2092 { | |
2093 memcpy(&color_fg, &style->text[GTK_STATE_SELECTED], sizeof(color_fg)); | |
2094 memcpy(&color_bg, &style->base[GTK_STATE_SELECTED], sizeof(color_bg)); | |
2095 } | |
2096 else | |
2097 { | |
2098 memcpy(&color_fg, &style->text[GTK_STATE_NORMAL], sizeof(color_fg)); | |
2099 memcpy(&color_bg, &style->base[GTK_STATE_NORMAL], sizeof(color_bg)); | |
2100 } | |
2101 | |
2102 if (fd && ICON_DATA(fd)->selected & SELECTION_PRELIGHT) | |
2103 { | |
2104 #if 0 | |
2105 shift_color(&color_fg, -1, 0); | |
2106 #endif | |
2107 shift_color(&color_bg, -1, 0); | |
2108 } | |
2109 | |
2110 if (GQV_IS_CELL_RENDERER_ICON(cell)) | |
2111 { | |
2112 if (fd) | |
2113 { | |
2114 g_object_set(cell, "pixbuf", fd->pixbuf, | |
2115 "text", fd->name, | |
2116 "cell-background-gdk", &color_bg, | |
2117 "cell-background-set", TRUE, | |
2118 "foreground-gdk", &color_fg, | |
2119 "foreground-set", TRUE, | |
2120 "has-focus", (vfi->focus_fd == fd), NULL); | |
2121 } | |
2122 else | |
2123 { | |
2124 g_object_set(cell, "pixbuf", NULL, | |
2125 "text", NULL, | |
2126 "cell-background-set", FALSE, | |
2127 "foreground-set", FALSE, | |
2128 "has-focus", FALSE, NULL); | |
2129 } | |
2130 } | |
2131 } | |
2132 | |
2133 static void vficon_append_column(ViewFileIcon *vfi, gint n) | |
2134 { | |
2135 ColumnData *cd; | |
2136 GtkTreeViewColumn *column; | |
2137 GtkCellRenderer *renderer; | |
2138 | |
2139 column = gtk_tree_view_column_new(); | |
2140 gtk_tree_view_column_set_min_width(column, 0); | |
2141 | |
2142 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); | |
2143 gtk_tree_view_column_set_alignment(column, 0.5); | |
2144 | |
2145 renderer = gqv_cell_renderer_icon_new(); | |
2146 gtk_tree_view_column_pack_start(column, renderer, FALSE); | |
2147 g_object_set(G_OBJECT(renderer), "xpad", THUMB_BORDER_PADDING * 2, | |
2148 "ypad", THUMB_BORDER_PADDING, | |
2149 "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE, NULL); | |
2150 | |
2151 g_object_set_data(G_OBJECT(column), "column_number", GINT_TO_POINTER(n)); | |
2152 | |
2153 cd = g_new0(ColumnData, 1); | |
2154 cd->vfi = vfi; | |
2155 cd->number = n; | |
2156 gtk_tree_view_column_set_cell_data_func(column, renderer, vficon_cell_data_cb, cd, g_free); | |
2157 | |
2158 gtk_tree_view_append_column(GTK_TREE_VIEW(vfi->listview), column); | |
2159 } | |
2160 | |
2161 /* | |
2162 *----------------------------------------------------------------------------- | |
2163 * base | |
2164 *----------------------------------------------------------------------------- | |
2165 */ | |
2166 | |
2167 gint vficon_set_path(ViewFileIcon *vfi, const gchar *path) | |
2168 { | |
2169 gint ret; | |
2170 | |
2171 if (!path) return FALSE; | |
2172 if (vfi->path && strcmp(path, vfi->path) == 0) return TRUE; | |
2173 | |
2174 g_free(vfi->path); | |
2175 vfi->path = g_strdup(path); | |
2176 | |
2177 g_list_free(vfi->selection); | |
2178 vfi->selection = NULL; | |
2179 | |
2180 iconlist_free(vfi->list); | |
2181 vfi->list = NULL; | |
2182 | |
2183 /* NOTE: populate will clear the store for us */ | |
2184 ret = vficon_refresh_real(vfi, FALSE); | |
2185 | |
2186 vfi->focus_fd = NULL; | |
2187 vficon_move_focus(vfi, 0, 0, FALSE); | |
2188 | |
2189 return ret; | |
2190 } | |
2191 | |
2192 static void vficon_destroy_cb(GtkWidget *widget, gpointer data) | |
2193 { | |
2194 ViewFileIcon *vfi = data; | |
2195 | |
2196 if (vfi->popup) | |
2197 { | |
2198 g_signal_handlers_disconnect_matched(G_OBJECT(vfi->popup), G_SIGNAL_MATCH_DATA, | |
2199 0, 0, 0, NULL, vfi); | |
2200 gtk_widget_destroy(vfi->popup); | |
2201 } | |
2202 | |
2203 if (vfi->sync_idle_id != -1) g_source_remove(vfi->sync_idle_id); | |
2204 | |
2205 tip_unschedule(vfi); | |
2206 | |
2207 vficon_thumb_cleanup(vfi); | |
2208 | |
2209 g_free(vfi->path); | |
2210 | |
2211 iconlist_free(vfi->list); | |
2212 g_list_free(vfi->selection); | |
2213 g_free(vfi); | |
2214 } | |
2215 | |
2216 ViewFileIcon *vficon_new(const gchar *path) | |
2217 { | |
2218 ViewFileIcon *vfi; | |
2219 GtkListStore *store; | |
2220 GtkTreeSelection *selection; | |
2221 gint i; | |
2222 | |
2223 vfi = g_new0(ViewFileIcon, 1); | |
2224 | |
2225 vfi->path = NULL; | |
2226 vfi->sort_method = SORT_NAME; | |
2227 vfi->sort_ascend = TRUE; | |
2228 | |
2229 vfi->selection = NULL; | |
2230 vfi->prev_selection = NULL; | |
2231 | |
2232 vfi->tip_window = NULL; | |
2233 vfi->tip_delay_id = -1; | |
2234 | |
2235 vfi->focus_row = 0; | |
2236 vfi->focus_column = 0; | |
2237 vfi->focus_fd = NULL; | |
2238 | |
2239 vfi->show_text = show_icon_names; | |
2240 | |
2241 vfi->sync_idle_id = -1; | |
2242 | |
2243 vfi->popup = NULL; | |
2244 | |
2245 vfi->widget = gtk_scrolled_window_new(NULL, NULL); | |
2246 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(vfi->widget), GTK_SHADOW_IN); | |
2247 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vfi->widget), | |
2248 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
2249 g_signal_connect(G_OBJECT(vfi->widget), "destroy", | |
2250 G_CALLBACK(vficon_destroy_cb), vfi); | |
2251 | |
2252 store = gtk_list_store_new(1, G_TYPE_POINTER); | |
2253 vfi->listview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); | |
2254 g_object_unref(store); | |
2255 | |
2256 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vfi->listview)); | |
2257 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_NONE); | |
2258 | |
2259 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(vfi->listview), FALSE); | |
2260 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(vfi->listview), FALSE); | |
2261 | |
2262 for (i = 0; i < VFICON_MAX_COLUMNS; i++) | |
2263 { | |
2264 vficon_append_column(vfi, i); | |
2265 } | |
2266 | |
2267 /* zero width column to hide tree view focus, we draw it ourselves */ | |
2268 vficon_append_column(vfi, i); | |
2269 /* end column to fill white space */ | |
2270 vficon_append_column(vfi, i); | |
2271 | |
2272 g_signal_connect(G_OBJECT(vfi->listview), "size_allocate", | |
2273 G_CALLBACK(vficon_sized_cb), vfi); | |
2274 g_signal_connect(G_OBJECT(vfi->listview), "key_press_event", | |
2275 G_CALLBACK(vficon_press_key_cb), vfi); | |
2276 | |
2277 gtk_container_add(GTK_CONTAINER(vfi->widget), vfi->listview); | |
2278 gtk_widget_show(vfi->listview); | |
2279 | |
2280 vficon_dnd_init(vfi); | |
2281 | |
2282 gtk_widget_set_events(vfi->listview, GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK | | |
2283 GDK_BUTTON_PRESS_MASK | GDK_LEAVE_NOTIFY_MASK); | |
2284 g_signal_connect(G_OBJECT(vfi->listview), "button_press_event", | |
2285 G_CALLBACK(vficon_press_cb), vfi); | |
2286 g_signal_connect(G_OBJECT(vfi->listview), "button_release_event", | |
2287 G_CALLBACK(vficon_release_cb), vfi); | |
2288 g_signal_connect(G_OBJECT(vfi->listview),"motion_notify_event", | |
2289 G_CALLBACK(vficon_motion_cb), vfi); | |
2290 g_signal_connect(G_OBJECT(vfi->listview), "leave_notify_event", | |
2291 G_CALLBACK(vficon_leave_cb), vfi); | |
2292 | |
2293 /* force vfi->columns to be at least 1 (sane) - this will be corrected in the size_cb */ | |
2294 vficon_populate_at_new_size(vfi, 1, 1, FALSE); | |
2295 | |
2296 if (path) vficon_set_path(vfi, path); | |
2297 | |
2298 return vfi; | |
2299 } | |
2300 | |
2301 void vficon_set_status_func(ViewFileIcon *vfi, | |
2302 void (*func)(ViewFileIcon *vfi, gpointer data), gpointer data) | |
2303 { | |
2304 vfi->func_status = func; | |
2305 vfi->data_status = data; | |
2306 } | |
2307 | |
2308 void vficon_set_thumb_status_func(ViewFileIcon *vfi, | |
2309 void (*func)(ViewFileIcon *vfi, gdouble val, const gchar *text, gpointer data), | |
2310 gpointer data) | |
2311 { | |
2312 vfi->func_thumb_status = func; | |
2313 vfi->data_thumb_status = data; | |
2314 } | |
2315 | |
2316 void vficon_set_layout(ViewFileIcon *vfi, LayoutWindow *layout) | |
2317 { | |
2318 vfi->layout = layout; | |
2319 } | |
2320 | |
2321 /* | |
2322 *----------------------------------------------------------------------------- | |
2323 * maintenance (for rename, move, remove) | |
2324 *----------------------------------------------------------------------------- | |
2325 */ | |
2326 | |
2327 static gint vficon_maint_find_closest(ViewFileIcon *vfi, gint row, gint count, GList *ignore_list) | |
2328 { | |
2329 GList *list = NULL; | |
2330 GList *work; | |
2331 gint rev = row - 1; | |
2332 row ++; | |
2333 | |
2334 work = ignore_list; | |
2335 while (work) | |
2336 { | |
2337 gint f = vficon_index_by_path(vfi, work->data); | |
2338 if (f >= 0) list = g_list_prepend(list, GINT_TO_POINTER(f)); | |
2339 work = work->next; | |
2340 } | |
2341 | |
2342 while (list) | |
2343 { | |
2344 gint c = TRUE; | |
2345 work = list; | |
2346 while (work && c) | |
2347 { | |
2348 gpointer p = work->data; | |
2349 work = work->next; | |
2350 if (row == GPOINTER_TO_INT(p)) | |
2351 { | |
2352 row++; | |
2353 c = FALSE; | |
2354 } | |
2355 if (rev == GPOINTER_TO_INT(p)) | |
2356 { | |
2357 rev--; | |
2358 c = FALSE; | |
2359 } | |
2360 if (!c) list = g_list_remove(list, p); | |
2361 } | |
2362 if (c && list) | |
2363 { | |
2364 g_list_free(list); | |
2365 list = NULL; | |
2366 } | |
2367 } | |
2368 if (row > count - 1) | |
2369 { | |
2370 if (rev < 0) | |
2371 return -1; | |
2372 else | |
2373 return rev; | |
2374 } | |
2375 else | |
2376 { | |
2377 return row; | |
2378 } | |
2379 } | |
2380 | |
2381 gint vficon_maint_renamed(ViewFileIcon *vfi, const gchar *source, const gchar *dest) | |
2382 { | |
2383 gint ret = FALSE; | |
2384 gint row; | |
2385 gchar *source_base; | |
2386 gchar *dest_base; | |
2387 GList *work; | |
2388 FileData *fd; | |
2389 | |
2390 row = vficon_index_by_path(vfi, source); | |
2391 if (row < 0) return FALSE; | |
2392 | |
2393 source_base = remove_level_from_path(source); | |
2394 dest_base = remove_level_from_path(dest); | |
2395 | |
2396 work = g_list_nth(vfi->list, row); | |
2397 fd = work->data; | |
2398 | |
2399 if (strcmp(source_base, dest_base) == 0) | |
2400 { | |
2401 vfi->list = g_list_remove(vfi->list, fd); | |
2402 g_free(fd->path); | |
2403 | |
2404 fd->path = g_strdup(dest); | |
2405 fd->name = filename_from_path(fd->path); | |
2406 | |
2407 vfi->list = filelist_insert_sort(vfi->list, fd, vfi->sort_method, vfi->sort_ascend); | |
2408 | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
2409 vficon_sync_idle(vfi); |
9 | 2410 ret = TRUE; |
2411 } | |
2412 else | |
2413 { | |
2414 ret = vficon_maint_removed(vfi, source, NULL); | |
2415 } | |
2416 | |
2417 g_free(source_base); | |
2418 g_free(dest_base); | |
2419 | |
2420 return ret; | |
2421 } | |
2422 | |
2423 gint vficon_maint_removed(ViewFileIcon *vfi, const gchar *path, GList *ignore_list) | |
2424 { | |
2425 FileData *fd; | |
2426 gint row; | |
2427 gint new_row = -1; | |
2428 GtkTreeModel *store; | |
2429 GtkTreeIter iter; | |
2430 | |
2431 row = vficon_index_by_path(vfi, path); | |
2432 if (row < 0) return FALSE; | |
2433 | |
2434 fd = g_list_nth_data(vfi->list, row); | |
2435 if (!fd) return FALSE; | |
2436 | |
2437 if ((ICON_DATA(fd)->selected & SELECTION_SELECTED) && | |
2438 layout_image_get_collection(vfi->layout, NULL) == NULL) | |
2439 { | |
2440 vficon_unselect(vfi, fd); | |
2441 | |
2442 if (!vfi->selection) | |
2443 { | |
2444 gint n; | |
2445 | |
2446 n = vficon_count(vfi, NULL); | |
2447 if (ignore_list) | |
2448 { | |
2449 new_row = vficon_maint_find_closest(vfi, row, n, ignore_list); | |
2450 if (debug) printf("row = %d, closest is %d\n", row, new_row); | |
2451 } | |
2452 else | |
2453 { | |
2454 if (row + 1 < n) | |
2455 { | |
2456 new_row = row + 1; | |
2457 } | |
2458 else if (row > 0) | |
2459 { | |
2460 new_row = row - 1; | |
2461 } | |
2462 } | |
2463 } | |
2464 else if (ignore_list) | |
2465 { | |
2466 GList *work; | |
2467 | |
2468 work = vfi->selection; | |
2469 while (work) | |
2470 { | |
2471 FileData *ignore_fd; | |
2472 GList *tmp; | |
2473 gint match = FALSE; | |
2474 | |
2475 ignore_fd = work->data; | |
2476 work = work->next; | |
2477 | |
2478 tmp = ignore_list; | |
2479 while (tmp && !match) | |
2480 { | |
2481 const gchar *ignore_path; | |
2482 | |
2483 ignore_path = tmp->data; | |
2484 tmp = tmp->next; | |
2485 | |
2486 if (strcmp(ignore_fd->path, ignore_path) == 0) | |
2487 { | |
2488 match = TRUE; | |
2489 } | |
2490 } | |
2491 if (!match) | |
2492 { | |
2493 new_row = g_list_index(vfi->list, ignore_fd); | |
2494 work = NULL; | |
2495 } | |
2496 } | |
2497 if (new_row == -1) | |
2498 { | |
2499 /* selection all ignored, use closest */ | |
2500 new_row = vficon_maint_find_closest(vfi, row, vficon_count(vfi, NULL), ignore_list); | |
2501 } | |
2502 } | |
2503 else | |
2504 { | |
2505 new_row = g_list_index(vfi->list, vfi->selection->data); | |
2506 } | |
2507 if (new_row >= 0) | |
2508 { | |
2509 FileData *fdn; | |
2510 | |
2511 fdn = g_list_nth_data(vfi->list, new_row); | |
2512 vficon_select(vfi, fdn); | |
2513 vficon_send_layout_select(vfi, fdn); | |
2514 } | |
2515 } | |
2516 | |
2517 /* Thumb loader check */ | |
2518 if (fd == vfi->thumbs_fd) vfi->thumbs_fd = NULL; | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
2519 if (vfi->thumbs_count > 0) vfi->thumbs_count--; |
9 | 2520 |
2521 if (vfi->prev_selection == fd) vfi->prev_selection = NULL; | |
2522 if (vfi->click_fd == fd) vfi->click_fd = NULL; | |
2523 | |
2524 /* remove pointer to this fd from grid */ | |
2525 store = gtk_tree_view_get_model(GTK_TREE_VIEW(vfi->listview)); | |
111
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
2526 if (ICON_DATA(fd)->row >= 0 && |
3a69a7a3f461
Wed Nov 15 02:05:27 2006 John Ellis <johne@verizon.net>
gqview
parents:
85
diff
changeset
|
2527 gtk_tree_model_iter_nth_child(store, &iter, NULL, ICON_DATA(fd)->row)) |
9 | 2528 { |
2529 GList *list; | |
2530 | |
2531 gtk_tree_model_get(store, &iter, FILE_COLUMN_POINTER, &list, -1); | |
2532 list = g_list_find(list, fd); | |
2533 if (list) list->data = NULL; | |
2534 } | |
2535 | |
2536 vfi->list = g_list_remove(vfi->list, fd); | |
2537 file_data_free(fd); | |
2538 | |
2539 vficon_sync_idle(vfi); | |
2540 vficon_send_update(vfi); | |
2541 | |
2542 return TRUE; | |
2543 } | |
2544 | |
2545 gint vficon_maint_moved(ViewFileIcon *vfi, const gchar *source, const gchar *dest, GList *ignore_list) | |
2546 { | |
2547 gint ret = FALSE; | |
2548 gchar *buf; | |
2549 | |
2550 if (!source || !vfi->path) return FALSE; | |
2551 | |
2552 buf = remove_level_from_path(source); | |
2553 | |
2554 if (strcmp(buf, vfi->path) == 0) | |
2555 { | |
2556 ret = vficon_maint_removed(vfi, source, ignore_list); | |
2557 } | |
2558 | |
2559 g_free(buf); | |
2560 | |
2561 return ret; | |
2562 } | |
2563 |