1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2
3 /*
4 * GImageView
5 * Copyright (C) 2001 Takuro Ashie
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * $Id: fileload.c,v 1.50 2004/06/17 03:49:42 makeinu Exp $
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <dirent.h>
30 #include <unistd.h>
31
32 #include "gimageview.h"
33
34 #include "charset.h"
35 #include "fr-command.h"
36 #include "fr-archive.h"
37 #include "gimv_image.h"
38 #include "gfileutil.h"
39 #include "gtkutils.h"
40 #include "prefs.h"
41 #include "fileload.h"
42 #include "fileutil.h"
43 #include "gimv_icon_stock.h"
44 #include "gimv_image_info.h"
45 #include "gimv_image_win.h"
46 #include "gimv_thumb_view.h"
47 #include "gimv_thumb_win.h"
48
49
50 /* for filebrowser call back functions */
51 typedef struct _FileSel
52 {
53 GtkWidget *filebrowser;
54 GimvThumbWin *tw;
55 } FileSel;
56
57
58 static void cb_file_load_cancel (GtkWidget *widget, FilesLoader *files);
59 static void cb_file_load_stop (GtkWidget *widget, FilesLoader *files);
60 static void filebrowser_open_files (FileSel *filesel, ImgWinType type);
61 static void cb_filebrowser_open_selected_files (GtkWidget *widget, FileSel *filesel);
62 static void cb_filebrowser_add_thumbnail (GtkWidget *widget, FileSel *filesel);
63 static void cb_filebrowser_ok_sel (GtkWidget *widget, FileSel *filesel);
64 static void cb_filebrowser_close (GtkWidget *widget, gpointer parent);
65
66
67 GList *files_loader_list = NULL;
68 gboolean loading_stop = FALSE;
69
70
71 FilesLoader *
files_loader_new(void)72 files_loader_new (void)
73 {
74 FilesLoader *files;
75 gboolean reset_sensitive;
76
77 files = g_new0 (FilesLoader, 1);
78 files->filelist = NULL;
79 files->dirlist = NULL;
80 files->dirname = NULL;
81 files->archive = NULL;
82 files->window = NULL;
83 files->progressbar = NULL;
84 files->thumb_load_type = LOAD_CACHE;
85 files->status = GETTING_FILELIST;
86 files->now_file = NULL;
87 files->pos = 0;
88 files->num = 0;
89
90 reset_sensitive = !files_loader_list;
91 files_loader_list = g_list_append (files_loader_list, files);
92
93 if (reset_sensitive) {
94 GList *node = gimv_thumb_win_get_list();
95
96 loading_stop = FALSE;
97
98 while (node) {
99 GimvThumbWin *tw = node->data;
100 gimv_thumb_win_set_sensitive (tw, GIMV_THUMB_WIN_STATUS_LOADING);
101 node = g_list_next (node);
102 }
103 }
104
105 return files;
106 }
107
108
109 void
files_loader_delete(FilesLoader * files)110 files_loader_delete (FilesLoader *files)
111 {
112 g_return_if_fail (files);
113
114 g_list_foreach (files->filelist, (GFunc) g_free, NULL);
115 g_list_foreach (files->dirlist, (GFunc) g_free, NULL);
116
117 g_list_free (files->filelist);
118 g_list_free (files->dirlist);
119
120 files_loader_list = g_list_remove (files_loader_list, files);
121
122 if (!files_loader_list) {
123 GList *node = gimv_thumb_win_get_list();
124 while (node) {
125 GimvThumbWin *tw = node->data;
126 gimv_thumb_win_set_sensitive (tw, GIMV_THUMB_WIN_STATUS_NORMAL);
127 node = g_list_next (node);
128 }
129 }
130
131 if (files->archive)
132 gtk_object_unref (GTK_OBJECT (files->archive));
133
134 loading_stop = FALSE;
135
136 g_free (files);
137 }
138
139
140 gboolean
files_loader_query_loading(void)141 files_loader_query_loading (void)
142 {
143 if (files_loader_list)
144 return TRUE;
145 else
146 return FALSE;
147 }
148
149
150 void
files_loader_stop(void)151 files_loader_stop (void)
152 {
153 GList *node = files_loader_list;
154
155 if (!files_loader_list) return;
156
157 while (node) {
158 FilesLoader *files = node->data;
159 files->status = STOP;
160 if (files->archive
161 && files->archive->process
162 && files->archive->process->running)
163 {
164 fr_process_stop (files->archive->process);
165 }
166 node = g_list_next (node);
167 }
168
169 get_dir_stop ();
170
171 loading_stop = TRUE;
172 }
173
174
175 static void
cb_file_load_cancel(GtkWidget * widget,FilesLoader * files)176 cb_file_load_cancel (GtkWidget *widget, FilesLoader *files)
177 {
178 files->status = CANCEL;
179 if (files_loader_query_loading ())
180 files_loader_stop ();
181 }
182
183
184 static void
cb_file_load_stop(GtkWidget * widget,FilesLoader * files)185 cb_file_load_stop (GtkWidget *widget, FilesLoader *files)
186 {
187 files->status = STOP;
188 }
189
190
191 void
files_loader_create_progress_window(FilesLoader * files)192 files_loader_create_progress_window (FilesLoader *files)
193 {
194 GtkWidget *window;
195 GtkWidget *vbox, *hbox;
196 GtkWidget *label;
197 GtkWidget *progressbar;
198 GtkWidget *button;
199
200 /* create dialog window */
201 window = gtk_window_new(GTK_WINDOW_POPUP);
202 gtk_widget_realize (window);
203 gtk_container_border_width (GTK_CONTAINER (window), 3);
204 gtk_window_set_title (GTK_WINDOW (window), _("*Loading Image Files* - GImageView - "));
205 gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
206 vbox = gtk_vbox_new (FALSE, 0);
207 gtk_container_add (GTK_CONTAINER(window), vbox);
208
209 /* label */
210 label = gtk_label_new (_("Now Opening Image Files..."));
211 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
212
213 /* progress bar */
214 progressbar = gtk_progress_bar_new();
215 gtk_progress_set_show_text(GTK_PROGRESS(progressbar), TRUE);
216 gtk_box_pack_start (GTK_BOX (vbox), progressbar, FALSE, FALSE, 0);
217
218 /* hbox */
219 hbox = gtk_hbox_new (TRUE, 0);
220 gtk_container_add (GTK_CONTAINER(vbox), hbox);
221
222 /* cancel button */
223 button = gtk_button_new_with_label (_("Skip"));
224 gtk_container_border_width (GTK_CONTAINER (button), 5);
225 gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
226 gtk_signal_connect (GTK_OBJECT(button), "clicked",
227 GTK_SIGNAL_FUNC(cb_file_load_cancel), files);
228
229 /* stop button */
230 button = gtk_button_new_with_label (_("Stop"));
231 gtk_container_border_width (GTK_CONTAINER (button), 5);
232 gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
233 gtk_signal_connect (GTK_OBJECT(button), "clicked",
234 GTK_SIGNAL_FUNC(cb_file_load_stop), files);
235
236
237 files->window = window;
238 files->progressbar = progressbar;
239
240 gtk_widget_show_all (window);
241 }
242
243
244 void
files_loader_destroy_progress_window(FilesLoader * files)245 files_loader_destroy_progress_window (FilesLoader *files)
246 {
247 g_return_if_fail (files);
248
249 if (files->window)
250 gtk_widget_destroy (files->window);
251
252 files->window = NULL;
253 files->progressbar = NULL;
254 }
255
256
257 void
files_loader_progress_update(FilesLoader * files,gfloat progress,const gchar * text)258 files_loader_progress_update (FilesLoader *files,
259 gfloat progress,
260 const gchar *text)
261 {
262 g_return_if_fail (files);
263
264 if (files->progressbar) {
265 gdk_window_raise (files->window->window);
266 gtk_progress_bar_update (GTK_PROGRESS_BAR(files->progressbar), progress);
267 gtk_progress_set_format_string(GTK_PROGRESS(files->progressbar), text);
268 }
269 }
270
271
272 gint
open_image_files_in_image_view(FilesLoader * files)273 open_image_files_in_image_view (FilesLoader *files)
274 {
275 gint listnum, pos;
276 gint retval = FALSE;
277 gfloat progress;
278 gchar buf[32];
279 GList *node;
280
281 while (gtk_events_pending()) gtk_main_iteration();
282
283 listnum = g_list_length (g_list_first(files->filelist));
284
285 if (listnum < 1) {
286 return FALSE;
287 }
288
289 retval = TRUE;
290
291 if (listnum > 2) {
292 files_loader_create_progress_window (files);
293 } else {
294 files->window = NULL;
295 files->progressbar = NULL;
296 }
297
298 node = files->filelist;
299 while (node) {
300 gchar *filename = node->data;
301
302 node = g_list_next (node);
303
304 if (files->status == CANCEL || files->status == STOP) {
305 retval = files->status;
306 break;
307 }
308
309 /* Load Image */
310 if (conf.disp_filename_stdout)
311 g_print (_("filename = %s\n"), filename);
312
313 /* Open Archive File */
314 if (fr_archive_utils_get_file_name_ext (filename)) {
315 g_print (_("The file is archive: %s\n"), filename);
316 open_archive_images (filename, NULL, NULL, LOAD_CACHE);
317
318 /* open iamge window */
319 } else {
320 GimvImageInfo *info = gimv_image_info_get (filename);
321 if (info)
322 gimv_image_win_open_window (info);
323 }
324
325 pos = g_list_position (files->filelist, node) + 1;
326 progress = (gfloat) pos / (gfloat) listnum;
327 g_snprintf (buf, 32, "%d/%d files", pos, listnum);
328 files_loader_progress_update (files, progress, buf);
329 }
330
331 files_loader_destroy_progress_window (files);
332
333 return retval;
334 }
335
336
337 static GimvThumbWin *
select_thumbnail_window(GimvThumbWin * tw)338 select_thumbnail_window (GimvThumbWin *tw)
339 {
340 GimvThumbWin *retval;
341 GList *node;
342
343 if (tw && g_list_find (gimv_thumb_win_get_list(), tw)) {
344 retval = (GimvThumbWin *) tw;
345 }
346 else if (g_list_length (gimv_thumb_win_get_list()) < 1) {
347 retval = gimv_thumb_win_open_window ();
348 } else {
349 node = g_list_last (gimv_thumb_win_get_list());
350 retval = node->data;
351 }
352
353 return retval;
354 }
355
356
357 gint
open_image_files_in_thumbnail_view(FilesLoader * files,GimvThumbWin * tw,GimvThumbView * tv_org)358 open_image_files_in_thumbnail_view (FilesLoader *files,
359 GimvThumbWin *tw, GimvThumbView *tv_org)
360 {
361 GimvThumbWin *tw_tmp;
362 GimvThumbView *tv;
363
364 if (g_list_length(files->filelist) < 1) {
365 return FALSE;
366 }
367
368 /* select thumbnail window */
369 tw_tmp = select_thumbnail_window (tw);
370 if (conf.thumbwin_raise_window)
371 gdk_window_raise (GTK_WIDGET (tw_tmp)->window);
372
373 /* select notebook page and open files */
374 tv = gimv_thumb_win_find_thumbtable (tw_tmp, GIMV_THUMB_WIN_CURRENT_PAGE);
375
376 if (!tv_org && tv && tv->mode == GIMV_THUMB_VIEW_MODE_COLLECTION) {
377 gimv_thumb_view_append_thumbnail (tv, files, FALSE);
378 } else {
379 if (tv_org)
380 tv = tv_org;
381 else
382 tv = gimv_thumb_win_create_new_tab (tw_tmp);
383 gimv_thumb_view_reload (tv, files, GIMV_THUMB_VIEW_MODE_COLLECTION);
384
385 if (files->status == STOP || files->status < 0)
386 return files->status;
387 }
388
389 gimv_thumb_win_set_statusbar_page_info (tw_tmp, GIMV_THUMB_WIN_CURRENT_PAGE);
390
391 return TRUE;
392 }
393
394
395 gint
open_image_files(FilesLoader * files)396 open_image_files (FilesLoader *files)
397 {
398 if (g_list_length(files->filelist) < 1) {
399 return FALSE;
400 }
401
402 if (conf.default_file_open_window == THUMBNAIL_WINDOW)
403 return open_image_files_in_thumbnail_view (files, NULL, NULL);
404 else
405 return open_image_files_in_image_view (files);
406 }
407
408
409 gint
open_dir_images(const gchar * dir,GimvThumbWin * tw,GimvThumbView * tv_org,ThumbLoadType type,ScanSubDirType scan_subdir)410 open_dir_images (const gchar *dir,
411 GimvThumbWin *tw,
412 GimvThumbView *tv_org,
413 ThumbLoadType type,
414 ScanSubDirType scan_subdir)
415 {
416 FilesLoader *files;
417 GimvThumbWin *tw_tmp = NULL;
418 GimvThumbView *tv;
419 gint retval = FALSE, flags;
420 gchar *dirname;
421 gboolean open_in_one_tab = FALSE;
422
423 g_return_val_if_fail (dir && *dir, THUMB_LOAD_DONE);
424
425 if (!(!tw && conf.default_dir_open_window == IMAGE_VIEW_WINDOW)
426 && scan_subdir == SCAN_SUB_DIR_ONE_TAB)
427 {
428 open_in_one_tab = TRUE;
429 }
430
431 dirname = add_slash (dir);
432
433 if (access (dirname, R_OK)) {
434 gchar error_message[BUF_SIZE], *dir_internal;
435 GtkWindow *window = tw ? GTK_WINDOW (tw) : NULL;
436
437 dir_internal = charset_to_internal (dirname,
438 conf.charset_filename,
439 conf.charset_auto_detect_fn,
440 conf.charset_filename_mode);
441 g_snprintf (error_message, BUF_SIZE,
442 _("Permission denied: %s"),
443 dir_internal);
444 gtkutil_message_dialog (_("Error!!"), error_message, window);
445
446 g_free (dir_internal);
447 g_free (dirname);
448 return NO_OPEN_FILE;
449 }
450
451 tv = gimv_thumb_view_find_opened_dir (dirname);
452 if (!tv_org && tv && (tw || (!tw && conf.default_dir_open_window == THUMBNAIL_WINDOW))
453 && scan_subdir != SCAN_SUB_DIR_ONE_TAB)
454 {
455 gint pagenum;
456 tw_tmp = tv->tw;
457 gdk_window_raise (GTK_WIDGET (tw_tmp)->window);
458 pagenum = gtk_notebook_page_num (GTK_NOTEBOOK (tw_tmp->notebook),
459 tv->container);
460 gtk_notebook_set_page (GTK_NOTEBOOK (tw_tmp->notebook), pagenum);
461 if (!scan_subdir) {
462 g_free (dirname);
463 return THUMB_LOAD_DONE;
464 }
465 }
466
467 /* allocate FilesLoader structure for this direcory */
468 files = files_loader_new ();
469 files->dirname = dirname;
470 files->thumb_load_type = type;
471
472 /* get files & directories list */
473 flags = GETDIR_ENABLE_CANCEL;
474 if (!scan_subdir || conf.recursive_follow_link)
475 flags = flags | GETDIR_FOLLOW_SYMLINK;
476 if (conf.read_dotfile)
477 flags = flags | GETDIR_READ_DOT;
478 if (conf.detect_filetype_by_ext)
479 flags = flags | GETDIR_DETECT_EXT;
480 if (conf.thumbview_show_archive)
481 flags = flags | GETDIR_GET_ARCHIVE;
482 if (conf.disp_filename_stdout)
483 flags = flags | GETDIR_DISP_STDOUT;
484 if (open_in_one_tab)
485 flags = flags | GETDIR_RECURSIVE;
486
487 get_dir (dirname, flags, &files->filelist, &files->dirlist);
488
489 if (loading_stop) goto FUNC_END;
490
491 if (tv && scan_subdir && scan_subdir != SCAN_SUB_DIR_ONE_TAB)
492 goto OPEN_SUB_DIR;
493
494 if (!conf.thumbwin_force_open_tab && g_list_length(files->filelist) < 1) {
495 if (conf.disp_filename_stdout)
496 g_print (_("No image files in this directory: %s\n"), dirname);
497 goto OPEN_SUB_DIR;
498 }
499
500 files->filelist = g_list_first (files->filelist);
501 if (!tw && conf.default_dir_open_window == IMAGE_VIEW_WINDOW) {
502 /* (!tw && conf.default_dir_open_window == THUMBNAIL_WINDOW)) { */
503 retval = open_image_files_in_image_view (files);
504 } else {
505 tw_tmp = select_thumbnail_window (tw);
506 if (conf.thumbwin_raise_window)
507 gdk_window_raise (GTK_WIDGET (tw_tmp)->window);
508
509 if (tv_org)
510 tv = tv_org;
511 else
512 tv = gimv_thumb_win_create_new_tab (tw_tmp);
513
514 if (open_in_one_tab) {
515 gimv_thumb_view_reload (tv, files, GIMV_THUMB_VIEW_MODE_RECURSIVE_DIR);
516 } else {
517 gimv_thumb_view_reload (tv, files, GIMV_THUMB_VIEW_MODE_DIR);
518 }
519
520 /* error handling */
521 if (files->status == STOP || files->status < 0) {
522 retval = files->status;
523 } else {
524 retval = THUMB_LOAD_DONE;
525 }
526 }
527
528 /* open directories recursively */
529 OPEN_SUB_DIR:
530 if (scan_subdir && g_list_length(files->dirlist) > 0
531 && files->status != STOP && files->status >= 0
532 && !open_in_one_tab)
533 {
534 retval = open_dirs (files, tw_tmp, type, scan_subdir);
535 }
536
537 FUNC_END:
538 /* free files (allocated at head of this function) */
539 files_loader_delete (files);
540
541 g_free (dirname);
542
543 return retval;
544 }
545 /* END FIXME!! */
546
547
548
549 static gint
progress_timeout(gpointer data)550 progress_timeout (gpointer data)
551 {
552 gfloat new_val;
553 GtkAdjustment *adj;
554
555 adj = GTK_PROGRESS (data)->adjustment;
556
557 new_val = adj->value + 1;
558 if (new_val > adj->upper)
559 new_val = adj->lower;
560
561 gtk_progress_set_value (GTK_PROGRESS (data), new_val);
562
563 return (TRUE);
564 }
565
566
567
568 static void
cb_archive_action_started(FRArchive * archive,FRAction action,gpointer data)569 cb_archive_action_started (FRArchive *archive,
570 FRAction action,
571 gpointer data)
572 {
573 }
574
575
576 static void
cb_archive_action_performed(FRArchive * archive,FRAction action,FRProcError error,gpointer data)577 cb_archive_action_performed (FRArchive *archive,
578 FRAction action,
579 FRProcError error,
580 gpointer data)
581 {
582 GimvThumbWin *tw = data;
583 GtkWindow *window = tw ? GTK_WINDOW (tw) : NULL;
584
585 if (error != FR_PROC_ERROR_NONE) {
586 if (error == FR_PROC_ERROR_COMMAND_NOT_FOUND) {
587 gtkutil_message_dialog (_("Error!!"),
588 _("Command not found!!\n"),
589 window);
590 } else if (error == FR_PROC_ERROR_STOPPED) {
591 gtkutil_message_dialog (_("Canceled"),
592 _("Processing the archive file was\n"
593 "canceled by user."),
594 window);
595 } else {
596 g_print (_("An error occured while processing archive file...\n"));
597 gtkutil_message_dialog (_("Error!!"),
598 _("An error occured while processing\n"
599 "archive file..."),
600 window);
601 }
602 goto ERROR;
603 }
604
605 switch (action) {
606 case FR_ACTION_LIST:
607 break;
608
609 default:
610 break;
611 }
612
613 ERROR:
614 gtk_main_quit ();
615 }
616
617
618 static void
cb_archive_destroy(FRArchive * archive,gpointer data)619 cb_archive_destroy (FRArchive *archive,
620 gpointer data)
621 {
622 gchar *temp_dir;
623 temp_dir = gtk_object_get_data (GTK_OBJECT (archive), "temp-dir");
624
625 if (!temp_dir || !*temp_dir) return;
626
627 /* remove temporary files */
628 if (isdir (temp_dir)) {
629 remove_dir (temp_dir);
630 }
631 }
632
633
634 gint
open_archive_images(const gchar * filename,GimvThumbWin * tw,GimvThumbView * tv_org,ThumbLoadType type)635 open_archive_images (const gchar *filename,
636 GimvThumbWin *tw, GimvThumbView *tv_org,
637 ThumbLoadType type)
638 {
639 FRArchive *archive;
640 GimvThumbWin *tw_tmp;
641 GimvThumbView *tv;
642 gboolean success;
643 gchar *ext, *temp_dir;
644 FilesLoader *files;
645 GList *node;
646 guint timer = 0;
647
648 g_return_val_if_fail (filename, THUMB_LOAD_DONE);
649
650 tv = gimv_thumb_view_find_opened_archive (filename);
651 if (!tv_org && tv) {
652 gint pagenum;
653 tw_tmp = tv->tw;
654 gdk_window_raise (GTK_WIDGET (tw_tmp)->window);
655 pagenum = gtk_notebook_page_num (GTK_NOTEBOOK (tw_tmp->notebook),
656 tv->container);
657 gtk_notebook_set_page (GTK_NOTEBOOK (tw_tmp->notebook), pagenum);
658 return THUMB_LOAD_DONE;
659 }
660
661 node = files_loader_list;
662 while (node) {
663 FilesLoader *fl = node->data;
664 if (fl && fl->archive && !strcmp (fl->archive->filename, filename))
665 return THUMB_LOAD_DONE;
666 node = g_list_next (node);
667 }
668
669 ext = fr_archive_utils_get_file_name_ext (filename);
670 g_return_val_if_fail (ext, THUMB_LOAD_DONE);
671
672 archive = fr_archive_new ();
673 g_return_val_if_fail (archive, THUMB_LOAD_DONE);
674
675 /* set progress bar */
676 if (tw) {
677 gtk_progress_set_activity_mode (GTK_PROGRESS (tw->progressbar), TRUE);
678 timer = gtk_timeout_add (50, (GtkFunction)progress_timeout, tw->progressbar);
679 }
680
681 gtk_signal_connect (GTK_OBJECT (archive),
682 "start",
683 GTK_SIGNAL_FUNC (cb_archive_action_started),
684 NULL);
685 gtk_signal_connect (GTK_OBJECT (archive),
686 "done",
687 GTK_SIGNAL_FUNC (cb_archive_action_performed),
688 tw);
689 gtk_signal_connect (GTK_OBJECT (archive),
690 "destroy",
691 GTK_SIGNAL_FUNC (cb_archive_destroy),
692 NULL);
693
694 temp_dir = g_strconcat (get_temp_dir_name (),
695 FR_ARCHIVE (archive)->filename,
696 NULL);
697 gtk_object_set_data_full (GTK_OBJECT (archive), "temp-dir", temp_dir,
698 (GtkDestroyNotify) g_free);
699
700 files = files_loader_new ();
701 files->thumb_load_type = type;
702 files->archive = archive;
703
704 tw_tmp = select_thumbnail_window (tw);
705 if (!tw_tmp) goto ERROR;
706
707 if (tv_org)
708 tv = tv_org;
709 else
710 tv = gimv_thumb_win_create_new_tab (tw_tmp);
711
712 /* get file list from archive */
713 success = fr_archive_load (archive, filename);
714 if (!success) {
715 GtkWindow *window = tw_tmp ? GTK_WINDOW (tw_tmp) : NULL;
716 gtk_object_unref (GTK_OBJECT (archive));
717 /* gtk_object_remove_data (GTK_OBJECT (archive), "progress-bar"); */
718 gtkutil_message_dialog (_("Error!!"),
719 _("Cannot load this archive file.\n"),
720 window);
721 goto ERROR;
722 }
723
724 gtk_main (); /* wait */
725
726 if (archive->process->error == FR_PROC_ERROR_NONE) {
727 gimv_thumb_view_reload (tv, files, GIMV_THUMB_VIEW_MODE_ARCHIVE);
728 }
729
730 ERROR:
731 files_loader_delete (files);
732
733 /* unset progress bar */
734 if (tw) {
735 if (timer)
736 gtk_timeout_remove (timer);
737 gtk_progress_set_activity_mode (GTK_PROGRESS (tw->progressbar), FALSE);
738 gtk_progress_bar_update (GTK_PROGRESS_BAR(tw->progressbar), 0.0);
739 }
740 if (tw_tmp) {
741 gimv_thumb_win_set_statusbar_page_info (tw_tmp,
742 GIMV_THUMB_WIN_CURRENT_PAGE);
743 }
744 return THUMB_LOAD_DONE;
745 }
746
747
748 gint
open_dirs(FilesLoader * files,GimvThumbWin * tw,ThumbLoadType type,gboolean scan_subdir)749 open_dirs (FilesLoader *files, GimvThumbWin *tw,
750 ThumbLoadType type, gboolean scan_subdir)
751 {
752 gint i;
753 gint listnum;
754 gint retval = FALSE;
755 LoadStatus status;
756
757 if (g_list_length (files->dirlist) > 0) {
758 listnum = g_list_length (g_list_first(files->dirlist));
759 for (i = 0; i < listnum; i++) {
760
761 while (gtk_events_pending()) gtk_main_iteration();
762
763 status = open_dir_images (files->dirlist->data, tw, NULL,
764 type, scan_subdir);
765
766 if (files->status == STOP || files->status < 0
767 || status == STOP || status < 0
768 || loading_stop)
769 {
770 return files->status = STOP;
771 } else {
772 retval = status || retval;
773 }
774
775 files->dirlist = g_list_next (files->dirlist);
776 }
777 }
778
779 return retval;
780 }
781
782
783 gint
open_images_dirs(GList * list,GimvThumbWin * tw,ThumbLoadType type,gboolean scan_subdir)784 open_images_dirs (GList *list, GimvThumbWin *tw,
785 ThumbLoadType type, gboolean scan_subdir)
786 {
787 FilesLoader *files;
788 GList *node;
789 gchar *path;
790 LoadStatus retval = FALSE;
791
792 files = files_loader_new ();
793 files->thumb_load_type = type;
794
795 node = list;
796 while (node) {
797 path = node->data;
798 if (isdir (path)) {
799 files->dirlist = g_list_append (files->dirlist, g_strdup (path));
800 } else if (file_exists (path)
801 && (!conf.detect_filetype_by_ext
802 || gimv_image_detect_type_by_ext (path)
803 || fr_archive_utils_get_file_name_ext (path)))
804 {
805 files->filelist = g_list_append (files->filelist, g_strdup (path));
806 }
807 node = g_list_next (node);
808 }
809
810 if (files->filelist) {
811 if (tw)
812 retval = open_image_files_in_thumbnail_view (files, tw, NULL);
813 else
814 retval = open_image_files (files);
815 }
816
817 if (files->dirlist)
818 retval = open_dirs (files, tw, type, scan_subdir) || retval;
819
820 files_loader_delete (files);
821
822 return retval;
823 }
824
825
826 static void
filebrowser_open_files(FileSel * filesel,ImgWinType type)827 filebrowser_open_files (FileSel *filesel, ImgWinType type)
828 {
829 GtkFileSelection *fsel = GTK_FILE_SELECTION(filesel->filebrowser);
830
831 #ifdef USE_GTK2
832 FilesLoader *files;
833 gint i;
834 gchar **path = gtk_file_selection_get_selections (fsel);
835
836 if (!path) return;
837
838 files = files_loader_new ();
839
840 for (i = 0; path[i]; i++) {
841 if (!(conf.detect_filetype_by_ext)
842 || gimv_image_detect_type_by_ext (path[i])
843 || fr_archive_utils_get_file_name_ext (path[i]))
844 {
845 files->filelist = g_list_append (files->filelist, g_strdup (path[i]));
846 }
847 }
848
849 if (type == THUMBNAIL_WINDOW) {
850 files->status = THUMB_LOADING;
851 open_image_files_in_thumbnail_view (files, filesel->tw, NULL);
852 } else {
853 files->status = IMAGE_LOADING;
854 open_image_files_in_image_view (files);
855 }
856
857 files_loader_delete (files);
858
859 g_strfreev (path);
860 #else
861 GList *sel_list = NULL, *node;
862 gchar *path, *path_tail, *file;
863 FilesLoader *files;
864
865 /* get directory path */
866 path = g_strdup(gtk_file_selection_get_filename(fsel));
867 if(!path) return;
868 path_tail = (gchar *) strrchr(path, '/');
869 if (path_tail) *(path_tail + 1) = '\0';
870
871 /* get selected files */
872 node = GTK_CLIST(fsel->file_list)->selection;
873 if (node) {
874 files = files_loader_new ();
875
876 while(node) {
877 gtk_clist_get_text(GTK_CLIST(fsel->file_list),
878 GPOINTER_TO_INT(node->data), 0, &file);
879 file = g_strconcat(path, file, NULL);
880 if (!(conf.detect_filetype_by_ext)
881 || gimv_image_detect_type_by_ext (file)
882 || fr_archive_utils_get_file_name_ext (file))
883 {
884 files->filelist = g_list_append (files->filelist, file);
885 }
886
887 node = g_list_next(node);
888 }
889
890 files->filelist = g_list_first (files->filelist);
891
892 if (type == THUMBNAIL_WINDOW) {
893 files->status = THUMB_LOADING;
894 open_image_files_in_thumbnail_view (files, filesel->tw, NULL);
895 } else {
896 files->status = IMAGE_LOADING;
897 open_image_files_in_image_view (files);
898 }
899
900 files_loader_delete (files);
901 }
902
903 g_free (path);
904 g_list_free(sel_list);
905 #endif
906 }
907
908
909 static void
cb_filebrowser_open_selected_files(GtkWidget * widget,FileSel * filesel)910 cb_filebrowser_open_selected_files(GtkWidget *widget, FileSel *filesel)
911 {
912 /* GtkFileSelection *fsel = GTK_FILE_SELECTION(filesel->filebrowser); */
913
914 filebrowser_open_files (filesel, IMAGE_VIEW_WINDOW);
915
916 #if 0
917 /* FIXME!! If filebrowser is destoryed before loading complete,
918 this will cause segmentation fault */
919 gtk_clist_unselect_all(GTK_CLIST (fsel->file_list));
920 gtk_entry_set_text(GTK_ENTRY(fsel->selection_entry), "");
921 #endif
922 }
923
924
925 static void
cb_filebrowser_add_thumbnail(GtkWidget * widget,FileSel * filesel)926 cb_filebrowser_add_thumbnail (GtkWidget *widget, FileSel *filesel)
927 {
928 /* GtkFileSelection *fsel = GTK_FILE_SELECTION(filesel->filebrowser); */
929
930 filebrowser_open_files (filesel, THUMBNAIL_WINDOW);
931
932 #if 0
933 /* FIXME!! If filebrowser is destoryed before loading complete,
934 this will cause segmentation fault */
935 gtk_clist_unselect_all(GTK_CLIST (fsel->file_list));
936 gtk_entry_set_text(GTK_ENTRY (fsel->selection_entry), "");
937 #endif
938 }
939
940
941 static void
cb_filebrowser_ok_sel(GtkWidget * widget,FileSel * filesel)942 cb_filebrowser_ok_sel (GtkWidget *widget, FileSel *filesel)
943 {
944 GimvImageWin *iw;
945 gchar *filename;
946 struct stat st;
947
948 filename = g_strdup(gtk_file_selection_get_filename
949 (GTK_FILE_SELECTION (filesel->filebrowser)));
950
951 if (!filename) {
952 g_print (_("File name not specified!!\n"));
953 return;
954 }
955
956 if (!stat(filename, &st)) {
957 /* if path is directory */
958 if (S_ISDIR(st.st_mode)) {
959 open_dir_images(filename, filesel->tw, NULL, LOAD_CACHE,
960 conf.scan_dir_recursive);
961
962 /* if path is archvie file */
963 } else if (fr_archive_utils_get_file_name_ext (filename)) {
964 open_archive_images (filename, filesel->tw, NULL, LOAD_CACHE);
965
966 /* if path is file */
967 } else if (!(conf.detect_filetype_by_ext)
968 || gimv_image_detect_type_by_ext (filename))
969 {
970 GimvImageInfo *info = gimv_image_info_get (filename);
971 if (info)
972 iw = gimv_image_win_open_window_auto (info);
973 } else {
974 g_print (_("Not an image (or unsupported) file!!\n"));
975 }
976 }
977
978 g_free (filename);
979 }
980
981
982 /*
983 * cb_filebrowser_ok_sel:
984 * @ Callback function for filebrowser "Close" button.
985 *
986 * widget :
987 * parent :
988 */
989 static void
cb_filebrowser_close(GtkWidget * widget,gpointer parent)990 cb_filebrowser_close (GtkWidget *widget, gpointer parent)
991 {
992 GimvThumbWin *tw = parent;
993
994 if (tw && g_list_find (gimv_thumb_win_get_list(), tw)) {
995 tw->open_dialog = NULL;
996 }
997 }
998
999
1000 /*
1001 * create_filebrowser:
1002 * @ File open dialog (extend Gtk+'s original file open dialog widget)
1003 *
1004 * parent : Pointer to parent window.
1005 * Return : Pointer to new filebrowser.
1006 */
1007 GtkWidget *
create_filebrowser(gpointer parent)1008 create_filebrowser (gpointer parent)
1009 {
1010 GtkWidget *filebrowser, *bbox, *add_selected, *add_all;
1011 FileSel *filesel;
1012
1013 filebrowser = gtk_file_selection_new(_("Load file(s)"));
1014 gtk_signal_connect (GTK_OBJECT (filebrowser), "destroy",
1015 GTK_SIGNAL_FUNC(cb_filebrowser_close), parent);
1016
1017 filesel = g_new0 (FileSel, 1);
1018 filesel->filebrowser = filebrowser;
1019 filesel->tw = (GimvThumbWin *) parent;
1020 gtk_object_set_data_full (GTK_OBJECT (filebrowser), "filesel",
1021 filesel, (GtkDestroyNotify) g_free);
1022
1023 if (filesel->tw)
1024 gtk_window_set_transient_for (GTK_WINDOW (filebrowser),
1025 GTK_WINDOW (filesel->tw));
1026
1027 #ifdef USE_GTK2
1028 gtk_file_selection_set_select_multiple (GTK_FILE_SELECTION(filebrowser),
1029 TRUE);
1030 #else
1031 gtk_clist_set_selection_mode (
1032 GTK_CLIST(GTK_FILE_SELECTION(filebrowser)->file_list),
1033 GTK_SELECTION_EXTENDED);
1034 #endif
1035 /*
1036 gtk_signal_connect(
1037 GTK_OBJECT(GTK_FILE_SELECTION(filebrowser)->selection_entry),
1038 "changed", GTK_SIGNAL_FUNC(filebrowser_changed), filebrowser);
1039 */
1040 gtk_signal_connect(
1041 GTK_OBJECT(GTK_FILE_SELECTION(filebrowser)->ok_button),
1042 "clicked",
1043 GTK_SIGNAL_FUNC(cb_filebrowser_ok_sel),
1044 filesel);
1045 gtk_signal_connect_object(
1046 GTK_OBJECT(GTK_FILE_SELECTION(filebrowser)->cancel_button),
1047 "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
1048 GTK_OBJECT(filebrowser));
1049
1050 bbox = gtk_hbutton_box_new();
1051 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1052 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 0);
1053 gtk_box_pack_end(GTK_BOX(GTK_FILE_SELECTION(filebrowser)->action_area),
1054 bbox, TRUE, TRUE, 0);
1055
1056 add_selected = gtk_button_new_with_label(_("Open selected files"));
1057 gtk_box_pack_start(GTK_BOX(bbox), add_selected, FALSE, FALSE, 0);
1058 gtk_signal_connect(GTK_OBJECT(add_selected),
1059 "clicked",
1060 GTK_SIGNAL_FUNC(cb_filebrowser_open_selected_files),
1061 filesel);
1062
1063 add_all = gtk_button_new_with_label(_("Thumbnail for selected files"));
1064 gtk_box_pack_start(GTK_BOX(bbox), add_all, FALSE, FALSE, 0);
1065 gtk_signal_connect(GTK_OBJECT(add_all),
1066 "clicked",
1067 GTK_SIGNAL_FUNC (cb_filebrowser_add_thumbnail),
1068 filesel);
1069 gtk_widget_show_all(bbox);
1070
1071 #if 0
1072 /*
1073 * 2004-06-17 Takuro Ashie <ashie@homa.ne.jp>
1074 * This code causes clash on latest Gtk+2.
1075 */
1076 /*
1077 * Change the Cancel buttons caption to Close.
1078 */
1079 label = gtk_label_new(_("Close"));
1080 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
1081 gtk_container_remove(GTK_CONTAINER(GTK_FILE_SELECTION(filebrowser)->cancel_button),
1082 gtk_container_children(GTK_CONTAINER(GTK_FILE_SELECTION(filebrowser)->cancel_button))->data);
1083 gtk_container_add(GTK_CONTAINER(GTK_FILE_SELECTION(filebrowser)->cancel_button), label);
1084 gtk_widget_show(label);
1085 #endif
1086
1087 gtk_widget_show(filebrowser);
1088
1089 gimv_icon_stock_set_window_icon (filebrowser->window, "nfolder");
1090
1091 return filebrowser;
1092 }
1093
1094
1095
1096 #ifdef GIMV_DEBUG
1097 void
file_disp_loading_status(FilesLoader * files)1098 file_disp_loading_status (FilesLoader *files)
1099 {
1100 g_print ("Loading ID: %p ", files);
1101 g_print ("status ID: %d ", files->status);
1102
1103 switch (files->status) {
1104 case NO_OPEN_FILE:
1105 g_print ("Loading status: NO_OPEN_FILE\n");
1106 break;
1107 case END:
1108 g_print ("Loading status: END\n");
1109 break;
1110 case GETTING_FILELIST:
1111 g_print ("Loading status: GETTING_FILELIST\n");
1112 break;
1113 case IMAGE_LOADING:
1114 g_print ("Loading status: IMAGE_LOADING\n");
1115 break;
1116 case IMAGE_LOAD_DONE:
1117 g_print ("Loading status: IMAGE_LOAD_DONE\n");
1118 break;
1119 case THUMB_LOADING:
1120 g_print ("Loading status: THUMB_LOADING\n");
1121 break;
1122 case THUMB_LOAD_DONE:
1123 g_print ("Loading status: THUMB_LOAD_DONE\n");
1124 break;
1125 case CANCEL:
1126 g_print ("Loading status: CANCEL\n");
1127 break;
1128 case STOP:
1129 g_print ("Loading status: STOP\n");
1130 break;
1131 case CONTAINER_DESTROYED:
1132 g_print ("Loading status: CONTAINER_DESTROYED\n");
1133 break;
1134 case WINDOW_DESTROYED:
1135 g_print ("Loading status: WINDOW_DESTROYED\n");
1136 break;
1137 default:
1138 break;
1139 }
1140 }
1141 #endif /* GIMV_DEBUG */
1142