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