1
|
1 /*
|
|
2 * GQview image viewer
|
3
|
3 * (C)2000 John Ellis
|
1
|
4 *
|
|
5 * Author: John Ellis
|
|
6 *
|
|
7 */
|
|
8
|
|
9 #include "gqview.h"
|
|
10
|
|
11 static gint filelist_click_row = -1;
|
|
12
|
|
13 static void update_progressbar(gfloat val);
|
|
14
|
|
15 static gint file_is_hidden(gchar *name);
|
|
16 static gint file_is_in_filter(gchar *name);
|
|
17 static void add_to_filter(gchar *text, gint add);
|
|
18
|
|
19 static gint sort_list_cb(void *a, void *b);
|
|
20 static void filelist_read(gchar *path);
|
|
21
|
|
22 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list);
|
|
23
|
|
24 static void history_menu_select_cb(GtkWidget *widget, gpointer data);
|
|
25 static gchar *truncate_hist_text(gchar *t, gint l);
|
|
26 static void filelist_set_history(gchar *path);
|
|
27
|
|
28 /*
|
|
29 *-----------------------------------------------------------------------------
|
|
30 * file status information (private)
|
|
31 *-----------------------------------------------------------------------------
|
|
32 */
|
|
33
|
|
34 static void update_progressbar(gfloat val)
|
|
35 {
|
|
36 gtk_progress_bar_update (GTK_PROGRESS_BAR(info_progress_bar), val);
|
|
37 }
|
|
38
|
|
39 void update_status_label(gchar *text)
|
|
40 {
|
|
41 gchar *buf;
|
|
42 gint count;
|
|
43 gchar *ss = "";
|
|
44
|
|
45 if (text)
|
|
46 {
|
|
47 gtk_label_set(GTK_LABEL(info_status), text);
|
|
48 return;
|
|
49 }
|
|
50
|
|
51 if (slideshow_is_running()) ss = _(" Slideshow");
|
|
52
|
|
53 count = file_selection_count();
|
|
54 if (count > 0)
|
|
55 buf = g_strdup_printf(_("%d files (%d)%s"), file_count(), count, ss);
|
|
56 else
|
|
57 buf = g_strdup_printf(_("%d files%s"), file_count(), ss);
|
|
58
|
|
59 gtk_label_set(GTK_LABEL(info_status), buf);
|
|
60 g_free(buf);
|
|
61 }
|
|
62
|
|
63 /*
|
|
64 *-----------------------------------------------------------------------------
|
|
65 * file filtering
|
|
66 *-----------------------------------------------------------------------------
|
|
67 */
|
|
68
|
|
69 static gint file_is_hidden(gchar *name)
|
|
70 {
|
|
71 if (name[0] != '.') return FALSE;
|
|
72 if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE;
|
|
73 return TRUE;
|
|
74 }
|
|
75
|
|
76 static gint file_is_in_filter(gchar *name)
|
|
77 {
|
|
78 GList *work;
|
|
79 if (!filename_filter || file_filter_disable) return TRUE;
|
|
80
|
|
81 work = filename_filter;
|
|
82 while (work)
|
|
83 {
|
|
84 gchar *filter = work->data;
|
|
85 gint lf = strlen(filter);
|
|
86 gint ln = strlen(name);
|
|
87 if (ln >= lf)
|
|
88 {
|
|
89 if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE;
|
|
90 }
|
|
91 work = work->next;
|
|
92 }
|
|
93
|
|
94 return FALSE;
|
|
95 }
|
|
96
|
|
97 static void add_to_filter(gchar *text, gint add)
|
|
98 {
|
|
99 if (add) filename_filter = g_list_append(filename_filter, g_strdup(text));
|
|
100 }
|
|
101
|
|
102 void rebuild_file_filter()
|
|
103 {
|
|
104 if (filename_filter)
|
|
105 {
|
|
106 g_list_foreach(filename_filter,(GFunc)g_free,NULL);
|
|
107 g_list_free(filename_filter);
|
|
108 filename_filter = NULL;
|
|
109 }
|
|
110
|
|
111 add_to_filter(".jpg", filter_include_jpg);
|
|
112 add_to_filter(".jpeg", filter_include_jpg);
|
|
113 add_to_filter(".xpm", filter_include_xpm);
|
|
114 add_to_filter(".tif", filter_include_tif);
|
|
115 add_to_filter(".tiff", filter_include_tif);
|
|
116 add_to_filter(".gif", filter_include_gif);
|
|
117 add_to_filter(".png", filter_include_png);
|
|
118 add_to_filter(".ppm", filter_include_ppm);
|
|
119 add_to_filter(".pgm", filter_include_pgm);
|
|
120 add_to_filter(".pcx", filter_include_pcx);
|
|
121 add_to_filter(".bmp", filter_include_bmp);
|
|
122
|
|
123 if (custom_filter)
|
|
124 {
|
|
125 gchar *buf = g_strdup(custom_filter);
|
|
126 gchar *pos_ptr_b;
|
3
|
127 gchar *pos_ptr_e = buf;
|
1
|
128 while(pos_ptr_e[0] != '\0')
|
|
129 {
|
|
130 pos_ptr_b = pos_ptr_e;
|
|
131 while (pos_ptr_e[0] != ';' && pos_ptr_e[0] != '\0') pos_ptr_e++;
|
|
132 if (pos_ptr_e[0] == ';')
|
|
133 {
|
|
134 pos_ptr_e[0] = '\0';
|
|
135 pos_ptr_e++;
|
|
136 }
|
|
137 add_to_filter(pos_ptr_b, TRUE);
|
|
138 }
|
|
139 g_free(buf);
|
|
140 }
|
|
141 }
|
|
142
|
|
143 /*
|
|
144 *-----------------------------------------------------------------------------
|
|
145 * load file list (private)
|
|
146 *-----------------------------------------------------------------------------
|
|
147 */
|
|
148
|
|
149 static gint sort_list_cb(void *a, void *b)
|
|
150 {
|
|
151 return strcmp((gchar *)a, (gchar *)b);
|
|
152 }
|
|
153
|
|
154 static void filelist_read(gchar *path)
|
|
155 {
|
|
156 DIR *dp;
|
|
157 struct dirent *dir;
|
|
158 struct stat ent_sbuf;
|
|
159
|
|
160 if((dp = opendir(path))==NULL)
|
|
161 {
|
|
162 /* dir not found */
|
|
163 return;
|
|
164 }
|
|
165
|
|
166 g_list_foreach(dir_list,(GFunc)g_free,NULL);
|
|
167 g_list_free(dir_list);
|
|
168 dir_list = NULL;
|
|
169
|
|
170 g_list_foreach(file_list,(GFunc)g_free,NULL);
|
|
171 g_list_free(file_list);
|
|
172 file_list = NULL;
|
|
173
|
|
174 while ((dir = readdir(dp)) != NULL)
|
|
175 {
|
|
176 /* skips removed files */
|
|
177 if (dir->d_ino > 0)
|
|
178 {
|
|
179 gchar *name = dir->d_name;
|
|
180 if (show_dot_files || !file_is_hidden(name))
|
|
181 {
|
|
182 gchar *filepath = g_strconcat(path, "/", name, NULL);
|
|
183 if (stat(filepath,&ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
|
|
184 {
|
|
185 dir_list = g_list_prepend(dir_list, g_strdup(name));
|
|
186 }
|
|
187 else
|
|
188 {
|
|
189 if (file_is_in_filter(name))
|
|
190 file_list = g_list_prepend(file_list, g_strdup(name));
|
|
191 }
|
|
192 g_free(filepath);
|
|
193 }
|
|
194 }
|
|
195 }
|
|
196
|
|
197 closedir(dp);
|
|
198
|
|
199 dir_list = g_list_sort(dir_list, (GCompareFunc) sort_list_cb);
|
|
200 file_list = g_list_sort(file_list, (GCompareFunc) sort_list_cb);
|
|
201 }
|
|
202
|
|
203 /*
|
|
204 *-----------------------------------------------------------------------------
|
|
205 * file list utilities to retrieve information (public)
|
|
206 *-----------------------------------------------------------------------------
|
|
207 */
|
|
208
|
|
209 gint file_count()
|
|
210 {
|
|
211 return g_list_length(file_list);
|
|
212 }
|
|
213
|
|
214 gint file_selection_count()
|
|
215 {
|
|
216 gint count = 0;
|
|
217 GList *work = GTK_CLIST(file_clist)->selection;
|
|
218 while(work)
|
|
219 {
|
|
220 count++;
|
|
221 if (debug) printf("s = %d\n", GPOINTER_TO_INT(work->data));
|
|
222 work = work->next;
|
|
223 }
|
|
224
|
|
225 if (debug) printf("files selected = %d\n", count);
|
|
226
|
|
227 return count;
|
|
228 }
|
|
229
|
|
230 gint find_file_in_list(gchar *path)
|
|
231 {
|
|
232 GList *work = file_list;
|
|
233 gchar *buf;
|
|
234 gchar *name;
|
|
235 gint count = -1;
|
|
236
|
|
237 if (!path) return -1;
|
|
238
|
|
239 buf = remove_level_from_path(path);
|
|
240 if (strcmp(buf, current_path) != 0)
|
|
241 {
|
|
242 g_free(buf);
|
|
243 return -1;
|
|
244 }
|
|
245 g_free(buf);
|
|
246
|
|
247 name = filename_from_path(path);
|
|
248 while(work)
|
|
249 {
|
|
250 count++;
|
|
251 if (strcmp(name, work->data) == 0) return count;
|
|
252 work = work->next;
|
|
253 }
|
|
254
|
|
255 return -1;
|
|
256 }
|
|
257
|
|
258 gchar *file_get_path(gint row)
|
|
259 {
|
|
260 gchar *path = NULL;
|
|
261 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
|
|
262
|
|
263 if (name) path = g_strconcat(current_path, "/", name, NULL);
|
|
264
|
|
265 return path;
|
|
266 }
|
|
267
|
|
268 gint file_is_selected(gint row)
|
|
269 {
|
|
270 GList *work = GTK_CLIST(file_clist)->selection;
|
|
271
|
|
272 while(work)
|
|
273 {
|
|
274 if (GPOINTER_TO_INT(work->data) == row) return TRUE;
|
|
275 work = work->next;
|
|
276 }
|
|
277
|
|
278 return FALSE;
|
|
279 }
|
|
280
|
|
281 /*
|
|
282 *-----------------------------------------------------------------------------
|
|
283 * utilities to retrieve list of selected files (public)
|
|
284 *-----------------------------------------------------------------------------
|
|
285 */
|
|
286
|
|
287 GList *file_get_selected_list()
|
|
288 {
|
|
289 GList *list = NULL;
|
|
290 GList *work = GTK_CLIST(file_clist)->selection;
|
|
291
|
|
292 while(work)
|
|
293 {
|
|
294 gchar *name = gtk_clist_get_row_data(GTK_CLIST(file_clist),
|
|
295 GPOINTER_TO_INT(work->data));
|
|
296 list = g_list_prepend(list, g_strconcat(current_path, "/", name, NULL));
|
|
297 work = work->next;
|
|
298 }
|
|
299
|
|
300 list = g_list_reverse(list);
|
|
301
|
|
302 return list;
|
|
303 }
|
|
304
|
|
305 void free_selected_list(GList *list)
|
|
306 {
|
|
307 g_list_foreach(list, (GFunc)g_free, NULL);
|
|
308 g_list_free(list);
|
|
309 }
|
|
310
|
|
311 gint file_clicked_is_selected()
|
|
312 {
|
|
313 return file_is_selected(filelist_click_row);
|
|
314 }
|
|
315
|
|
316 gchar *file_clicked_get_path()
|
|
317 {
|
|
318 return file_get_path(filelist_click_row);
|
|
319 }
|
|
320
|
|
321 /*
|
|
322 *-----------------------------------------------------------------------------
|
|
323 * image change routines
|
|
324 *-----------------------------------------------------------------------------
|
|
325 */
|
|
326
|
|
327 void file_image_change_to(gint row)
|
|
328 {
|
|
329 gtk_clist_unselect_all(GTK_CLIST(file_clist));
|
|
330 gtk_clist_select_row(GTK_CLIST(file_clist), row, -1);
|
|
331 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), row) != GTK_VISIBILITY_FULL)
|
|
332 {
|
|
333 gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
|
|
334 }
|
|
335 }
|
|
336
|
|
337 void file_next_image()
|
|
338 {
|
3
|
339 gint current;
|
|
340 gint total;
|
|
341
|
|
342 if (slideshow_is_running())
|
|
343 {
|
|
344 slideshow_next();
|
|
345 return;
|
|
346 }
|
|
347
|
|
348 current = find_file_in_list(image_get_path());
|
|
349 total = file_count();
|
1
|
350
|
|
351 if (current >= 0)
|
|
352 {
|
|
353 if (current < total - 1)
|
|
354 {
|
|
355 file_image_change_to(current + 1);
|
|
356 }
|
|
357 }
|
|
358 else
|
|
359 {
|
|
360 file_image_change_to(0);
|
|
361 }
|
|
362 }
|
|
363
|
|
364 void file_prev_image()
|
|
365 {
|
3
|
366 gint current;
|
|
367
|
|
368 if (slideshow_is_running())
|
|
369 {
|
|
370 slideshow_prev();
|
|
371 return;
|
|
372 }
|
|
373
|
|
374 current = find_file_in_list(image_get_path());
|
1
|
375
|
|
376 if (current >= 0)
|
|
377 {
|
|
378 if (current > 0)
|
|
379 {
|
|
380 file_image_change_to(current - 1);
|
|
381 }
|
|
382 }
|
|
383 else
|
|
384 {
|
|
385 file_image_change_to(file_count() - 1);
|
|
386 }
|
|
387 }
|
|
388
|
|
389 void file_first_image()
|
|
390 {
|
|
391 gint current = find_file_in_list(image_get_path());
|
|
392 if (current != 0 && file_count() > 0)
|
|
393 {
|
|
394 file_image_change_to(0);
|
|
395 }
|
|
396 }
|
|
397
|
|
398 void file_last_image()
|
|
399 {
|
|
400 gint current = find_file_in_list(image_get_path());
|
|
401 gint count = file_count();
|
|
402 if (current != count - 1 && count > 0)
|
|
403 {
|
|
404 file_image_change_to(count - 1);
|
|
405 }
|
|
406 }
|
|
407
|
|
408 /*
|
|
409 *-----------------------------------------------------------------------------
|
|
410 * file delete/rename update routines
|
|
411 *-----------------------------------------------------------------------------
|
|
412 */
|
|
413
|
|
414 static gint file_find_closest_unaccounted(gint row, gint count, GList *ignore_list)
|
|
415 {
|
|
416 GList *list = NULL;
|
|
417 GList *work;
|
|
418 gint rev = row - 1;
|
|
419 row ++;
|
|
420
|
|
421 work = ignore_list;
|
|
422 while(work)
|
|
423 {
|
|
424 gint f = find_file_in_list(work->data);
|
|
425 if (f >= 0) list = g_list_append(list, GINT_TO_POINTER(f));
|
|
426 work = work->next;
|
|
427 }
|
|
428
|
|
429 while(list)
|
|
430 {
|
|
431 gint c = TRUE;
|
|
432 work = list;
|
|
433 while(work && c)
|
|
434 {
|
|
435 gpointer p = work->data;
|
|
436 work = work->next;
|
|
437 if (row == GPOINTER_TO_INT(p))
|
|
438 {
|
|
439 row++;
|
|
440 c = FALSE;
|
|
441 }
|
|
442 if (rev == GPOINTER_TO_INT(p))
|
|
443 {
|
|
444 rev--;
|
|
445 c = FALSE;
|
|
446 }
|
|
447 if (!c) list = g_list_remove(list, p);
|
|
448 }
|
|
449 if (c && list)
|
|
450 {
|
|
451 g_list_free(list);
|
|
452 list = NULL;
|
|
453 }
|
|
454 }
|
|
455 if (row > count - 1)
|
|
456 {
|
|
457 if (rev < 0)
|
|
458 return -1;
|
|
459 else
|
|
460 return rev;
|
|
461 }
|
|
462 else
|
|
463 {
|
|
464 return row;
|
|
465 }
|
|
466 }
|
|
467
|
|
468 void file_is_gone(gchar *path, GList *ignore_list)
|
|
469 {
|
|
470 GList *list;
|
|
471 gchar *name;
|
|
472 gint row;
|
|
473 gint new_row = -1;
|
|
474 row = find_file_in_list(path);
|
|
475 if (row < 0) return;
|
|
476
|
|
477 if (file_is_selected(row) /* && file_selection_count() == 1 */)
|
|
478 {
|
|
479 gint n = file_count();
|
|
480 if (ignore_list)
|
|
481 {
|
|
482 new_row = file_find_closest_unaccounted(row, n, ignore_list);
|
|
483 if (debug) printf("row = %d, closest is %d\n", row, new_row);
|
|
484 }
|
|
485 else
|
|
486 {
|
|
487 if (row + 1 < n)
|
|
488 {
|
|
489 new_row = row + 1;
|
|
490 }
|
|
491 else if (row > 0)
|
|
492 {
|
|
493 new_row = row - 1;
|
|
494 }
|
|
495 }
|
|
496 gtk_clist_unselect_all(GTK_CLIST(file_clist));
|
|
497 if (new_row >= 0)
|
|
498 {
|
|
499 gtk_clist_select_row(GTK_CLIST(file_clist), new_row, -1);
|
|
500 file_image_change_to(new_row);
|
|
501 }
|
|
502 else
|
|
503 {
|
|
504 image_change_to(NULL);
|
|
505 }
|
|
506 }
|
|
507
|
|
508 gtk_clist_remove(GTK_CLIST(file_clist), row);
|
|
509 list = g_list_nth(file_list, row);
|
|
510 name = list->data;
|
|
511 file_list = g_list_remove(file_list, name);
|
|
512 g_free(name);
|
|
513 update_status_label(NULL);
|
|
514 }
|
|
515
|
|
516 void file_is_renamed(gchar *source, gchar *dest)
|
|
517 {
|
|
518 gint row;
|
|
519 gchar *source_base;
|
|
520 gchar *dest_base;
|
|
521
|
|
522 if (image_get_path() && !strcmp(source, image_get_path()))
|
|
523 {
|
|
524 image_set_path(dest);
|
|
525 }
|
|
526
|
|
527 row = find_file_in_list(source);
|
|
528 if (row < 0) return;
|
|
529
|
|
530 source_base = remove_level_from_path(source);
|
|
531 dest_base = remove_level_from_path(dest);
|
|
532
|
|
533 if (strcmp(source_base, dest_base) == 0)
|
|
534 {
|
|
535 gchar *name;
|
|
536 gint n;
|
|
537 GList *work = g_list_nth(file_list, row);
|
|
538 name = work->data;
|
|
539 file_list = g_list_remove(file_list, name);
|
|
540 g_free(name);
|
|
541 name = g_strdup(filename_from_path(dest));
|
|
542 file_list = g_list_insert_sorted(file_list, name, (GCompareFunc) sort_list_cb);
|
|
543 n = g_list_index(file_list, name);
|
|
544
|
|
545 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist), row, 0) != GTK_CELL_PIXTEXT)
|
|
546 {
|
|
547 gtk_clist_set_text (GTK_CLIST(file_clist), row, 0, name);
|
|
548 }
|
|
549 else
|
|
550 {
|
|
551 guint8 spacing = 0;
|
|
552 GdkPixmap *pixmap = NULL;
|
|
553 GdkBitmap *mask = NULL;
|
|
554 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row, 0,
|
|
555 NULL, &spacing, &pixmap, &mask);
|
|
556 gtk_clist_set_pixtext(GTK_CLIST(file_clist), row, 0,
|
|
557 name, spacing, pixmap, mask);
|
|
558 }
|
|
559
|
|
560 gtk_clist_set_row_data(GTK_CLIST(file_clist), row, name);
|
|
561 gtk_clist_row_move(GTK_CLIST(file_clist), row, n);
|
|
562 }
|
|
563 else
|
|
564 {
|
|
565 GList *work = g_list_nth(file_list, row);
|
|
566 gchar *name = work->data;
|
|
567 file_list = g_list_remove(file_list, name);
|
|
568 gtk_clist_remove(GTK_CLIST(file_clist), row);
|
|
569 g_free(name);
|
|
570 update_status_label(NULL);
|
|
571 }
|
|
572
|
|
573 g_free(source_base);
|
|
574 g_free(dest_base);
|
|
575
|
|
576 }
|
|
577
|
|
578 /*
|
|
579 *-----------------------------------------------------------------------------
|
|
580 * directory list callbacks
|
|
581 *-----------------------------------------------------------------------------
|
|
582 */
|
|
583
|
|
584 void dir_select_cb(GtkWidget *widget, gint row, gint col,
|
|
585 GdkEvent *event, gpointer data)
|
|
586 {
|
|
587 gchar *name;
|
|
588 gchar *new_path;
|
|
589 name = gtk_clist_get_row_data (GTK_CLIST(dir_clist), row);
|
|
590 if (strcmp(name, ".") == 0)
|
|
591 {
|
|
592 new_path = g_strdup(current_path);
|
|
593 }
|
|
594 else if (strcmp(name, "..") == 0)
|
|
595 {
|
|
596 new_path = remove_level_from_path(current_path);
|
|
597 }
|
|
598 else
|
|
599 {
|
|
600 if (strcmp(current_path, "/") == 0)
|
|
601 new_path = g_strconcat(current_path, name, NULL);
|
|
602 else
|
|
603 new_path = g_strconcat(current_path, "/", name, NULL);
|
|
604 }
|
|
605 filelist_change_to(new_path);
|
|
606 g_free(new_path);
|
|
607 }
|
|
608
|
|
609 void dir_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
|
|
610 {
|
|
611 gint row = -1;
|
|
612 gint col = -1;
|
|
613
|
|
614 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
|
|
615
|
|
616 if (bevent->button == 2)
|
|
617 {
|
|
618 gtk_object_set_user_data(GTK_OBJECT(dir_clist), GINT_TO_POINTER(row));
|
|
619 }
|
|
620 }
|
|
621
|
|
622 /*
|
|
623 *-----------------------------------------------------------------------------
|
|
624 * file list callbacks
|
|
625 *-----------------------------------------------------------------------------
|
|
626 */
|
|
627
|
|
628 void file_press_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
|
|
629 {
|
|
630 gint row = -1;
|
|
631 gint col = -1;
|
|
632
|
|
633 gtk_clist_get_selection_info (GTK_CLIST (widget), bevent->x, bevent->y, &row, &col);
|
|
634 if (row == -1 || col == -1)
|
|
635 {
|
|
636 filelist_click_row = -1;
|
|
637 return;
|
|
638 }
|
|
639
|
|
640 filelist_click_row = row;
|
|
641
|
|
642 if (bevent->button == 3)
|
|
643 {
|
|
644 file_clist_highlight_set();
|
|
645 gtk_menu_popup (GTK_MENU(menu_file_popup), NULL, NULL, NULL, NULL,
|
|
646 bevent->button, bevent->time);
|
|
647 }
|
|
648 }
|
|
649
|
|
650 void file_select_cb(GtkWidget *widget, gint row, gint col,
|
|
651 GdkEvent *event, gpointer data)
|
|
652 {
|
|
653 gchar *name;
|
|
654 gchar *path;
|
|
655
|
|
656 if (file_selection_count() != 1)
|
|
657 {
|
|
658 update_status_label(NULL);
|
|
659 return;
|
|
660 }
|
|
661
|
|
662 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
|
|
663 path = g_strconcat(current_path, "/", name, NULL);
|
|
664 image_change_to(path);
|
|
665 update_status_label(NULL);
|
|
666 g_free(path);
|
|
667 }
|
|
668
|
|
669 void file_unselect_cb(GtkWidget *widget, gint row, gint col,
|
|
670 GdkEvent *event, gpointer data)
|
|
671 {
|
|
672 #if 0
|
|
673 gchar *name;
|
|
674 gchar *path;
|
|
675
|
|
676 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), row);
|
|
677 path = g_strconcat(current_path, "/", name, NULL);
|
|
678
|
|
679 if (strcmp(path, image_get_path()) == 0)
|
|
680 {
|
|
681 if (file_selection_count() > 0 && !file_is_selected(find_file_in_list(image_get_path())) )
|
|
682 {
|
|
683 gint new_row = GPOINTER_TO_INT(GTK_CLIST(file_clist)->selection->data);
|
|
684 gchar *new_name = gtk_clist_get_row_data(GTK_CLIST(file_clist), new_row);
|
|
685 gchar *new_path = g_strconcat(current_path, "/", new_name, NULL);
|
|
686 image_change_to(new_path);
|
|
687 g_free(new_path);
|
|
688 }
|
|
689 }
|
|
690 g_free(path);
|
|
691 #endif
|
|
692 update_status_label(NULL);
|
|
693 }
|
|
694
|
|
695 /*
|
|
696 *-----------------------------------------------------------------------------
|
|
697 * file list highlight utils
|
|
698 *-----------------------------------------------------------------------------
|
|
699 */
|
|
700
|
|
701 void file_clist_highlight_set()
|
|
702 {
|
|
703 if (file_clicked_is_selected()) return;
|
|
704
|
|
705 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row,
|
|
706 >K_WIDGET (file_clist)->style->bg[GTK_STATE_PRELIGHT]);
|
|
707 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row,
|
|
708 >K_WIDGET (file_clist)->style->fg[GTK_STATE_PRELIGHT]);
|
|
709 }
|
|
710
|
|
711 void file_clist_highlight_unset()
|
|
712 {
|
|
713 if (file_clicked_is_selected()) return;
|
|
714
|
|
715 gtk_clist_set_background(GTK_CLIST(file_clist), filelist_click_row, NULL);
|
|
716 gtk_clist_set_foreground(GTK_CLIST(file_clist), filelist_click_row, NULL);
|
|
717 }
|
|
718
|
|
719 /*
|
|
720 *-----------------------------------------------------------------------------
|
|
721 * path entry and history menu
|
|
722 *-----------------------------------------------------------------------------
|
|
723 */
|
|
724
|
3
|
725 void path_entry_tab_cb(gchar *newdir, gpointer data)
|
|
726 {
|
|
727 gchar *new_path;
|
|
728 gchar *buf;
|
|
729 gint found = FALSE;
|
|
730
|
|
731 new_path = g_strdup(newdir);
|
|
732 parse_out_relatives(new_path);
|
|
733 buf = remove_level_from_path(new_path);
|
|
734
|
|
735 if (buf && current_path && strcmp(buf, current_path) == 0)
|
|
736 {
|
|
737 GList *work;
|
|
738 gchar *part;
|
|
739
|
|
740 part = filename_from_path(new_path);
|
|
741 work = file_list;
|
|
742
|
|
743 while(part && work)
|
|
744 {
|
|
745 gchar *name = work->data;
|
|
746 work = work->next;
|
|
747
|
|
748 if (strncmp(part, name, strlen(part)) == 0)
|
|
749 {
|
|
750 gint row = g_list_index(file_list, name);
|
|
751 if (!gtk_clist_row_is_visible(GTK_CLIST(file_clist), row) != GTK_VISIBILITY_FULL)
|
|
752 {
|
|
753 gtk_clist_moveto(GTK_CLIST(file_clist), row, -1, 0.5, 0.0);
|
|
754 }
|
|
755 found = TRUE;
|
|
756 break;
|
|
757 }
|
|
758 }
|
|
759 }
|
|
760
|
|
761 if (!found && new_path && current_path &&
|
|
762 strcmp(new_path, current_path) != 0 && isdir(new_path))
|
|
763 {
|
|
764 filelist_change_to(new_path);
|
|
765 /* we are doing tab completion, add '/' back */
|
|
766 gtk_entry_append_text(GTK_ENTRY(path_entry), "/");
|
|
767 }
|
|
768
|
|
769 g_free(buf);
|
|
770 g_free(new_path);
|
|
771 }
|
|
772
|
1
|
773 void path_entry_cb(gchar *newdir, gpointer data)
|
|
774 {
|
|
775 gchar *new_path = g_strdup(newdir);
|
|
776 parse_out_relatives(new_path);
|
|
777 if (isdir(new_path))
|
|
778 filelist_change_to(new_path);
|
|
779 else if (isfile(new_path))
|
|
780 {
|
|
781 gchar *path = remove_level_from_path(new_path);
|
|
782 filelist_change_to(path);
|
|
783 g_free(path);
|
|
784 image_change_to(new_path);
|
|
785 }
|
|
786 g_free(new_path);
|
|
787 }
|
|
788
|
|
789 static void history_menu_select_cb(GtkWidget *widget, gpointer data)
|
|
790 {
|
|
791 gchar *new_path = data;
|
|
792 filelist_change_to(new_path);
|
|
793 }
|
|
794
|
|
795 static gchar *truncate_hist_text(gchar *t, gint l)
|
|
796 {
|
|
797 gchar *tp;
|
|
798 gchar *tbuf;
|
|
799 if (l >= strlen(t)) return g_strdup(t);
|
|
800 tp = t + strlen(t) - l;
|
|
801 while (tp[0] != '/' && tp < t + strlen(t)) tp++;
|
|
802 /* this checks to see if directory name is longer than l, if so
|
|
803 * reset the length of name to l, it's better to have a partial
|
|
804 * name than no name at all.
|
|
805 */
|
|
806 if (tp >= t + strlen(t)) tp = t + strlen(t) - l;
|
|
807 tbuf = g_strconcat("/...", tp, NULL);
|
|
808 return tbuf;
|
|
809 }
|
|
810
|
|
811 static void filelist_set_history(gchar *path)
|
|
812 {
|
|
813 static GList *history_list = NULL;
|
|
814 gchar *buf;
|
|
815 gchar *buf_ptr;
|
|
816 GtkWidget *menu;
|
|
817 GtkWidget *item;
|
|
818
|
|
819 if (!path) return;
|
|
820
|
|
821 gtk_entry_set_text(GTK_ENTRY(path_entry), current_path);
|
|
822
|
|
823 if (history_list)
|
|
824 {
|
|
825 g_list_foreach(history_list, (GFunc)g_free, NULL);
|
|
826 g_list_free(history_list);
|
|
827 history_list = NULL;
|
|
828 }
|
|
829
|
|
830 menu = gtk_menu_new();
|
|
831
|
|
832 buf = g_strdup(path);
|
|
833 buf_ptr = buf + strlen(buf) - 1 ;
|
|
834 while (buf_ptr > buf)
|
|
835 {
|
|
836 gchar *full_path;
|
|
837 gchar *truncated;
|
|
838 truncated = truncate_hist_text(buf, 32);
|
|
839
|
|
840 full_path = g_strdup(buf);
|
|
841 history_list = g_list_append(history_list, full_path);
|
|
842
|
|
843 item = gtk_menu_item_new_with_label (truncated);
|
|
844 gtk_signal_connect (GTK_OBJECT (item), "activate",
|
|
845 (GtkSignalFunc) history_menu_select_cb, full_path);
|
|
846
|
|
847 gtk_menu_append (GTK_MENU (menu), item);
|
|
848 gtk_widget_show (item);
|
|
849
|
|
850 g_free(truncated);
|
|
851
|
|
852 while (buf_ptr[0] != '/' && buf_ptr > buf) buf_ptr--;
|
|
853 buf_ptr[0] = '\0';
|
|
854 }
|
|
855 g_free(buf);
|
|
856
|
|
857 item = gtk_menu_item_new_with_label ("/");
|
|
858
|
|
859 gtk_signal_connect (GTK_OBJECT (item), "activate",
|
|
860 (GtkSignalFunc) history_menu_select_cb, "/");
|
|
861
|
|
862 gtk_menu_append (GTK_MENU (menu), item);
|
|
863 gtk_widget_show (item);
|
|
864
|
|
865 gtk_option_menu_set_menu(GTK_OPTION_MENU(history_menu), menu);
|
|
866 }
|
|
867
|
|
868 /*
|
|
869 *-----------------------------------------------------------------------------
|
|
870 * list update routines (public)
|
|
871 *-----------------------------------------------------------------------------
|
|
872 */
|
|
873
|
|
874 static gint thumbs_running = 0;
|
|
875
|
|
876 void interrupt_thumbs()
|
|
877 {
|
|
878 if (thumbs_running > 0) thumbs_running ++;
|
|
879 }
|
|
880
|
|
881 void filelist_populate_clist()
|
|
882 {
|
|
883 GList *work;
|
|
884 gint width;
|
|
885 gint tmp_width;
|
|
886 gint row;
|
|
887 gchar *image_name = NULL;
|
|
888 gchar *buf;
|
|
889
|
|
890 gint row_p = 0;
|
|
891 gchar *text;
|
|
892 guint8 spacing;
|
|
893 GdkPixmap *nopixmap;
|
|
894 GdkBitmap *nomask;
|
|
895
|
|
896 interrupt_thumbs();
|
|
897
|
|
898 filelist_set_history(current_path);
|
|
899
|
|
900 gtk_clist_freeze (GTK_CLIST (dir_clist));
|
|
901 gtk_clist_clear (GTK_CLIST (dir_clist));
|
|
902
|
|
903 width = 0;
|
|
904 work = dir_list;
|
|
905 while(work)
|
|
906 {
|
|
907 gchar *buf[2];
|
|
908 buf[0] = work->data;
|
|
909 buf[1] = NULL;
|
|
910 row = gtk_clist_append(GTK_CLIST(dir_clist), buf);
|
|
911 gtk_clist_set_row_data (GTK_CLIST(dir_clist), row, work->data);
|
|
912 tmp_width = gdk_string_width(dir_clist->style->font, buf[0]);
|
|
913 if (tmp_width > width) width = tmp_width;
|
|
914 work = work->next;
|
|
915 }
|
|
916
|
|
917 gtk_clist_set_column_width(GTK_CLIST(dir_clist), 0, width);
|
|
918 gtk_clist_thaw(GTK_CLIST (dir_clist));
|
|
919
|
|
920 buf = remove_level_from_path(image_get_path());
|
|
921 if (buf && strcmp(buf, current_path) == 0)
|
|
922 {
|
|
923 image_name = image_get_name();
|
|
924 }
|
|
925 g_free(buf);
|
|
926
|
|
927 gtk_clist_freeze (GTK_CLIST (file_clist));
|
|
928
|
|
929 if (!thumbnails_enabled)
|
|
930 {
|
|
931 gtk_clist_set_row_height (GTK_CLIST(file_clist),
|
|
932 GTK_WIDGET(file_clist)->style->font->ascent +
|
|
933 GTK_WIDGET(file_clist)->style->font->descent + 1);
|
|
934 }
|
|
935 else
|
|
936 {
|
|
937 gtk_clist_set_row_height (GTK_CLIST(file_clist), thumb_max_height + 2);
|
|
938 maintain_thumbnail_dir(current_path, FALSE);
|
|
939 }
|
|
940
|
|
941 width = 0;
|
|
942 work = file_list;
|
|
943
|
|
944 while(work)
|
|
945 {
|
|
946 gint has_pixmap;
|
|
947 gint match;
|
|
948 gchar *name = work->data;
|
|
949 gint done = FALSE;
|
|
950
|
|
951 while (!done)
|
|
952 {
|
|
953 if (GTK_CLIST(file_clist)->rows > row_p)
|
|
954 {
|
|
955 if (gtk_clist_get_cell_type(GTK_CLIST(file_clist),row_p, 0) == GTK_CELL_PIXTEXT)
|
|
956 {
|
|
957 gtk_clist_get_pixtext(GTK_CLIST(file_clist), row_p, 0, &text, &spacing, &nopixmap, &nomask);
|
|
958 has_pixmap = TRUE;
|
|
959 }
|
|
960 else
|
|
961 {
|
|
962 gtk_clist_get_text(GTK_CLIST(file_clist), row_p, 0, &text);
|
|
963 has_pixmap = FALSE;
|
|
964 }
|
|
965 match = strcmp(name, text);
|
|
966 }
|
|
967 else
|
|
968 {
|
|
969 match = -1;
|
|
970 }
|
|
971
|
|
972 if (match < 0)
|
|
973 {
|
|
974 gchar *buf[2];
|
|
975 buf[0] = name;
|
|
976 buf[1] = NULL;
|
|
977 row = gtk_clist_insert(GTK_CLIST(file_clist), row_p, buf);
|
|
978 gtk_clist_set_row_data (GTK_CLIST(file_clist), row, name);
|
|
979 if (thumbnails_enabled)
|
|
980 gtk_clist_set_shift(GTK_CLIST(file_clist), row, 0, 0, 5 + thumb_max_width);
|
|
981 done = TRUE;
|
|
982 if (image_name && strcmp(name, image_name) == 0)
|
|
983 gtk_clist_select_row(GTK_CLIST(file_clist), row, 0);
|
|
984 }
|
|
985 else if (match > 0)
|
|
986 {
|
|
987 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
|
|
988 }
|
|
989 else
|
|
990 {
|
|
991 if (thumbnails_enabled && !has_pixmap)
|
|
992 gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 5 + thumb_max_width);
|
|
993 if (!thumbnails_enabled/* && has_pixmap*/)
|
|
994 {
|
|
995 gtk_clist_set_text(GTK_CLIST(file_clist), row_p, 0, name);
|
|
996 gtk_clist_set_shift(GTK_CLIST(file_clist), row_p, 0, 0, 0);
|
|
997 }
|
|
998 gtk_clist_set_row_data (GTK_CLIST(file_clist), row_p, name);
|
|
999 done = TRUE;
|
|
1000 }
|
|
1001 }
|
|
1002 row_p++;
|
|
1003
|
|
1004 if (thumbnails_enabled)
|
|
1005 tmp_width = gdk_string_width(file_clist->style->font, name) + thumb_max_width + 5;
|
|
1006 else
|
|
1007 tmp_width = gdk_string_width(file_clist->style->font, name);
|
|
1008 if (tmp_width > width) width = tmp_width;
|
|
1009 work = work->next;
|
|
1010 }
|
|
1011
|
|
1012 while (GTK_CLIST(file_clist)->rows > row_p)
|
|
1013 gtk_clist_remove(GTK_CLIST(file_clist), row_p);
|
|
1014
|
|
1015 gtk_clist_set_column_width(GTK_CLIST(file_clist), 0, width);
|
|
1016 gtk_clist_thaw(GTK_CLIST (file_clist));
|
|
1017
|
|
1018 if (thumbnails_enabled)
|
|
1019 {
|
|
1020 GList *done_list = NULL;
|
|
1021 gint past_run;
|
|
1022 gint finished = FALSE;
|
|
1023 gint j;
|
|
1024 gint count = 0;
|
|
1025 update_status_label(_("Loading thumbs..."));
|
|
1026
|
|
1027 for (j = 0; j < GTK_CLIST(file_clist)->rows; j++)
|
|
1028 {
|
|
1029 done_list = g_list_prepend(done_list, GINT_TO_POINTER(FALSE));
|
|
1030 }
|
|
1031
|
|
1032 /* load thumbs */
|
|
1033
|
|
1034 while (!finished && done_list)
|
|
1035 {
|
|
1036 gint p = -1;
|
|
1037 gint r = -1;
|
|
1038 gint c = -1;
|
|
1039 gtk_clist_get_selection_info (GTK_CLIST(file_clist), 1, 1, &r, &c);
|
|
1040 if (r != -1)
|
|
1041 {
|
|
1042 work = g_list_nth(done_list, r);
|
|
1043 while (work)
|
|
1044 {
|
|
1045 if (gtk_clist_row_is_visible(GTK_CLIST(file_clist), r))
|
|
1046 {
|
|
1047 if (!GPOINTER_TO_INT(work->data))
|
|
1048 {
|
|
1049 work->data = GINT_TO_POINTER(TRUE);
|
|
1050 p = r;
|
|
1051 work = NULL;
|
|
1052 }
|
|
1053 else
|
|
1054 {
|
|
1055 r++;
|
|
1056 work = work->next;
|
|
1057 }
|
|
1058 }
|
|
1059 else
|
|
1060 {
|
|
1061 work = NULL;
|
|
1062 }
|
|
1063 }
|
|
1064 }
|
|
1065 if (p == -1)
|
|
1066 {
|
|
1067 work = done_list;
|
|
1068 r = 0;
|
|
1069 while(work && p == -1)
|
|
1070 {
|
|
1071 if (!GPOINTER_TO_INT(work->data))
|
|
1072 {
|
|
1073 p = r;
|
|
1074 work->data = GINT_TO_POINTER(TRUE);
|
|
1075 }
|
|
1076 else
|
|
1077 {
|
|
1078 r++;
|
|
1079 work = work->next;
|
|
1080 if (!work) finished = TRUE;
|
|
1081 }
|
|
1082 }
|
|
1083 }
|
|
1084
|
|
1085 count++;
|
|
1086
|
|
1087 if (!finished && gtk_clist_get_cell_type(GTK_CLIST(file_clist), p, 0) != GTK_CELL_PIXTEXT)
|
|
1088 {
|
|
1089 GdkPixmap *pixmap = NULL;
|
|
1090 GdkBitmap *mask = NULL;
|
|
1091 gchar *name;
|
|
1092 gchar *path;
|
|
1093
|
|
1094 thumbs_running ++;
|
|
1095 past_run = thumbs_running;
|
|
1096 while(gtk_events_pending()) gtk_main_iteration();
|
|
1097 if (thumbs_running > past_run)
|
|
1098 {
|
|
1099 thumbs_running -= 2;
|
|
1100 update_progressbar(0.0);
|
|
1101 update_status_label(NULL);
|
|
1102 g_list_free(done_list);
|
|
1103 return;
|
|
1104 }
|
|
1105 thumbs_running --;
|
|
1106
|
|
1107 name = gtk_clist_get_row_data(GTK_CLIST(file_clist), p);
|
|
1108 path = g_strconcat (current_path, "/", name, NULL);
|
|
1109 spacing = create_thumbnail(path, &pixmap, &mask);
|
|
1110 g_free(path);
|
|
1111 gtk_clist_set_pixtext (GTK_CLIST(file_clist), p, 0, name, spacing + 5, pixmap, mask);
|
|
1112 gtk_clist_set_shift(GTK_CLIST(file_clist), p, 0, 0, 0);
|
|
1113
|
|
1114 update_progressbar((gfloat)(count) / GTK_CLIST(file_clist)->rows);
|
|
1115 }
|
|
1116 }
|
|
1117 update_progressbar(0.0);
|
|
1118 g_list_free(done_list);
|
|
1119 }
|
|
1120
|
|
1121 update_status_label(NULL);
|
|
1122 }
|
|
1123
|
|
1124 void filelist_refresh()
|
|
1125 {
|
|
1126 filelist_read(current_path);
|
|
1127 filelist_populate_clist();
|
|
1128 filelist_click_row = -1;
|
|
1129 }
|
|
1130
|
|
1131 void filelist_change_to(gchar *path)
|
|
1132 {
|
|
1133 if (!isdir(path)) return;
|
|
1134
|
|
1135 g_free(current_path);
|
|
1136 current_path = g_strdup(path);
|
|
1137
|
|
1138 filelist_refresh();
|
|
1139 }
|