~ubuntu-branches/debian/sid/file-roller/sid

« back to all changes in this revision

Viewing changes to .pc/11_search_as_you_type.patch/src/fr-window.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl, Josselin Mouette, Michael Biebl
  • Date: 2011-10-13 22:43:53 UTC
  • mfrom: (5.1.5 experimental)
  • Revision ID: package-import@ubuntu.com-20111013224353-7fub412oa8jwkcgt
Tags: 3.0.2-2
[ Josselin Mouette ]
* file-roller.mime: dropped. We don’t do necromancy anymore.
* Drop desktop-check-mime-types call too.

[ Michael Biebl ]
* Upload to unstable.
* debian/control.in:
  - Set pkg-gnome-maintainers@lists.alioth.debian.org as Maintainer.
* debian/watch:
  - Switch to .xz tarballs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 
2
 
 
3
/*
 
4
 *  File-Roller
 
5
 *
 
6
 *  Copyright (C) 2007 Free Software Foundation, Inc.
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 2 of the License, or
 
11
 *  (at your option) any later version.
 
12
 *
 
13
 *  This program is distributed in the hope that it will be useful,
 
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 *  GNU General Public License for more details.
 
17
 *
 
18
 *  You should have received a copy of the GNU General Public License
 
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
#include <math.h>
 
24
#include <string.h>
 
25
 
 
26
#include <glib/gi18n.h>
 
27
#include <gio/gio.h>
 
28
#include <gtk/gtk.h>
 
29
#include <gdk/gdk.h>
 
30
#include <gdk/gdkkeysyms.h>
 
31
#include <gdk-pixbuf/gdk-pixbuf.h>
 
32
 
 
33
#include "actions.h"
 
34
#include "dlg-batch-add.h"
 
35
#include "dlg-delete.h"
 
36
#include "dlg-extract.h"
 
37
#include "dlg-open-with.h"
 
38
#include "dlg-ask-password.h"
 
39
#include "dlg-package-installer.h"
 
40
#include "dlg-update.h"
 
41
#include "eggtreemultidnd.h"
 
42
#include "fr-marshal.h"
 
43
#include "fr-list-model.h"
 
44
#include "fr-archive.h"
 
45
#include "fr-error.h"
 
46
#include "fr-stock.h"
 
47
#include "fr-window.h"
 
48
#include "file-data.h"
 
49
#include "file-utils.h"
 
50
#include "glib-utils.h"
 
51
#include "fr-init.h"
 
52
#include "gtk-utils.h"
 
53
#include "open-file.h"
 
54
#include "typedefs.h"
 
55
#include "ui.h"
 
56
 
 
57
#define LAST_OUTPUT_SCHEMA_NAME "LastOutput"
 
58
#define MAX_HISTORY_LEN 5
 
59
#define ACTIVITY_DELAY 100
 
60
#define ACTIVITY_PULSE_STEP (0.033)
 
61
#define MAX_MESSAGE_LENGTH 50
 
62
 
 
63
#define PROGRESS_DIALOG_DEFAULT_WIDTH 400
 
64
#define PROGRESS_TIMEOUT_MSECS 5000
 
65
#define PROGRESS_BAR_HEIGHT 10
 
66
#undef  LOG_PROGRESS
 
67
 
 
68
#define HIDE_PROGRESS_TIMEOUT_MSECS 500
 
69
#define DEFAULT_NAME_COLUMN_WIDTH 250
 
70
#define OTHER_COLUMNS_WIDTH 100
 
71
#define RECENT_ITEM_MAX_WIDTH 25
 
72
 
 
73
#define DEF_WIN_WIDTH 600
 
74
#define DEF_WIN_HEIGHT 480
 
75
#define DEF_SIDEBAR_WIDTH 200
 
76
 
 
77
#define FILE_LIST_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
 
78
#define DIR_TREE_ICON_SIZE GTK_ICON_SIZE_MENU
 
79
 
 
80
#define BAD_CHARS "/\\*"
 
81
 
 
82
static GHashTable     *pixbuf_hash = NULL;
 
83
static GHashTable     *tree_pixbuf_hash = NULL;
 
84
static GtkIconTheme   *icon_theme = NULL;
 
85
static int             file_list_icon_size = 0;
 
86
static int             dir_tree_icon_size = 0;
 
87
 
 
88
#define XDS_FILENAME "xds.txt"
 
89
#define MAX_XDS_ATOM_VAL_LEN 4096
 
90
#define XDS_ATOM   gdk_atom_intern  ("XdndDirectSave0", FALSE)
 
91
#define TEXT_ATOM  gdk_atom_intern  ("text/plain", FALSE)
 
92
#define OCTET_ATOM gdk_atom_intern  ("application/octet-stream", FALSE)
 
93
#define XFR_ATOM   gdk_atom_intern  ("XdndFileRoller0", FALSE)
 
94
 
 
95
#define FR_CLIPBOARD (gdk_atom_intern_static_string ("_FILE_ROLLER_SPECIAL_CLIPBOARD"))
 
96
#define FR_SPECIAL_URI_LIST (gdk_atom_intern_static_string ("application/file-roller-uri-list"))
 
97
 
 
98
static GtkTargetEntry clipboard_targets[] = {
 
99
        { "application/file-roller-uri-list", 0, 1 }
 
100
};
 
101
 
 
102
static GtkTargetEntry target_table[] = {
 
103
        { "XdndFileRoller0", 0, 0 },
 
104
        { "text/uri-list", 0, 1 },
 
105
};
 
106
 
 
107
static GtkTargetEntry folder_tree_targets[] = {
 
108
        { "XdndFileRoller0", 0, 0 },
 
109
        { "XdndDirectSave0", 0, 2 }
 
110
};
 
111
 
 
112
 
 
113
typedef struct {
 
114
        FrBatchActionType type;
 
115
        void *            data;
 
116
        GFreeFunc         free_func;
 
117
} FRBatchAction;
 
118
 
 
119
 
 
120
typedef struct {
 
121
        guint      converting : 1;
 
122
        char      *temp_dir;
 
123
        FrArchive *new_archive;
 
124
        char      *password;
 
125
        gboolean   encrypt_header;
 
126
        guint      volume_size;
 
127
        char      *new_file;
 
128
} FRConvertData;
 
129
 
 
130
 
 
131
typedef enum {
 
132
        FR_CLIPBOARD_OP_CUT,
 
133
        FR_CLIPBOARD_OP_COPY
 
134
} FRClipboardOp;
 
135
 
 
136
 
 
137
typedef struct {
 
138
        GList    *file_list;
 
139
        char     *extract_to_dir;
 
140
        char     *base_dir;
 
141
        gboolean  skip_older;
 
142
        gboolean  overwrite;
 
143
        gboolean  junk_paths;
 
144
        char     *password;
 
145
        gboolean  extract_here;
 
146
} ExtractData;
 
147
 
 
148
 
 
149
typedef enum {
 
150
        FR_WINDOW_AREA_MENUBAR,
 
151
        FR_WINDOW_AREA_TOOLBAR,
 
152
        FR_WINDOW_AREA_LOCATIONBAR,
 
153
        FR_WINDOW_AREA_CONTENTS,
 
154
        FR_WINDOW_AREA_FILTERBAR,
 
155
        FR_WINDOW_AREA_STATUSBAR,
 
156
} FrWindowArea;
 
157
 
 
158
 
 
159
typedef enum {
 
160
        DIALOG_RESPONSE_NONE = 1,
 
161
        DIALOG_RESPONSE_OPEN_ARCHIVE,
 
162
        DIALOG_RESPONSE_OPEN_DESTINATION_FOLDER,
 
163
        DIALOG_RESPONSE_QUIT
 
164
} DialogResponse;
 
165
 
 
166
 
 
167
/* -- FrClipboardData -- */
 
168
 
 
169
 
 
170
typedef struct {
 
171
        int            refs;
 
172
        char          *archive_filename;
 
173
        char          *archive_password;
 
174
        FRClipboardOp  op;
 
175
        char          *base_dir;
 
176
        GList         *files;
 
177
        char          *tmp_dir;
 
178
        char          *current_dir;
 
179
} FrClipboardData;
 
180
 
 
181
 
 
182
static FrClipboardData*
 
183
fr_clipboard_data_new (void)
 
184
{
 
185
        FrClipboardData *data;
 
186
 
 
187
        data = g_new0 (FrClipboardData, 1);
 
188
        data->refs = 1;
 
189
 
 
190
        return data;
 
191
}
 
192
 
 
193
 
 
194
static FrClipboardData *
 
195
fr_clipboard_data_ref (FrClipboardData *clipboard_data)
 
196
{
 
197
        clipboard_data->refs++;
 
198
        return clipboard_data;
 
199
}
 
200
 
 
201
 
 
202
static void
 
203
fr_clipboard_data_unref (FrClipboardData *clipboard_data)
 
204
{
 
205
        if (clipboard_data == NULL)
 
206
                return;
 
207
        if (--clipboard_data->refs > 0)
 
208
                return;
 
209
 
 
210
        g_free (clipboard_data->archive_filename);
 
211
        g_free (clipboard_data->archive_password);
 
212
        g_free (clipboard_data->base_dir);
 
213
        g_free (clipboard_data->tmp_dir);
 
214
        g_free (clipboard_data->current_dir);
 
215
        g_list_foreach (clipboard_data->files, (GFunc) g_free, NULL);
 
216
        g_list_free (clipboard_data->files);
 
217
        g_free (clipboard_data);
 
218
}
 
219
 
 
220
 
 
221
static void
 
222
fr_clipboard_data_set_password (FrClipboardData *clipboard_data,
 
223
                                const char      *password)
 
224
{
 
225
        if (clipboard_data->archive_password != password)
 
226
                g_free (clipboard_data->archive_password);
 
227
        if (password != NULL)
 
228
                clipboard_data->archive_password = g_strdup (password);
 
229
}
 
230
 
 
231
 
 
232
/**/
 
233
 
 
234
enum {
 
235
        ARCHIVE_LOADED,
 
236
        PROGRESS,
 
237
        READY,
 
238
        LAST_SIGNAL
 
239
};
 
240
 
 
241
static GtkWindowClass *parent_class = NULL;
 
242
static guint fr_window_signals[LAST_SIGNAL] = { 0 };
 
243
 
 
244
struct _FrWindowPrivateData {
 
245
        GtkWidget         *layout;
 
246
        GtkWidget         *contents;
 
247
        GtkWidget         *list_view;
 
248
        GtkListStore      *list_store;
 
249
        GtkWidget         *tree_view;
 
250
        GtkTreeStore      *tree_store;
 
251
        GtkWidget         *toolbar;
 
252
        GtkWidget         *statusbar;
 
253
        GtkWidget         *progress_bar;
 
254
        GtkWidget         *location_bar;
 
255
        GtkWidget         *location_entry;
 
256
        GtkWidget         *location_label;
 
257
        GtkWidget         *filter_bar;
 
258
        GtkWidget         *filter_entry;
 
259
        GtkWidget         *paned;
 
260
        GtkWidget         *sidepane;
 
261
        GtkTreePath       *tree_hover_path;
 
262
        GtkTreePath       *list_hover_path;
 
263
        GtkTreeViewColumn *filename_column;
 
264
 
 
265
        gboolean         filter_mode;
 
266
        gint             current_view_length;
 
267
 
 
268
        guint            help_message_cid;
 
269
        guint            list_info_cid;
 
270
        guint            progress_cid;
 
271
        char *           last_status_message;
 
272
 
 
273
        GtkWidget *      up_arrows[5];
 
274
        GtkWidget *      down_arrows[5];
 
275
 
 
276
        FrAction         action;
 
277
        gboolean         archive_present;
 
278
        gboolean         archive_new;        /* A new archive has been created
 
279
                                              * but it doesn't contain any
 
280
                                              * file yet.  The real file will
 
281
                                              * be created only when the user
 
282
                                              * adds some file to the
 
283
                                              * archive.*/
 
284
 
 
285
        char *           archive_uri;
 
286
        char *           open_default_dir;    /* default directory to be used
 
287
                                               * in the Open dialog. */
 
288
        char *           add_default_dir;     /* default directory to be used
 
289
                                               * in the Add dialog. */
 
290
        char *           extract_default_dir; /* default directory to be used
 
291
                                               * in the Extract dialog. */
 
292
        gboolean         freeze_default_dir;
 
293
        gboolean         asked_for_password;
 
294
        gboolean         ask_to_open_destination_after_extraction;
 
295
        gboolean         destroy_with_error_dialog;
 
296
 
 
297
        FRBatchAction    current_batch_action;
 
298
 
 
299
        gboolean         give_focus_to_the_list;
 
300
        gboolean         single_click;
 
301
        GtkTreePath     *path_clicked;
 
302
 
 
303
        FrWindowSortMethod sort_method;
 
304
        GtkSortType      sort_type;
 
305
 
 
306
        char *           last_location;
 
307
 
 
308
        gboolean         view_folders;
 
309
        FrWindowListMode list_mode;
 
310
        FrWindowListMode last_list_mode;
 
311
        GList *          history;
 
312
        GList *          history_current;
 
313
        char *           password;
 
314
        char *           password_for_paste;
 
315
        gboolean         encrypt_header;
 
316
        FrCompression    compression;
 
317
        guint            volume_size;
 
318
 
 
319
        guint            activity_timeout_handle;   /* activity timeout
 
320
                                                     * handle. */
 
321
        gint             activity_ref;              /* when > 0 some activity
 
322
                                                     * is present. */
 
323
 
 
324
        guint            update_timeout_handle;     /* update file list
 
325
                                                     * timeout handle. */
 
326
 
 
327
        FRConvertData    convert_data;
 
328
 
 
329
        gboolean         stoppable;
 
330
        gboolean         closing;
 
331
 
 
332
        FrClipboardData *clipboard_data;
 
333
        FrClipboardData *copy_data;
 
334
 
 
335
        FrArchive       *copy_from_archive;
 
336
 
 
337
        GtkActionGroup  *actions;
 
338
 
 
339
        GtkRecentManager *recent_manager;
 
340
        GtkWidget        *recent_chooser_menu;
 
341
        GtkWidget        *recent_chooser_toolbar;
 
342
 
 
343
        GtkWidget        *file_popup_menu;
 
344
        GtkWidget        *folder_popup_menu;
 
345
        GtkWidget        *sidebar_folder_popup_menu;
 
346
        GtkWidget        *mitem_recents_menu;
 
347
        GtkWidget        *recent_toolbar_menu;
 
348
        GtkAction        *open_action;
 
349
 
 
350
        /* dragged files data */
 
351
 
 
352
        char             *drag_destination_folder;
 
353
        char             *drag_base_dir;
 
354
        GError           *drag_error;
 
355
        GList            *drag_file_list;        /* the list of files we are
 
356
                                                  * dragging*/
 
357
 
 
358
        /* progress dialog data */
 
359
 
 
360
        GtkWidget        *progress_dialog;
 
361
        GtkWidget        *pd_action;
 
362
        GtkWidget        *pd_archive;
 
363
        GtkWidget        *pd_message;
 
364
        GtkWidget        *pd_progress_bar;
 
365
        GtkWidget        *pd_cancel_button;
 
366
        GtkWidget        *pd_close_button;
 
367
        GtkWidget        *pd_open_archive_button;
 
368
        GtkWidget        *pd_open_destination_button;
 
369
        GtkWidget        *pd_quit_button;
 
370
        gboolean          progress_pulse;
 
371
        guint             progress_timeout;  /* Timeout to display the progress dialog. */
 
372
        guint             hide_progress_timeout;  /* Timeout to hide the progress dialog. */
 
373
        FrAction          pd_last_action;
 
374
        char             *pd_last_archive;
 
375
        char             *working_archive;
 
376
        double            pd_last_fraction;
 
377
        char             *pd_last_message;
 
378
        gboolean          use_progress_dialog;
 
379
 
 
380
        /* update dialog data */
 
381
 
 
382
        gpointer          update_dialog;
 
383
        GList            *open_files;
 
384
 
 
385
        /* batch mode data */
 
386
 
 
387
        gboolean          batch_mode;          /* whether we are in a non interactive
 
388
                                                * mode. */
 
389
        GList            *batch_action_list;   /* FRBatchAction * elements */
 
390
        GList            *batch_action;        /* current action. */
 
391
 
 
392
        /* misc */
 
393
 
 
394
        GSettings        *settings_listing;
 
395
        GSettings        *settings_ui;
 
396
        GSettings        *settings_general;
 
397
        GSettings        *settings_dialogs;
 
398
        GSettings        *settings_nautilus;
 
399
 
 
400
        gulong            theme_changed_handler_id;
 
401
        gboolean          non_interactive;
 
402
        char             *extract_here_dir;
 
403
        gboolean          extract_interact_use_default_dir;
 
404
        gboolean          update_dropped_files;
 
405
        gboolean          batch_adding_one_file;
 
406
 
 
407
        GtkWindow        *load_error_parent_window;
 
408
        gboolean          showing_error_dialog;
 
409
        GtkWindow        *error_dialog_parent;
 
410
};
 
411
 
 
412
 
 
413
/* -- fr_window_free_private_data -- */
 
414
 
 
415
 
 
416
static void
 
417
fr_window_free_batch_data (FrWindow *window)
 
418
{
 
419
        GList *scan;
 
420
 
 
421
        for (scan = window->priv->batch_action_list; scan; scan = scan->next) {
 
422
                FRBatchAction *adata = scan->data;
 
423
 
 
424
                if ((adata->data != NULL) && (adata->free_func != NULL))
 
425
                        (*adata->free_func) (adata->data);
 
426
                g_free (adata);
 
427
        }
 
428
 
 
429
        g_list_free (window->priv->batch_action_list);
 
430
        window->priv->batch_action_list = NULL;
 
431
        window->priv->batch_action = NULL;
 
432
}
 
433
 
 
434
 
 
435
static void
 
436
gh_unref_pixbuf (gpointer key,
 
437
                 gpointer value,
 
438
                 gpointer user_data)
 
439
{
 
440
        g_object_unref (value);
 
441
}
 
442
 
 
443
 
 
444
static void
 
445
fr_window_clipboard_remove_file_list (FrWindow *window,
 
446
                                      GList    *file_list)
 
447
{
 
448
        GList *scan1;
 
449
 
 
450
        if (window->priv->copy_data == NULL)
 
451
                return;
 
452
 
 
453
        if (file_list == NULL) {
 
454
                fr_clipboard_data_unref  (window->priv->copy_data);
 
455
                window->priv->copy_data = NULL;
 
456
                return;
 
457
        }
 
458
 
 
459
        for (scan1 = file_list; scan1; scan1 = scan1->next) {
 
460
                const char *name1 = scan1->data;
 
461
                GList      *scan2;
 
462
 
 
463
                for (scan2 = window->priv->copy_data->files; scan2;) {
 
464
                        const char *name2 = scan2->data;
 
465
 
 
466
                        if (strcmp (name1, name2) == 0) {
 
467
                                GList *tmp = scan2->next;
 
468
                                window->priv->copy_data->files = g_list_remove_link (window->priv->copy_data->files, scan2);
 
469
                                g_free (scan2->data);
 
470
                                g_list_free (scan2);
 
471
                                scan2 = tmp;
 
472
                        }
 
473
                        else
 
474
                                scan2 = scan2->next;
 
475
                }
 
476
        }
 
477
 
 
478
        if (window->priv->copy_data->files == NULL) {
 
479
                fr_clipboard_data_unref (window->priv->copy_data);
 
480
                window->priv->copy_data = NULL;
 
481
        }
 
482
}
 
483
 
 
484
 
 
485
static void
 
486
fr_window_history_clear (FrWindow *window)
 
487
{
 
488
        if (window->priv->history != NULL)
 
489
                path_list_free (window->priv->history);
 
490
        window->priv->history = NULL;
 
491
        window->priv->history_current = NULL;
 
492
        g_free (window->priv->last_location);
 
493
        window->priv->last_location = NULL;
 
494
}
 
495
 
 
496
 
 
497
static void
 
498
fr_window_free_open_files (FrWindow *window)
 
499
{
 
500
        GList *scan;
 
501
 
 
502
        for (scan = window->priv->open_files; scan; scan = scan->next) {
 
503
                OpenFile *file = scan->data;
 
504
 
 
505
                if (file->monitor != NULL)
 
506
                        g_file_monitor_cancel (file->monitor);
 
507
                open_file_free (file);
 
508
        }
 
509
        g_list_free (window->priv->open_files);
 
510
        window->priv->open_files = NULL;
 
511
}
 
512
 
 
513
 
 
514
static void
 
515
fr_window_convert_data_free (FrWindow   *window,
 
516
                             gboolean    all)
 
517
{
 
518
        if (all) {
 
519
                g_free (window->priv->convert_data.new_file);
 
520
                window->priv->convert_data.new_file = NULL;
 
521
        }
 
522
 
 
523
        window->priv->convert_data.converting = FALSE;
 
524
 
 
525
        if (window->priv->convert_data.temp_dir != NULL) {
 
526
                g_free (window->priv->convert_data.temp_dir);
 
527
                window->priv->convert_data.temp_dir = NULL;
 
528
        }
 
529
 
 
530
        if (window->priv->convert_data.new_archive != NULL) {
 
531
                g_object_unref (window->priv->convert_data.new_archive);
 
532
                window->priv->convert_data.new_archive = NULL;
 
533
        }
 
534
 
 
535
        if (window->priv->convert_data.password != NULL) {
 
536
                g_free (window->priv->convert_data.password);
 
537
                window->priv->convert_data.password = NULL;
 
538
        }
 
539
}
 
540
 
 
541
 
 
542
static void
 
543
fr_window_free_private_data (FrWindow *window)
 
544
{
 
545
        if (window->priv->update_timeout_handle != 0) {
 
546
                g_source_remove (window->priv->update_timeout_handle);
 
547
                window->priv->update_timeout_handle = 0;
 
548
        }
 
549
 
 
550
        if (window->priv->open_action != NULL) {
 
551
                g_object_unref (window->priv->open_action);
 
552
                window->priv->open_action = NULL;
 
553
        }
 
554
 
 
555
        if (window->priv->recent_toolbar_menu != NULL) {
 
556
                gtk_widget_destroy (window->priv->recent_toolbar_menu);
 
557
                window->priv->recent_toolbar_menu = NULL;
 
558
        }
 
559
 
 
560
        while (window->priv->activity_ref > 0)
 
561
                fr_window_stop_activity_mode (window);
 
562
 
 
563
        if (window->priv->progress_timeout != 0) {
 
564
                g_source_remove (window->priv->progress_timeout);
 
565
                window->priv->progress_timeout = 0;
 
566
        }
 
567
 
 
568
        if (window->priv->hide_progress_timeout != 0) {
 
569
                g_source_remove (window->priv->hide_progress_timeout);
 
570
                window->priv->hide_progress_timeout = 0;
 
571
        }
 
572
 
 
573
        if (window->priv->theme_changed_handler_id != 0)
 
574
                g_signal_handler_disconnect (icon_theme, window->priv->theme_changed_handler_id);
 
575
 
 
576
        fr_window_history_clear (window);
 
577
 
 
578
        g_free (window->priv->open_default_dir);
 
579
        g_free (window->priv->add_default_dir);
 
580
        g_free (window->priv->extract_default_dir);
 
581
        g_free (window->priv->archive_uri);
 
582
 
 
583
        g_free (window->priv->password);
 
584
        g_free (window->priv->password_for_paste);
 
585
 
 
586
        g_object_unref (window->priv->list_store);
 
587
 
 
588
        if (window->priv->clipboard_data != NULL) {
 
589
                fr_clipboard_data_unref (window->priv->clipboard_data);
 
590
                window->priv->clipboard_data = NULL;
 
591
        }
 
592
        if (window->priv->copy_data != NULL) {
 
593
                fr_clipboard_data_unref (window->priv->copy_data);
 
594
                window->priv->copy_data = NULL;
 
595
        }
 
596
        if (window->priv->copy_from_archive != NULL) {
 
597
                g_object_unref (window->priv->copy_from_archive);
 
598
                window->priv->copy_from_archive = NULL;
 
599
        }
 
600
 
 
601
        fr_window_free_open_files (window);
 
602
 
 
603
        fr_window_convert_data_free (window, TRUE);
 
604
 
 
605
        g_clear_error (&window->priv->drag_error);
 
606
        path_list_free (window->priv->drag_file_list);
 
607
        window->priv->drag_file_list = NULL;
 
608
 
 
609
        if (window->priv->file_popup_menu != NULL) {
 
610
                gtk_widget_destroy (window->priv->file_popup_menu);
 
611
                window->priv->file_popup_menu = NULL;
 
612
        }
 
613
 
 
614
        if (window->priv->folder_popup_menu != NULL) {
 
615
                gtk_widget_destroy (window->priv->folder_popup_menu);
 
616
                window->priv->folder_popup_menu = NULL;
 
617
        }
 
618
 
 
619
        if (window->priv->sidebar_folder_popup_menu != NULL) {
 
620
                gtk_widget_destroy (window->priv->sidebar_folder_popup_menu);
 
621
                window->priv->sidebar_folder_popup_menu = NULL;
 
622
        }
 
623
 
 
624
        g_free (window->priv->last_location);
 
625
 
 
626
        fr_window_free_batch_data (window);
 
627
        fr_window_reset_current_batch_action (window);
 
628
 
 
629
        g_free (window->priv->pd_last_archive);
 
630
        g_free (window->priv->pd_last_message);
 
631
        g_free (window->priv->extract_here_dir);
 
632
        g_free (window->priv->last_status_message);
 
633
 
 
634
        g_settings_set_enum (window->priv->settings_listing, PREF_LISTING_SORT_METHOD, window->priv->sort_method);
 
635
        g_settings_set_enum (window->priv->settings_listing, PREF_LISTING_SORT_TYPE, window->priv->sort_type);
 
636
        g_settings_set_enum (window->priv->settings_listing, PREF_LISTING_LIST_MODE, window->priv->last_list_mode);
 
637
 
 
638
        _g_object_unref (window->priv->settings_listing);
 
639
        _g_object_unref (window->priv->settings_ui);
 
640
        _g_object_unref (window->priv->settings_general);
 
641
        _g_object_unref (window->priv->settings_dialogs);
 
642
        _g_object_unref (window->priv->settings_nautilus);
 
643
}
 
644
 
 
645
 
 
646
static void
 
647
fr_window_finalize (GObject *object)
 
648
{
 
649
        FrWindow *window = FR_WINDOW (object);
 
650
 
 
651
        fr_window_free_open_files (window);
 
652
 
 
653
        if (window->archive != NULL) {
 
654
                g_object_unref (window->archive);
 
655
                window->archive = NULL;
 
656
        }
 
657
 
 
658
        if (window->priv != NULL) {
 
659
                fr_window_free_private_data (window);
 
660
                g_free (window->priv);
 
661
                window->priv = NULL;
 
662
        }
 
663
 
 
664
        WindowList = g_list_remove (WindowList, window);
 
665
 
 
666
        G_OBJECT_CLASS (parent_class)->finalize (object);
 
667
 
 
668
        if (WindowList == NULL) {
 
669
                if (pixbuf_hash != NULL) {
 
670
                        g_hash_table_foreach (pixbuf_hash,
 
671
                                              gh_unref_pixbuf,
 
672
                                              NULL);
 
673
                        g_hash_table_destroy (pixbuf_hash);
 
674
                        pixbuf_hash = NULL;
 
675
                }
 
676
                if (tree_pixbuf_hash != NULL) {
 
677
                        g_hash_table_foreach (tree_pixbuf_hash,
 
678
                                              gh_unref_pixbuf,
 
679
                                              NULL);
 
680
                        g_hash_table_destroy (tree_pixbuf_hash);
 
681
                        tree_pixbuf_hash = NULL;
 
682
                }
 
683
 
 
684
                gtk_main_quit ();
 
685
        }
 
686
}
 
687
 
 
688
 
 
689
static gboolean
 
690
close__step2 (gpointer data)
 
691
{
 
692
        gtk_widget_destroy (GTK_WIDGET (data));
 
693
        return FALSE;
 
694
}
 
695
 
 
696
 
 
697
void
 
698
fr_window_close (FrWindow *window)
 
699
{
 
700
        if (window->priv->activity_ref > 0)
 
701
                return;
 
702
 
 
703
        window->priv->closing = TRUE;
 
704
 
 
705
        if (gtk_widget_get_realized (GTK_WIDGET (window))) {
 
706
                int width, height;
 
707
 
 
708
                width = gtk_widget_get_allocated_width (GTK_WIDGET (window));
 
709
                height = gtk_widget_get_allocated_height (GTK_WIDGET (window));
 
710
                g_settings_set_int (window->priv->settings_ui, PREF_UI_WINDOW_WIDTH, width);
 
711
                g_settings_set_int (window->priv->settings_ui, PREF_UI_WINDOW_HEIGHT, height);
 
712
 
 
713
                width = gtk_paned_get_position (GTK_PANED (window->priv->paned));
 
714
                if (width > 0)
 
715
                        g_settings_set_int (window->priv->settings_ui, PREF_UI_SIDEBAR_WIDTH, width);
 
716
 
 
717
                width = gtk_tree_view_column_get_width (window->priv->filename_column);
 
718
                if (width > 0)
 
719
                        g_settings_set_int (window->priv->settings_listing, PREF_LISTING_NAME_COLUMN_WIDTH, width);
 
720
        }
 
721
 
 
722
        g_idle_add (close__step2, window);
 
723
}
 
724
 
 
725
 
 
726
static void
 
727
fr_window_class_init (FrWindowClass *class)
 
728
{
 
729
        GObjectClass   *gobject_class;
 
730
        GtkWidgetClass *widget_class;
 
731
 
 
732
        parent_class = g_type_class_peek_parent (class);
 
733
 
 
734
        fr_window_signals[ARCHIVE_LOADED] =
 
735
                g_signal_new ("archive-loaded",
 
736
                              G_TYPE_FROM_CLASS (class),
 
737
                              G_SIGNAL_RUN_LAST,
 
738
                              G_STRUCT_OFFSET (FrWindowClass, archive_loaded),
 
739
                              NULL, NULL,
 
740
                              fr_marshal_VOID__BOOLEAN,
 
741
                              G_TYPE_NONE, 1,
 
742
                              G_TYPE_BOOLEAN);
 
743
        fr_window_signals[PROGRESS] =
 
744
                g_signal_new ("progress",
 
745
                              G_TYPE_FROM_CLASS (class),
 
746
                              G_SIGNAL_RUN_LAST,
 
747
                              G_STRUCT_OFFSET (FrWindowClass, progress),
 
748
                              NULL, NULL,
 
749
                              fr_marshal_VOID__DOUBLE_STRING,
 
750
                              G_TYPE_NONE, 2,
 
751
                              G_TYPE_DOUBLE,
 
752
                              G_TYPE_STRING);
 
753
        fr_window_signals[READY] =
 
754
                g_signal_new ("ready",
 
755
                              G_TYPE_FROM_CLASS (class),
 
756
                              G_SIGNAL_RUN_LAST,
 
757
                              G_STRUCT_OFFSET (FrWindowClass, ready),
 
758
                              NULL, NULL,
 
759
                              fr_marshal_VOID__POINTER,
 
760
                              G_TYPE_NONE, 1,
 
761
                              G_TYPE_POINTER);
 
762
 
 
763
        gobject_class = (GObjectClass*) class;
 
764
        gobject_class->finalize = fr_window_finalize;
 
765
 
 
766
        widget_class = (GtkWidgetClass*) class;
 
767
}
 
768
 
 
769
 
 
770
static void fr_window_update_paste_command_sensitivity (FrWindow *, GtkClipboard *);
 
771
 
 
772
 
 
773
static void
 
774
clipboard_owner_change_cb (GtkClipboard *clipboard,
 
775
                           GdkEvent     *event,
 
776
                           gpointer      user_data)
 
777
{
 
778
        fr_window_update_paste_command_sensitivity ((FrWindow *) user_data, clipboard);
 
779
}
 
780
 
 
781
 
 
782
static void
 
783
fr_window_realized (GtkWidget *window,
 
784
                    gpointer  *data)
 
785
{
 
786
        GtkClipboard *clipboard;
 
787
 
 
788
        clipboard = gtk_widget_get_clipboard (window, FR_CLIPBOARD);
 
789
        g_signal_connect (clipboard,
 
790
                          "owner_change",
 
791
                          G_CALLBACK (clipboard_owner_change_cb),
 
792
                          window);
 
793
}
 
794
 
 
795
 
 
796
static void
 
797
fr_window_unrealized (GtkWidget *window,
 
798
                      gpointer  *data)
 
799
{
 
800
        GtkClipboard *clipboard;
 
801
 
 
802
        clipboard = gtk_widget_get_clipboard (window, FR_CLIPBOARD);
 
803
        g_signal_handlers_disconnect_by_func (clipboard,
 
804
                                              G_CALLBACK (clipboard_owner_change_cb),
 
805
                                              window);
 
806
}
 
807
 
 
808
 
 
809
static void
 
810
fr_window_init (FrWindow *window)
 
811
{
 
812
        window->priv = g_new0 (FrWindowPrivateData, 1);
 
813
        window->priv->update_dropped_files = FALSE;
 
814
        window->priv->filter_mode = FALSE;
 
815
        window->priv->use_progress_dialog = TRUE;
 
816
 
 
817
        g_signal_connect (window,
 
818
                          "realize",
 
819
                          G_CALLBACK (fr_window_realized),
 
820
                          NULL);
 
821
        g_signal_connect (window,
 
822
                          "unrealize",
 
823
                          G_CALLBACK (fr_window_unrealized),
 
824
                          NULL);
 
825
 
 
826
        WindowList = g_list_prepend (WindowList, window);
 
827
}
 
828
 
 
829
 
 
830
GType
 
831
fr_window_get_type (void)
 
832
{
 
833
        static GType type = 0;
 
834
 
 
835
        if (! type) {
 
836
                GTypeInfo type_info = {
 
837
                        sizeof (FrWindowClass),
 
838
                        NULL,
 
839
                        NULL,
 
840
                        (GClassInitFunc) fr_window_class_init,
 
841
                        NULL,
 
842
                        NULL,
 
843
                        sizeof (FrWindow),
 
844
                        0,
 
845
                        (GInstanceInitFunc) fr_window_init
 
846
                };
 
847
 
 
848
                type = g_type_register_static (GTK_TYPE_WINDOW,
 
849
                                               "FrWindow",
 
850
                                               &type_info,
 
851
                                               0);
 
852
        }
 
853
 
 
854
        return type;
 
855
}
 
856
 
 
857
 
 
858
/* -- window history -- */
 
859
 
 
860
 
 
861
#if 0
 
862
static void
 
863
fr_window_history_print (FrWindow *window)
 
864
{
 
865
        GList *list;
 
866
 
 
867
        debug (DEBUG_INFO, "history:\n");
 
868
        for (list = window->priv->history; list; list = list->next)
 
869
                g_print ("\t%s %s\n",
 
870
                         (char*) list->data,
 
871
                         (list == window->priv->history_current)? "<-": "");
 
872
        g_print ("\n");
 
873
}
 
874
#endif
 
875
 
 
876
 
 
877
static void
 
878
fr_window_history_add (FrWindow   *window,
 
879
                       const char *path)
 
880
{
 
881
        if ((window->priv->history != NULL) && (window->priv->history_current != NULL)) {
 
882
                if (strcmp (window->priv->history_current->data, path) == 0)
 
883
                        return;
 
884
 
 
885
                /* Add locations visited using the back button to the history
 
886
                 * list. */
 
887
                if (window->priv->history != window->priv->history_current) {
 
888
                        GList *scan = window->priv->history->next;
 
889
                        while (scan != window->priv->history_current->next) {
 
890
                                window->priv->history = g_list_prepend (window->priv->history, g_strdup (scan->data));
 
891
                                scan = scan->next;
 
892
                        }
 
893
                }
 
894
        }
 
895
 
 
896
        window->priv->history = g_list_prepend (window->priv->history, g_strdup (path));
 
897
        window->priv->history_current = window->priv->history;
 
898
}
 
899
 
 
900
 
 
901
static void
 
902
fr_window_history_pop (FrWindow *window)
 
903
{
 
904
        GList *first;
 
905
 
 
906
        if (window->priv->history == NULL)
 
907
                return;
 
908
 
 
909
        first = window->priv->history;
 
910
        window->priv->history = g_list_remove_link (window->priv->history, first);
 
911
        if (window->priv->history_current == first)
 
912
                window->priv->history_current = window->priv->history;
 
913
        g_free (first->data);
 
914
        g_list_free (first);
 
915
}
 
916
 
 
917
 
 
918
/* -- window_update_file_list -- */
 
919
 
 
920
 
 
921
static GPtrArray *
 
922
fr_window_get_current_dir_list (FrWindow *window)
 
923
{
 
924
        GPtrArray *files;
 
925
        int        i;
 
926
 
 
927
        files = g_ptr_array_sized_new (128);
 
928
 
 
929
        for (i = 0; i < window->archive->command->files->len; i++) {
 
930
                FileData *fdata = g_ptr_array_index (window->archive->command->files, i);
 
931
 
 
932
                if (fdata->list_name == NULL)
 
933
                        continue;
 
934
                g_ptr_array_add (files, fdata);
 
935
        }
 
936
 
 
937
        return files;
 
938
}
 
939
 
 
940
 
 
941
static gint
 
942
sort_by_name (gconstpointer  ptr1,
 
943
              gconstpointer  ptr2)
 
944
{
 
945
        FileData *fdata1 = *((FileData **) ptr1);
 
946
        FileData *fdata2 = *((FileData **) ptr2);
 
947
 
 
948
        if (file_data_is_dir (fdata1) != file_data_is_dir (fdata2)) {
 
949
                if (file_data_is_dir (fdata1))
 
950
                        return -1;
 
951
                else
 
952
                        return 1;
 
953
        }
 
954
 
 
955
        return strcasecmp (fdata1->list_name, fdata2->list_name);
 
956
}
 
957
 
 
958
 
 
959
static gint
 
960
sort_by_size (gconstpointer  ptr1,
 
961
              gconstpointer  ptr2)
 
962
{
 
963
        FileData *fdata1 = *((FileData **) ptr1);
 
964
        FileData *fdata2 = *((FileData **) ptr2);
 
965
 
 
966
        if (file_data_is_dir (fdata1) != file_data_is_dir (fdata2)) {
 
967
                if (file_data_is_dir (fdata1))
 
968
                        return -1;
 
969
                else
 
970
                        return 1;
 
971
        }
 
972
        else if (file_data_is_dir (fdata1) && file_data_is_dir (fdata2)) {
 
973
                if (fdata1->dir_size > fdata2->dir_size)
 
974
                        return 1;
 
975
                else
 
976
                        return -1;
 
977
        }
 
978
 
 
979
        if (fdata1->size == fdata2->size)
 
980
                return sort_by_name (ptr1, ptr2);
 
981
        else if (fdata1->size > fdata2->size)
 
982
                return 1;
 
983
        else
 
984
                return -1;
 
985
}
 
986
 
 
987
 
 
988
static gint
 
989
sort_by_type (gconstpointer  ptr1,
 
990
              gconstpointer  ptr2)
 
991
{
 
992
        FileData    *fdata1 = *((FileData **) ptr1);
 
993
        FileData    *fdata2 = *((FileData **) ptr2);
 
994
        int          result;
 
995
        const char  *desc1, *desc2;
 
996
 
 
997
        if (file_data_is_dir (fdata1) != file_data_is_dir (fdata2)) {
 
998
                if (file_data_is_dir (fdata1))
 
999
                        return -1;
 
1000
                else
 
1001
                        return 1;
 
1002
        }
 
1003
        else if (file_data_is_dir (fdata1) && file_data_is_dir (fdata2))
 
1004
                return sort_by_name (ptr1, ptr2);
 
1005
 
 
1006
        desc1 = g_content_type_get_description (fdata1->content_type);
 
1007
        desc2 = g_content_type_get_description (fdata2->content_type);
 
1008
 
 
1009
        result = strcasecmp (desc1, desc2);
 
1010
        if (result == 0)
 
1011
                return sort_by_name (ptr1, ptr2);
 
1012
        else
 
1013
                return result;
 
1014
}
 
1015
 
 
1016
 
 
1017
static gint
 
1018
sort_by_time (gconstpointer  ptr1,
 
1019
              gconstpointer  ptr2)
 
1020
{
 
1021
        FileData *fdata1 = *((FileData **) ptr1);
 
1022
        FileData *fdata2 = *((FileData **) ptr2);
 
1023
 
 
1024
        if (file_data_is_dir (fdata1) != file_data_is_dir (fdata2)) {
 
1025
                if (file_data_is_dir (fdata1))
 
1026
                        return -1;
 
1027
                else
 
1028
                        return 1;
 
1029
        }
 
1030
        else if (file_data_is_dir (fdata1) && file_data_is_dir (fdata2))
 
1031
                return sort_by_name (ptr1, ptr2);
 
1032
 
 
1033
        if (fdata1->modified == fdata2->modified)
 
1034
                return sort_by_name (ptr1, ptr2);
 
1035
        else if (fdata1->modified > fdata2->modified)
 
1036
                return 1;
 
1037
        else
 
1038
                return -1;
 
1039
}
 
1040
 
 
1041
 
 
1042
static gint
 
1043
sort_by_path (gconstpointer  ptr1,
 
1044
              gconstpointer  ptr2)
 
1045
{
 
1046
        FileData *fdata1 = *((FileData **) ptr1);
 
1047
        FileData *fdata2 = *((FileData **) ptr2);
 
1048
        int       result;
 
1049
 
 
1050
        if (file_data_is_dir (fdata1) != file_data_is_dir (fdata2)) {
 
1051
                if (file_data_is_dir (fdata1))
 
1052
                        return -1;
 
1053
                else
 
1054
                        return 1;
 
1055
        }
 
1056
        else if (file_data_is_dir (fdata1) && file_data_is_dir (fdata2))
 
1057
                return sort_by_name (ptr1, ptr2);
 
1058
 
 
1059
        /* 2 files */
 
1060
 
 
1061
        result = strcasecmp (fdata1->path, fdata2->path);
 
1062
        if (result == 0)
 
1063
                return sort_by_name (ptr1, ptr2);
 
1064
        else
 
1065
                return result;
 
1066
}
 
1067
 
 
1068
 
 
1069
static guint64
 
1070
get_dir_size (FrWindow   *window,
 
1071
              const char *current_dir,
 
1072
              const char *name)
 
1073
{
 
1074
        guint64  size;
 
1075
        char    *dirname;
 
1076
        int      dirname_l;
 
1077
        int      i;
 
1078
 
 
1079
        dirname = g_strconcat (current_dir, name, "/", NULL);
 
1080
        dirname_l = strlen (dirname);
 
1081
 
 
1082
        size = 0;
 
1083
        for (i = 0; i < window->archive->command->files->len; i++) {
 
1084
                FileData *fd = g_ptr_array_index (window->archive->command->files, i);
 
1085
 
 
1086
                if (strncmp (dirname, fd->full_path, dirname_l) == 0)
 
1087
                        size += fd->size;
 
1088
        }
 
1089
 
 
1090
        g_free (dirname);
 
1091
 
 
1092
        return size;
 
1093
}
 
1094
 
 
1095
 
 
1096
static gboolean
 
1097
file_data_respects_filter (FrWindow *window,
 
1098
                           FileData *fdata)
 
1099
{
 
1100
        const char *filter;
 
1101
 
 
1102
        filter = gtk_entry_get_text (GTK_ENTRY (window->priv->filter_entry));
 
1103
        if ((fdata == NULL) || (filter == NULL) || (*filter == '\0'))
 
1104
                return TRUE;
 
1105
 
 
1106
        if (fdata->dir || (fdata->name == NULL))
 
1107
                return FALSE;
 
1108
 
 
1109
        return strncasecmp (fdata->name, filter, strlen (filter)) == 0;
 
1110
}
 
1111
 
 
1112
 
 
1113
static gboolean
 
1114
compute_file_list_name (FrWindow   *window,
 
1115
                        FileData   *fdata,
 
1116
                        const char *current_dir,
 
1117
                        int         current_dir_len,
 
1118
                        GHashTable *names_hash,
 
1119
                        gboolean   *different_name)
 
1120
{
 
1121
        register char *scan, *end;
 
1122
 
 
1123
        *different_name = FALSE;
 
1124
 
 
1125
        if (! file_data_respects_filter (window, fdata))
 
1126
                return FALSE;
 
1127
 
 
1128
        if (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT) {
 
1129
                fdata->list_name = g_strdup (fdata->name);
 
1130
                if (fdata->dir)
 
1131
                        fdata->dir_size = 0;
 
1132
                return FALSE;
 
1133
        }
 
1134
 
 
1135
        if (strncmp (fdata->full_path, current_dir, current_dir_len) != 0) {
 
1136
                *different_name = TRUE;
 
1137
                return FALSE;
 
1138
        }
 
1139
 
 
1140
        if (strlen (fdata->full_path) == current_dir_len)
 
1141
                return FALSE;
 
1142
 
 
1143
        scan = fdata->full_path + current_dir_len;
 
1144
        end = strchr (scan, '/');
 
1145
        if ((end == NULL) && ! fdata->dir) { /* file */
 
1146
                fdata->list_name = g_strdup (scan);
 
1147
        }
 
1148
        else { /* folder */
 
1149
                char *dir_name;
 
1150
 
 
1151
                if (end != NULL)
 
1152
                        dir_name = g_strndup (scan, end - scan);
 
1153
                else
 
1154
                        dir_name = g_strdup (scan);
 
1155
 
 
1156
                /* avoid to insert duplicated folders */
 
1157
                if (g_hash_table_lookup (names_hash, dir_name) != NULL) {
 
1158
                        g_free (dir_name);
 
1159
                        return FALSE;
 
1160
                }
 
1161
                g_hash_table_insert (names_hash, dir_name, GINT_TO_POINTER (1));
 
1162
 
 
1163
                if ((end != NULL) && (*(end + 1) != '\0'))
 
1164
                        fdata->list_dir = TRUE;
 
1165
                fdata->list_name = dir_name;
 
1166
                fdata->dir_size = get_dir_size (window, current_dir, dir_name);
 
1167
        }
 
1168
 
 
1169
        return TRUE;
 
1170
}
 
1171
 
 
1172
 
 
1173
static void
 
1174
fr_window_compute_list_names (FrWindow  *window,
 
1175
                              GPtrArray *files)
 
1176
{
 
1177
        const char *current_dir;
 
1178
        int         current_dir_len;
 
1179
        GHashTable *names_hash;
 
1180
        int         i;
 
1181
        gboolean    visible_list_started = FALSE;
 
1182
        gboolean    visible_list_completed = FALSE;
 
1183
        gboolean    different_name;
 
1184
 
 
1185
        current_dir = fr_window_get_current_location (window);
 
1186
        current_dir_len = strlen (current_dir);
 
1187
        names_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
1188
 
 
1189
        for (i = 0; i < files->len; i++) {
 
1190
                FileData *fdata = g_ptr_array_index (files, i);
 
1191
 
 
1192
                g_free (fdata->list_name);
 
1193
                fdata->list_name = NULL;
 
1194
                fdata->list_dir = FALSE;
 
1195
 
 
1196
                /* the files array is sorted by path, when the visible list
 
1197
                 * is started and we find a path that doesn't match the
 
1198
                 * current_dir path, the following files can't match
 
1199
                 * the current_dir path. */
 
1200
 
 
1201
                if (visible_list_completed)
 
1202
                        continue;
 
1203
 
 
1204
                if (compute_file_list_name (window, fdata, current_dir, current_dir_len, names_hash, &different_name)) {
 
1205
                        visible_list_started = TRUE;
 
1206
                }
 
1207
                else if (visible_list_started && different_name)
 
1208
                        visible_list_completed = TRUE;
 
1209
        }
 
1210
 
 
1211
        g_hash_table_destroy (names_hash);
 
1212
}
 
1213
 
 
1214
 
 
1215
static gboolean
 
1216
fr_window_dir_exists_in_archive (FrWindow   *window,
 
1217
                                 const char *dir_name)
 
1218
{
 
1219
        int dir_name_len;
 
1220
        int i;
 
1221
 
 
1222
        if (dir_name == NULL)
 
1223
                return FALSE;
 
1224
 
 
1225
        dir_name_len = strlen (dir_name);
 
1226
        if (dir_name_len == 0)
 
1227
                return TRUE;
 
1228
 
 
1229
        if (strcmp (dir_name, "/") == 0)
 
1230
                return TRUE;
 
1231
 
 
1232
        for (i = 0; i < window->archive->command->files->len; i++) {
 
1233
                FileData *fdata = g_ptr_array_index (window->archive->command->files, i);
 
1234
 
 
1235
                if (strncmp (dir_name, fdata->full_path, dir_name_len) == 0) {
 
1236
                        return TRUE;
 
1237
                }
 
1238
                else if (fdata->dir
 
1239
                         && (fdata->full_path[strlen (fdata->full_path)] != '/')
 
1240
                         && (strncmp (dir_name, fdata->full_path, dir_name_len - 1) == 0))
 
1241
                {
 
1242
                        return TRUE;
 
1243
                }
 
1244
        }
 
1245
 
 
1246
        return FALSE;
 
1247
}
 
1248
 
 
1249
 
 
1250
static char *
 
1251
get_parent_dir (const char *current_dir)
 
1252
{
 
1253
        char *dir;
 
1254
        char *new_dir;
 
1255
        char *retval;
 
1256
 
 
1257
        if (current_dir == NULL)
 
1258
                return NULL;
 
1259
        if (strcmp (current_dir, "/") == 0)
 
1260
                return g_strdup ("/");
 
1261
 
 
1262
        dir = g_strdup (current_dir);
 
1263
        dir[strlen (dir) - 1] = 0;
 
1264
        new_dir = remove_level_from_path (dir);
 
1265
        g_free (dir);
 
1266
 
 
1267
        if (new_dir[strlen (new_dir) - 1] == '/')
 
1268
                retval = new_dir;
 
1269
        else {
 
1270
                retval = g_strconcat (new_dir, "/", NULL);
 
1271
                g_free (new_dir);
 
1272
        }
 
1273
 
 
1274
        return retval;
 
1275
}
 
1276
 
 
1277
 
 
1278
static void fr_window_update_statusbar_list_info (FrWindow *window);
 
1279
 
 
1280
 
 
1281
static GdkPixbuf *
 
1282
get_mime_type_icon (const char *mime_type)
 
1283
{
 
1284
        GdkPixbuf *pixbuf = NULL;
 
1285
 
 
1286
        pixbuf = g_hash_table_lookup (tree_pixbuf_hash, mime_type);
 
1287
        if (pixbuf != NULL) {
 
1288
                g_object_ref (G_OBJECT (pixbuf));
 
1289
                return pixbuf;
 
1290
        }
 
1291
 
 
1292
        pixbuf = get_mime_type_pixbuf (mime_type, file_list_icon_size, icon_theme);
 
1293
        if (pixbuf == NULL)
 
1294
                return NULL;
 
1295
 
 
1296
        pixbuf = gdk_pixbuf_copy (pixbuf);
 
1297
        g_hash_table_insert (tree_pixbuf_hash, (gpointer) mime_type, pixbuf);
 
1298
        g_object_ref (G_OBJECT (pixbuf));
 
1299
 
 
1300
        return pixbuf;
 
1301
}
 
1302
 
 
1303
 
 
1304
static GdkPixbuf *
 
1305
get_icon (GtkWidget *widget,
 
1306
          FileData  *fdata)
 
1307
{
 
1308
        GdkPixbuf  *pixbuf = NULL;
 
1309
        const char *content_type;
 
1310
        GIcon      *icon;
 
1311
 
 
1312
        if (file_data_is_dir (fdata))
 
1313
                content_type = MIME_TYPE_DIRECTORY;
 
1314
        else
 
1315
                content_type = fdata->content_type;
 
1316
 
 
1317
        /* look in the hash table. */
 
1318
 
 
1319
        pixbuf = g_hash_table_lookup (pixbuf_hash, content_type);
 
1320
        if (pixbuf != NULL) {
 
1321
                g_object_ref (G_OBJECT (pixbuf));
 
1322
                return pixbuf;
 
1323
        }
 
1324
 
 
1325
        icon = g_content_type_get_icon (content_type);
 
1326
        pixbuf = get_icon_pixbuf (icon, file_list_icon_size, icon_theme);
 
1327
        g_object_unref (icon);
 
1328
 
 
1329
        if (pixbuf == NULL)
 
1330
                return NULL;
 
1331
 
 
1332
        pixbuf = gdk_pixbuf_copy (pixbuf);
 
1333
        g_hash_table_insert (pixbuf_hash, (gpointer) content_type, pixbuf);
 
1334
        g_object_ref (G_OBJECT (pixbuf));
 
1335
 
 
1336
        return pixbuf;
 
1337
}
 
1338
 
 
1339
 
 
1340
static GdkPixbuf *
 
1341
get_emblem (GtkWidget *widget,
 
1342
            FileData  *fdata)
 
1343
{
 
1344
        GdkPixbuf *pixbuf = NULL;
 
1345
 
 
1346
        if (! fdata->encrypted)
 
1347
                return NULL;
 
1348
 
 
1349
        /* encrypted */
 
1350
 
 
1351
        pixbuf = g_hash_table_lookup (pixbuf_hash, "emblem-nowrite");
 
1352
        if (pixbuf != NULL) {
 
1353
                g_object_ref (G_OBJECT (pixbuf));
 
1354
                return pixbuf;
 
1355
        }
 
1356
 
 
1357
        pixbuf = gtk_icon_theme_load_icon (icon_theme,
 
1358
                                           "emblem-nowrite",
 
1359
                                           file_list_icon_size,
 
1360
                                           0,
 
1361
                                           NULL);
 
1362
        if (pixbuf == NULL)
 
1363
                return NULL;
 
1364
 
 
1365
        pixbuf = gdk_pixbuf_copy (pixbuf);
 
1366
        g_hash_table_insert (pixbuf_hash, (gpointer) "emblem-nowrite", pixbuf);
 
1367
        g_object_ref (G_OBJECT (pixbuf));
 
1368
 
 
1369
        return pixbuf;
 
1370
}
 
1371
 
 
1372
 
 
1373
static int
 
1374
get_column_from_sort_method (FrWindowSortMethod sort_method)
 
1375
{
 
1376
        switch (sort_method) {
 
1377
        case FR_WINDOW_SORT_BY_NAME: return COLUMN_NAME;
 
1378
        case FR_WINDOW_SORT_BY_SIZE: return COLUMN_SIZE;
 
1379
        case FR_WINDOW_SORT_BY_TYPE: return COLUMN_TYPE;
 
1380
        case FR_WINDOW_SORT_BY_TIME: return COLUMN_TIME;
 
1381
        case FR_WINDOW_SORT_BY_PATH: return COLUMN_PATH;
 
1382
        default:
 
1383
                break;
 
1384
        }
 
1385
 
 
1386
        return COLUMN_NAME;
 
1387
}
 
1388
 
 
1389
 
 
1390
static int
 
1391
get_sort_method_from_column (int column_id)
 
1392
{
 
1393
        switch (column_id) {
 
1394
        case COLUMN_NAME: return FR_WINDOW_SORT_BY_NAME;
 
1395
        case COLUMN_SIZE: return FR_WINDOW_SORT_BY_SIZE;
 
1396
        case COLUMN_TYPE: return FR_WINDOW_SORT_BY_TYPE;
 
1397
        case COLUMN_TIME: return FR_WINDOW_SORT_BY_TIME;
 
1398
        case COLUMN_PATH: return FR_WINDOW_SORT_BY_PATH;
 
1399
        default:
 
1400
                break;
 
1401
        }
 
1402
 
 
1403
        return FR_WINDOW_SORT_BY_NAME;
 
1404
}
 
1405
 
 
1406
 
 
1407
static void
 
1408
add_selected_from_list_view (GtkTreeModel *model,
 
1409
                             GtkTreePath  *path,
 
1410
                             GtkTreeIter  *iter,
 
1411
                             gpointer      data)
 
1412
{
 
1413
        GList    **list = data;
 
1414
        FileData  *fdata;
 
1415
 
 
1416
        gtk_tree_model_get (model, iter,
 
1417
                            COLUMN_FILE_DATA, &fdata,
 
1418
                            -1);
 
1419
        *list = g_list_prepend (*list, fdata);
 
1420
}
 
1421
 
 
1422
 
 
1423
static void
 
1424
add_selected_from_tree_view (GtkTreeModel *model,
 
1425
                             GtkTreePath  *path,
 
1426
                             GtkTreeIter  *iter,
 
1427
                             gpointer      data)
 
1428
{
 
1429
        GList **list = data;
 
1430
        char   *dir_path;
 
1431
 
 
1432
        gtk_tree_model_get (model, iter,
 
1433
                            TREE_COLUMN_PATH, &dir_path,
 
1434
                            -1);
 
1435
        *list = g_list_prepend (*list, dir_path);
 
1436
}
 
1437
 
 
1438
 
 
1439
static void
 
1440
add_selected_fd (GtkTreeModel *model,
 
1441
                 GtkTreePath  *path,
 
1442
                 GtkTreeIter  *iter,
 
1443
                 gpointer      data)
 
1444
{
 
1445
        GList    **list = data;
 
1446
        FileData  *fdata;
 
1447
 
 
1448
        gtk_tree_model_get (model, iter,
 
1449
                            COLUMN_FILE_DATA, &fdata,
 
1450
                            -1);
 
1451
        if (! fdata->list_dir)
 
1452
                *list = g_list_prepend (*list, fdata);
 
1453
}
 
1454
 
 
1455
 
 
1456
static GList *
 
1457
get_selection_as_fd (FrWindow *window)
 
1458
{
 
1459
        GtkTreeSelection *selection;
 
1460
        GList            *list = NULL;
 
1461
 
 
1462
        if (! gtk_widget_get_realized (window->priv->list_view))
 
1463
                return NULL;
 
1464
 
 
1465
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
1466
        if (selection == NULL)
 
1467
                return NULL;
 
1468
        gtk_tree_selection_selected_foreach (selection, add_selected_fd, &list);
 
1469
 
 
1470
        return list;
 
1471
}
 
1472
 
 
1473
 
 
1474
static void
 
1475
fr_window_update_statusbar_list_info (FrWindow *window)
 
1476
{
 
1477
        char    *info, *archive_info, *selected_info;
 
1478
        char    *size_txt, *sel_size_txt;
 
1479
        int      tot_n, sel_n;
 
1480
        goffset  tot_size, sel_size;
 
1481
        GList   *scan;
 
1482
 
 
1483
        if (window == NULL)
 
1484
                return;
 
1485
 
 
1486
        if ((window->archive == NULL) || (window->archive->command == NULL)) {
 
1487
                gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar), window->priv->list_info_cid);
 
1488
                return;
 
1489
        }
 
1490
 
 
1491
        tot_n = 0;
 
1492
        tot_size = 0;
 
1493
 
 
1494
        if (window->priv->archive_present) {
 
1495
                GPtrArray *files = fr_window_get_current_dir_list (window);
 
1496
                int        i;
 
1497
 
 
1498
                for (i = 0; i < files->len; i++) {
 
1499
                        FileData *fd = g_ptr_array_index (files, i);
 
1500
 
 
1501
                        tot_n++;
 
1502
                        if (! file_data_is_dir (fd))
 
1503
                                tot_size += fd->size;
 
1504
                        else
 
1505
                                tot_size += fd->dir_size;
 
1506
                }
 
1507
                g_ptr_array_free (files, TRUE);
 
1508
        }
 
1509
 
 
1510
        sel_n = 0;
 
1511
        sel_size = 0;
 
1512
 
 
1513
        if (window->priv->archive_present) {
 
1514
                GList *selection = get_selection_as_fd (window);
 
1515
 
 
1516
                for (scan = selection; scan; scan = scan->next) {
 
1517
                        FileData *fd = scan->data;
 
1518
 
 
1519
                        sel_n++;
 
1520
                        if (! file_data_is_dir (fd))
 
1521
                                sel_size += fd->size;
 
1522
                }
 
1523
                g_list_free (selection);
 
1524
        }
 
1525
 
 
1526
        size_txt = g_format_size_for_display (tot_size);
 
1527
        sel_size_txt = g_format_size_for_display (sel_size);
 
1528
 
 
1529
        if (tot_n == 0)
 
1530
                archive_info = g_strdup ("");
 
1531
        else
 
1532
                archive_info = g_strdup_printf (ngettext ("%d object (%s)", "%d objects (%s)", tot_n), tot_n, size_txt);
 
1533
 
 
1534
        if (sel_n == 0)
 
1535
                selected_info = g_strdup ("");
 
1536
        else
 
1537
                selected_info = g_strdup_printf (ngettext ("%d object selected (%s)", "%d objects selected (%s)", sel_n), sel_n, sel_size_txt);
 
1538
 
 
1539
        info = g_strconcat (archive_info,
 
1540
                            ((sel_n == 0) ? NULL : ", "),
 
1541
                            selected_info,
 
1542
                            NULL);
 
1543
 
 
1544
        gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar), window->priv->list_info_cid, info);
 
1545
 
 
1546
        g_free (size_txt);
 
1547
        g_free (sel_size_txt);
 
1548
        g_free (archive_info);
 
1549
        g_free (selected_info);
 
1550
        g_free (info);
 
1551
}
 
1552
 
 
1553
 
 
1554
static void
 
1555
fr_window_populate_file_list (FrWindow  *window,
 
1556
                              GPtrArray *files)
 
1557
{
 
1558
        int i;
 
1559
 
 
1560
        gtk_list_store_clear (window->priv->list_store);
 
1561
 
 
1562
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (window->priv->list_store),
 
1563
                                              GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
 
1564
                                              GTK_SORT_ASCENDING);
 
1565
 
 
1566
        for (i = 0; i < files->len; i++) {
 
1567
                FileData    *fdata = g_ptr_array_index (files, i);
 
1568
                GtkTreeIter  iter;
 
1569
                GdkPixbuf   *icon, *emblem;
 
1570
                char        *utf8_name;
 
1571
 
 
1572
                if (fdata->list_name == NULL)
 
1573
                        continue;
 
1574
 
 
1575
                gtk_list_store_append (window->priv->list_store, &iter);
 
1576
 
 
1577
                icon = get_icon (GTK_WIDGET (window), fdata);
 
1578
                utf8_name = g_filename_display_name (fdata->list_name);
 
1579
                emblem = get_emblem (GTK_WIDGET (window), fdata);
 
1580
 
 
1581
                if (file_data_is_dir (fdata)) {
 
1582
                        char *utf8_path;
 
1583
                        char *tmp;
 
1584
                        char *s_size;
 
1585
                        char *s_time;
 
1586
 
 
1587
                        if (fdata->list_dir)
 
1588
                                tmp = remove_ending_separator (fr_window_get_current_location (window));
 
1589
 
 
1590
                        else
 
1591
                                tmp = remove_level_from_path (fdata->path);
 
1592
                        utf8_path = g_filename_display_name (tmp);
 
1593
                        g_free (tmp);
 
1594
 
 
1595
                        s_size = g_format_size_for_display (fdata->dir_size);
 
1596
 
 
1597
                        if (fdata->list_dir)
 
1598
                                s_time = g_strdup ("");
 
1599
                        else
 
1600
                                s_time = get_time_string (fdata->modified);
 
1601
 
 
1602
                        gtk_list_store_set (window->priv->list_store, &iter,
 
1603
                                            COLUMN_FILE_DATA, fdata,
 
1604
                                            COLUMN_ICON, icon,
 
1605
                                            COLUMN_NAME, utf8_name,
 
1606
                                            COLUMN_EMBLEM, emblem,
 
1607
                                            COLUMN_TYPE, _("Folder"),
 
1608
                                            COLUMN_SIZE, s_size,
 
1609
                                            COLUMN_TIME, s_time,
 
1610
                                            COLUMN_PATH, utf8_path,
 
1611
                                            -1);
 
1612
                        g_free (utf8_path);
 
1613
                        g_free (s_size);
 
1614
                        g_free (s_time);
 
1615
                }
 
1616
                else {
 
1617
                        char       *utf8_path;
 
1618
                        char       *s_size;
 
1619
                        char       *s_time;
 
1620
                        const char *desc;
 
1621
 
 
1622
                        utf8_path = g_filename_display_name (fdata->path);
 
1623
 
 
1624
                        s_size = g_format_size_for_display (fdata->size);
 
1625
                        s_time = get_time_string (fdata->modified);
 
1626
                        desc = g_content_type_get_description (fdata->content_type);
 
1627
 
 
1628
                        gtk_list_store_set (window->priv->list_store, &iter,
 
1629
                                            COLUMN_FILE_DATA, fdata,
 
1630
                                            COLUMN_ICON, icon,
 
1631
                                            COLUMN_NAME, utf8_name,
 
1632
                                            COLUMN_EMBLEM, emblem,
 
1633
                                            COLUMN_TYPE, desc,
 
1634
                                            COLUMN_SIZE, s_size,
 
1635
                                            COLUMN_TIME, s_time,
 
1636
                                            COLUMN_PATH, utf8_path,
 
1637
                                            -1);
 
1638
                        g_free (utf8_path);
 
1639
                        g_free (s_size);
 
1640
                        g_free (s_time);
 
1641
                }
 
1642
                g_free (utf8_name);
 
1643
                if (icon != NULL)
 
1644
                        g_object_unref (icon);
 
1645
                if (emblem != NULL)
 
1646
                        g_object_unref (emblem);
 
1647
        }
 
1648
 
 
1649
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (window->priv->list_store),
 
1650
                                              get_column_from_sort_method (window->priv->sort_method),
 
1651
                                              window->priv->sort_type);
 
1652
 
 
1653
        fr_window_update_statusbar_list_info (window);
 
1654
        fr_window_stop_activity_mode (window);
 
1655
}
 
1656
 
 
1657
 
 
1658
static int
 
1659
path_compare (gconstpointer a,
 
1660
              gconstpointer b)
 
1661
{
 
1662
        char *path_a = *((char**) a);
 
1663
        char *path_b = *((char**) b);
 
1664
 
 
1665
        return strcmp (path_a, path_b);
 
1666
}
 
1667
 
 
1668
 
 
1669
static gboolean
 
1670
get_tree_iter_from_path (FrWindow    *window,
 
1671
                         const char  *path,
 
1672
                         GtkTreeIter *parent,
 
1673
                         GtkTreeIter *iter)
 
1674
{
 
1675
        gboolean    result = FALSE;
 
1676
 
 
1677
        if (! gtk_tree_model_iter_children (GTK_TREE_MODEL (window->priv->tree_store), iter, parent))
 
1678
                return FALSE;
 
1679
 
 
1680
        do {
 
1681
                GtkTreeIter  tmp;
 
1682
                char        *iter_path;
 
1683
 
 
1684
                if (get_tree_iter_from_path (window, path, iter, &tmp)) {
 
1685
                        *iter = tmp;
 
1686
                        return TRUE;
 
1687
                }
 
1688
 
 
1689
                gtk_tree_model_get (GTK_TREE_MODEL (window->priv->tree_store),
 
1690
                                    iter,
 
1691
                                    TREE_COLUMN_PATH, &iter_path,
 
1692
                                    -1);
 
1693
 
 
1694
                if ((iter_path != NULL) && (strcmp (path, iter_path) == 0)) {
 
1695
                        result = TRUE;
 
1696
                        g_free (iter_path);
 
1697
                        break;
 
1698
                }
 
1699
                g_free (iter_path);
 
1700
        } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (window->priv->tree_store), iter));
 
1701
 
 
1702
        return result;
 
1703
}
 
1704
 
 
1705
 
 
1706
static void
 
1707
set_sensitive (FrWindow   *window,
 
1708
               const char *action_name,
 
1709
               gboolean    sensitive)
 
1710
{
 
1711
        GtkAction *action;
 
1712
 
 
1713
        action = gtk_action_group_get_action (window->priv->actions, action_name);
 
1714
        g_object_set (action, "sensitive", sensitive, NULL);
 
1715
}
 
1716
 
 
1717
 
 
1718
static void
 
1719
fr_window_update_current_location (FrWindow *window)
 
1720
{
 
1721
        const char *current_dir = fr_window_get_current_location (window);
 
1722
        char       *path;
 
1723
        GtkTreeIter iter;
 
1724
 
 
1725
        if (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT) {
 
1726
                gtk_widget_hide (window->priv->location_bar);
 
1727
                return;
 
1728
        }
 
1729
 
 
1730
        gtk_widget_show (window->priv->location_bar);
 
1731
 
 
1732
        gtk_entry_set_text (GTK_ENTRY (window->priv->location_entry), window->priv->archive_present? current_dir: "");
 
1733
 
 
1734
        set_sensitive (window, "GoBack", window->priv->archive_present && (current_dir != NULL) && (window->priv->history_current != NULL) && (window->priv->history_current->next != NULL));
 
1735
        set_sensitive (window, "GoForward", window->priv->archive_present && (current_dir != NULL) && (window->priv->history_current != NULL) && (window->priv->history_current->prev != NULL));
 
1736
        set_sensitive (window, "GoUp", window->priv->archive_present && (current_dir != NULL) && (strcmp (current_dir, "/") != 0));
 
1737
        set_sensitive (window, "GoHome", window->priv->archive_present);
 
1738
        gtk_widget_set_sensitive (window->priv->location_entry, window->priv->archive_present);
 
1739
        gtk_widget_set_sensitive (window->priv->location_label, window->priv->archive_present);
 
1740
        gtk_widget_set_sensitive (window->priv->filter_entry, window->priv->archive_present);
 
1741
 
 
1742
#if 0
 
1743
        fr_window_history_print (window);
 
1744
#endif
 
1745
 
 
1746
        path = remove_ending_separator (current_dir);
 
1747
        if (get_tree_iter_from_path (window, path, NULL, &iter)) {
 
1748
                GtkTreeSelection *selection;
 
1749
                GtkTreePath      *t_path;
 
1750
 
 
1751
                t_path = gtk_tree_model_get_path (GTK_TREE_MODEL (window->priv->tree_store), &iter);
 
1752
                gtk_tree_view_expand_to_path (GTK_TREE_VIEW (window->priv->tree_view), t_path);
 
1753
                gtk_tree_path_free (t_path);
 
1754
 
 
1755
                selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->tree_view));
 
1756
                gtk_tree_selection_select_iter (selection, &iter);
 
1757
        }
 
1758
        g_free (path);
 
1759
}
 
1760
 
 
1761
 
 
1762
void
 
1763
fr_window_update_dir_tree (FrWindow *window)
 
1764
{
 
1765
        GPtrArray  *dirs;
 
1766
        GHashTable *dir_cache;
 
1767
        int         i;
 
1768
        GdkPixbuf  *icon;
 
1769
 
 
1770
        gtk_tree_store_clear (window->priv->tree_store);
 
1771
 
 
1772
        if (! window->priv->view_folders
 
1773
            || ! window->priv->archive_present
 
1774
            || (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT))
 
1775
        {
 
1776
                gtk_widget_set_sensitive (window->priv->tree_view, FALSE);
 
1777
                gtk_widget_hide (window->priv->sidepane);
 
1778
                return;
 
1779
        }
 
1780
        else {
 
1781
                gtk_widget_set_sensitive (window->priv->tree_view, TRUE);
 
1782
                if (! gtk_widget_get_visible (window->priv->sidepane))
 
1783
                        gtk_widget_show_all (window->priv->sidepane);
 
1784
        }
 
1785
 
 
1786
        if (gtk_widget_get_realized (window->priv->tree_view))
 
1787
                gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (window->priv->tree_view), 0, 0);
 
1788
 
 
1789
        /**/
 
1790
 
 
1791
        dirs = g_ptr_array_sized_new (128);
 
1792
 
 
1793
        dir_cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
 
1794
        for (i = 0; i < window->archive->command->files->len; i++) {
 
1795
                FileData *fdata = g_ptr_array_index (window->archive->command->files, i);
 
1796
                char     *dir;
 
1797
 
 
1798
                if (gtk_entry_get_text (GTK_ENTRY (window->priv->filter_entry)) != NULL) {
 
1799
                        if (! file_data_respects_filter (window, fdata))
 
1800
                                continue;
 
1801
                }
 
1802
 
 
1803
                if (fdata->dir)
 
1804
                        dir = remove_ending_separator (fdata->full_path);
 
1805
                else
 
1806
                        dir = remove_level_from_path (fdata->full_path);
 
1807
 
 
1808
                while ((dir != NULL) && (strcmp (dir, "/") != 0)) {
 
1809
                        char *new_dir;
 
1810
 
 
1811
                        if (g_hash_table_lookup (dir_cache, dir) != NULL)
 
1812
                                break;
 
1813
 
 
1814
                        new_dir = dir;
 
1815
                        g_ptr_array_add (dirs, new_dir);
 
1816
                        g_hash_table_replace (dir_cache, new_dir, "1");
 
1817
 
 
1818
                        dir = remove_level_from_path (new_dir);
 
1819
                }
 
1820
 
 
1821
                g_free (dir);
 
1822
        }
 
1823
        g_hash_table_destroy (dir_cache);
 
1824
 
 
1825
        g_ptr_array_sort (dirs, path_compare);
 
1826
        dir_cache = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gtk_tree_path_free);
 
1827
 
 
1828
        /**/
 
1829
 
 
1830
        icon = get_mime_type_icon (MIME_TYPE_ARCHIVE);
 
1831
        {
 
1832
                GtkTreeIter  node;
 
1833
                char        *uri;
 
1834
                char        *name;
 
1835
 
 
1836
                uri = g_file_get_uri (window->archive->file);
 
1837
                name = g_uri_display_basename (uri);
 
1838
 
 
1839
                gtk_tree_store_append (window->priv->tree_store, &node, NULL);
 
1840
                gtk_tree_store_set (window->priv->tree_store, &node,
 
1841
                                    TREE_COLUMN_ICON, icon,
 
1842
                                    TREE_COLUMN_NAME, name,
 
1843
                                    TREE_COLUMN_PATH, "/",
 
1844
                                    TREE_COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
 
1845
                                    -1);
 
1846
                g_hash_table_replace (dir_cache, "/", gtk_tree_model_get_path (GTK_TREE_MODEL (window->priv->tree_store), &node));
 
1847
 
 
1848
                g_free (name);
 
1849
                g_free (uri);
 
1850
        }
 
1851
        g_object_unref (icon);
 
1852
 
 
1853
        /**/
 
1854
 
 
1855
        icon = get_mime_type_icon (MIME_TYPE_DIRECTORY);
 
1856
        for (i = 0; i < dirs->len; i++) {
 
1857
                char        *dir = g_ptr_array_index (dirs, i);
 
1858
                char        *parent_dir;
 
1859
                GtkTreePath *parent_path;
 
1860
                GtkTreeIter  parent;
 
1861
                GtkTreeIter  node;
 
1862
 
 
1863
                parent_dir = remove_level_from_path (dir);
 
1864
                if (parent_dir == NULL)
 
1865
                        continue;
 
1866
 
 
1867
                parent_path = g_hash_table_lookup (dir_cache, parent_dir);
 
1868
                gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->tree_store),
 
1869
                                         &parent,
 
1870
                                         parent_path);
 
1871
                gtk_tree_store_append (window->priv->tree_store, &node, &parent);
 
1872
                gtk_tree_store_set (window->priv->tree_store, &node,
 
1873
                                    TREE_COLUMN_ICON, icon,
 
1874
                                    TREE_COLUMN_NAME, file_name_from_path (dir),
 
1875
                                    TREE_COLUMN_PATH, dir,
 
1876
                                    TREE_COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
 
1877
                                    -1);
 
1878
                g_hash_table_replace (dir_cache, dir, gtk_tree_model_get_path (GTK_TREE_MODEL (window->priv->tree_store), &node));
 
1879
 
 
1880
                g_free (parent_dir);
 
1881
        }
 
1882
        g_hash_table_destroy (dir_cache);
 
1883
        if (icon != NULL)
 
1884
                g_object_unref (icon);
 
1885
 
 
1886
        g_ptr_array_free (dirs, TRUE);
 
1887
 
 
1888
        fr_window_update_current_location (window);
 
1889
}
 
1890
 
 
1891
 
 
1892
static void
 
1893
fr_window_update_filter_bar_visibility (FrWindow *window)
 
1894
{
 
1895
        const char *filter;
 
1896
 
 
1897
        filter = gtk_entry_get_text (GTK_ENTRY (window->priv->filter_entry));
 
1898
        if ((filter == NULL) || (*filter == '\0'))
 
1899
                gtk_widget_hide (window->priv->filter_bar);
 
1900
        else
 
1901
                gtk_widget_show (window->priv->filter_bar);
 
1902
}
 
1903
 
 
1904
 
 
1905
static void
 
1906
fr_window_update_file_list (FrWindow *window,
 
1907
                            gboolean  update_view)
 
1908
{
 
1909
        GPtrArray  *files;
 
1910
        gboolean    free_files = FALSE;
 
1911
 
 
1912
        if (gtk_widget_get_realized (window->priv->list_view))
 
1913
                gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (window->priv->list_view), 0, 0);
 
1914
 
 
1915
        if (! window->priv->archive_present || window->priv->archive_new) {
 
1916
                if (update_view)
 
1917
                        gtk_list_store_clear (window->priv->list_store);
 
1918
 
 
1919
                window->priv->current_view_length = 0;
 
1920
 
 
1921
                if (window->priv->archive_new) {
 
1922
                        gtk_widget_set_sensitive (window->priv->list_view, TRUE);
 
1923
                        gtk_widget_show_all (gtk_widget_get_parent (window->priv->list_view));
 
1924
                }
 
1925
                else {
 
1926
                        gtk_widget_set_sensitive (window->priv->list_view, FALSE);
 
1927
                        gtk_widget_hide (gtk_widget_get_parent (window->priv->list_view));
 
1928
                }
 
1929
 
 
1930
                return;
 
1931
        }
 
1932
        else {
 
1933
                gtk_widget_set_sensitive (window->priv->list_view, TRUE);
 
1934
                gtk_widget_show_all (gtk_widget_get_parent (window->priv->list_view));
 
1935
        }
 
1936
 
 
1937
        if (window->priv->give_focus_to_the_list) {
 
1938
                gtk_widget_grab_focus (window->priv->list_view);
 
1939
                window->priv->give_focus_to_the_list = FALSE;
 
1940
        }
 
1941
 
 
1942
        /**/
 
1943
 
 
1944
        fr_window_start_activity_mode (window);
 
1945
 
 
1946
        if (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT) {
 
1947
                fr_window_compute_list_names (window, window->archive->command->files);
 
1948
                files = window->archive->command->files;
 
1949
                free_files = FALSE;
 
1950
        }
 
1951
        else {
 
1952
                char *current_dir = g_strdup (fr_window_get_current_location (window));
 
1953
 
 
1954
                while (! fr_window_dir_exists_in_archive (window, current_dir)) {
 
1955
                        char *tmp;
 
1956
 
 
1957
                        fr_window_history_pop (window);
 
1958
 
 
1959
                        tmp = get_parent_dir (current_dir);
 
1960
                        g_free (current_dir);
 
1961
                        current_dir = tmp;
 
1962
 
 
1963
                        fr_window_history_add (window, current_dir);
 
1964
                }
 
1965
                g_free (current_dir);
 
1966
 
 
1967
                fr_window_compute_list_names (window, window->archive->command->files);
 
1968
                files = fr_window_get_current_dir_list (window);
 
1969
                free_files = TRUE;
 
1970
        }
 
1971
 
 
1972
        if (files != NULL)
 
1973
                window->priv->current_view_length = files->len;
 
1974
        else
 
1975
                window->priv->current_view_length = 0;
 
1976
 
 
1977
        if (update_view)
 
1978
                fr_window_populate_file_list (window, files);
 
1979
 
 
1980
        if (free_files)
 
1981
                g_ptr_array_free (files, TRUE);
 
1982
}
 
1983
 
 
1984
 
 
1985
void
 
1986
fr_window_update_list_order (FrWindow *window)
 
1987
{
 
1988
        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (window->priv->list_store), get_column_from_sort_method (window->priv->sort_method), window->priv->sort_type);
 
1989
}
 
1990
 
 
1991
 
 
1992
static void
 
1993
fr_window_update_title (FrWindow *window)
 
1994
{
 
1995
        if (! window->priv->archive_present)
 
1996
                gtk_window_set_title (GTK_WINDOW (window), _("Archive Manager"));
 
1997
        else {
 
1998
                char *title;
 
1999
                char *name;
 
2000
 
 
2001
                name = g_uri_display_basename (fr_window_get_archive_uri (window));
 
2002
                title = g_strdup_printf ("%s %s",
 
2003
                                         name,
 
2004
                                         window->archive->read_only ? _("[read only]") : "");
 
2005
 
 
2006
                gtk_window_set_title (GTK_WINDOW (window), title);
 
2007
                g_free (title);
 
2008
                g_free (name);
 
2009
        }
 
2010
}
 
2011
 
 
2012
 
 
2013
static void
 
2014
check_whether_has_a_dir (GtkTreeModel *model,
 
2015
                         GtkTreePath  *path,
 
2016
                         GtkTreeIter  *iter,
 
2017
                         gpointer      data)
 
2018
{
 
2019
        gboolean *has_a_dir = data;
 
2020
        FileData *fdata;
 
2021
 
 
2022
        gtk_tree_model_get (model, iter,
 
2023
                            COLUMN_FILE_DATA, &fdata,
 
2024
                            -1);
 
2025
        if (file_data_is_dir (fdata))
 
2026
                *has_a_dir = TRUE;
 
2027
}
 
2028
 
 
2029
 
 
2030
static gboolean
 
2031
selection_has_a_dir (FrWindow *window)
 
2032
{
 
2033
        GtkTreeSelection *selection;
 
2034
        gboolean          has_a_dir = FALSE;
 
2035
 
 
2036
        if (! gtk_widget_get_realized (window->priv->list_view))
 
2037
                return FALSE;
 
2038
 
 
2039
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
2040
        if (selection == NULL)
 
2041
                return FALSE;
 
2042
 
 
2043
        gtk_tree_selection_selected_foreach (selection,
 
2044
                                             check_whether_has_a_dir,
 
2045
                                             &has_a_dir);
 
2046
 
 
2047
        return has_a_dir;
 
2048
}
 
2049
 
 
2050
 
 
2051
static void
 
2052
set_active (FrWindow   *window,
 
2053
            const char *action_name,
 
2054
            gboolean    is_active)
 
2055
{
 
2056
        GtkAction *action;
 
2057
 
 
2058
        action = gtk_action_group_get_action (window->priv->actions, action_name);
 
2059
        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), is_active);
 
2060
}
 
2061
 
 
2062
 
 
2063
static void
 
2064
fr_window_update_paste_command_sensitivity (FrWindow     *window,
 
2065
                                            GtkClipboard *clipboard)
 
2066
{
 
2067
        gboolean running;
 
2068
        gboolean no_archive;
 
2069
        gboolean ro;
 
2070
        gboolean compr_file;
 
2071
 
 
2072
        if (window->priv->closing)
 
2073
                return;
 
2074
 
 
2075
        if (clipboard == NULL)
 
2076
                clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window), FR_CLIPBOARD);
 
2077
        running    = window->priv->activity_ref > 0;
 
2078
        no_archive = (window->archive == NULL) || ! window->priv->archive_present;
 
2079
        ro         = ! no_archive && window->archive->read_only;
 
2080
        compr_file = ! no_archive && window->archive->is_compressed_file;
 
2081
 
 
2082
        set_sensitive (window, "Paste", ! no_archive && ! ro && ! running && ! compr_file && (window->priv->list_mode != FR_WINDOW_LIST_MODE_FLAT) && gtk_clipboard_wait_is_target_available (clipboard, FR_SPECIAL_URI_LIST));
 
2083
}
 
2084
 
 
2085
 
 
2086
static void
 
2087
fr_window_update_sensitivity (FrWindow *window)
 
2088
{
 
2089
        gboolean no_archive;
 
2090
        gboolean ro;
 
2091
        gboolean file_op;
 
2092
        gboolean running;
 
2093
        gboolean compr_file;
 
2094
        gboolean sel_not_null;
 
2095
        gboolean one_file_selected;
 
2096
        gboolean dir_selected;
 
2097
        int      n_selected;
 
2098
 
 
2099
        if (window->priv->batch_mode)
 
2100
                return;
 
2101
 
 
2102
        running           = window->priv->activity_ref > 0;
 
2103
        no_archive        = (window->archive == NULL) || ! window->priv->archive_present;
 
2104
        ro                = ! no_archive && window->archive->read_only;
 
2105
        file_op           = ! no_archive && ! window->priv->archive_new  && ! running;
 
2106
        compr_file        = ! no_archive && window->archive->is_compressed_file;
 
2107
        n_selected        = fr_window_get_n_selected_files (window);
 
2108
        sel_not_null      = n_selected > 0;
 
2109
        one_file_selected = n_selected == 1;
 
2110
        dir_selected      = selection_has_a_dir (window);
 
2111
 
 
2112
        set_sensitive (window, "AddFiles", ! no_archive && ! ro && ! running && ! compr_file);
 
2113
        set_sensitive (window, "AddFiles_Toolbar", ! no_archive && ! ro && ! running && ! compr_file);
 
2114
        set_sensitive (window, "AddFolder", ! no_archive && ! ro && ! running && ! compr_file);
 
2115
        set_sensitive (window, "AddFolder_Toolbar", ! no_archive && ! ro && ! running && ! compr_file);
 
2116
        set_sensitive (window, "Copy", ! no_archive && ! ro && ! running && ! compr_file && sel_not_null && (window->priv->list_mode != FR_WINDOW_LIST_MODE_FLAT));
 
2117
        set_sensitive (window, "Cut", ! no_archive && ! ro && ! running && ! compr_file && sel_not_null && (window->priv->list_mode != FR_WINDOW_LIST_MODE_FLAT));
 
2118
        set_sensitive (window, "Delete", ! no_archive && ! ro && ! window->priv->archive_new && ! running && ! compr_file);
 
2119
        set_sensitive (window, "DeselectAll", ! no_archive && sel_not_null);
 
2120
        set_sensitive (window, "Extract", file_op);
 
2121
        set_sensitive (window, "Extract_Toolbar", file_op);
 
2122
        set_sensitive (window, "Find", ! no_archive);
 
2123
        set_sensitive (window, "LastOutput", ((window->archive != NULL)
 
2124
                                              && (window->archive->process != NULL)
 
2125
                                              && (window->archive->process->out.raw != NULL)));
 
2126
        set_sensitive (window, "New", ! running);
 
2127
        set_sensitive (window, "Open", ! running);
 
2128
        set_sensitive (window, "Open_Toolbar", ! running);
 
2129
        set_sensitive (window, "OpenSelection", file_op && sel_not_null && ! dir_selected);
 
2130
        set_sensitive (window, "OpenFolder", file_op && one_file_selected && dir_selected);
 
2131
        set_sensitive (window, "Password", ! running && (window->priv->asked_for_password || (! no_archive && window->archive->command->propPassword)));
 
2132
        set_sensitive (window, "Properties", file_op);
 
2133
        set_sensitive (window, "Close", !running || window->priv->stoppable);
 
2134
        set_sensitive (window, "Reload", ! (no_archive || running));
 
2135
        set_sensitive (window, "Rename", ! no_archive && ! ro && ! running && ! compr_file && one_file_selected);
 
2136
        set_sensitive (window, "SaveAs", ! no_archive && ! compr_file && ! running);
 
2137
        set_sensitive (window, "SelectAll", ! no_archive);
 
2138
        set_sensitive (window, "Stop", running && window->priv->stoppable);
 
2139
        set_sensitive (window, "TestArchive", ! no_archive && ! running && window->archive->command->propTest);
 
2140
        set_sensitive (window, "ViewSelection", file_op && one_file_selected && ! dir_selected);
 
2141
        set_sensitive (window, "ViewSelection_Toolbar", file_op && one_file_selected && ! dir_selected);
 
2142
 
 
2143
        if (window->priv->progress_dialog != NULL)
 
2144
                gtk_dialog_set_response_sensitive (GTK_DIALOG (window->priv->progress_dialog),
 
2145
                                                   GTK_RESPONSE_OK,
 
2146
                                                   running && window->priv->stoppable);
 
2147
 
 
2148
        fr_window_update_paste_command_sensitivity (window, NULL);
 
2149
 
 
2150
        set_sensitive (window, "SelectAll", (window->priv->current_view_length > 0) && (window->priv->current_view_length != n_selected));
 
2151
        set_sensitive (window, "DeselectAll", n_selected > 0);
 
2152
        set_sensitive (window, "OpenRecentMenu", ! running);
 
2153
 
 
2154
        set_sensitive (window, "ViewFolders", (window->priv->list_mode == FR_WINDOW_LIST_MODE_AS_DIR));
 
2155
 
 
2156
        set_sensitive (window, "ViewAllFiles", ! window->priv->filter_mode);
 
2157
        set_sensitive (window, "ViewAsFolder", ! window->priv->filter_mode);
 
2158
}
 
2159
 
 
2160
 
 
2161
static gboolean
 
2162
location_entry_key_press_event_cb (GtkWidget   *widget,
 
2163
                                   GdkEventKey *event,
 
2164
                                   FrWindow    *window)
 
2165
{
 
2166
        if ((event->keyval == GDK_KEY_Return)
 
2167
            || (event->keyval == GDK_KEY_KP_Enter)
 
2168
            || (event->keyval == GDK_KEY_ISO_Enter))
 
2169
        {
 
2170
                fr_window_go_to_location (window, gtk_entry_get_text (GTK_ENTRY (window->priv->location_entry)), FALSE);
 
2171
        }
 
2172
 
 
2173
        return FALSE;
 
2174
}
 
2175
 
 
2176
 
 
2177
static gboolean
 
2178
real_close_progress_dialog (gpointer data)
 
2179
{
 
2180
        FrWindow *window = data;
 
2181
 
 
2182
        if (window->priv->hide_progress_timeout != 0) {
 
2183
                g_source_remove (window->priv->hide_progress_timeout);
 
2184
                window->priv->hide_progress_timeout = 0;
 
2185
        }
 
2186
 
 
2187
        if (window->priv->progress_dialog != NULL)
 
2188
                gtk_widget_hide (window->priv->progress_dialog);
 
2189
 
 
2190
        return FALSE;
 
2191
}
 
2192
 
 
2193
 
 
2194
static void
 
2195
close_progress_dialog (FrWindow *window,
 
2196
                       gboolean  close_now)
 
2197
{
 
2198
        if (window->priv->progress_timeout != 0) {
 
2199
                g_source_remove (window->priv->progress_timeout);
 
2200
                window->priv->progress_timeout = 0;
 
2201
        }
 
2202
 
 
2203
        if (! window->priv->batch_mode && gtk_widget_get_mapped (GTK_WIDGET (window)))
 
2204
                gtk_widget_hide (window->priv->progress_bar);
 
2205
 
 
2206
        if (window->priv->progress_dialog == NULL)
 
2207
                return;
 
2208
 
 
2209
        if (close_now) {
 
2210
                if (window->priv->hide_progress_timeout != 0) {
 
2211
                        g_source_remove (window->priv->hide_progress_timeout);
 
2212
                        window->priv->hide_progress_timeout = 0;
 
2213
                }
 
2214
                real_close_progress_dialog (window);
 
2215
        }
 
2216
        else {
 
2217
                if (window->priv->hide_progress_timeout != 0)
 
2218
                        return;
 
2219
                window->priv->hide_progress_timeout = g_timeout_add (HIDE_PROGRESS_TIMEOUT_MSECS,
 
2220
                                                                     real_close_progress_dialog,
 
2221
                                                                     window);
 
2222
        }
 
2223
}
 
2224
 
 
2225
 
 
2226
static gboolean
 
2227
progress_dialog_delete_event (GtkWidget *caller,
 
2228
                              GdkEvent  *event,
 
2229
                              FrWindow  *window)
 
2230
{
 
2231
        if (window->priv->stoppable) {
 
2232
                activate_action_stop (NULL, window);
 
2233
                close_progress_dialog (window, TRUE);
 
2234
        }
 
2235
 
 
2236
        return TRUE;
 
2237
}
 
2238
 
 
2239
 
 
2240
static void
 
2241
open_folder (GtkWindow  *parent,
 
2242
             const char *folder)
 
2243
{
 
2244
        GError *error = NULL;
 
2245
 
 
2246
        if (folder == NULL)
 
2247
                return;
 
2248
 
 
2249
        if (! show_uri (gtk_window_get_screen (parent), folder, GDK_CURRENT_TIME, &error)) {
 
2250
                GtkWidget *d;
 
2251
                char      *utf8_name;
 
2252
                char      *message;
 
2253
 
 
2254
                utf8_name = g_filename_display_name (folder);
 
2255
                message = g_strdup_printf (_("Could not display the folder \"%s\""), utf8_name);
 
2256
                g_free (utf8_name);
 
2257
 
 
2258
                d = _gtk_error_dialog_new (parent,
 
2259
                                           GTK_DIALOG_MODAL,
 
2260
                                           NULL,
 
2261
                                           message,
 
2262
                                           "%s",
 
2263
                                           error->message);
 
2264
                gtk_dialog_run (GTK_DIALOG (d));
 
2265
                gtk_widget_destroy (d);
 
2266
 
 
2267
                g_free (message);
 
2268
                g_clear_error (&error);
 
2269
        }
 
2270
}
 
2271
 
 
2272
 
 
2273
static void
 
2274
fr_window_view_extraction_destination_folder (FrWindow *window)
 
2275
{
 
2276
        open_folder (GTK_WINDOW (window), fr_archive_get_last_extraction_destination (window->archive));
 
2277
}
 
2278
 
 
2279
 
 
2280
static void
 
2281
progress_dialog_response (GtkDialog *dialog,
 
2282
                          int        response_id,
 
2283
                          FrWindow  *window)
 
2284
{
 
2285
        GtkWidget *new_window;
 
2286
 
 
2287
        switch (response_id) {
 
2288
        case GTK_RESPONSE_CANCEL:
 
2289
                if (window->priv->stoppable) {
 
2290
                        activate_action_stop (NULL, window);
 
2291
                        close_progress_dialog (window, TRUE);
 
2292
                }
 
2293
                break;
 
2294
        case GTK_RESPONSE_CLOSE:
 
2295
                close_progress_dialog (window, TRUE);
 
2296
                break;
 
2297
        case DIALOG_RESPONSE_OPEN_ARCHIVE:
 
2298
                new_window = fr_window_new ();
 
2299
                gtk_widget_show (new_window);
 
2300
                fr_window_archive_open (FR_WINDOW (new_window), window->priv->convert_data.new_file, GTK_WINDOW (new_window));
 
2301
                close_progress_dialog (window, TRUE);
 
2302
                break;
 
2303
        case DIALOG_RESPONSE_OPEN_DESTINATION_FOLDER:
 
2304
                fr_window_view_extraction_destination_folder (window);
 
2305
                close_progress_dialog (window, TRUE);
 
2306
                break;
 
2307
        case DIALOG_RESPONSE_QUIT:
 
2308
                fr_window_close (window);
 
2309
                break;
 
2310
        default:
 
2311
                break;
 
2312
        }
 
2313
}
 
2314
 
 
2315
 
 
2316
static const char*
 
2317
get_message_from_action (FrAction action)
 
2318
{
 
2319
        char *message = "";
 
2320
 
 
2321
        switch (action) {
 
2322
        case FR_ACTION_CREATING_NEW_ARCHIVE:
 
2323
                message = _("Creating archive");
 
2324
                break;
 
2325
        case FR_ACTION_LOADING_ARCHIVE:
 
2326
                message = _("Loading archive");
 
2327
                break;
 
2328
        case FR_ACTION_LISTING_CONTENT:
 
2329
                message = _("Reading archive");
 
2330
                break;
 
2331
        case FR_ACTION_DELETING_FILES:
 
2332
                message = _("Deleting files from archive");
 
2333
                break;
 
2334
        case FR_ACTION_TESTING_ARCHIVE:
 
2335
                message = _("Testing archive");
 
2336
                break;
 
2337
        case FR_ACTION_GETTING_FILE_LIST:
 
2338
                message = _("Getting the file list");
 
2339
                break;
 
2340
        case FR_ACTION_COPYING_FILES_FROM_REMOTE:
 
2341
                message = _("Copying the file list");
 
2342
                break;
 
2343
        case FR_ACTION_ADDING_FILES:
 
2344
                message = _("Adding files to archive");
 
2345
                break;
 
2346
        case FR_ACTION_EXTRACTING_FILES:
 
2347
                message = _("Extracting files from archive");
 
2348
                break;
 
2349
        case FR_ACTION_COPYING_FILES_TO_REMOTE:
 
2350
                message = _("Copying the file list");
 
2351
                break;
 
2352
        case FR_ACTION_CREATING_ARCHIVE:
 
2353
                message = _("Creating archive");
 
2354
                break;
 
2355
        case FR_ACTION_SAVING_REMOTE_ARCHIVE:
 
2356
                message = _("Saving archive");
 
2357
                break;
 
2358
        default:
 
2359
                message = "";
 
2360
                break;
 
2361
        }
 
2362
 
 
2363
        return message;
 
2364
}
 
2365
 
 
2366
 
 
2367
static void
 
2368
progress_dialog__set_last_action (FrWindow *window,
 
2369
                                  FrAction  action)
 
2370
{
 
2371
        const char *title;
 
2372
        char       *markup;
 
2373
 
 
2374
        window->priv->pd_last_action = action;
 
2375
        title = get_message_from_action (window->priv->pd_last_action);
 
2376
        gtk_window_set_title (GTK_WINDOW (window->priv->progress_dialog), title);
 
2377
        markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"larger\">%s</span>", title);
 
2378
        gtk_label_set_markup (GTK_LABEL (window->priv->pd_action), markup);
 
2379
        g_free (markup);
 
2380
}
 
2381
 
 
2382
 
 
2383
static void
 
2384
pd_update_archive_name (FrWindow *window)
 
2385
{
 
2386
        char *current_archive;
 
2387
 
 
2388
        if (window->priv->convert_data.converting)
 
2389
                current_archive = window->priv->convert_data.new_file;
 
2390
        else if (window->priv->working_archive != NULL)
 
2391
                current_archive = window->priv->working_archive;
 
2392
        else
 
2393
                current_archive = window->priv->archive_uri;
 
2394
 
 
2395
        if (strcmp_null_tolerant (window->priv->pd_last_archive, current_archive) != 0) {
 
2396
                g_free (window->priv->pd_last_archive);
 
2397
                if (current_archive == NULL) {
 
2398
                        window->priv->pd_last_archive = NULL;
 
2399
                        gtk_label_set_text (GTK_LABEL (window->priv->pd_archive), "");
 
2400
#ifdef LOG_PROGRESS
 
2401
                        g_print ("archive name > (none)\n");
 
2402
#endif
 
2403
                }
 
2404
                else {
 
2405
                        char *name;
 
2406
 
 
2407
                        window->priv->pd_last_archive = g_strdup (current_archive);
 
2408
 
 
2409
                        name = g_uri_display_basename (window->priv->pd_last_archive);
 
2410
                        gtk_label_set_text (GTK_LABEL (window->priv->pd_archive), name);
 
2411
#ifdef LOG_PROGRESS
 
2412
                        g_print ("archive name > %s\n", name);
 
2413
#endif
 
2414
                        g_free (name);
 
2415
                }
 
2416
        }
 
2417
}
 
2418
 
 
2419
 
 
2420
static gboolean
 
2421
fr_window_working_archive_cb (FrCommand  *command,
 
2422
                              const char *archive_filename,
 
2423
                              FrWindow   *window)
 
2424
{
 
2425
        g_free (window->priv->working_archive);
 
2426
        window->priv->working_archive = NULL;
 
2427
        if (archive_filename != NULL)
 
2428
                window->priv->working_archive = g_strdup (archive_filename);
 
2429
        pd_update_archive_name (window);
 
2430
 
 
2431
        return TRUE;
 
2432
}
 
2433
 
 
2434
 
 
2435
static gboolean
 
2436
fr_window_message_cb (FrCommand  *command,
 
2437
                      const char *msg,
 
2438
                      FrWindow   *window)
 
2439
{
 
2440
        if (window->priv->progress_dialog == NULL)
 
2441
                return TRUE;
 
2442
 
 
2443
        if (msg != NULL) {
 
2444
                while (*msg == ' ')
 
2445
                        msg++;
 
2446
                if (*msg == 0)
 
2447
                        msg = NULL;
 
2448
        }
 
2449
 
 
2450
        if (msg == NULL) {
 
2451
                gtk_label_set_text (GTK_LABEL (window->priv->pd_message), "");
 
2452
        }
 
2453
        else {
 
2454
                char *utf8_msg;
 
2455
 
 
2456
                if (! g_utf8_validate (msg, -1, NULL))
 
2457
                        utf8_msg = g_locale_to_utf8 (msg, -1 , 0, 0, 0);
 
2458
                else
 
2459
                        utf8_msg = g_strdup (msg);
 
2460
                if (utf8_msg == NULL)
 
2461
                        return TRUE;
 
2462
 
 
2463
                if (g_utf8_validate (utf8_msg, -1, NULL))
 
2464
                        gtk_label_set_text (GTK_LABEL (window->priv->pd_message), utf8_msg);
 
2465
 
 
2466
                g_free (window->priv->pd_last_message);
 
2467
                window->priv->pd_last_message = g_strdup (utf8_msg);
 
2468
 
 
2469
                g_signal_emit (G_OBJECT (window),
 
2470
                               fr_window_signals[PROGRESS],
 
2471
                               0,
 
2472
                               window->priv->pd_last_fraction,
 
2473
                               window->priv->pd_last_message);
 
2474
 
 
2475
#ifdef LOG_PROGRESS
 
2476
                g_print ("message > %s\n", utf8_msg);
 
2477
#endif
 
2478
 
 
2479
                g_free (utf8_msg);
 
2480
        }
 
2481
 
 
2482
        if (window->priv->convert_data.converting) {
 
2483
                if (window->priv->pd_last_action != FR_ACTION_CREATING_ARCHIVE)
 
2484
                        progress_dialog__set_last_action (window, FR_ACTION_CREATING_ARCHIVE);
 
2485
        }
 
2486
        else if (window->priv->pd_last_action != window->priv->action)
 
2487
                progress_dialog__set_last_action (window, window->priv->action);
 
2488
 
 
2489
        pd_update_archive_name (window);
 
2490
 
 
2491
        return TRUE;
 
2492
}
 
2493
 
 
2494
 
 
2495
static void
 
2496
create_the_progress_dialog (FrWindow *window)
 
2497
{
 
2498
        GtkWindow     *parent;
 
2499
        GtkDialog     *d;
 
2500
        GtkWidget     *vbox;
 
2501
        GtkWidget     *align;
 
2502
        GtkWidget     *progress_vbox;
 
2503
        GtkWidget     *lbl;
 
2504
        const char    *title;
 
2505
        char          *markup;
 
2506
        PangoAttrList *attr_list;
 
2507
 
 
2508
        if (window->priv->progress_dialog != NULL)
 
2509
                return;
 
2510
 
 
2511
        if (window->priv->batch_mode)
 
2512
                parent = NULL;
 
2513
        else
 
2514
                parent = GTK_WINDOW (window);
 
2515
 
 
2516
        window->priv->pd_last_action = window->priv->action;
 
2517
        title = get_message_from_action (window->priv->pd_last_action);
 
2518
        window->priv->progress_dialog = gtk_dialog_new_with_buttons (title,
 
2519
                                                                     parent,
 
2520
                                                                     GTK_DIALOG_DESTROY_WITH_PARENT,
 
2521
                                                                     NULL);
 
2522
 
 
2523
        window->priv->pd_quit_button = gtk_dialog_add_button (GTK_DIALOG (window->priv->progress_dialog), GTK_STOCK_QUIT, DIALOG_RESPONSE_QUIT);
 
2524
        window->priv->pd_open_archive_button = gtk_dialog_add_button (GTK_DIALOG (window->priv->progress_dialog), _("_Open the Archive"), DIALOG_RESPONSE_OPEN_ARCHIVE);
 
2525
        window->priv->pd_open_destination_button = gtk_dialog_add_button (GTK_DIALOG (window->priv->progress_dialog), _("_Show the Files"), DIALOG_RESPONSE_OPEN_DESTINATION_FOLDER);
 
2526
        window->priv->pd_close_button = gtk_dialog_add_button (GTK_DIALOG (window->priv->progress_dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
 
2527
        window->priv->pd_cancel_button = gtk_dialog_add_button (GTK_DIALOG (window->priv->progress_dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
 
2528
 
 
2529
        d = GTK_DIALOG (window->priv->progress_dialog);
 
2530
        gtk_window_set_resizable (GTK_WINDOW (d), TRUE);
 
2531
        gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_OK);
 
2532
        gtk_window_set_default_size (GTK_WINDOW (d), PROGRESS_DIALOG_DEFAULT_WIDTH, -1);
 
2533
 
 
2534
        /* Main */
 
2535
 
 
2536
        vbox = gtk_vbox_new (FALSE, 5);
 
2537
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
 
2538
        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (d)), vbox, FALSE, FALSE, 10);
 
2539
 
 
2540
        /* action label */
 
2541
 
 
2542
        lbl = window->priv->pd_action = gtk_label_new ("");
 
2543
 
 
2544
        markup = g_markup_printf_escaped ("<span weight=\"bold\" size=\"larger\">%s</span>", title);
 
2545
        gtk_label_set_markup (GTK_LABEL (lbl), markup);
 
2546
        g_free (markup);
 
2547
 
 
2548
        align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
 
2549
        gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 12, 0, 0);
 
2550
 
 
2551
        gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5);
 
2552
        gtk_misc_set_padding (GTK_MISC (lbl), 0, 0);
 
2553
        gtk_label_set_ellipsize (GTK_LABEL (lbl), PANGO_ELLIPSIZE_END);
 
2554
 
 
2555
        gtk_container_add (GTK_CONTAINER (align), lbl);
 
2556
        gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
 
2557
 
 
2558
        /* archive name */
 
2559
 
 
2560
        g_free (window->priv->pd_last_archive);
 
2561
        window->priv->pd_last_archive = NULL;
 
2562
        if (window->priv->archive_uri != NULL) {
 
2563
                GtkWidget *hbox;
 
2564
                char      *name;
 
2565
 
 
2566
                hbox = gtk_hbox_new (FALSE, 6);
 
2567
                gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
2568
 
 
2569
                lbl = gtk_label_new ("");
 
2570
                markup = g_markup_printf_escaped ("<b>%s</b>", _("Archive:"));
 
2571
                gtk_label_set_markup (GTK_LABEL (lbl), markup);
 
2572
                g_free (markup);
 
2573
                gtk_box_pack_start (GTK_BOX (hbox), lbl, FALSE, FALSE, 0);
 
2574
 
 
2575
                window->priv->pd_last_archive = g_strdup (window->priv->archive_uri);
 
2576
                name = g_uri_display_basename (window->priv->pd_last_archive);
 
2577
                lbl = window->priv->pd_archive = gtk_label_new (name);
 
2578
                g_free (name);
 
2579
 
 
2580
                gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5);
 
2581
                gtk_label_set_ellipsize (GTK_LABEL (lbl), PANGO_ELLIPSIZE_END);
 
2582
                gtk_box_pack_start (GTK_BOX (hbox), lbl, TRUE, TRUE, 0);
 
2583
        }
 
2584
 
 
2585
        /* progress and details */
 
2586
 
 
2587
        align = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
 
2588
        gtk_alignment_set_padding (GTK_ALIGNMENT (align), 0, 6, 0, 0);
 
2589
 
 
2590
        progress_vbox = gtk_vbox_new (FALSE, 6);
 
2591
        gtk_container_add (GTK_CONTAINER (align), progress_vbox);
 
2592
        gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
 
2593
 
 
2594
        /* progress bar */
 
2595
 
 
2596
        window->priv->pd_progress_bar = gtk_progress_bar_new ();
 
2597
        gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (window->priv->pd_progress_bar), ACTIVITY_PULSE_STEP);
 
2598
        gtk_box_pack_start (GTK_BOX (progress_vbox), window->priv->pd_progress_bar, TRUE, TRUE, 0);
 
2599
 
 
2600
        /* details label */
 
2601
 
 
2602
        lbl = window->priv->pd_message = gtk_label_new ("");
 
2603
 
 
2604
        attr_list = pango_attr_list_new ();
 
2605
        pango_attr_list_insert (attr_list, pango_attr_style_new (PANGO_STYLE_ITALIC));
 
2606
        gtk_label_set_attributes (GTK_LABEL (lbl), attr_list);
 
2607
        pango_attr_list_unref (attr_list);
 
2608
 
 
2609
        gtk_misc_set_alignment (GTK_MISC (lbl), 0.0, 0.5);
 
2610
        gtk_label_set_ellipsize (GTK_LABEL (lbl), PANGO_ELLIPSIZE_END);
 
2611
        gtk_box_pack_start (GTK_BOX (progress_vbox), lbl, TRUE, TRUE, 0);
 
2612
 
 
2613
        gtk_widget_show_all (vbox);
 
2614
 
 
2615
        /* signals */
 
2616
 
 
2617
        g_signal_connect (G_OBJECT (window->priv->progress_dialog),
 
2618
                          "response",
 
2619
                          G_CALLBACK (progress_dialog_response),
 
2620
                          window);
 
2621
        g_signal_connect (G_OBJECT (window->priv->progress_dialog),
 
2622
                          "delete_event",
 
2623
                          G_CALLBACK (progress_dialog_delete_event),
 
2624
                          window);
 
2625
}
 
2626
 
 
2627
 
 
2628
static gboolean
 
2629
display_progress_dialog (gpointer data)
 
2630
{
 
2631
        FrWindow *window = data;
 
2632
 
 
2633
        if (window->priv->progress_timeout != 0)
 
2634
                g_source_remove (window->priv->progress_timeout);
 
2635
 
 
2636
        if (window->priv->use_progress_dialog && (window->priv->progress_dialog != NULL)) {
 
2637
                gtk_dialog_set_response_sensitive (GTK_DIALOG (window->priv->progress_dialog),
 
2638
                                                   GTK_RESPONSE_OK,
 
2639
                                                   window->priv->stoppable);
 
2640
                if (! window->priv->non_interactive)
 
2641
                        gtk_widget_show (GTK_WIDGET (window));
 
2642
                gtk_widget_hide (window->priv->progress_bar);
 
2643
                gtk_widget_show (window->priv->progress_dialog);
 
2644
                fr_window_message_cb (NULL, window->priv->last_status_message, window);
 
2645
        }
 
2646
 
 
2647
        window->priv->progress_timeout = 0;
 
2648
 
 
2649
        return FALSE;
 
2650
}
 
2651
 
 
2652
 
 
2653
static void
 
2654
open_progress_dialog (FrWindow *window,
 
2655
                      gboolean  open_now)
 
2656
{
 
2657
        if (window->priv->hide_progress_timeout != 0) {
 
2658
                g_source_remove (window->priv->hide_progress_timeout);
 
2659
                window->priv->hide_progress_timeout = 0;
 
2660
        }
 
2661
 
 
2662
        if (open_now) {
 
2663
                if (window->priv->progress_timeout != 0)
 
2664
                        g_source_remove (window->priv->progress_timeout);
 
2665
                window->priv->progress_timeout = 0;
 
2666
        }
 
2667
 
 
2668
        if ((window->priv->progress_timeout != 0)
 
2669
            || ((window->priv->progress_dialog != NULL) && gtk_widget_get_visible (window->priv->progress_dialog)))
 
2670
                return;
 
2671
 
 
2672
        if (! window->priv->batch_mode && ! open_now)
 
2673
                gtk_widget_show (window->priv->progress_bar);
 
2674
 
 
2675
        create_the_progress_dialog (window);
 
2676
        gtk_widget_show (window->priv->pd_cancel_button);
 
2677
        gtk_widget_hide (window->priv->pd_open_archive_button);
 
2678
        gtk_widget_hide (window->priv->pd_open_destination_button);
 
2679
        gtk_widget_hide (window->priv->pd_quit_button);
 
2680
        gtk_widget_hide (window->priv->pd_close_button);
 
2681
 
 
2682
        if (open_now)
 
2683
                display_progress_dialog (window);
 
2684
        else
 
2685
                window->priv->progress_timeout = g_timeout_add (PROGRESS_TIMEOUT_MSECS,
 
2686
                                                                display_progress_dialog,
 
2687
                                                                window);
 
2688
}
 
2689
 
 
2690
 
 
2691
static gboolean
 
2692
fr_window_progress_cb (FrCommand  *command,
 
2693
                       double      fraction,
 
2694
                       FrWindow   *window)
 
2695
{
 
2696
        window->priv->progress_pulse = (fraction < 0.0);
 
2697
        if (! window->priv->progress_pulse) {
 
2698
                fraction = CLAMP (fraction, 0.0, 1.0);
 
2699
                if (window->priv->progress_dialog != NULL)
 
2700
                        gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->pd_progress_bar), fraction);
 
2701
                gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress_bar), fraction);
 
2702
 
 
2703
                window->priv->pd_last_fraction = fraction;
 
2704
 
 
2705
                g_signal_emit (G_OBJECT (window),
 
2706
                               fr_window_signals[PROGRESS],
 
2707
                               0,
 
2708
                               window->priv->pd_last_fraction,
 
2709
                               window->priv->pd_last_message);
 
2710
 
 
2711
#ifdef LOG_PROGRESS
 
2712
                g_print ("progress > %2.2f\n", fraction);
 
2713
#endif
 
2714
        }
 
2715
        return TRUE;
 
2716
}
 
2717
 
 
2718
 
 
2719
static void
 
2720
open_progress_dialog_with_open_destination (FrWindow *window)
 
2721
{
 
2722
        window->priv->ask_to_open_destination_after_extraction = FALSE;
 
2723
 
 
2724
        if (window->priv->hide_progress_timeout != 0) {
 
2725
                g_source_remove (window->priv->hide_progress_timeout);
 
2726
                window->priv->hide_progress_timeout = 0;
 
2727
        }
 
2728
        if (window->priv->progress_timeout != 0) {
 
2729
                g_source_remove (window->priv->progress_timeout);
 
2730
                window->priv->progress_timeout = 0;
 
2731
        }
 
2732
 
 
2733
        create_the_progress_dialog (window);
 
2734
        gtk_widget_hide (window->priv->pd_cancel_button);
 
2735
        gtk_widget_hide (window->priv->pd_open_archive_button);
 
2736
        gtk_widget_show (window->priv->pd_open_destination_button);
 
2737
        gtk_widget_show (window->priv->pd_quit_button);
 
2738
        gtk_widget_show (window->priv->pd_close_button);
 
2739
        display_progress_dialog (window);
 
2740
        fr_window_progress_cb (NULL, 1.0, window);
 
2741
        fr_window_message_cb (NULL, _("Extraction completed successfully"), window);
 
2742
}
 
2743
 
 
2744
 
 
2745
static void
 
2746
open_progress_dialog_with_open_archive (FrWindow *window)
 
2747
{
 
2748
        if (window->priv->hide_progress_timeout != 0) {
 
2749
                g_source_remove (window->priv->hide_progress_timeout);
 
2750
                window->priv->hide_progress_timeout = 0;
 
2751
        }
 
2752
        if (window->priv->progress_timeout != 0) {
 
2753
                g_source_remove (window->priv->progress_timeout);
 
2754
                window->priv->progress_timeout = 0;
 
2755
        }
 
2756
 
 
2757
        create_the_progress_dialog (window);
 
2758
        gtk_widget_hide (window->priv->pd_cancel_button);
 
2759
        gtk_widget_hide (window->priv->pd_open_destination_button);
 
2760
        gtk_widget_show (window->priv->pd_open_archive_button);
 
2761
        gtk_widget_show (window->priv->pd_close_button);
 
2762
        display_progress_dialog (window);
 
2763
        fr_window_progress_cb (NULL, 1.0, window);
 
2764
        fr_window_message_cb (NULL, _("Archive created successfully"), window);
 
2765
}
 
2766
 
 
2767
 
 
2768
void
 
2769
fr_window_push_message (FrWindow   *window,
 
2770
                        const char *msg)
 
2771
{
 
2772
        if (! gtk_widget_get_mapped (GTK_WIDGET (window)))
 
2773
                return;
 
2774
 
 
2775
        g_free (window->priv->last_status_message);
 
2776
        window->priv->last_status_message = g_strdup (msg);
 
2777
 
 
2778
        gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar), window->priv->progress_cid, window->priv->last_status_message);
 
2779
        if (window->priv->progress_dialog != NULL)
 
2780
                gtk_label_set_text (GTK_LABEL (window->priv->pd_message), window->priv->last_status_message);
 
2781
}
 
2782
 
 
2783
 
 
2784
void
 
2785
fr_window_pop_message (FrWindow *window)
 
2786
{
 
2787
        if (! gtk_widget_get_mapped (GTK_WIDGET (window)))
 
2788
                return;
 
2789
        gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar), window->priv->progress_cid);
 
2790
        if (window->priv->progress_dialog != NULL)
 
2791
                gtk_label_set_text (GTK_LABEL (window->priv->pd_message), "");
 
2792
}
 
2793
 
 
2794
 
 
2795
static void
 
2796
action_started (FrArchive *archive,
 
2797
                FrAction   action,
 
2798
                gpointer   data)
 
2799
{
 
2800
        FrWindow   *window = data;
 
2801
        const char *message;
 
2802
        char       *full_msg;
 
2803
 
 
2804
        window->priv->action = action;
 
2805
        fr_window_start_activity_mode (window);
 
2806
 
 
2807
#ifdef DEBUG
 
2808
        debug (DEBUG_INFO, "%s [START] (FR::Window)\n", action_names[action]);
 
2809
#endif
 
2810
 
 
2811
        message = get_message_from_action (action);
 
2812
        full_msg = g_strdup_printf ("%s, %s", message, _("please wait..."));
 
2813
        fr_window_push_message (window, full_msg);
 
2814
 
 
2815
        switch (action) {
 
2816
        case FR_ACTION_EXTRACTING_FILES:
 
2817
                open_progress_dialog (window, window->priv->ask_to_open_destination_after_extraction || window->priv->convert_data.converting || window->priv->batch_mode);
 
2818
                break;
 
2819
        default:
 
2820
                open_progress_dialog (window, window->priv->batch_mode);
 
2821
                break;
 
2822
        }
 
2823
 
 
2824
        if (archive->command != NULL) {
 
2825
                fr_command_progress (archive->command, -1.0);
 
2826
                fr_command_message (archive->command, message);
 
2827
        }
 
2828
 
 
2829
        g_free (full_msg);
 
2830
}
 
2831
 
 
2832
 
 
2833
static void
 
2834
fr_window_add_to_recent_list (FrWindow *window,
 
2835
                              char     *uri)
 
2836
{
 
2837
        if (window->priv->batch_mode)
 
2838
                return;
 
2839
 
 
2840
        if (is_temp_dir (uri))
 
2841
                return;
 
2842
 
 
2843
        if (window->archive->content_type != NULL) {
 
2844
                GtkRecentData *recent_data;
 
2845
 
 
2846
                recent_data = g_new0 (GtkRecentData, 1);
 
2847
                recent_data->mime_type = g_content_type_get_mime_type (window->archive->content_type);
 
2848
                recent_data->app_name = "File Roller";
 
2849
                recent_data->app_exec = "file-roller";
 
2850
                gtk_recent_manager_add_full (window->priv->recent_manager, uri, recent_data);
 
2851
 
 
2852
                g_free (recent_data);
 
2853
        }
 
2854
        else
 
2855
                gtk_recent_manager_add_item (window->priv->recent_manager, uri);
 
2856
}
 
2857
 
 
2858
 
 
2859
static void
 
2860
fr_window_remove_from_recent_list (FrWindow *window,
 
2861
                                   char     *filename)
 
2862
{
 
2863
        if (filename != NULL)
 
2864
                gtk_recent_manager_remove_item (window->priv->recent_manager, filename, NULL);
 
2865
}
 
2866
 
 
2867
 
 
2868
static void
 
2869
error_dialog_response_cb (GtkDialog *dialog,
 
2870
                          gint       arg1,
 
2871
                          gpointer   user_data)
 
2872
{
 
2873
        FrWindow  *window = user_data;
 
2874
        GtkWindow *dialog_parent = window->priv->error_dialog_parent;
 
2875
 
 
2876
        window->priv->showing_error_dialog = FALSE;
 
2877
        window->priv->error_dialog_parent = NULL;
 
2878
 
 
2879
        if ((dialog_parent != NULL) && (gtk_widget_get_toplevel (GTK_WIDGET (dialog_parent)) != (GtkWidget*) dialog_parent))
 
2880
                gtk_window_set_modal (dialog_parent, TRUE);
 
2881
        gtk_widget_destroy (GTK_WIDGET (dialog));
 
2882
 
 
2883
        if (window->priv->destroy_with_error_dialog)
 
2884
                gtk_widget_destroy (GTK_WIDGET (window));
 
2885
}
 
2886
 
 
2887
 
 
2888
static void
 
2889
fr_window_show_error_dialog (FrWindow   *window,
 
2890
                             GtkWidget  *dialog,
 
2891
                             GtkWindow  *dialog_parent,
 
2892
                             const char *details)
 
2893
{
 
2894
        if (window->priv->batch_mode && ! window->priv->use_progress_dialog) {
 
2895
                GError *error;
 
2896
 
 
2897
                error = g_error_new_literal (FR_ERROR, FR_PROC_ERROR_GENERIC, details ? details : _("Command exited abnormally."));
 
2898
                g_signal_emit (window,
 
2899
                               fr_window_signals[READY],
 
2900
                               0,
 
2901
                               error);
 
2902
 
 
2903
                gtk_widget_destroy (GTK_WIDGET (window));
 
2904
 
 
2905
                return;
 
2906
        }
 
2907
 
 
2908
        close_progress_dialog (window, TRUE);
 
2909
 
 
2910
        if (window->priv->batch_mode)
 
2911
                fr_window_destroy_with_error_dialog (window);
 
2912
 
 
2913
        if (dialog_parent != NULL)
 
2914
                gtk_window_set_modal (dialog_parent, FALSE);
 
2915
        g_signal_connect (dialog,
 
2916
                          "response",
 
2917
                          G_CALLBACK (error_dialog_response_cb),
 
2918
                          window);
 
2919
        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
 
2920
        gtk_widget_show (dialog);
 
2921
 
 
2922
        window->priv->showing_error_dialog = TRUE;
 
2923
        window->priv->error_dialog_parent = dialog_parent;
 
2924
}
 
2925
 
 
2926
 
 
2927
void
 
2928
fr_window_destroy_with_error_dialog (FrWindow *window)
 
2929
{
 
2930
        window->priv->destroy_with_error_dialog = TRUE;
 
2931
}
 
2932
 
 
2933
 
 
2934
static gboolean
 
2935
handle_errors (FrWindow    *window,
 
2936
               FrArchive   *archive,
 
2937
               FrAction     action,
 
2938
               FrProcError *error)
 
2939
{
 
2940
        if (error->type == FR_PROC_ERROR_ASK_PASSWORD) {
 
2941
                close_progress_dialog (window, TRUE);
 
2942
                dlg_ask_password (window);
 
2943
                return FALSE;
 
2944
        }
 
2945
        else if (error->type == FR_PROC_ERROR_UNSUPPORTED_FORMAT) {
 
2946
                close_progress_dialog (window, TRUE);
 
2947
                dlg_package_installer (window, archive, action);
 
2948
                return FALSE;
 
2949
        }
 
2950
#if 0
 
2951
        else if (error->type == FR_PROC_ERROR_BAD_CHARSET) {
 
2952
                close_progress_dialog (window, TRUE);
 
2953
                /* dlg_ask_archive_charset (window); FIXME: implement after feature freeze */
 
2954
                return FALSE;
 
2955
        }
 
2956
#endif
 
2957
        else if (error->type == FR_PROC_ERROR_STOPPED) {
 
2958
                /* nothing */
 
2959
        }
 
2960
        else if (error->type != FR_PROC_ERROR_NONE) {
 
2961
                char      *msg = NULL;
 
2962
                char      *utf8_name;
 
2963
                char      *details = NULL;
 
2964
                GtkWindow *dialog_parent;
 
2965
                GtkWidget *dialog;
 
2966
                FrProcess *process = archive->process;
 
2967
                GList     *output = NULL;
 
2968
 
 
2969
                if (window->priv->batch_mode) {
 
2970
                        dialog_parent = NULL;
 
2971
                        window->priv->load_error_parent_window = NULL;
 
2972
                }
 
2973
                else {
 
2974
                        dialog_parent = (GtkWindow *) window;
 
2975
                        if (window->priv->load_error_parent_window == NULL)
 
2976
                                window->priv->load_error_parent_window = (GtkWindow *) window;
 
2977
                }
 
2978
 
 
2979
                if ((action == FR_ACTION_LISTING_CONTENT) || (action == FR_ACTION_LOADING_ARCHIVE))
 
2980
                        fr_window_archive_close (window);
 
2981
 
 
2982
                switch (action) {
 
2983
                case FR_ACTION_CREATING_NEW_ARCHIVE:
 
2984
                        dialog_parent = window->priv->load_error_parent_window;
 
2985
                        msg = _("Could not create the archive");
 
2986
                        break;
 
2987
 
 
2988
                case FR_ACTION_EXTRACTING_FILES:
 
2989
                case FR_ACTION_COPYING_FILES_TO_REMOTE:
 
2990
                        msg = _("An error occurred while extracting files.");
 
2991
                        break;
 
2992
 
 
2993
                case FR_ACTION_LOADING_ARCHIVE:
 
2994
                        dialog_parent = window->priv->load_error_parent_window;
 
2995
                        utf8_name = g_uri_display_basename (window->priv->archive_uri);
 
2996
                        msg = g_strdup_printf (_("Could not open \"%s\""), utf8_name);
 
2997
                        g_free (utf8_name);
 
2998
                        break;
 
2999
 
 
3000
                case FR_ACTION_LISTING_CONTENT:
 
3001
                        msg = _("An error occurred while loading the archive.");
 
3002
                        break;
 
3003
 
 
3004
                case FR_ACTION_DELETING_FILES:
 
3005
                        msg = _("An error occurred while deleting files from the archive.");
 
3006
                        break;
 
3007
 
 
3008
                case FR_ACTION_ADDING_FILES:
 
3009
                case FR_ACTION_GETTING_FILE_LIST:
 
3010
                case FR_ACTION_COPYING_FILES_FROM_REMOTE:
 
3011
                        msg = _("An error occurred while adding files to the archive.");
 
3012
                        break;
 
3013
 
 
3014
                case FR_ACTION_TESTING_ARCHIVE:
 
3015
                        msg = _("An error occurred while testing archive.");
 
3016
                        break;
 
3017
 
 
3018
                case FR_ACTION_SAVING_REMOTE_ARCHIVE:
 
3019
                        msg = _("An error occurred while saving the archive.");
 
3020
                        break;
 
3021
 
 
3022
                default:
 
3023
                        msg = _("An error occurred.");
 
3024
                        break;
 
3025
                }
 
3026
 
 
3027
                switch (error->type) {
 
3028
                case FR_PROC_ERROR_COMMAND_NOT_FOUND:
 
3029
                        details = _("Command not found.");
 
3030
                        break;
 
3031
                case FR_PROC_ERROR_EXITED_ABNORMALLY:
 
3032
                        details = _("Command exited abnormally.");
 
3033
                        break;
 
3034
                case FR_PROC_ERROR_SPAWN:
 
3035
                        details = error->gerror->message;
 
3036
                        break;
 
3037
                default:
 
3038
                        if (error->gerror != NULL)
 
3039
                                details = error->gerror->message;
 
3040
                        else
 
3041
                                details = NULL;
 
3042
                        break;
 
3043
                }
 
3044
 
 
3045
                if (error->type != FR_PROC_ERROR_GENERIC)
 
3046
                        output = (process->err.raw != NULL) ? process->err.raw : process->out.raw;
 
3047
 
 
3048
                dialog = _gtk_error_dialog_new (dialog_parent,
 
3049
                                                0,
 
3050
                                                output,
 
3051
                                                msg,
 
3052
                                                ((details != NULL) ? "%s" : NULL),
 
3053
                                                details);
 
3054
                fr_window_show_error_dialog (window, dialog, dialog_parent, details);
 
3055
 
 
3056
                return FALSE;
 
3057
        }
 
3058
 
 
3059
        return TRUE;
 
3060
}
 
3061
 
 
3062
 
 
3063
static void
 
3064
convert__action_performed (FrArchive   *archive,
 
3065
                           FrAction     action,
 
3066
                           FrProcError *error,
 
3067
                           gpointer     data)
 
3068
{
 
3069
        FrWindow *window = data;
 
3070
 
 
3071
#ifdef DEBUG
 
3072
        debug (DEBUG_INFO, "%s [CONVERT::DONE] (FR::Window)\n", action_names[action]);
 
3073
#endif
 
3074
 
 
3075
        if ((action == FR_ACTION_GETTING_FILE_LIST) || (action == FR_ACTION_ADDING_FILES)) {
 
3076
                fr_window_stop_activity_mode (window);
 
3077
                fr_window_pop_message (window);
 
3078
                close_progress_dialog (window, FALSE);
 
3079
        }
 
3080
 
 
3081
        if (action != FR_ACTION_ADDING_FILES)
 
3082
                return;
 
3083
 
 
3084
        handle_errors (window, archive, action, error);
 
3085
 
 
3086
        if (error->type == FR_PROC_ERROR_NONE)
 
3087
                open_progress_dialog_with_open_archive (window);
 
3088
 
 
3089
        remove_local_directory (window->priv->convert_data.temp_dir);
 
3090
        fr_window_convert_data_free (window, FALSE);
 
3091
 
 
3092
        fr_window_update_sensitivity (window);
 
3093
        fr_window_update_statusbar_list_info (window);
 
3094
}
 
3095
 
 
3096
 
 
3097
static void fr_window_exec_next_batch_action (FrWindow *window);
 
3098
 
 
3099
 
 
3100
static void
 
3101
action_performed (FrArchive   *archive,
 
3102
                  FrAction     action,
 
3103
                  FrProcError *error,
 
3104
                  gpointer     data)
 
3105
{
 
3106
        FrWindow *window = data;
 
3107
        gboolean  continue_batch = FALSE;
 
3108
        char     *archive_dir;
 
3109
        gboolean  temp_dir;
 
3110
 
 
3111
#ifdef DEBUG
 
3112
        debug (DEBUG_INFO, "%s [DONE] (FR::Window)\n", action_names[action]);
 
3113
#endif
 
3114
 
 
3115
        fr_window_stop_activity_mode (window);
 
3116
        fr_window_pop_message (window);
 
3117
 
 
3118
        continue_batch = handle_errors (window, archive, action, error);
 
3119
 
 
3120
        if ((error->type == FR_PROC_ERROR_ASK_PASSWORD)
 
3121
            || (error->type == FR_PROC_ERROR_UNSUPPORTED_FORMAT)
 
3122
            /*|| (error->type == FR_PROC_ERROR_BAD_CHARSET)*/)
 
3123
        {
 
3124
                return;
 
3125
        }
 
3126
 
 
3127
        switch (action) {
 
3128
        case FR_ACTION_CREATING_NEW_ARCHIVE:
 
3129
        case FR_ACTION_CREATING_ARCHIVE:
 
3130
                close_progress_dialog (window, FALSE);
 
3131
                if (error->type != FR_PROC_ERROR_STOPPED) {
 
3132
                        fr_window_history_clear (window);
 
3133
                        fr_window_go_to_location (window, "/", TRUE);
 
3134
                        fr_window_update_dir_tree (window);
 
3135
                        fr_window_update_title (window);
 
3136
                        fr_window_update_sensitivity (window);
 
3137
                }
 
3138
                break;
 
3139
 
 
3140
        case FR_ACTION_LOADING_ARCHIVE:
 
3141
                close_progress_dialog (window, FALSE);
 
3142
                if (error->type != FR_PROC_ERROR_NONE) {
 
3143
                        fr_window_remove_from_recent_list (window, window->priv->archive_uri);
 
3144
                        if (window->priv->non_interactive) {
 
3145
                                fr_window_archive_close (window);
 
3146
                                fr_window_stop_batch (window);
 
3147
                        }
 
3148
                }
 
3149
                else {
 
3150
                        fr_window_add_to_recent_list (window, window->priv->archive_uri);
 
3151
                        if (! window->priv->non_interactive)
 
3152
                                gtk_window_present (GTK_WINDOW (window));
 
3153
                }
 
3154
                continue_batch = FALSE;
 
3155
                g_signal_emit (window,
 
3156
                               fr_window_signals[ARCHIVE_LOADED],
 
3157
                               0,
 
3158
                               error->type == FR_PROC_ERROR_NONE);
 
3159
                break;
 
3160
 
 
3161
        case FR_ACTION_LISTING_CONTENT:
 
3162
                /* update the uri because multi-volume archives can have
 
3163
                 * a different name after loading. */
 
3164
                g_free (window->priv->archive_uri);
 
3165
                window->priv->archive_uri = g_file_get_uri (window->archive->file);
 
3166
 
 
3167
                close_progress_dialog (window, FALSE);
 
3168
                if (error->type != FR_PROC_ERROR_NONE) {
 
3169
                        fr_window_remove_from_recent_list (window, window->priv->archive_uri);
 
3170
                        fr_window_archive_close (window);
 
3171
                        fr_window_set_password (window, NULL);
 
3172
                        break;
 
3173
                }
 
3174
 
 
3175
                archive_dir = remove_level_from_path (window->priv->archive_uri);
 
3176
                temp_dir = is_temp_dir (archive_dir);
 
3177
                if (! window->priv->archive_present) {
 
3178
                        window->priv->archive_present = TRUE;
 
3179
 
 
3180
                        fr_window_history_clear (window);
 
3181
                        fr_window_history_add (window, "/");
 
3182
 
 
3183
                        if (! temp_dir) {
 
3184
                                fr_window_set_open_default_dir (window, archive_dir);
 
3185
                                fr_window_set_add_default_dir (window, archive_dir);
 
3186
                                if (! window->priv->freeze_default_dir)
 
3187
                                        fr_window_set_extract_default_dir (window, archive_dir, FALSE);
 
3188
                        }
 
3189
 
 
3190
                        window->priv->archive_new = FALSE;
 
3191
                }
 
3192
                g_free (archive_dir);
 
3193
 
 
3194
                if (! temp_dir)
 
3195
                        fr_window_add_to_recent_list (window, window->priv->archive_uri);
 
3196
 
 
3197
                fr_window_update_title (window);
 
3198
                fr_window_go_to_location (window, fr_window_get_current_location (window), TRUE);
 
3199
                fr_window_update_dir_tree (window);
 
3200
                if (! window->priv->batch_mode && window->priv->non_interactive)
 
3201
                        gtk_window_present (GTK_WINDOW (window));
 
3202
                break;
 
3203
 
 
3204
        case FR_ACTION_DELETING_FILES:
 
3205
                close_progress_dialog (window, FALSE);
 
3206
                fr_window_archive_reload (window);
 
3207
                return;
 
3208
 
 
3209
        case FR_ACTION_ADDING_FILES:
 
3210
                close_progress_dialog (window, FALSE);
 
3211
 
 
3212
                /* update the uri because multi-volume archives can have
 
3213
                 * a different name after creation. */
 
3214
                g_free (window->priv->archive_uri);
 
3215
                window->priv->archive_uri = g_file_get_uri (window->archive->file);
 
3216
 
 
3217
                if (error->type == FR_PROC_ERROR_NONE) {
 
3218
                        if (window->priv->archive_new)
 
3219
                                window->priv->archive_new = FALSE;
 
3220
                        fr_window_add_to_recent_list (window, window->priv->archive_uri);
 
3221
                }
 
3222
                if (! window->priv->batch_mode) {
 
3223
                        fr_window_archive_reload (window);
 
3224
                        return;
 
3225
                }
 
3226
                break;
 
3227
 
 
3228
        case FR_ACTION_TESTING_ARCHIVE:
 
3229
                close_progress_dialog (window, FALSE);
 
3230
                if (error->type == FR_PROC_ERROR_NONE)
 
3231
                        fr_window_view_last_output (window, _("Test Result"));
 
3232
                return;
 
3233
 
 
3234
        case FR_ACTION_EXTRACTING_FILES:
 
3235
                if (error->type != FR_PROC_ERROR_NONE) {
 
3236
                        if (window->priv->convert_data.converting) {
 
3237
                                remove_local_directory (window->priv->convert_data.temp_dir);
 
3238
                                fr_window_convert_data_free (window, TRUE);
 
3239
                        }
 
3240
                        break;
 
3241
                }
 
3242
                if (window->priv->convert_data.converting) {
 
3243
                        char *source_dir;
 
3244
 
 
3245
                        source_dir = g_filename_to_uri (window->priv->convert_data.temp_dir, NULL, NULL);
 
3246
                        fr_archive_add_with_wildcard (
 
3247
                                  window->priv->convert_data.new_archive,
 
3248
                                  "*",
 
3249
                                  NULL,
 
3250
                                  NULL,
 
3251
                                  source_dir,
 
3252
                                  NULL,
 
3253
                                  FALSE,
 
3254
                                  TRUE,
 
3255
                                  window->priv->convert_data.password,
 
3256
                                  window->priv->convert_data.encrypt_header,
 
3257
                                  window->priv->compression,
 
3258
                                  window->priv->convert_data.volume_size);
 
3259
                        g_free (source_dir);
 
3260
                }
 
3261
                else {
 
3262
                        if (window->priv->ask_to_open_destination_after_extraction)
 
3263
                                open_progress_dialog_with_open_destination (window);
 
3264
                        else
 
3265
                                close_progress_dialog (window, FALSE);
 
3266
                }
 
3267
                break;
 
3268
 
 
3269
        default:
 
3270
                close_progress_dialog (window, FALSE);
 
3271
                continue_batch = FALSE;
 
3272
                break;
 
3273
        }
 
3274
 
 
3275
        if (window->priv->batch_action == NULL) {
 
3276
                fr_window_update_sensitivity (window);
 
3277
                fr_window_update_statusbar_list_info (window);
 
3278
        }
 
3279
 
 
3280
        if (continue_batch) {
 
3281
                if (error->type != FR_PROC_ERROR_NONE)
 
3282
                        fr_window_stop_batch (window);
 
3283
                else
 
3284
                        fr_window_exec_next_batch_action (window);
 
3285
        }
 
3286
}
 
3287
 
 
3288
 
 
3289
/* -- selections -- */
 
3290
 
 
3291
 
 
3292
static GList *
 
3293
get_dir_list_from_path (FrWindow *window,
 
3294
                        char     *path)
 
3295
{
 
3296
        char  *dirname;
 
3297
        int    dirname_l;
 
3298
        GList *list = NULL;
 
3299
        int    i;
 
3300
 
 
3301
        if (path[strlen (path) - 1] != '/')
 
3302
                dirname = g_strconcat (path, "/", NULL);
 
3303
        else
 
3304
                dirname = g_strdup (path);
 
3305
        dirname_l = strlen (dirname);
 
3306
        for (i = 0; i < window->archive->command->files->len; i++) {
 
3307
                FileData *fd = g_ptr_array_index (window->archive->command->files, i);
 
3308
 
 
3309
                if (strncmp (dirname, fd->full_path, dirname_l) == 0)
 
3310
                        list = g_list_prepend (list, g_strdup (fd->original_path));
 
3311
        }
 
3312
        g_free (dirname);
 
3313
 
 
3314
        return g_list_reverse (list);
 
3315
}
 
3316
 
 
3317
 
 
3318
static GList *
 
3319
get_dir_list_from_file_data (FrWindow *window,
 
3320
                                   FileData *fdata)
 
3321
{
 
3322
        char  *dirname;
 
3323
        GList *list;
 
3324
 
 
3325
        dirname = g_strconcat (fr_window_get_current_location (window),
 
3326
                               fdata->list_name,
 
3327
                               NULL);
 
3328
        list = get_dir_list_from_path (window, dirname);
 
3329
        g_free (dirname);
 
3330
 
 
3331
        return list;
 
3332
}
 
3333
 
 
3334
 
 
3335
GList *
 
3336
fr_window_get_file_list_selection (FrWindow *window,
 
3337
                                   gboolean  recursive,
 
3338
                                   gboolean *has_dirs)
 
3339
{
 
3340
        GtkTreeSelection *selection;
 
3341
        GList            *selections = NULL, *list, *scan;
 
3342
 
 
3343
        g_return_val_if_fail (window != NULL, NULL);
 
3344
 
 
3345
        if (has_dirs != NULL)
 
3346
                *has_dirs = FALSE;
 
3347
 
 
3348
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
3349
        if (selection == NULL)
 
3350
                return NULL;
 
3351
        gtk_tree_selection_selected_foreach (selection, add_selected_from_list_view, &selections);
 
3352
 
 
3353
        list = NULL;
 
3354
        for (scan = selections; scan; scan = scan->next) {
 
3355
                FileData *fd = scan->data;
 
3356
 
 
3357
                if (!fd)
 
3358
                        continue;
 
3359
 
 
3360
                if (file_data_is_dir (fd)) {
 
3361
                        if (has_dirs != NULL)
 
3362
                                *has_dirs = TRUE;
 
3363
 
 
3364
                        if (recursive)
 
3365
                                list = g_list_concat (list, get_dir_list_from_file_data (window, fd));
 
3366
                }
 
3367
                else
 
3368
                        list = g_list_prepend (list, g_strdup (fd->original_path));
 
3369
        }
 
3370
        if (selections)
 
3371
                g_list_free (selections);
 
3372
 
 
3373
        return g_list_reverse (list);
 
3374
}
 
3375
 
 
3376
 
 
3377
GList *
 
3378
fr_window_get_folder_tree_selection (FrWindow *window,
 
3379
                                     gboolean  recursive,
 
3380
                                     gboolean *has_dirs)
 
3381
{
 
3382
        GtkTreeSelection *tree_selection;
 
3383
        GList            *selections, *list, *scan;
 
3384
 
 
3385
        g_return_val_if_fail (window != NULL, NULL);
 
3386
 
 
3387
        if (has_dirs != NULL)
 
3388
                *has_dirs = FALSE;
 
3389
 
 
3390
        tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->tree_view));
 
3391
        if (tree_selection == NULL)
 
3392
                return NULL;
 
3393
 
 
3394
        selections = NULL;
 
3395
        gtk_tree_selection_selected_foreach (tree_selection, add_selected_from_tree_view, &selections);
 
3396
        if (selections == NULL)
 
3397
                return NULL;
 
3398
 
 
3399
        if (has_dirs != NULL)
 
3400
                *has_dirs = TRUE;
 
3401
 
 
3402
        list = NULL;
 
3403
        for (scan = selections; scan; scan = scan->next) {
 
3404
                char *path = scan->data;
 
3405
 
 
3406
                if (recursive)
 
3407
                        list = g_list_concat (list, get_dir_list_from_path (window, path));
 
3408
        }
 
3409
        path_list_free (selections);
 
3410
 
 
3411
        return g_list_reverse (list);
 
3412
}
 
3413
 
 
3414
 
 
3415
GList *
 
3416
fr_window_get_file_list_from_path_list (FrWindow *window,
 
3417
                                        GList    *path_list,
 
3418
                                        gboolean *has_dirs)
 
3419
{
 
3420
        GtkTreeModel *model;
 
3421
        GList        *selections, *list, *scan;
 
3422
 
 
3423
        g_return_val_if_fail (window != NULL, NULL);
 
3424
 
 
3425
        model = GTK_TREE_MODEL (window->priv->list_store);
 
3426
        selections = NULL;
 
3427
 
 
3428
        if (has_dirs != NULL)
 
3429
                *has_dirs = FALSE;
 
3430
 
 
3431
        for (scan = path_list; scan; scan = scan->next) {
 
3432
                GtkTreeRowReference *reference = scan->data;
 
3433
                GtkTreePath         *path;
 
3434
                GtkTreeIter          iter;
 
3435
                FileData            *fdata;
 
3436
 
 
3437
                path = gtk_tree_row_reference_get_path (reference);
 
3438
                if (path == NULL)
 
3439
                        continue;
 
3440
 
 
3441
                if (! gtk_tree_model_get_iter (model, &iter, path))
 
3442
                        continue;
 
3443
 
 
3444
                gtk_tree_model_get (model, &iter,
 
3445
                                    COLUMN_FILE_DATA, &fdata,
 
3446
                                    -1);
 
3447
 
 
3448
                selections = g_list_prepend (selections, fdata);
 
3449
        }
 
3450
 
 
3451
        list = NULL;
 
3452
        for (scan = selections; scan; scan = scan->next) {
 
3453
                FileData *fd = scan->data;
 
3454
 
 
3455
                if (!fd)
 
3456
                        continue;
 
3457
 
 
3458
                if (file_data_is_dir (fd)) {
 
3459
                        if (has_dirs != NULL)
 
3460
                                *has_dirs = TRUE;
 
3461
                        list = g_list_concat (list, get_dir_list_from_file_data (window, fd));
 
3462
                }
 
3463
                else
 
3464
                        list = g_list_prepend (list, g_strdup (fd->original_path));
 
3465
        }
 
3466
 
 
3467
        if (selections != NULL)
 
3468
                g_list_free (selections);
 
3469
 
 
3470
        return g_list_reverse (list);
 
3471
}
 
3472
 
 
3473
 
 
3474
GList *
 
3475
fr_window_get_file_list_pattern (FrWindow    *window,
 
3476
                                 const char  *pattern)
 
3477
{
 
3478
        GRegex **regexps;
 
3479
        GList   *list;
 
3480
        int      i;
 
3481
 
 
3482
        g_return_val_if_fail (window != NULL, NULL);
 
3483
 
 
3484
        regexps = search_util_get_regexps (pattern, G_REGEX_CASELESS);
 
3485
        list = NULL;
 
3486
        for (i = 0; i < window->archive->command->files->len; i++) {
 
3487
                FileData *fd = g_ptr_array_index (window->archive->command->files, i);
 
3488
                char     *utf8_name;
 
3489
 
 
3490
                /* FIXME: only files in the current location ? */
 
3491
 
 
3492
                if (fd == NULL)
 
3493
                        continue;
 
3494
 
 
3495
                utf8_name = g_filename_to_utf8 (fd->name, -1, NULL, NULL, NULL);
 
3496
                if (match_regexps (regexps, utf8_name, 0))
 
3497
                        list = g_list_prepend (list, g_strdup (fd->original_path));
 
3498
                g_free (utf8_name);
 
3499
        }
 
3500
        free_regexps (regexps);
 
3501
 
 
3502
        return g_list_reverse (list);
 
3503
}
 
3504
 
 
3505
 
 
3506
int
 
3507
fr_window_get_n_selected_files (FrWindow *window)
 
3508
{
 
3509
        return _gtk_count_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view)));
 
3510
}
 
3511
 
 
3512
 
 
3513
/**/
 
3514
 
 
3515
 
 
3516
static int
 
3517
dir_tree_button_press_cb (GtkWidget      *widget,
 
3518
                          GdkEventButton *event,
 
3519
                          gpointer        data)
 
3520
{
 
3521
        FrWindow         *window = data;
 
3522
        GtkTreeSelection *selection;
 
3523
 
 
3524
        if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (window->priv->tree_view)))
 
3525
                return FALSE;
 
3526
 
 
3527
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->tree_view));
 
3528
        if (selection == NULL)
 
3529
                return FALSE;
 
3530
 
 
3531
        if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
 
3532
                GtkTreePath *path;
 
3533
                GtkTreeIter  iter;
 
3534
 
 
3535
                if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (window->priv->tree_view),
 
3536
                                                   event->x, event->y,
 
3537
                                                   &path, NULL, NULL, NULL)) {
 
3538
 
 
3539
                        if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->tree_store), &iter, path)) {
 
3540
                                gtk_tree_path_free (path);
 
3541
                                return FALSE;
 
3542
                        }
 
3543
                        gtk_tree_path_free (path);
 
3544
 
 
3545
                        if (! gtk_tree_selection_iter_is_selected (selection, &iter)) {
 
3546
                                gtk_tree_selection_unselect_all (selection);
 
3547
                                gtk_tree_selection_select_iter (selection, &iter);
 
3548
                        }
 
3549
 
 
3550
                        gtk_menu_popup (GTK_MENU (window->priv->sidebar_folder_popup_menu),
 
3551
                                        NULL, NULL, NULL,
 
3552
                                        window,
 
3553
                                        event->button,
 
3554
                                        event->time);
 
3555
                }
 
3556
                else
 
3557
                        gtk_tree_selection_unselect_all (selection);
 
3558
 
 
3559
                return TRUE;
 
3560
        }
 
3561
        else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 8)) {
 
3562
                fr_window_go_back (window);
 
3563
                return TRUE;
 
3564
        }
 
3565
        else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 9)) {
 
3566
                fr_window_go_forward (window);
 
3567
                return TRUE;
 
3568
        }
 
3569
 
 
3570
        return FALSE;
 
3571
}
 
3572
 
 
3573
 
 
3574
static FileData *
 
3575
fr_window_get_selected_item_from_file_list (FrWindow *window)
 
3576
{
 
3577
        GtkTreeSelection *tree_selection;
 
3578
        GList            *selection;
 
3579
        FileData         *fdata = NULL;
 
3580
 
 
3581
        g_return_val_if_fail (window != NULL, NULL);
 
3582
 
 
3583
        tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
3584
        if (tree_selection == NULL)
 
3585
                return NULL;
 
3586
 
 
3587
        selection = NULL;
 
3588
        gtk_tree_selection_selected_foreach (tree_selection, add_selected_from_list_view, &selection);
 
3589
        if ((selection == NULL) || (selection->next != NULL)) {
 
3590
                /* return NULL if the selection contains more than one entry. */
 
3591
                g_list_free (selection);
 
3592
                return NULL;
 
3593
        }
 
3594
 
 
3595
        fdata = file_data_copy (selection->data);
 
3596
        g_list_free (selection);
 
3597
 
 
3598
        return fdata;
 
3599
}
 
3600
 
 
3601
 
 
3602
static char *
 
3603
fr_window_get_selected_folder_in_tree_view (FrWindow *window)
 
3604
{
 
3605
        GtkTreeSelection *tree_selection;
 
3606
        GList            *selections;
 
3607
        char             *path = NULL;
 
3608
 
 
3609
        g_return_val_if_fail (window != NULL, NULL);
 
3610
 
 
3611
        tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->tree_view));
 
3612
        if (tree_selection == NULL)
 
3613
                return NULL;
 
3614
 
 
3615
        selections = NULL;
 
3616
        gtk_tree_selection_selected_foreach (tree_selection, add_selected_from_tree_view, &selections);
 
3617
 
 
3618
        if (selections != NULL) {
 
3619
                path = selections->data;
 
3620
                g_list_free (selections);
 
3621
        }
 
3622
 
 
3623
        return path;
 
3624
}
 
3625
 
 
3626
 
 
3627
void
 
3628
fr_window_current_folder_activated (FrWindow *window,
 
3629
                                   gboolean   from_sidebar)
 
3630
{
 
3631
        char *dir_path;
 
3632
 
 
3633
        if (! from_sidebar) {
 
3634
                FileData *fdata;
 
3635
                char     *dir_name;
 
3636
 
 
3637
                fdata = fr_window_get_selected_item_from_file_list (window);
 
3638
                if ((fdata == NULL) || ! file_data_is_dir (fdata)) {
 
3639
                        file_data_free (fdata);
 
3640
                        return;
 
3641
                }
 
3642
                dir_name = g_strdup (fdata->list_name);
 
3643
                dir_path = g_strconcat (fr_window_get_current_location (window),
 
3644
                                        dir_name,
 
3645
                                        "/",
 
3646
                                        NULL);
 
3647
                g_free (dir_name);
 
3648
                file_data_free (fdata);
 
3649
        }
 
3650
        else
 
3651
                dir_path = fr_window_get_selected_folder_in_tree_view (window);
 
3652
 
 
3653
        fr_window_go_to_location (window, dir_path, FALSE);
 
3654
 
 
3655
        g_free (dir_path);
 
3656
}
 
3657
 
 
3658
 
 
3659
static gboolean
 
3660
row_activated_cb (GtkTreeView       *tree_view,
 
3661
                  GtkTreePath       *path,
 
3662
                  GtkTreeViewColumn *column,
 
3663
                  gpointer           data)
 
3664
{
 
3665
        FrWindow    *window = data;
 
3666
        FileData    *fdata;
 
3667
        GtkTreeIter  iter;
 
3668
 
 
3669
        if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->list_store),
 
3670
                                       &iter,
 
3671
                                       path))
 
3672
                return FALSE;
 
3673
 
 
3674
        gtk_tree_model_get (GTK_TREE_MODEL (window->priv->list_store), &iter,
 
3675
                            COLUMN_FILE_DATA, &fdata,
 
3676
                            -1);
 
3677
 
 
3678
        if (! file_data_is_dir (fdata)) {
 
3679
                GList *list = g_list_prepend (NULL, fdata->original_path);
 
3680
                fr_window_open_files (window, list, FALSE);
 
3681
                g_list_free (list);
 
3682
        }
 
3683
        else if (window->priv->list_mode == FR_WINDOW_LIST_MODE_AS_DIR) {
 
3684
                char *new_dir;
 
3685
                new_dir = g_strconcat (fr_window_get_current_location (window),
 
3686
                                       fdata->list_name,
 
3687
                                       "/",
 
3688
                                       NULL);
 
3689
                fr_window_go_to_location (window, new_dir, FALSE);
 
3690
                g_free (new_dir);
 
3691
        }
 
3692
 
 
3693
        return FALSE;
 
3694
}
 
3695
 
 
3696
 
 
3697
static int
 
3698
file_button_press_cb (GtkWidget      *widget,
 
3699
                      GdkEventButton *event,
 
3700
                      gpointer        data)
 
3701
{
 
3702
        FrWindow         *window = data;
 
3703
        GtkTreeSelection *selection;
 
3704
 
 
3705
        if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (window->priv->list_view)))
 
3706
                return FALSE;
 
3707
 
 
3708
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
3709
        if (selection == NULL)
 
3710
                return FALSE;
 
3711
 
 
3712
        if (window->priv->path_clicked != NULL) {
 
3713
                gtk_tree_path_free (window->priv->path_clicked);
 
3714
                window->priv->path_clicked = NULL;
 
3715
        }
 
3716
 
 
3717
        if ((event->type == GDK_BUTTON_PRESS) && (event->button == 3)) {
 
3718
                GtkTreePath *path;
 
3719
                GtkTreeIter  iter;
 
3720
                int          n_selected;
 
3721
 
 
3722
                if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (window->priv->list_view),
 
3723
                                                   event->x, event->y,
 
3724
                                                   &path, NULL, NULL, NULL)) {
 
3725
 
 
3726
                        if (! gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->list_store), &iter, path)) {
 
3727
                                gtk_tree_path_free (path);
 
3728
                                return FALSE;
 
3729
                        }
 
3730
                        gtk_tree_path_free (path);
 
3731
 
 
3732
                        if (! gtk_tree_selection_iter_is_selected (selection, &iter)) {
 
3733
                                gtk_tree_selection_unselect_all (selection);
 
3734
                                gtk_tree_selection_select_iter (selection, &iter);
 
3735
                        }
 
3736
                }
 
3737
                else
 
3738
                        gtk_tree_selection_unselect_all (selection);
 
3739
 
 
3740
                n_selected = fr_window_get_n_selected_files (window);
 
3741
                if ((n_selected == 1) && selection_has_a_dir (window))
 
3742
                        gtk_menu_popup (GTK_MENU (window->priv->folder_popup_menu),
 
3743
                                        NULL, NULL, NULL,
 
3744
                                        window,
 
3745
                                        event->button,
 
3746
                                        event->time);
 
3747
                else
 
3748
                        gtk_menu_popup (GTK_MENU (window->priv->file_popup_menu),
 
3749
                                        NULL, NULL, NULL,
 
3750
                                        window,
 
3751
                                        event->button,
 
3752
                                        event->time);
 
3753
                return TRUE;
 
3754
        }
 
3755
        else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 1)) {
 
3756
                GtkTreePath *path = NULL;
 
3757
 
 
3758
                if (! gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (window->priv->list_view),
 
3759
                                                     event->x, event->y,
 
3760
                                                     &path, NULL, NULL, NULL)) {
 
3761
                        gtk_tree_selection_unselect_all (selection);
 
3762
                }
 
3763
 
 
3764
                if (window->priv->path_clicked != NULL) {
 
3765
                        gtk_tree_path_free (window->priv->path_clicked);
 
3766
                        window->priv->path_clicked = NULL;
 
3767
                }
 
3768
 
 
3769
                if (path != NULL) {
 
3770
                        window->priv->path_clicked = gtk_tree_path_copy (path);
 
3771
                        gtk_tree_path_free (path);
 
3772
                }
 
3773
 
 
3774
                return FALSE;
 
3775
        }
 
3776
        else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 8)) {
 
3777
                // go back
 
3778
                fr_window_go_back (window);
 
3779
                return TRUE;
 
3780
        }
 
3781
        else if ((event->type == GDK_BUTTON_PRESS) && (event->button == 9)) {
 
3782
                // go forward
 
3783
                fr_window_go_forward (window);
 
3784
                return TRUE;
 
3785
        }
 
3786
 
 
3787
        return FALSE;
 
3788
}
 
3789
 
 
3790
 
 
3791
static int
 
3792
file_button_release_cb (GtkWidget      *widget,
 
3793
                        GdkEventButton *event,
 
3794
                        gpointer        data)
 
3795
{
 
3796
        FrWindow         *window = data;
 
3797
        GtkTreeSelection *selection;
 
3798
 
 
3799
        if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (window->priv->list_view)))
 
3800
                return FALSE;
 
3801
 
 
3802
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
3803
        if (selection == NULL)
 
3804
                return FALSE;
 
3805
 
 
3806
        if (window->priv->path_clicked == NULL)
 
3807
                return FALSE;
 
3808
 
 
3809
        if ((event->type == GDK_BUTTON_RELEASE)
 
3810
            && (event->button == 1)
 
3811
            && (window->priv->path_clicked != NULL)) {
 
3812
                GtkTreePath *path = NULL;
 
3813
 
 
3814
                if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (window->priv->list_view),
 
3815
                                                   event->x, event->y,
 
3816
                                                   &path, NULL, NULL, NULL)) {
 
3817
 
 
3818
                        if ((gtk_tree_path_compare (window->priv->path_clicked, path) == 0)
 
3819
                            && window->priv->single_click
 
3820
                            && ! ((event->state & GDK_CONTROL_MASK) || (event->state & GDK_SHIFT_MASK))) {
 
3821
                                gtk_tree_view_set_cursor (GTK_TREE_VIEW (widget),
 
3822
                                                          path,
 
3823
                                                          NULL,
 
3824
                                                          FALSE);
 
3825
                                gtk_tree_view_row_activated (GTK_TREE_VIEW (widget),
 
3826
                                                             path,
 
3827
                                                             NULL);
 
3828
                        }
 
3829
                }
 
3830
 
 
3831
                if (path != NULL)
 
3832
                        gtk_tree_path_free (path);
 
3833
        }
 
3834
 
 
3835
        if (window->priv->path_clicked != NULL) {
 
3836
                gtk_tree_path_free (window->priv->path_clicked);
 
3837
                window->priv->path_clicked = NULL;
 
3838
        }
 
3839
 
 
3840
        return FALSE;
 
3841
}
 
3842
 
 
3843
 
 
3844
static gboolean
 
3845
file_motion_notify_callback (GtkWidget *widget,
 
3846
                             GdkEventMotion *event,
 
3847
                             gpointer user_data)
 
3848
{
 
3849
        FrWindow    *window = user_data;
 
3850
        GdkCursor   *cursor;
 
3851
        GtkTreePath *last_hover_path;
 
3852
        GtkTreeIter  iter;
 
3853
 
 
3854
        if (! window->priv->single_click)
 
3855
                return FALSE;
 
3856
 
 
3857
        if (event->window != gtk_tree_view_get_bin_window (GTK_TREE_VIEW (window->priv->list_view)))
 
3858
                return FALSE;
 
3859
 
 
3860
        last_hover_path = window->priv->list_hover_path;
 
3861
 
 
3862
        gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
 
3863
                                       event->x, event->y,
 
3864
                                       &window->priv->list_hover_path,
 
3865
                                       NULL, NULL, NULL);
 
3866
 
 
3867
        if (window->priv->list_hover_path != NULL)
 
3868
                cursor = gdk_cursor_new (GDK_HAND2);
 
3869
        else
 
3870
                cursor = NULL;
 
3871
 
 
3872
        gdk_window_set_cursor (event->window, cursor);
 
3873
 
 
3874
        /* only redraw if the hover row has changed */
 
3875
        if (!(last_hover_path == NULL && window->priv->list_hover_path == NULL) &&
 
3876
            (!(last_hover_path != NULL && window->priv->list_hover_path != NULL) ||
 
3877
             gtk_tree_path_compare (last_hover_path, window->priv->list_hover_path)))
 
3878
        {
 
3879
                if (last_hover_path) {
 
3880
                        gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->list_store),
 
3881
                                                 &iter, last_hover_path);
 
3882
                        gtk_tree_model_row_changed (GTK_TREE_MODEL (window->priv->list_store),
 
3883
                                                    last_hover_path, &iter);
 
3884
                }
 
3885
 
 
3886
                if (window->priv->list_hover_path) {
 
3887
                        gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->list_store),
 
3888
                                                 &iter, window->priv->list_hover_path);
 
3889
                        gtk_tree_model_row_changed (GTK_TREE_MODEL (window->priv->list_store),
 
3890
                                                    window->priv->list_hover_path, &iter);
 
3891
                }
 
3892
        }
 
3893
 
 
3894
        gtk_tree_path_free (last_hover_path);
 
3895
 
 
3896
        return FALSE;
 
3897
}
 
3898
 
 
3899
 
 
3900
static gboolean
 
3901
file_leave_notify_callback (GtkWidget *widget,
 
3902
                            GdkEventCrossing *event,
 
3903
                            gpointer user_data)
 
3904
{
 
3905
        FrWindow    *window = user_data;
 
3906
        GtkTreeIter  iter;
 
3907
 
 
3908
        if (window->priv->single_click && (window->priv->list_hover_path != NULL)) {
 
3909
                gtk_tree_model_get_iter (GTK_TREE_MODEL (window->priv->list_store),
 
3910
                                         &iter,
 
3911
                                         window->priv->list_hover_path);
 
3912
                gtk_tree_model_row_changed (GTK_TREE_MODEL (window->priv->list_store),
 
3913
                                            window->priv->list_hover_path,
 
3914
                                            &iter);
 
3915
 
 
3916
                gtk_tree_path_free (window->priv->list_hover_path);
 
3917
                window->priv->list_hover_path = NULL;
 
3918
        }
 
3919
 
 
3920
        return FALSE;
 
3921
}
 
3922
 
 
3923
 
 
3924
/* -- drag and drop -- */
 
3925
 
 
3926
 
 
3927
static GList *
 
3928
get_uri_list_from_selection_data (char *uri_list)
 
3929
{
 
3930
        GList  *list = NULL;
 
3931
        char  **uris;
 
3932
        int     i;
 
3933
 
 
3934
        if (uri_list == NULL)
 
3935
                return NULL;
 
3936
 
 
3937
        uris = g_uri_list_extract_uris (uri_list);
 
3938
        for (i = 0; uris[i] != NULL; i++)
 
3939
                list = g_list_prepend (list, g_strdup (uris[i]));
 
3940
        g_strfreev (uris);
 
3941
 
 
3942
        return g_list_reverse (list);
 
3943
}
 
3944
 
 
3945
 
 
3946
static gboolean
 
3947
fr_window_drag_motion (GtkWidget      *widget,
 
3948
                       GdkDragContext *context,
 
3949
                       gint            x,
 
3950
                       gint            y,
 
3951
                       guint           time,
 
3952
                       gpointer        user_data)
 
3953
{
 
3954
        FrWindow  *window = user_data;
 
3955
 
 
3956
        if ((gtk_drag_get_source_widget (context) == window->priv->list_view)
 
3957
            || (gtk_drag_get_source_widget (context) == window->priv->tree_view))
 
3958
        {
 
3959
                gdk_drag_status (context, 0, time);
 
3960
                return FALSE;
 
3961
        }
 
3962
 
 
3963
        return TRUE;
 
3964
}
 
3965
 
 
3966
 
 
3967
static void fr_window_paste_from_clipboard_data (FrWindow *window, FrClipboardData *data);
 
3968
 
 
3969
 
 
3970
static FrClipboardData*
 
3971
get_clipboard_data_from_selection_data (FrWindow   *window,
 
3972
                                        const char *data)
 
3973
{
 
3974
        FrClipboardData  *clipboard_data;
 
3975
        char            **uris;
 
3976
        int               i;
 
3977
 
 
3978
        clipboard_data = fr_clipboard_data_new ();
 
3979
 
 
3980
        uris = g_strsplit (data, "\r\n", -1);
 
3981
 
 
3982
        clipboard_data->archive_filename = g_strdup (uris[0]);
 
3983
        if (window->priv->password_for_paste != NULL)
 
3984
                clipboard_data->archive_password = g_strdup (window->priv->password_for_paste);
 
3985
        else if (strcmp (uris[1], "") != 0)
 
3986
                clipboard_data->archive_password = g_strdup (uris[1]);
 
3987
        clipboard_data->op = (strcmp (uris[2], "copy") == 0) ? FR_CLIPBOARD_OP_COPY : FR_CLIPBOARD_OP_CUT;
 
3988
        clipboard_data->base_dir = g_strdup (uris[3]);
 
3989
        for (i = 4; uris[i] != NULL; i++)
 
3990
                if (uris[i][0] != '\0')
 
3991
                        clipboard_data->files = g_list_prepend (clipboard_data->files, g_strdup (uris[i]));
 
3992
        clipboard_data->files = g_list_reverse (clipboard_data->files);
 
3993
 
 
3994
        g_strfreev (uris);
 
3995
 
 
3996
        return clipboard_data;
 
3997
}
 
3998
 
 
3999
 
 
4000
static void
 
4001
fr_window_drag_data_received  (GtkWidget          *widget,
 
4002
                               GdkDragContext     *context,
 
4003
                               gint                x,
 
4004
                               gint                y,
 
4005
                               GtkSelectionData   *data,
 
4006
                               guint               info,
 
4007
                               guint               time,
 
4008
                               gpointer            extra_data)
 
4009
{
 
4010
        FrWindow  *window = extra_data;
 
4011
        GList     *list;
 
4012
        gboolean   one_file;
 
4013
        gboolean   is_an_archive;
 
4014
 
 
4015
        debug (DEBUG_INFO, "::DragDataReceived -->\n");
 
4016
 
 
4017
        if ((gtk_drag_get_source_widget (context) == window->priv->list_view)
 
4018
            || (gtk_drag_get_source_widget (context) == window->priv->tree_view))
 
4019
        {
 
4020
                gtk_drag_finish (context, FALSE, FALSE, time);
 
4021
                return;
 
4022
        }
 
4023
 
 
4024
        if (! ((gtk_selection_data_get_length (data) >= 0) && (gtk_selection_data_get_format (data) == 8))) {
 
4025
                gtk_drag_finish (context, FALSE, FALSE, time);
 
4026
                return;
 
4027
        }
 
4028
 
 
4029
        if (window->priv->activity_ref > 0) {
 
4030
                gtk_drag_finish (context, FALSE, FALSE, time);
 
4031
                return;
 
4032
        }
 
4033
 
 
4034
        gtk_drag_finish (context, TRUE, FALSE, time);
 
4035
 
 
4036
        if (gtk_selection_data_get_target (data) == XFR_ATOM) {
 
4037
                FrClipboardData *dnd_data;
 
4038
 
 
4039
                dnd_data = get_clipboard_data_from_selection_data (window, (char*) gtk_selection_data_get_data (data));
 
4040
                dnd_data->current_dir = g_strdup (fr_window_get_current_location (window));
 
4041
                fr_window_paste_from_clipboard_data (window, dnd_data);
 
4042
 
 
4043
                return;
 
4044
        }
 
4045
 
 
4046
        list = get_uri_list_from_selection_data ((char*) gtk_selection_data_get_data (data));
 
4047
        if (list == NULL) {
 
4048
                GtkWidget *d;
 
4049
 
 
4050
                d = _gtk_error_dialog_new (GTK_WINDOW (window),
 
4051
                                           GTK_DIALOG_MODAL,
 
4052
                                           NULL,
 
4053
                                           _("Could not perform the operation"),
 
4054
                                           NULL);
 
4055
                gtk_dialog_run (GTK_DIALOG (d));
 
4056
                gtk_widget_destroy(d);
 
4057
 
 
4058
                return;
 
4059
        }
 
4060
 
 
4061
        one_file = (list->next == NULL);
 
4062
        if (one_file)
 
4063
                is_an_archive = uri_is_archive (list->data);
 
4064
        else
 
4065
                is_an_archive = FALSE;
 
4066
 
 
4067
        if (window->priv->archive_present
 
4068
            && (window->archive != NULL)
 
4069
            && ! window->archive->read_only
 
4070
            && ! window->archive->is_compressed_file)
 
4071
        {
 
4072
                if (one_file && is_an_archive) {
 
4073
                        GtkWidget *d;
 
4074
                        gint       r;
 
4075
 
 
4076
                        d = _gtk_message_dialog_new (GTK_WINDOW (window),
 
4077
                                                     GTK_DIALOG_MODAL,
 
4078
                                                     GTK_STOCK_DIALOG_QUESTION,
 
4079
                                                     _("Do you want to add this file to the current archive or open it as a new archive?"),
 
4080
                                                     NULL,
 
4081
                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
4082
                                                     GTK_STOCK_ADD, 0,
 
4083
                                                     GTK_STOCK_OPEN, 1,
 
4084
                                                     NULL);
 
4085
 
 
4086
                        gtk_dialog_set_default_response (GTK_DIALOG (d), 2);
 
4087
 
 
4088
                        r = gtk_dialog_run (GTK_DIALOG (d));
 
4089
                        gtk_widget_destroy (GTK_WIDGET (d));
 
4090
 
 
4091
                        if (r == 0)  /* Add */
 
4092
                                fr_window_archive_add_dropped_items (window, list, FALSE);
 
4093
                        else if (r == 1)  /* Open */
 
4094
                                fr_window_archive_open (window, list->data, GTK_WINDOW (window));
 
4095
                }
 
4096
                else
 
4097
                        fr_window_archive_add_dropped_items (window, list, FALSE);
 
4098
        }
 
4099
        else {
 
4100
                if (one_file && is_an_archive)
 
4101
                        fr_window_archive_open (window, list->data, GTK_WINDOW (window));
 
4102
                else {
 
4103
                        GtkWidget *d;
 
4104
                        int        r;
 
4105
 
 
4106
                        d = _gtk_message_dialog_new (GTK_WINDOW (window),
 
4107
                                                     GTK_DIALOG_MODAL,
 
4108
                                                     GTK_STOCK_DIALOG_QUESTION,
 
4109
                                                     _("Do you want to create a new archive with these files?"),
 
4110
                                                     NULL,
 
4111
                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
4112
                                                     _("Create _Archive"), GTK_RESPONSE_YES,
 
4113
                                                     NULL);
 
4114
 
 
4115
                        gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_YES);
 
4116
                        r = gtk_dialog_run (GTK_DIALOG (d));
 
4117
                        gtk_widget_destroy (GTK_WIDGET (d));
 
4118
 
 
4119
                        if (r == GTK_RESPONSE_YES) {
 
4120
                                char       *first_item;
 
4121
                                char       *folder;
 
4122
                                char       *local_path = NULL;
 
4123
                                char       *utf8_path = NULL;
 
4124
                                const char *archive_name;
 
4125
 
 
4126
                                fr_window_free_batch_data (window);
 
4127
                                fr_window_append_batch_action (window,
 
4128
                                                               FR_BATCH_ACTION_ADD,
 
4129
                                                               path_list_dup (list),
 
4130
                                                               (GFreeFunc) path_list_free);
 
4131
 
 
4132
                                first_item = (char*) list->data;
 
4133
                                folder = remove_level_from_path (first_item);
 
4134
                                if (folder != NULL)
 
4135
                                        fr_window_set_open_default_dir (window, folder);
 
4136
 
 
4137
                                if ((list->next != NULL) && (folder != NULL)) {
 
4138
                                        archive_name = file_name_from_path (folder);
 
4139
                                }
 
4140
                                else {
 
4141
                                        if (uri_is_local (first_item)) {
 
4142
                                                local_path = g_filename_from_uri (first_item, NULL, NULL);
 
4143
                                                if (local_path)
 
4144
                                                        utf8_path = g_filename_to_utf8 (local_path, -1, NULL, NULL, NULL);
 
4145
                                                if (!utf8_path)
 
4146
                                                        utf8_path= g_strdup (first_item);
 
4147
                                                g_free (local_path);
 
4148
                                        }
 
4149
                                        else {
 
4150
                                                utf8_path = g_strdup (first_item);
 
4151
                                        }
 
4152
                                        archive_name = file_name_from_path (utf8_path);
 
4153
                                }
 
4154
 
 
4155
                                show_new_archive_dialog (window, archive_name);
 
4156
                                g_free (utf8_path);
 
4157
 
 
4158
                                g_free (folder);
 
4159
                        }
 
4160
                }
 
4161
        }
 
4162
 
 
4163
        path_list_free (list);
 
4164
 
 
4165
        debug (DEBUG_INFO, "::DragDataReceived <--\n");
 
4166
}
 
4167
 
 
4168
 
 
4169
static gboolean
 
4170
file_list_drag_begin (GtkWidget          *widget,
 
4171
                      GdkDragContext     *context,
 
4172
                      gpointer            data)
 
4173
{
 
4174
        FrWindow *window = data;
 
4175
 
 
4176
        debug (DEBUG_INFO, "::DragBegin -->\n");
 
4177
 
 
4178
        if (window->priv->activity_ref > 0)
 
4179
                return FALSE;
 
4180
 
 
4181
        g_free (window->priv->drag_destination_folder);
 
4182
        window->priv->drag_destination_folder = NULL;
 
4183
 
 
4184
        g_free (window->priv->drag_base_dir);
 
4185
        window->priv->drag_base_dir = NULL;
 
4186
 
 
4187
        gdk_property_change (gdk_drag_context_get_source_window (context),
 
4188
                             XDS_ATOM, TEXT_ATOM,
 
4189
                             8, GDK_PROP_MODE_REPLACE,
 
4190
                             (guchar *) XDS_FILENAME,
 
4191
                             strlen (XDS_FILENAME));
 
4192
 
 
4193
        return TRUE;
 
4194
}
 
4195
 
 
4196
 
 
4197
static void
 
4198
file_list_drag_end (GtkWidget      *widget,
 
4199
                    GdkDragContext *context,
 
4200
                    gpointer        data)
 
4201
{
 
4202
        FrWindow *window = data;
 
4203
 
 
4204
        debug (DEBUG_INFO, "::DragEnd -->\n");
 
4205
 
 
4206
        gdk_property_delete (gdk_drag_context_get_source_window (context), XDS_ATOM);
 
4207
 
 
4208
        if (window->priv->drag_error != NULL) {
 
4209
                _gtk_error_dialog_run (GTK_WINDOW (window),
 
4210
                                       _("Extraction not performed"),
 
4211
                                       "%s",
 
4212
                                       window->priv->drag_error->message);
 
4213
                g_clear_error (&window->priv->drag_error);
 
4214
        }
 
4215
        else if (window->priv->drag_destination_folder != NULL) {
 
4216
                fr_window_archive_extract (window,
 
4217
                                           window->priv->drag_file_list,
 
4218
                                           window->priv->drag_destination_folder,
 
4219
                                           window->priv->drag_base_dir,
 
4220
                                           FALSE,
 
4221
                                           TRUE,
 
4222
                                           FALSE,
 
4223
                                           FALSE);
 
4224
                path_list_free (window->priv->drag_file_list);
 
4225
                window->priv->drag_file_list = NULL;
 
4226
        }
 
4227
 
 
4228
        debug (DEBUG_INFO, "::DragEnd <--\n");
 
4229
}
 
4230
 
 
4231
 
 
4232
/* The following three functions taken from bugzilla
 
4233
 * (http://bugzilla.gnome.org/attachment.cgi?id=49362&action=view)
 
4234
 * Author: Christian Neumair
 
4235
 * Copyright: 2005 Free Software Foundation, Inc
 
4236
 * License: GPL */
 
4237
static char *
 
4238
get_xds_atom_value (GdkDragContext *context)
 
4239
{
 
4240
        char *ret;
 
4241
 
 
4242
        g_return_val_if_fail (context != NULL, NULL);
 
4243
        g_return_val_if_fail (gdk_drag_context_get_source_window (context) != NULL, NULL);
 
4244
 
 
4245
        if (gdk_property_get (gdk_drag_context_get_source_window (context),
 
4246
                              XDS_ATOM, TEXT_ATOM,
 
4247
                              0, MAX_XDS_ATOM_VAL_LEN,
 
4248
                              FALSE, NULL, NULL, NULL,
 
4249
                              (unsigned char **) &ret))
 
4250
                return ret;
 
4251
 
 
4252
        return NULL;
 
4253
}
 
4254
 
 
4255
 
 
4256
static gboolean
 
4257
context_offers_target (GdkDragContext *context,
 
4258
                       GdkAtom target)
 
4259
{
 
4260
        return (g_list_find (gdk_drag_context_list_targets (context), target) != NULL);
 
4261
}
 
4262
 
 
4263
 
 
4264
static gboolean
 
4265
nautilus_xds_dnd_is_valid_xds_context (GdkDragContext *context)
 
4266
{
 
4267
        char *tmp;
 
4268
        gboolean ret;
 
4269
 
 
4270
        g_return_val_if_fail (context != NULL, FALSE);
 
4271
 
 
4272
        tmp = NULL;
 
4273
        if (context_offers_target (context, XDS_ATOM)) {
 
4274
                tmp = get_xds_atom_value (context);
 
4275
        }
 
4276
 
 
4277
        ret = (tmp != NULL);
 
4278
        g_free (tmp);
 
4279
 
 
4280
        return ret;
 
4281
}
 
4282
 
 
4283
 
 
4284
static char *
 
4285
get_selection_data_from_clipboard_data (FrWindow        *window,
 
4286
                                        FrClipboardData *data)
 
4287
{
 
4288
        GString *list;
 
4289
        char    *local_filename;
 
4290
        GList   *scan;
 
4291
 
 
4292
        list = g_string_new (NULL);
 
4293
 
 
4294
        local_filename = g_file_get_uri (window->archive->local_copy);
 
4295
        g_string_append (list, local_filename);
 
4296
        g_free (local_filename);
 
4297
 
 
4298
        g_string_append (list, "\r\n");
 
4299
        if (window->priv->password != NULL)
 
4300
                g_string_append (list, window->priv->password);
 
4301
        g_string_append (list, "\r\n");
 
4302
        g_string_append (list, (data->op == FR_CLIPBOARD_OP_COPY) ? "copy" : "cut");
 
4303
        g_string_append (list, "\r\n");
 
4304
        g_string_append (list, data->base_dir);
 
4305
        g_string_append (list, "\r\n");
 
4306
        for (scan = data->files; scan; scan = scan->next) {
 
4307
                g_string_append (list, scan->data);
 
4308
                g_string_append (list, "\r\n");
 
4309
        }
 
4310
 
 
4311
        return g_string_free (list, FALSE);
 
4312
}
 
4313
 
 
4314
 
 
4315
static gboolean
 
4316
fr_window_folder_tree_drag_data_get (GtkWidget        *widget,
 
4317
                                     GdkDragContext   *context,
 
4318
                                     GtkSelectionData *selection_data,
 
4319
                                     guint             info,
 
4320
                                     guint             time,
 
4321
                                     gpointer          user_data)
 
4322
{
 
4323
        FrWindow *window = user_data;
 
4324
        GList    *file_list;
 
4325
        char     *destination;
 
4326
        char     *destination_folder;
 
4327
 
 
4328
        debug (DEBUG_INFO, "::DragDataGet -->\n");
 
4329
 
 
4330
        if (window->priv->activity_ref > 0)
 
4331
                return FALSE;
 
4332
 
 
4333
        file_list = fr_window_get_folder_tree_selection (window, TRUE, NULL);
 
4334
        if (file_list == NULL)
 
4335
                return FALSE;
 
4336
 
 
4337
        if (gtk_selection_data_get_target (selection_data) == XFR_ATOM) {
 
4338
                FrClipboardData *tmp;
 
4339
                char            *data;
 
4340
 
 
4341
                tmp = fr_clipboard_data_new ();
 
4342
                tmp->files = file_list;
 
4343
                tmp->op = FR_CLIPBOARD_OP_COPY;
 
4344
                tmp->base_dir = g_strdup (fr_window_get_current_location (window));
 
4345
 
 
4346
                data = get_selection_data_from_clipboard_data (window, tmp);
 
4347
                gtk_selection_data_set (selection_data, XFR_ATOM, 8, (guchar *) data, strlen (data));
 
4348
 
 
4349
                fr_clipboard_data_unref (tmp);
 
4350
                g_free (data);
 
4351
 
 
4352
                return TRUE;
 
4353
        }
 
4354
 
 
4355
        if (! nautilus_xds_dnd_is_valid_xds_context (context))
 
4356
                return FALSE;
 
4357
 
 
4358
        destination = get_xds_atom_value (context);
 
4359
        g_return_val_if_fail (destination != NULL, FALSE);
 
4360
 
 
4361
        destination_folder = remove_level_from_path (destination);
 
4362
        g_free (destination);
 
4363
 
 
4364
        /* check whether the extraction can be performed in the destination
 
4365
         * folder */
 
4366
 
 
4367
        g_clear_error (&window->priv->drag_error);
 
4368
 
 
4369
        if (! check_permissions (destination_folder, R_OK | W_OK)) {
 
4370
                char *destination_folder_display_name;
 
4371
 
 
4372
                destination_folder_display_name = g_filename_display_name (destination_folder);
 
4373
                window->priv->drag_error = g_error_new (FR_ERROR, 0, _("You don't have the right permissions to extract archives in the folder \"%s\""), destination_folder_display_name);
 
4374
                g_free (destination_folder_display_name);
 
4375
        }
 
4376
 
 
4377
        if (window->priv->drag_error == NULL) {
 
4378
                g_free (window->priv->drag_destination_folder);
 
4379
                g_free (window->priv->drag_base_dir);
 
4380
                path_list_free (window->priv->drag_file_list);
 
4381
                window->priv->drag_destination_folder = g_strdup (destination_folder);
 
4382
                window->priv->drag_base_dir = fr_window_get_selected_folder_in_tree_view (window);
 
4383
                window->priv->drag_file_list = file_list;
 
4384
        }
 
4385
 
 
4386
        g_free (destination_folder);
 
4387
 
 
4388
        /* sends back the response */
 
4389
 
 
4390
        gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *) ((window->priv->drag_error == NULL) ? "S" : "E"), 1);
 
4391
 
 
4392
        debug (DEBUG_INFO, "::DragDataGet <--\n");
 
4393
 
 
4394
        return TRUE;
 
4395
}
 
4396
 
 
4397
 
 
4398
gboolean
 
4399
fr_window_file_list_drag_data_get (FrWindow         *window,
 
4400
                                   GdkDragContext   *context,
 
4401
                                   GtkSelectionData *selection_data,
 
4402
                                   GList            *path_list)
 
4403
{
 
4404
        char *destination;
 
4405
        char *destination_folder;
 
4406
 
 
4407
        debug (DEBUG_INFO, "::DragDataGet -->\n");
 
4408
 
 
4409
        if (window->priv->path_clicked != NULL) {
 
4410
                gtk_tree_path_free (window->priv->path_clicked);
 
4411
                window->priv->path_clicked = NULL;
 
4412
        }
 
4413
 
 
4414
        if (window->priv->activity_ref > 0)
 
4415
                return FALSE;
 
4416
 
 
4417
        if (gtk_selection_data_get_target (selection_data) == XFR_ATOM) {
 
4418
                FrClipboardData *tmp;
 
4419
                char            *data;
 
4420
 
 
4421
                tmp = fr_clipboard_data_new ();
 
4422
                tmp->files = fr_window_get_file_list_selection (window, TRUE, NULL);
 
4423
                tmp->op = FR_CLIPBOARD_OP_COPY;
 
4424
                tmp->base_dir = g_strdup (fr_window_get_current_location (window));
 
4425
 
 
4426
                data = get_selection_data_from_clipboard_data (window, tmp);
 
4427
                gtk_selection_data_set (selection_data, XFR_ATOM, 8, (guchar *) data, strlen (data));
 
4428
 
 
4429
                fr_clipboard_data_unref (tmp);
 
4430
                g_free (data);
 
4431
 
 
4432
                return TRUE;
 
4433
        }
 
4434
 
 
4435
        if (! nautilus_xds_dnd_is_valid_xds_context (context))
 
4436
                return FALSE;
 
4437
 
 
4438
        destination = get_xds_atom_value (context);
 
4439
        g_return_val_if_fail (destination != NULL, FALSE);
 
4440
 
 
4441
        destination_folder = remove_level_from_path (destination);
 
4442
        g_free (destination);
 
4443
 
 
4444
        /* check whether the extraction can be performed in the destination
 
4445
         * folder */
 
4446
 
 
4447
        g_clear_error (&window->priv->drag_error);
 
4448
 
 
4449
        if (! check_permissions (destination_folder, R_OK | W_OK)) {
 
4450
                char *destination_folder_display_name;
 
4451
 
 
4452
                destination_folder_display_name = g_filename_display_name (destination_folder);
 
4453
                window->priv->drag_error = g_error_new (FR_ERROR, 0, _("You don't have the right permissions to extract archives in the folder \"%s\""), destination_folder_display_name);
 
4454
                g_free (destination_folder_display_name);
 
4455
        }
 
4456
 
 
4457
        if (window->priv->drag_error == NULL) {
 
4458
                g_free (window->priv->drag_destination_folder);
 
4459
                g_free (window->priv->drag_base_dir);
 
4460
                path_list_free (window->priv->drag_file_list);
 
4461
                window->priv->drag_destination_folder = g_strdup (destination_folder);
 
4462
                window->priv->drag_base_dir = g_strdup (fr_window_get_current_location (window));
 
4463
                window->priv->drag_file_list = fr_window_get_file_list_from_path_list (window, path_list, NULL);
 
4464
        }
 
4465
 
 
4466
        g_free (destination_folder);
 
4467
 
 
4468
        /* sends back the response */
 
4469
 
 
4470
        gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *) ((window->priv->drag_error == NULL) ? "S" : "E"), 1);
 
4471
 
 
4472
        debug (DEBUG_INFO, "::DragDataGet <--\n");
 
4473
 
 
4474
        return TRUE;
 
4475
}
 
4476
 
 
4477
 
 
4478
/* -- window_new -- */
 
4479
 
 
4480
 
 
4481
static void
 
4482
fr_window_deactivate_filter (FrWindow *window)
 
4483
{
 
4484
        window->priv->filter_mode = FALSE;
 
4485
        window->priv->list_mode = window->priv->last_list_mode;
 
4486
 
 
4487
        gtk_entry_set_text (GTK_ENTRY (window->priv->filter_entry), "");
 
4488
        fr_window_update_filter_bar_visibility (window);
 
4489
 
 
4490
        gtk_list_store_clear (window->priv->list_store);
 
4491
 
 
4492
        fr_window_update_columns_visibility (window);
 
4493
        fr_window_update_file_list (window, TRUE);
 
4494
        fr_window_update_dir_tree (window);
 
4495
        fr_window_update_current_location (window);
 
4496
}
 
4497
 
 
4498
 
 
4499
static gboolean
 
4500
key_press_cb (GtkWidget   *widget,
 
4501
              GdkEventKey *event,
 
4502
              gpointer     data)
 
4503
{
 
4504
        FrWindow *window = data;
 
4505
        gboolean  retval = FALSE;
 
4506
        gboolean  alt;
 
4507
 
 
4508
        if (gtk_widget_has_focus (window->priv->location_entry))
 
4509
                return FALSE;
 
4510
 
 
4511
        if (gtk_widget_has_focus (window->priv->filter_entry)) {
 
4512
                switch (event->keyval) {
 
4513
                case GDK_KEY_Escape:
 
4514
                        fr_window_deactivate_filter (window);
 
4515
                        retval = TRUE;
 
4516
                        break;
 
4517
                default:
 
4518
                        break;
 
4519
                }
 
4520
                return retval;
 
4521
        }
 
4522
 
 
4523
        alt = (event->state & GDK_MOD1_MASK) == GDK_MOD1_MASK;
 
4524
 
 
4525
        switch (event->keyval) {
 
4526
        case GDK_KEY_Escape:
 
4527
                activate_action_stop (NULL, window);
 
4528
                if (window->priv->filter_mode)
 
4529
                        fr_window_deactivate_filter (window);
 
4530
                retval = TRUE;
 
4531
                break;
 
4532
 
 
4533
        case GDK_KEY_F10:
 
4534
                if (event->state & GDK_SHIFT_MASK) {
 
4535
                        GtkTreeSelection *selection;
 
4536
 
 
4537
                        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
4538
                        if (selection == NULL)
 
4539
                                return FALSE;
 
4540
 
 
4541
                        gtk_menu_popup (GTK_MENU (window->priv->file_popup_menu),
 
4542
                                        NULL, NULL, NULL,
 
4543
                                        window,
 
4544
                                        3,
 
4545
                                        GDK_CURRENT_TIME);
 
4546
                        retval = TRUE;
 
4547
                }
 
4548
                break;
 
4549
 
 
4550
        case GDK_KEY_Up:
 
4551
        case GDK_KEY_KP_Up:
 
4552
                if (alt) {
 
4553
                        fr_window_go_up_one_level (window);
 
4554
                        retval = TRUE;
 
4555
                }
 
4556
                break;
 
4557
 
 
4558
        case GDK_KEY_BackSpace:
 
4559
                fr_window_go_up_one_level (window);
 
4560
                retval = TRUE;
 
4561
                break;
 
4562
 
 
4563
        case GDK_KEY_Right:
 
4564
        case GDK_KEY_KP_Right:
 
4565
                if (alt) {
 
4566
                        fr_window_go_forward (window);
 
4567
                        retval = TRUE;
 
4568
                }
 
4569
                break;
 
4570
 
 
4571
        case GDK_KEY_Left:
 
4572
        case GDK_KEY_KP_Left:
 
4573
                if (alt) {
 
4574
                        fr_window_go_back (window);
 
4575
                        retval = TRUE;
 
4576
                }
 
4577
                break;
 
4578
 
 
4579
        case GDK_KEY_Home:
 
4580
        case GDK_KEY_KP_Home:
 
4581
                if (alt) {
 
4582
                        fr_window_go_to_location (window, "/", FALSE);
 
4583
                        retval = TRUE;
 
4584
                }
 
4585
                break;
 
4586
 
 
4587
        default:
 
4588
                break;
 
4589
        }
 
4590
 
 
4591
        return retval;
 
4592
}
 
4593
 
 
4594
 
 
4595
static gboolean
 
4596
dir_tree_selection_changed_cb (GtkTreeSelection *selection,
 
4597
                               gpointer          user_data)
 
4598
{
 
4599
        FrWindow    *window = user_data;
 
4600
        GtkTreeIter  iter;
 
4601
 
 
4602
        if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
 
4603
                char *path;
 
4604
 
 
4605
                gtk_tree_model_get (GTK_TREE_MODEL (window->priv->tree_store),
 
4606
                                    &iter,
 
4607
                                    TREE_COLUMN_PATH, &path,
 
4608
                                    -1);
 
4609
                fr_window_go_to_location (window, path, FALSE);
 
4610
                g_free (path);
 
4611
        }
 
4612
 
 
4613
        return FALSE;
 
4614
}
 
4615
 
 
4616
 
 
4617
static gboolean
 
4618
selection_changed_cb (GtkTreeSelection *selection,
 
4619
                      gpointer          user_data)
 
4620
{
 
4621
        FrWindow *window = user_data;
 
4622
 
 
4623
        fr_window_update_statusbar_list_info (window);
 
4624
        fr_window_update_sensitivity (window);
 
4625
 
 
4626
        return FALSE;
 
4627
}
 
4628
 
 
4629
 
 
4630
static void
 
4631
fr_window_delete_event_cb (GtkWidget *caller,
 
4632
                           GdkEvent  *event,
 
4633
                           FrWindow  *window)
 
4634
{
 
4635
        fr_window_close (window);
 
4636
}
 
4637
 
 
4638
 
 
4639
static gboolean
 
4640
is_single_click_policy (FrWindow *window)
 
4641
{
 
4642
        char     *value;
 
4643
        gboolean  result;
 
4644
 
 
4645
        value = g_settings_get_string (window->priv->settings_nautilus, NAUTILUS_CLICK_POLICY);
 
4646
        result = (value != NULL) && (strncmp (value, "single", 6) == 0);
 
4647
        g_free (value);
 
4648
 
 
4649
        return result;
 
4650
}
 
4651
 
 
4652
 
 
4653
static void
 
4654
filename_cell_data_func (GtkTreeViewColumn *column,
 
4655
                         GtkCellRenderer   *renderer,
 
4656
                         GtkTreeModel      *model,
 
4657
                         GtkTreeIter       *iter,
 
4658
                         FrWindow          *window)
 
4659
{
 
4660
        char           *text;
 
4661
        GtkTreePath    *path;
 
4662
        PangoUnderline  underline;
 
4663
 
 
4664
        gtk_tree_model_get (model, iter,
 
4665
                            COLUMN_NAME, &text,
 
4666
                            -1);
 
4667
 
 
4668
        if (window->priv->single_click) {
 
4669
                path = gtk_tree_model_get_path (model, iter);
 
4670
 
 
4671
                if ((window->priv->list_hover_path == NULL)
 
4672
                    || gtk_tree_path_compare (path, window->priv->list_hover_path))
 
4673
                        underline = PANGO_UNDERLINE_NONE;
 
4674
                else
 
4675
                        underline = PANGO_UNDERLINE_SINGLE;
 
4676
 
 
4677
                gtk_tree_path_free (path);
 
4678
        }
 
4679
        else
 
4680
                underline = PANGO_UNDERLINE_NONE;
 
4681
 
 
4682
        g_object_set (G_OBJECT (renderer),
 
4683
                      "text", text,
 
4684
                      "underline", underline,
 
4685
                      NULL);
 
4686
 
 
4687
        g_free (text);
 
4688
}
 
4689
 
 
4690
 
 
4691
static void
 
4692
add_dir_tree_columns (FrWindow    *window,
 
4693
                      GtkTreeView *treeview)
 
4694
{
 
4695
        GtkCellRenderer   *renderer;
 
4696
        GtkTreeViewColumn *column;
 
4697
        GValue             value = { 0, };
 
4698
 
 
4699
        /* First column. */
 
4700
 
 
4701
        column = gtk_tree_view_column_new ();
 
4702
        gtk_tree_view_column_set_title (column, _("Folders"));
 
4703
 
 
4704
        /* icon */
 
4705
 
 
4706
        renderer = gtk_cell_renderer_pixbuf_new ();
 
4707
        gtk_tree_view_column_pack_start (column, renderer, FALSE);
 
4708
        gtk_tree_view_column_set_attributes (column, renderer,
 
4709
                                             "pixbuf", TREE_COLUMN_ICON,
 
4710
                                             NULL);
 
4711
 
 
4712
        /* name */
 
4713
 
 
4714
        renderer = gtk_cell_renderer_text_new ();
 
4715
 
 
4716
        g_value_init (&value, PANGO_TYPE_ELLIPSIZE_MODE);
 
4717
        g_value_set_enum (&value, PANGO_ELLIPSIZE_END);
 
4718
        g_object_set_property (G_OBJECT (renderer), "ellipsize", &value);
 
4719
        g_value_unset (&value);
 
4720
 
 
4721
        gtk_tree_view_column_pack_start (column,
 
4722
                                         renderer,
 
4723
                                         TRUE);
 
4724
        gtk_tree_view_column_set_attributes (column, renderer,
 
4725
                                             "text", TREE_COLUMN_NAME,
 
4726
                                             "weight", TREE_COLUMN_WEIGHT,
 
4727
                                             NULL);
 
4728
 
 
4729
        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
 
4730
        gtk_tree_view_column_set_sort_column_id (column, TREE_COLUMN_NAME);
 
4731
 
 
4732
        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
4733
}
 
4734
 
 
4735
 
 
4736
static void
 
4737
add_file_list_columns (FrWindow    *window,
 
4738
                       GtkTreeView *treeview)
 
4739
{
 
4740
        static char       *titles[] = {NC_("File", "Size"),
 
4741
                                       NC_("File", "Type"),
 
4742
                                       NC_("File", "Date Modified"),
 
4743
                                       NC_("File", "Location")};
 
4744
        GtkCellRenderer   *renderer;
 
4745
        GtkTreeViewColumn *column;
 
4746
        GValue             value = { 0, };
 
4747
        int                i, j, w;
 
4748
 
 
4749
        /* First column. */
 
4750
 
 
4751
        window->priv->filename_column = column = gtk_tree_view_column_new ();
 
4752
        gtk_tree_view_column_set_title (column, C_("File", "Name"));
 
4753
 
 
4754
        /* emblem */
 
4755
 
 
4756
        renderer = gtk_cell_renderer_pixbuf_new ();
 
4757
        gtk_tree_view_column_pack_end (column, renderer, FALSE);
 
4758
        gtk_tree_view_column_set_attributes (column, renderer,
 
4759
                                             "pixbuf", COLUMN_EMBLEM,
 
4760
                                             NULL);
 
4761
 
 
4762
        /* icon */
 
4763
 
 
4764
        renderer = gtk_cell_renderer_pixbuf_new ();
 
4765
        gtk_tree_view_column_pack_start (column, renderer, FALSE);
 
4766
        gtk_tree_view_column_set_attributes (column, renderer,
 
4767
                                             "pixbuf", COLUMN_ICON,
 
4768
                                             NULL);
 
4769
 
 
4770
        /* name */
 
4771
 
 
4772
        window->priv->single_click = is_single_click_policy (window);
 
4773
 
 
4774
        renderer = gtk_cell_renderer_text_new ();
 
4775
 
 
4776
        g_value_init (&value, PANGO_TYPE_ELLIPSIZE_MODE);
 
4777
        g_value_set_enum (&value, PANGO_ELLIPSIZE_END);
 
4778
        g_object_set_property (G_OBJECT (renderer), "ellipsize", &value);
 
4779
        g_value_unset (&value);
 
4780
 
 
4781
        gtk_tree_view_column_pack_start (column,
 
4782
                                         renderer,
 
4783
                                         TRUE);
 
4784
        gtk_tree_view_column_set_attributes (column, renderer,
 
4785
                                             "text", COLUMN_NAME,
 
4786
                                             NULL);
 
4787
 
 
4788
        gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
 
4789
        w = g_settings_get_int (window->priv->settings_listing, PREF_LISTING_NAME_COLUMN_WIDTH);
 
4790
        if (w <= 0)
 
4791
                w = DEFAULT_NAME_COLUMN_WIDTH;
 
4792
        gtk_tree_view_column_set_fixed_width (column, w);
 
4793
        gtk_tree_view_column_set_resizable (column, TRUE);
 
4794
        gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
 
4795
        gtk_tree_view_column_set_cell_data_func (column, renderer,
 
4796
                                                 (GtkTreeCellDataFunc) filename_cell_data_func,
 
4797
                                                 window, NULL);
 
4798
 
 
4799
        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
4800
 
 
4801
        /* Other columns */
 
4802
 
 
4803
        for (j = 0, i = COLUMN_SIZE; i < NUMBER_OF_COLUMNS; i++, j++) {
 
4804
                GValue  value = { 0, };
 
4805
 
 
4806
                renderer = gtk_cell_renderer_text_new ();
 
4807
                column = gtk_tree_view_column_new_with_attributes (g_dpgettext2 (NULL, "File", titles[j]),
 
4808
                                                                   renderer,
 
4809
                                                                   "text", i,
 
4810
                                                                   NULL);
 
4811
 
 
4812
                gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
 
4813
                gtk_tree_view_column_set_fixed_width (column, OTHER_COLUMNS_WIDTH);
 
4814
                gtk_tree_view_column_set_resizable (column, TRUE);
 
4815
 
 
4816
                gtk_tree_view_column_set_sort_column_id (column, i);
 
4817
 
 
4818
                g_value_init (&value, PANGO_TYPE_ELLIPSIZE_MODE);
 
4819
                g_value_set_enum (&value, PANGO_ELLIPSIZE_END);
 
4820
                g_object_set_property (G_OBJECT (renderer), "ellipsize", &value);
 
4821
                g_value_unset (&value);
 
4822
 
 
4823
                gtk_tree_view_append_column (treeview, column);
 
4824
        }
 
4825
}
 
4826
 
 
4827
 
 
4828
static int
 
4829
name_column_sort_func (GtkTreeModel *model,
 
4830
                       GtkTreeIter  *a,
 
4831
                       GtkTreeIter  *b,
 
4832
                       gpointer      user_data)
 
4833
{
 
4834
        FileData *fdata1, *fdata2;
 
4835
 
 
4836
        gtk_tree_model_get (model, a, COLUMN_FILE_DATA, &fdata1, -1);
 
4837
        gtk_tree_model_get (model, b, COLUMN_FILE_DATA, &fdata2, -1);
 
4838
 
 
4839
        return sort_by_name (&fdata1, &fdata2);
 
4840
}
 
4841
 
 
4842
 
 
4843
static int
 
4844
size_column_sort_func (GtkTreeModel *model,
 
4845
                       GtkTreeIter  *a,
 
4846
                       GtkTreeIter  *b,
 
4847
                       gpointer      user_data)
 
4848
{
 
4849
        FileData *fdata1, *fdata2;
 
4850
 
 
4851
        gtk_tree_model_get (model, a, COLUMN_FILE_DATA, &fdata1, -1);
 
4852
        gtk_tree_model_get (model, b, COLUMN_FILE_DATA, &fdata2, -1);
 
4853
 
 
4854
        return sort_by_size (&fdata1, &fdata2);
 
4855
}
 
4856
 
 
4857
 
 
4858
static int
 
4859
type_column_sort_func (GtkTreeModel *model,
 
4860
                       GtkTreeIter  *a,
 
4861
                       GtkTreeIter  *b,
 
4862
                       gpointer      user_data)
 
4863
{
 
4864
        FileData *fdata1, *fdata2;
 
4865
 
 
4866
        gtk_tree_model_get (model, a, COLUMN_FILE_DATA, &fdata1, -1);
 
4867
        gtk_tree_model_get (model, b, COLUMN_FILE_DATA, &fdata2, -1);
 
4868
 
 
4869
        return sort_by_type (&fdata1, &fdata2);
 
4870
}
 
4871
 
 
4872
 
 
4873
static int
 
4874
time_column_sort_func (GtkTreeModel *model,
 
4875
                       GtkTreeIter  *a,
 
4876
                       GtkTreeIter  *b,
 
4877
                       gpointer      user_data)
 
4878
{
 
4879
        FileData *fdata1, *fdata2;
 
4880
 
 
4881
        gtk_tree_model_get (model, a, COLUMN_FILE_DATA, &fdata1, -1);
 
4882
        gtk_tree_model_get (model, b, COLUMN_FILE_DATA, &fdata2, -1);
 
4883
 
 
4884
        return sort_by_time (&fdata1, &fdata2);
 
4885
}
 
4886
 
 
4887
 
 
4888
static int
 
4889
path_column_sort_func (GtkTreeModel *model,
 
4890
                       GtkTreeIter  *a,
 
4891
                       GtkTreeIter  *b,
 
4892
                       gpointer      user_data)
 
4893
{
 
4894
        FileData *fdata1, *fdata2;
 
4895
 
 
4896
        gtk_tree_model_get (model, a, COLUMN_FILE_DATA, &fdata1, -1);
 
4897
        gtk_tree_model_get (model, b, COLUMN_FILE_DATA, &fdata2, -1);
 
4898
 
 
4899
        return sort_by_path (&fdata1, &fdata2);
 
4900
}
 
4901
 
 
4902
 
 
4903
static int
 
4904
no_sort_column_sort_func (GtkTreeModel *model,
 
4905
                          GtkTreeIter  *a,
 
4906
                          GtkTreeIter  *b,
 
4907
                          gpointer      user_data)
 
4908
{
 
4909
        return -1;
 
4910
}
 
4911
 
 
4912
 
 
4913
static void
 
4914
sort_column_changed_cb (GtkTreeSortable *sortable,
 
4915
                        gpointer         user_data)
 
4916
{
 
4917
        FrWindow    *window = user_data;
 
4918
        GtkSortType  order;
 
4919
        int          column_id;
 
4920
 
 
4921
        if (! gtk_tree_sortable_get_sort_column_id (sortable,
 
4922
                                                    &column_id,
 
4923
                                                    &order))
 
4924
                return;
 
4925
 
 
4926
        window->priv->sort_method = get_sort_method_from_column (column_id);
 
4927
        window->priv->sort_type = order;
 
4928
 
 
4929
        /*set_active (window, get_action_from_sort_method (window->priv->sort_method), TRUE);
 
4930
        set_active (window, "SortReverseOrder", (window->priv->sort_type == GTK_SORT_DESCENDING));*/
 
4931
}
 
4932
 
 
4933
 
 
4934
static gboolean
 
4935
fr_window_show_cb (GtkWidget *widget,
 
4936
                   FrWindow  *window)
 
4937
{
 
4938
        fr_window_update_current_location (window);
 
4939
 
 
4940
        set_active (window, "ViewToolbar", g_settings_get_boolean (window->priv->settings_ui, PREF_UI_VIEW_TOOLBAR));
 
4941
        set_active (window, "ViewStatusbar", g_settings_get_boolean (window->priv->settings_ui, PREF_UI_VIEW_STATUSBAR));
 
4942
 
 
4943
        window->priv->view_folders = g_settings_get_boolean (window->priv->settings_ui, PREF_UI_VIEW_FOLDERS);
 
4944
        set_active (window, "ViewFolders", window->priv->view_folders);
 
4945
 
 
4946
        fr_window_update_filter_bar_visibility (window);
 
4947
 
 
4948
        return TRUE;
 
4949
}
 
4950
 
 
4951
 
 
4952
/* preferences changes notification callbacks */
 
4953
 
 
4954
 
 
4955
static void
 
4956
pref_history_len_changed (GSettings  *settings,
 
4957
                          const char *key,
 
4958
                          gpointer    user_data)
 
4959
{
 
4960
        FrWindow *window = user_data;
 
4961
 
 
4962
        gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (window->priv->recent_chooser_menu),
 
4963
                                      g_settings_get_int (settings, PREF_UI_HISTORY_LEN));
 
4964
        gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (window->priv->recent_chooser_toolbar),
 
4965
                                      g_settings_get_int (settings, PREF_UI_HISTORY_LEN));
 
4966
}
 
4967
 
 
4968
 
 
4969
static void
 
4970
pref_view_toolbar_changed (GSettings  *settings,
 
4971
                           const char *key,
 
4972
                           gpointer    user_data)
 
4973
{
 
4974
        FrWindow *window = user_data;
 
4975
 
 
4976
        fr_window_set_toolbar_visibility (window, g_settings_get_boolean (settings, key));
 
4977
}
 
4978
 
 
4979
 
 
4980
static void
 
4981
pref_view_statusbar_changed (GSettings  *settings,
 
4982
                             const char *key,
 
4983
                             gpointer    user_data)
 
4984
{
 
4985
        FrWindow *window = user_data;
 
4986
 
 
4987
        fr_window_set_statusbar_visibility (window, g_settings_get_boolean (settings, key));
 
4988
}
 
4989
 
 
4990
 
 
4991
static void
 
4992
pref_view_folders_changed (GSettings  *settings,
 
4993
                           const char *key,
 
4994
                           gpointer    user_data)
 
4995
{
 
4996
        FrWindow *window = user_data;
 
4997
 
 
4998
        fr_window_set_folders_visibility (window, g_settings_get_boolean (settings, key));
 
4999
}
 
5000
 
 
5001
 
 
5002
static void
 
5003
pref_show_field_changed (GSettings  *settings,
 
5004
                         const char *key,
 
5005
                         gpointer    user_data)
 
5006
{
 
5007
        FrWindow *window = user_data;
 
5008
 
 
5009
        fr_window_update_columns_visibility (window);
 
5010
}
 
5011
 
 
5012
 
 
5013
static void
 
5014
pref_click_policy_changed (GSettings  *settings,
 
5015
                           const char *key,
 
5016
                           gpointer    user_data)
 
5017
{
 
5018
        FrWindow   *window = user_data;
 
5019
        GdkWindow  *win = gtk_tree_view_get_bin_window (GTK_TREE_VIEW (window->priv->list_view));
 
5020
        GdkDisplay *display;
 
5021
 
 
5022
        window->priv->single_click = is_single_click_policy (window);
 
5023
 
 
5024
        gdk_window_set_cursor (win, NULL);
 
5025
        display = gtk_widget_get_display (GTK_WIDGET (window->priv->list_view));
 
5026
        if (display != NULL)
 
5027
                gdk_display_flush (display);
 
5028
}
 
5029
 
 
5030
 
 
5031
static void gh_unref_pixbuf (gpointer  key,
 
5032
                             gpointer  value,
 
5033
                             gpointer  user_data);
 
5034
 
 
5035
 
 
5036
static void
 
5037
pref_use_mime_icons_changed (GSettings  *settings,
 
5038
                             const char *key,
 
5039
                             gpointer    user_data)
 
5040
{
 
5041
        FrWindow *window = user_data;
 
5042
 
 
5043
        if (pixbuf_hash != NULL) {
 
5044
                g_hash_table_foreach (pixbuf_hash,
 
5045
                                      gh_unref_pixbuf,
 
5046
                                      NULL);
 
5047
                g_hash_table_destroy (pixbuf_hash);
 
5048
                pixbuf_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
5049
        }
 
5050
        if (tree_pixbuf_hash != NULL) {
 
5051
                g_hash_table_foreach (tree_pixbuf_hash,
 
5052
                                      gh_unref_pixbuf,
 
5053
                                      NULL);
 
5054
                g_hash_table_destroy (tree_pixbuf_hash);
 
5055
                tree_pixbuf_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
5056
        }
 
5057
 
 
5058
        fr_window_update_file_list (window, FALSE);
 
5059
        fr_window_update_dir_tree (window);
 
5060
}
 
5061
 
 
5062
 
 
5063
static void
 
5064
theme_changed_cb (GtkIconTheme *theme, FrWindow *window)
 
5065
{
 
5066
        int icon_width, icon_height;
 
5067
 
 
5068
        gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (window)),
 
5069
                                           FILE_LIST_ICON_SIZE,
 
5070
                                           &icon_width, &icon_height);
 
5071
        file_list_icon_size = MAX (icon_width, icon_height);
 
5072
 
 
5073
        gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (window)),
 
5074
                                           DIR_TREE_ICON_SIZE,
 
5075
                                           &icon_width, &icon_height);
 
5076
        dir_tree_icon_size = MAX (icon_width, icon_height);
 
5077
 
 
5078
        if (pixbuf_hash != NULL) {
 
5079
                g_hash_table_foreach (pixbuf_hash,
 
5080
                                      gh_unref_pixbuf,
 
5081
                                      NULL);
 
5082
                g_hash_table_destroy (pixbuf_hash);
 
5083
                pixbuf_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
5084
        }
 
5085
        if (tree_pixbuf_hash != NULL) {
 
5086
                g_hash_table_foreach (tree_pixbuf_hash,
 
5087
                                      gh_unref_pixbuf,
 
5088
                                      NULL);
 
5089
                g_hash_table_destroy (tree_pixbuf_hash);
 
5090
                tree_pixbuf_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
5091
        }
 
5092
 
 
5093
        fr_window_update_file_list (window, TRUE);
 
5094
        fr_window_update_dir_tree (window);
 
5095
}
 
5096
 
 
5097
 
 
5098
static gboolean
 
5099
fr_window_stoppable_cb (FrCommand  *command,
 
5100
                        gboolean    stoppable,
 
5101
                        FrWindow   *window)
 
5102
{
 
5103
        window->priv->stoppable = stoppable;
 
5104
        set_sensitive (window, "Stop", stoppable);
 
5105
        if (window->priv->progress_dialog != NULL)
 
5106
                gtk_dialog_set_response_sensitive (GTK_DIALOG (window->priv->progress_dialog),
 
5107
                                                   GTK_RESPONSE_OK,
 
5108
                                                   stoppable);
 
5109
        return TRUE;
 
5110
}
 
5111
 
 
5112
 
 
5113
static gboolean
 
5114
fr_window_fake_load (FrArchive *archive,
 
5115
                     gpointer   data)
 
5116
{
 
5117
        /* fake loads are disabled to allow exact progress dialogs (#153281) */
 
5118
 
 
5119
        return FALSE;
 
5120
 
 
5121
#if 0
 
5122
        FrWindow *window = data;
 
5123
        gboolean  add_after_opening = FALSE;
 
5124
        gboolean  extract_after_opening = FALSE;
 
5125
        GList    *scan;
 
5126
 
 
5127
        /* fake loads are used only in batch mode to avoid unnecessary
 
5128
         * archive loadings. */
 
5129
 
 
5130
        if (! window->priv->batch_mode)
 
5131
                return FALSE;
 
5132
 
 
5133
        /* Check whether there is an ADD or EXTRACT action in the batch list. */
 
5134
 
 
5135
        for (scan = window->priv->batch_action; scan; scan = scan->next) {
 
5136
                FRBatchAction *action;
 
5137
 
 
5138
                action = (FRBatchAction *) scan->data;
 
5139
                if (action->type == FR_BATCH_ACTION_ADD) {
 
5140
                        add_after_opening = TRUE;
 
5141
                        break;
 
5142
                }
 
5143
                if ((action->type == FR_BATCH_ACTION_EXTRACT)
 
5144
                    || (action->type == FR_BATCH_ACTION_EXTRACT_HERE)
 
5145
                    || (action->type == FR_BATCH_ACTION_EXTRACT_INTERACT))
 
5146
                {
 
5147
                        extract_after_opening = TRUE;
 
5148
                        break;
 
5149
                }
 
5150
        }
 
5151
 
 
5152
        /* use fake load when in batch mode and the archive type supports all
 
5153
         * of the required features */
 
5154
 
 
5155
        return (window->priv->batch_mode
 
5156
                && ! (add_after_opening && window->priv->update_dropped_files && ! archive->command->propAddCanUpdate)
 
5157
                && ! (add_after_opening && ! window->priv->update_dropped_files && ! archive->command->propAddCanReplace)
 
5158
                && ! (extract_after_opening && !archive->command->propCanExtractAll));
 
5159
#endif
 
5160
}
 
5161
 
 
5162
 
 
5163
static gboolean
 
5164
fr_window_add_is_stoppable (FrArchive *archive,
 
5165
                            gpointer   data)
 
5166
{
 
5167
        FrWindow *window = data;
 
5168
        return window->priv->archive_new;
 
5169
}
 
5170
 
 
5171
 
 
5172
static void
 
5173
menu_item_select_cb (GtkMenuItem *proxy,
 
5174
                     FrWindow    *window)
 
5175
{
 
5176
        GtkAction *action;
 
5177
        char      *message;
 
5178
 
 
5179
        action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
 
5180
        g_return_if_fail (action != NULL);
 
5181
 
 
5182
        g_object_get (G_OBJECT (action), "tooltip", &message, NULL);
 
5183
        if (message) {
 
5184
                gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar),
 
5185
                                    window->priv->help_message_cid, message);
 
5186
                g_free (message);
 
5187
        }
 
5188
}
 
5189
 
 
5190
 
 
5191
static void
 
5192
menu_item_deselect_cb (GtkMenuItem *proxy,
 
5193
                       FrWindow    *window)
 
5194
{
 
5195
        gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar),
 
5196
                           window->priv->help_message_cid);
 
5197
}
 
5198
 
 
5199
 
 
5200
static void
 
5201
disconnect_proxy_cb (GtkUIManager *manager,
 
5202
                     GtkAction    *action,
 
5203
                     GtkWidget    *proxy,
 
5204
                     FrWindow     *window)
 
5205
{
 
5206
        if (GTK_IS_MENU_ITEM (proxy)) {
 
5207
                g_signal_handlers_disconnect_by_func
 
5208
                        (proxy, G_CALLBACK (menu_item_select_cb), window);
 
5209
                g_signal_handlers_disconnect_by_func
 
5210
                        (proxy, G_CALLBACK (menu_item_deselect_cb), window);
 
5211
        }
 
5212
}
 
5213
 
 
5214
 
 
5215
static void
 
5216
connect_proxy_cb (GtkUIManager *manager,
 
5217
                  GtkAction    *action,
 
5218
                  GtkWidget    *proxy,
 
5219
                  FrWindow     *window)
 
5220
{
 
5221
        if (GTK_IS_MENU_ITEM (proxy)) {
 
5222
                g_signal_connect (proxy, "select",
 
5223
                                  G_CALLBACK (menu_item_select_cb), window);
 
5224
                g_signal_connect (proxy, "deselect",
 
5225
                                  G_CALLBACK (menu_item_deselect_cb), window);
 
5226
        }
 
5227
}
 
5228
 
 
5229
 
 
5230
static void
 
5231
view_as_radio_action (GtkAction      *action,
 
5232
                      GtkRadioAction *current,
 
5233
                      gpointer        data)
 
5234
{
 
5235
        FrWindow *window = data;
 
5236
        fr_window_set_list_mode (window, gtk_radio_action_get_current_value (current));
 
5237
}
 
5238
 
 
5239
 
 
5240
static void
 
5241
sort_by_radio_action (GtkAction      *action,
 
5242
                      GtkRadioAction *current,
 
5243
                      gpointer        data)
 
5244
{
 
5245
        FrWindow *window = data;
 
5246
 
 
5247
        window->priv->sort_method = gtk_radio_action_get_current_value (current);
 
5248
        window->priv->sort_type = GTK_SORT_ASCENDING;
 
5249
        fr_window_update_list_order (window);
 
5250
}
 
5251
 
 
5252
 
 
5253
static void
 
5254
recent_chooser_item_activated_cb (GtkRecentChooser *chooser,
 
5255
                                  FrWindow         *window)
 
5256
{
 
5257
        char *uri;
 
5258
 
 
5259
        uri = gtk_recent_chooser_get_current_uri (chooser);
 
5260
        if (uri != NULL) {
 
5261
                fr_window_archive_open (window, uri, GTK_WINDOW (window));
 
5262
                g_free (uri);
 
5263
        }
 
5264
}
 
5265
 
 
5266
 
 
5267
static void
 
5268
fr_window_init_recent_chooser (FrWindow         *window,
 
5269
                               GtkRecentChooser *chooser)
 
5270
{
 
5271
        GtkRecentFilter *filter;
 
5272
        int              i;
 
5273
 
 
5274
        g_return_if_fail (chooser != NULL);
 
5275
 
 
5276
        filter = gtk_recent_filter_new ();
 
5277
        gtk_recent_filter_set_name (filter, _("All archives"));
 
5278
        for (i = 0; open_type[i] != -1; i++)
 
5279
                gtk_recent_filter_add_mime_type (filter, mime_type_desc[open_type[i]].mime_type);
 
5280
        gtk_recent_filter_add_application (filter, "File Roller");
 
5281
        gtk_recent_chooser_add_filter (chooser, filter);
 
5282
 
 
5283
        gtk_recent_chooser_set_local_only (chooser, FALSE);
 
5284
        gtk_recent_chooser_set_limit (chooser, g_settings_get_int (window->priv->settings_ui, PREF_UI_HISTORY_LEN));
 
5285
        gtk_recent_chooser_set_show_not_found (chooser, TRUE);
 
5286
        gtk_recent_chooser_set_sort_type (chooser, GTK_RECENT_SORT_MRU);
 
5287
 
 
5288
        g_signal_connect (G_OBJECT (chooser),
 
5289
                          "item_activated",
 
5290
                          G_CALLBACK (recent_chooser_item_activated_cb),
 
5291
                          window);
 
5292
}
 
5293
 
 
5294
 
 
5295
static void
 
5296
close_sidepane_button_clicked_cb (GtkButton *button,
 
5297
                                  FrWindow  *window)
 
5298
{
 
5299
        fr_window_set_folders_visibility (window, FALSE);
 
5300
}
 
5301
 
 
5302
 
 
5303
static void
 
5304
fr_window_activate_filter (FrWindow *window)
 
5305
{
 
5306
        GtkTreeView       *tree_view = GTK_TREE_VIEW (window->priv->list_view);
 
5307
        GtkTreeViewColumn *column;
 
5308
 
 
5309
        fr_window_update_filter_bar_visibility (window);
 
5310
        window->priv->list_mode = FR_WINDOW_LIST_MODE_FLAT;
 
5311
 
 
5312
        gtk_list_store_clear (window->priv->list_store);
 
5313
 
 
5314
        column = gtk_tree_view_get_column (tree_view, 4);
 
5315
        gtk_tree_view_column_set_visible (column, TRUE);
 
5316
 
 
5317
        fr_window_update_file_list (window, TRUE);
 
5318
        fr_window_update_dir_tree (window);
 
5319
        fr_window_update_current_location (window);
 
5320
}
 
5321
 
 
5322
 
 
5323
static void
 
5324
filter_entry_activate_cb (GtkEntry *entry,
 
5325
                          FrWindow *window)
 
5326
{
 
5327
        fr_window_activate_filter (window);
 
5328
}
 
5329
 
 
5330
 
 
5331
static void
 
5332
filter_entry_icon_release_cb (GtkEntry             *entry,
 
5333
                              GtkEntryIconPosition  icon_pos,
 
5334
                              GdkEventButton       *event,
 
5335
                              gpointer              user_data)
 
5336
{
 
5337
        FrWindow *window = FR_WINDOW (user_data);
 
5338
 
 
5339
        if ((event->button == 1) && (icon_pos == GTK_ENTRY_ICON_SECONDARY))
 
5340
                fr_window_deactivate_filter (window);
 
5341
}
 
5342
 
 
5343
 
 
5344
static void
 
5345
fr_window_attach (FrWindow      *window,
 
5346
                  GtkWidget     *child,
 
5347
                  FrWindowArea   area)
 
5348
{
 
5349
        int position;
 
5350
 
 
5351
        g_return_if_fail (window != NULL);
 
5352
        g_return_if_fail (FR_IS_WINDOW (window));
 
5353
        g_return_if_fail (child != NULL);
 
5354
        g_return_if_fail (GTK_IS_WIDGET (child));
 
5355
 
 
5356
        switch (area) {
 
5357
        case FR_WINDOW_AREA_MENUBAR:
 
5358
                position = 0;
 
5359
                break;
 
5360
        case FR_WINDOW_AREA_TOOLBAR:
 
5361
                position = 1;
 
5362
                break;
 
5363
        case FR_WINDOW_AREA_LOCATIONBAR:
 
5364
                position = 2;
 
5365
                break;
 
5366
        case FR_WINDOW_AREA_CONTENTS:
 
5367
                position = 3;
 
5368
                if (window->priv->contents != NULL)
 
5369
                        gtk_widget_destroy (window->priv->contents);
 
5370
                window->priv->contents = child;
 
5371
                break;
 
5372
        case FR_WINDOW_AREA_FILTERBAR:
 
5373
                position = 4;
 
5374
                break;
 
5375
        case FR_WINDOW_AREA_STATUSBAR:
 
5376
                position = 5;
 
5377
                break;
 
5378
        default:
 
5379
                g_critical ("%s: area not recognized!", G_STRFUNC);
 
5380
                return;
 
5381
                break;
 
5382
        }
 
5383
 
 
5384
        gtk_table_attach (GTK_TABLE (window->priv->layout),
 
5385
                          child,
 
5386
                          0, 1,
 
5387
                          position, position + 1,
 
5388
                          GTK_EXPAND | GTK_FILL,
 
5389
                          ((area == FR_WINDOW_AREA_CONTENTS) ? GTK_EXPAND : 0) | GTK_FILL,
 
5390
                          0, 0);
 
5391
}
 
5392
 
 
5393
 
 
5394
static void
 
5395
set_action_important (GtkUIManager *ui,
 
5396
                      const char   *action_name)
 
5397
{
 
5398
        GtkAction *action;
 
5399
 
 
5400
        action = gtk_ui_manager_get_action (ui, action_name);
 
5401
        g_object_set (action, "is_important", TRUE, NULL);
 
5402
        g_object_unref (action);
 
5403
}
 
5404
 
 
5405
 
 
5406
static void
 
5407
fr_window_construct (FrWindow *window)
 
5408
{
 
5409
        GtkWidget        *menubar;
 
5410
        GtkWidget        *toolbar;
 
5411
        GtkWidget        *list_scrolled_window;
 
5412
        GtkWidget        *location_box;
 
5413
        GtkStatusbar     *statusbar;
 
5414
        GtkWidget        *statusbar_box;
 
5415
        GtkWidget        *filter_box;
 
5416
        GtkWidget        *tree_scrolled_window;
 
5417
        GtkWidget        *sidepane_title;
 
5418
        GtkWidget        *sidepane_title_box;
 
5419
        GtkWidget        *sidepane_title_label;
 
5420
        GtkWidget        *close_sidepane_button;
 
5421
        GtkTreeSelection *selection;
 
5422
        int               icon_width, icon_height;
 
5423
        GtkActionGroup   *actions;
 
5424
        GtkUIManager     *ui;
 
5425
        GtkToolItem      *open_recent_tool_item;
 
5426
        GtkWidget        *menu_item;
 
5427
        GError           *error = NULL;
 
5428
 
 
5429
        /* data common to all windows. */
 
5430
 
 
5431
        if (pixbuf_hash == NULL)
 
5432
                pixbuf_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
5433
        if (tree_pixbuf_hash == NULL)
 
5434
                tree_pixbuf_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
5435
        if (icon_theme == NULL)
 
5436
                icon_theme = gtk_icon_theme_get_default ();
 
5437
 
 
5438
        /* Create the settings objects */
 
5439
 
 
5440
        window->priv->settings_listing = g_settings_new (FILE_ROLLER_SCHEMA_LISTING);
 
5441
        window->priv->settings_ui = g_settings_new (FILE_ROLLER_SCHEMA_UI);
 
5442
        window->priv->settings_general = g_settings_new (FILE_ROLLER_SCHEMA_GENERAL);
 
5443
        window->priv->settings_dialogs = g_settings_new (FILE_ROLLER_SCHEMA_DIALOGS);
 
5444
        window->priv->settings_nautilus = g_settings_new (NAUTILUS_SCHEMA);
 
5445
 
 
5446
        /* Create the application. */
 
5447
 
 
5448
        window->priv->layout = gtk_table_new (4, 1, FALSE);
 
5449
        gtk_container_add (GTK_CONTAINER (window), window->priv->layout);
 
5450
        gtk_widget_show (window->priv->layout);
 
5451
 
 
5452
        gtk_window_set_title (GTK_WINDOW (window), _("Archive Manager"));
 
5453
        gtk_window_set_has_resize_grip (GTK_WINDOW (window), TRUE);
 
5454
 
 
5455
        g_signal_connect (G_OBJECT (window),
 
5456
                          "delete_event",
 
5457
                          G_CALLBACK (fr_window_delete_event_cb),
 
5458
                          window);
 
5459
 
 
5460
        g_signal_connect (G_OBJECT (window),
 
5461
                          "show",
 
5462
                          G_CALLBACK (fr_window_show_cb),
 
5463
                          window);
 
5464
 
 
5465
        window->priv->theme_changed_handler_id =
 
5466
                g_signal_connect (icon_theme,
 
5467
                                  "changed",
 
5468
                                  G_CALLBACK (theme_changed_cb),
 
5469
                                  window);
 
5470
 
 
5471
        gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (window)),
 
5472
                                           FILE_LIST_ICON_SIZE,
 
5473
                                           &icon_width, &icon_height);
 
5474
        file_list_icon_size = MAX (icon_width, icon_height);
 
5475
 
 
5476
        gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (window)),
 
5477
                                           DIR_TREE_ICON_SIZE,
 
5478
                                           &icon_width, &icon_height);
 
5479
        dir_tree_icon_size = MAX (icon_width, icon_height);
 
5480
 
 
5481
        gtk_window_set_default_size (GTK_WINDOW (window),
 
5482
                                     g_settings_get_int (window->priv->settings_ui, PREF_UI_WINDOW_WIDTH),
 
5483
                                     g_settings_get_int (window->priv->settings_ui, PREF_UI_WINDOW_HEIGHT));
 
5484
 
 
5485
        gtk_drag_dest_set (GTK_WIDGET (window),
 
5486
                           GTK_DEST_DEFAULT_ALL,
 
5487
                           target_table, G_N_ELEMENTS (target_table),
 
5488
                           GDK_ACTION_COPY);
 
5489
 
 
5490
        g_signal_connect (G_OBJECT (window),
 
5491
                          "drag_data_received",
 
5492
                          G_CALLBACK (fr_window_drag_data_received),
 
5493
                          window);
 
5494
        g_signal_connect (G_OBJECT (window),
 
5495
                          "drag_motion",
 
5496
                          G_CALLBACK (fr_window_drag_motion),
 
5497
                          window);
 
5498
 
 
5499
        g_signal_connect (G_OBJECT (window),
 
5500
                          "key_press_event",
 
5501
                          G_CALLBACK (key_press_cb),
 
5502
                          window);
 
5503
 
 
5504
        /* Initialize Data. */
 
5505
 
 
5506
        window->archive = fr_archive_new ();
 
5507
        g_signal_connect (G_OBJECT (window->archive),
 
5508
                          "start",
 
5509
                          G_CALLBACK (action_started),
 
5510
                          window);
 
5511
        g_signal_connect (G_OBJECT (window->archive),
 
5512
                          "done",
 
5513
                          G_CALLBACK (action_performed),
 
5514
                          window);
 
5515
        g_signal_connect (G_OBJECT (window->archive),
 
5516
                          "progress",
 
5517
                          G_CALLBACK (fr_window_progress_cb),
 
5518
                          window);
 
5519
        g_signal_connect (G_OBJECT (window->archive),
 
5520
                          "message",
 
5521
                          G_CALLBACK (fr_window_message_cb),
 
5522
                          window);
 
5523
        g_signal_connect (G_OBJECT (window->archive),
 
5524
                          "stoppable",
 
5525
                          G_CALLBACK (fr_window_stoppable_cb),
 
5526
                          window);
 
5527
        g_signal_connect (G_OBJECT (window->archive),
 
5528
                          "working_archive",
 
5529
                          G_CALLBACK (fr_window_working_archive_cb),
 
5530
                          window);
 
5531
 
 
5532
        fr_archive_set_fake_load_func (window->archive,
 
5533
                                       fr_window_fake_load,
 
5534
                                       window);
 
5535
        fr_archive_set_add_is_stoppable_func (window->archive,
 
5536
                                              fr_window_add_is_stoppable,
 
5537
                                              window);
 
5538
 
 
5539
        window->priv->sort_method = g_settings_get_enum (window->priv->settings_listing, PREF_LISTING_SORT_METHOD);
 
5540
        window->priv->sort_type = g_settings_get_enum (window->priv->settings_listing, PREF_LISTING_SORT_TYPE);
 
5541
 
 
5542
        window->priv->list_mode = window->priv->last_list_mode = g_settings_get_enum (window->priv->settings_listing, PREF_LISTING_LIST_MODE);
 
5543
        g_settings_set_boolean (window->priv->settings_listing, PREF_LISTING_SHOW_PATH, (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT));
 
5544
 
 
5545
        window->priv->history = NULL;
 
5546
        window->priv->history_current = NULL;
 
5547
 
 
5548
        window->priv->action = FR_ACTION_NONE;
 
5549
 
 
5550
        window->priv->open_default_dir = g_strdup (get_home_uri ());
 
5551
        window->priv->add_default_dir = g_strdup (get_home_uri ());
 
5552
        window->priv->extract_default_dir = g_strdup (get_home_uri ());
 
5553
 
 
5554
        window->priv->give_focus_to_the_list = FALSE;
 
5555
 
 
5556
        window->priv->activity_ref = 0;
 
5557
        window->priv->activity_timeout_handle = 0;
 
5558
 
 
5559
        window->priv->update_timeout_handle = 0;
 
5560
 
 
5561
        window->priv->archive_present = FALSE;
 
5562
        window->priv->archive_new = FALSE;
 
5563
        window->priv->archive_uri = NULL;
 
5564
 
 
5565
        window->priv->drag_destination_folder = NULL;
 
5566
        window->priv->drag_base_dir = NULL;
 
5567
        window->priv->drag_error = NULL;
 
5568
        window->priv->drag_file_list = NULL;
 
5569
 
 
5570
        window->priv->batch_mode = FALSE;
 
5571
        window->priv->batch_action_list = NULL;
 
5572
        window->priv->batch_action = NULL;
 
5573
        window->priv->extract_interact_use_default_dir = FALSE;
 
5574
        window->priv->non_interactive = FALSE;
 
5575
 
 
5576
        window->priv->password = NULL;
 
5577
        window->priv->compression = g_settings_get_enum (window->priv->settings_general, PREF_GENERAL_COMPRESSION_LEVEL);
 
5578
        window->priv->encrypt_header = g_settings_get_boolean (window->priv->settings_general, PREF_GENERAL_ENCRYPT_HEADER);
 
5579
        window->priv->volume_size = 0;
 
5580
 
 
5581
        window->priv->convert_data.converting = FALSE;
 
5582
        window->priv->convert_data.temp_dir = NULL;
 
5583
        window->priv->convert_data.new_archive = NULL;
 
5584
        window->priv->convert_data.password = NULL;
 
5585
        window->priv->convert_data.encrypt_header = FALSE;
 
5586
        window->priv->convert_data.volume_size = 0;
 
5587
 
 
5588
        window->priv->stoppable = TRUE;
 
5589
 
 
5590
        window->priv->batch_adding_one_file = FALSE;
 
5591
 
 
5592
        window->priv->path_clicked = NULL;
 
5593
 
 
5594
        window->priv->current_view_length = 0;
 
5595
 
 
5596
        window->priv->current_batch_action.type = FR_BATCH_ACTION_NONE;
 
5597
        window->priv->current_batch_action.data = NULL;
 
5598
        window->priv->current_batch_action.free_func = NULL;
 
5599
 
 
5600
        window->priv->pd_last_archive = NULL;
 
5601
        window->priv->pd_last_message = NULL;
 
5602
        window->priv->pd_last_fraction = 0.0;
 
5603
 
 
5604
        /* Create the widgets. */
 
5605
 
 
5606
        /* * File list. */
 
5607
 
 
5608
        window->priv->list_store = fr_list_model_new (NUMBER_OF_COLUMNS,
 
5609
                                                      G_TYPE_POINTER,
 
5610
                                                      GDK_TYPE_PIXBUF,
 
5611
                                                      G_TYPE_STRING,
 
5612
                                                      GDK_TYPE_PIXBUF,
 
5613
                                                      G_TYPE_STRING,
 
5614
                                                      G_TYPE_STRING,
 
5615
                                                      G_TYPE_STRING,
 
5616
                                                      G_TYPE_STRING);
 
5617
        g_object_set_data (G_OBJECT (window->priv->list_store), "FrWindow", window);
 
5618
        window->priv->list_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window->priv->list_store));
 
5619
 
 
5620
        gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (window->priv->list_view), TRUE);
 
5621
        add_file_list_columns (window, GTK_TREE_VIEW (window->priv->list_view));
 
5622
        gtk_tree_view_set_enable_search (GTK_TREE_VIEW (window->priv->list_view),
 
5623
                                         FALSE);
 
5624
        gtk_tree_view_set_search_column (GTK_TREE_VIEW (window->priv->list_view),
 
5625
                                         COLUMN_NAME);
 
5626
 
 
5627
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (window->priv->list_store),
 
5628
                                         COLUMN_NAME, name_column_sort_func,
 
5629
                                         NULL, NULL);
 
5630
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (window->priv->list_store),
 
5631
                                         COLUMN_SIZE, size_column_sort_func,
 
5632
                                         NULL, NULL);
 
5633
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (window->priv->list_store),
 
5634
                                         COLUMN_TYPE, type_column_sort_func,
 
5635
                                         NULL, NULL);
 
5636
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (window->priv->list_store),
 
5637
                                         COLUMN_TIME, time_column_sort_func,
 
5638
                                         NULL, NULL);
 
5639
        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (window->priv->list_store),
 
5640
                                         COLUMN_PATH, path_column_sort_func,
 
5641
                                         NULL, NULL);
 
5642
 
 
5643
        gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (window->priv->list_store),
 
5644
                                                 no_sort_column_sort_func,
 
5645
                                                 NULL, NULL);
 
5646
 
 
5647
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view));
 
5648
        gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
 
5649
 
 
5650
        g_signal_connect (selection,
 
5651
                          "changed",
 
5652
                          G_CALLBACK (selection_changed_cb),
 
5653
                          window);
 
5654
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5655
                          "row_activated",
 
5656
                          G_CALLBACK (row_activated_cb),
 
5657
                          window);
 
5658
 
 
5659
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5660
                          "button_press_event",
 
5661
                          G_CALLBACK (file_button_press_cb),
 
5662
                          window);
 
5663
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5664
                          "button_release_event",
 
5665
                          G_CALLBACK (file_button_release_cb),
 
5666
                          window);
 
5667
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5668
                          "motion_notify_event",
 
5669
                          G_CALLBACK (file_motion_notify_callback),
 
5670
                          window);
 
5671
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5672
                          "leave_notify_event",
 
5673
                          G_CALLBACK (file_leave_notify_callback),
 
5674
                          window);
 
5675
 
 
5676
        g_signal_connect (G_OBJECT (window->priv->list_store),
 
5677
                          "sort_column_changed",
 
5678
                          G_CALLBACK (sort_column_changed_cb),
 
5679
                          window);
 
5680
 
 
5681
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5682
                          "drag_begin",
 
5683
                          G_CALLBACK (file_list_drag_begin),
 
5684
                          window);
 
5685
        g_signal_connect (G_OBJECT (window->priv->list_view),
 
5686
                          "drag_end",
 
5687
                          G_CALLBACK (file_list_drag_end),
 
5688
                          window);
 
5689
        egg_tree_multi_drag_add_drag_support (GTK_TREE_VIEW (window->priv->list_view));
 
5690
 
 
5691
        list_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
 
5692
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (list_scrolled_window),
 
5693
                                        GTK_POLICY_AUTOMATIC,
 
5694
                                        GTK_POLICY_AUTOMATIC);
 
5695
        gtk_container_add (GTK_CONTAINER (list_scrolled_window), window->priv->list_view);
 
5696
 
 
5697
        /* filter bar */
 
5698
 
 
5699
        window->priv->filter_bar = filter_box = gtk_hbox_new (FALSE, 6);
 
5700
        gtk_container_set_border_width (GTK_CONTAINER (filter_box), 3);
 
5701
        fr_window_attach (FR_WINDOW (window), window->priv->filter_bar, FR_WINDOW_AREA_FILTERBAR);
 
5702
 
 
5703
        gtk_box_pack_start (GTK_BOX (filter_box),
 
5704
                            gtk_label_new (_("Find:")), FALSE, FALSE, 0);
 
5705
 
 
5706
        /* * filter entry */
 
5707
 
 
5708
        window->priv->filter_entry = GTK_WIDGET (gtk_entry_new ());
 
5709
        gtk_entry_set_icon_from_stock (GTK_ENTRY (window->priv->filter_entry),
 
5710
                                       GTK_ENTRY_ICON_SECONDARY,
 
5711
                                       GTK_STOCK_CLEAR);
 
5712
 
 
5713
        gtk_widget_set_size_request (window->priv->filter_entry, 300, -1);
 
5714
        gtk_box_pack_start (GTK_BOX (filter_box),
 
5715
                            window->priv->filter_entry, FALSE, FALSE, 6);
 
5716
 
 
5717
        g_signal_connect (G_OBJECT (window->priv->filter_entry),
 
5718
                          "activate",
 
5719
                          G_CALLBACK (filter_entry_activate_cb),
 
5720
                          window);
 
5721
        g_signal_connect (G_OBJECT (window->priv->filter_entry),
 
5722
                          "icon-release",
 
5723
                          G_CALLBACK (filter_entry_icon_release_cb),
 
5724
                          window);
 
5725
 
 
5726
        gtk_widget_show_all (filter_box);
 
5727
 
 
5728
        /* tree view */
 
5729
 
 
5730
        window->priv->tree_store = gtk_tree_store_new (TREE_NUMBER_OF_COLUMNS,
 
5731
                                                       G_TYPE_STRING,
 
5732
                                                       GDK_TYPE_PIXBUF,
 
5733
                                                       G_TYPE_STRING,
 
5734
                                                       PANGO_TYPE_WEIGHT);
 
5735
        window->priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window->priv->tree_store));
 
5736
        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (window->priv->tree_view), FALSE);
 
5737
        add_dir_tree_columns (window, GTK_TREE_VIEW (window->priv->tree_view));
 
5738
 
 
5739
        g_signal_connect (G_OBJECT (window->priv->tree_view),
 
5740
                          "button_press_event",
 
5741
                          G_CALLBACK (dir_tree_button_press_cb),
 
5742
                          window);
 
5743
 
 
5744
        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->tree_view));
 
5745
        g_signal_connect (selection,
 
5746
                          "changed",
 
5747
                          G_CALLBACK (dir_tree_selection_changed_cb),
 
5748
                          window);
 
5749
 
 
5750
        g_signal_connect (G_OBJECT (window->priv->tree_view),
 
5751
                          "drag_begin",
 
5752
                          G_CALLBACK (file_list_drag_begin),
 
5753
                          window);
 
5754
        g_signal_connect (G_OBJECT (window->priv->tree_view),
 
5755
                          "drag_end",
 
5756
                          G_CALLBACK (file_list_drag_end),
 
5757
                          window);
 
5758
        g_signal_connect (G_OBJECT (window->priv->tree_view),
 
5759
                          "drag_data_get",
 
5760
                          G_CALLBACK (fr_window_folder_tree_drag_data_get),
 
5761
                          window);
 
5762
        gtk_drag_source_set (window->priv->tree_view,
 
5763
                             GDK_BUTTON1_MASK,
 
5764
                             folder_tree_targets, G_N_ELEMENTS (folder_tree_targets),
 
5765
                             GDK_ACTION_COPY);
 
5766
 
 
5767
        tree_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
 
5768
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (tree_scrolled_window),
 
5769
                                        GTK_POLICY_AUTOMATIC,
 
5770
                                        GTK_POLICY_AUTOMATIC);
 
5771
        gtk_container_add (GTK_CONTAINER (tree_scrolled_window), window->priv->tree_view);
 
5772
 
 
5773
        /* side pane */
 
5774
 
 
5775
        window->priv->sidepane = gtk_vbox_new (FALSE, 0);
 
5776
 
 
5777
        sidepane_title = gtk_frame_new (NULL);
 
5778
        gtk_frame_set_shadow_type (GTK_FRAME (sidepane_title), GTK_SHADOW_ETCHED_IN);
 
5779
 
 
5780
        sidepane_title_box = gtk_hbox_new (FALSE, 0);
 
5781
        gtk_container_set_border_width (GTK_CONTAINER (sidepane_title_box), 2);
 
5782
        gtk_container_add (GTK_CONTAINER (sidepane_title), sidepane_title_box);
 
5783
        sidepane_title_label = gtk_label_new (_("Folders"));
 
5784
 
 
5785
        gtk_misc_set_alignment (GTK_MISC (sidepane_title_label), 0.0, 0.5);
 
5786
        gtk_box_pack_start (GTK_BOX (sidepane_title_box), sidepane_title_label, TRUE, TRUE, 0);
 
5787
 
 
5788
        close_sidepane_button = gtk_button_new ();
 
5789
        gtk_container_add (GTK_CONTAINER (close_sidepane_button), gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
 
5790
        gtk_button_set_relief (GTK_BUTTON (close_sidepane_button), GTK_RELIEF_NONE);
 
5791
        gtk_widget_set_tooltip_text (close_sidepane_button, _("Close the folders pane"));
 
5792
        g_signal_connect (close_sidepane_button,
 
5793
                          "clicked",
 
5794
                          G_CALLBACK (close_sidepane_button_clicked_cb),
 
5795
                          window);
 
5796
        gtk_box_pack_end (GTK_BOX (sidepane_title_box), close_sidepane_button, FALSE, FALSE, 0);
 
5797
 
 
5798
        gtk_box_pack_start (GTK_BOX (window->priv->sidepane), sidepane_title, FALSE, FALSE, 0);
 
5799
        gtk_box_pack_start (GTK_BOX (window->priv->sidepane), tree_scrolled_window, TRUE, TRUE, 0);
 
5800
 
 
5801
        /* main content */
 
5802
 
 
5803
        window->priv->paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
 
5804
        gtk_paned_pack1 (GTK_PANED (window->priv->paned), window->priv->sidepane, FALSE, TRUE);
 
5805
        gtk_paned_pack2 (GTK_PANED (window->priv->paned), list_scrolled_window, TRUE, TRUE);
 
5806
        gtk_paned_set_position (GTK_PANED (window->priv->paned), g_settings_get_int (window->priv->settings_ui, PREF_UI_SIDEBAR_WIDTH));
 
5807
 
 
5808
        fr_window_attach (FR_WINDOW (window), window->priv->paned, FR_WINDOW_AREA_CONTENTS);
 
5809
        gtk_widget_show_all (window->priv->paned);
 
5810
 
 
5811
        /* Build the menu and the toolbar. */
 
5812
 
 
5813
        ui = gtk_ui_manager_new ();
 
5814
 
 
5815
        window->priv->actions = actions = gtk_action_group_new ("Actions");
 
5816
        gtk_action_group_set_translation_domain (actions, NULL);
 
5817
        gtk_action_group_add_actions (actions,
 
5818
                                      action_entries,
 
5819
                                      n_action_entries,
 
5820
                                      window);
 
5821
        gtk_action_group_add_toggle_actions (actions,
 
5822
                                             action_toggle_entries,
 
5823
                                             n_action_toggle_entries,
 
5824
                                             window);
 
5825
        gtk_action_group_add_radio_actions (actions,
 
5826
                                            view_as_entries,
 
5827
                                            n_view_as_entries,
 
5828
                                            window->priv->list_mode,
 
5829
                                            G_CALLBACK (view_as_radio_action),
 
5830
                                            window);
 
5831
        gtk_action_group_add_radio_actions (actions,
 
5832
                                            sort_by_entries,
 
5833
                                            n_sort_by_entries,
 
5834
                                            window->priv->sort_type,
 
5835
                                            G_CALLBACK (sort_by_radio_action),
 
5836
                                            window);
 
5837
 
 
5838
        g_signal_connect (ui, "connect_proxy",
 
5839
                          G_CALLBACK (connect_proxy_cb), window);
 
5840
        g_signal_connect (ui, "disconnect_proxy",
 
5841
                          G_CALLBACK (disconnect_proxy_cb), window);
 
5842
 
 
5843
        gtk_ui_manager_insert_action_group (ui, actions, 0);
 
5844
        gtk_window_add_accel_group (GTK_WINDOW (window),
 
5845
                                    gtk_ui_manager_get_accel_group (ui));
 
5846
 
 
5847
        /* Add a hidden short cut Ctrl-Q for power users */
 
5848
        gtk_accel_group_connect (gtk_ui_manager_get_accel_group (ui),
 
5849
                                 GDK_KEY_q, GDK_CONTROL_MASK, 0,
 
5850
                                 g_cclosure_new_swap (G_CALLBACK (fr_window_close), window, NULL));
 
5851
 
 
5852
 
 
5853
        if (!gtk_ui_manager_add_ui_from_string (ui, ui_info, -1, &error)) {
 
5854
                g_message ("building menus failed: %s", error->message);
 
5855
                g_error_free (error);
 
5856
        }
 
5857
 
 
5858
        menubar = gtk_ui_manager_get_widget (ui, "/MenuBar");
 
5859
        fr_window_attach (FR_WINDOW (window), menubar, FR_WINDOW_AREA_MENUBAR);
 
5860
        gtk_widget_show (menubar);
 
5861
 
 
5862
        window->priv->toolbar = toolbar = gtk_ui_manager_get_widget (ui, "/ToolBar");
 
5863
        gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), TRUE);
 
5864
        gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
 
5865
        set_action_important (ui, "/ToolBar/Extract_Toolbar");
 
5866
 
 
5867
        /* location bar */
 
5868
 
 
5869
        window->priv->location_bar = gtk_ui_manager_get_widget (ui, "/LocationBar");
 
5870
        gtk_toolbar_set_show_arrow (GTK_TOOLBAR (window->priv->location_bar), FALSE);
 
5871
        gtk_toolbar_set_style (GTK_TOOLBAR (window->priv->location_bar), GTK_TOOLBAR_BOTH_HORIZ);
 
5872
        gtk_style_context_add_class (gtk_widget_get_style_context (window->priv->location_bar), GTK_STYLE_CLASS_TOOLBAR);
 
5873
        set_action_important (ui, "/LocationBar/GoBack");
 
5874
 
 
5875
        /* current location */
 
5876
 
 
5877
        location_box = gtk_hbox_new (FALSE, 6);
 
5878
        /* Translators: after the colon there is a folder name. */
 
5879
        window->priv->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
 
5880
        gtk_box_pack_start (GTK_BOX (location_box),
 
5881
                            window->priv->location_label, FALSE, FALSE, 5);
 
5882
 
 
5883
        window->priv->location_entry = gtk_entry_new ();
 
5884
        gtk_entry_set_icon_from_stock (GTK_ENTRY (window->priv->location_entry),
 
5885
                                       GTK_ENTRY_ICON_PRIMARY,
 
5886
                                       GTK_STOCK_DIRECTORY);
 
5887
 
 
5888
        gtk_box_pack_start (GTK_BOX (location_box),
 
5889
                            window->priv->location_entry, TRUE, TRUE, 5);
 
5890
 
 
5891
        g_signal_connect (G_OBJECT (window->priv->location_entry),
 
5892
                          "key_press_event",
 
5893
                          G_CALLBACK (location_entry_key_press_event_cb),
 
5894
                          window);
 
5895
 
 
5896
        {
 
5897
                GtkToolItem *tool_item;
 
5898
 
 
5899
                tool_item = gtk_separator_tool_item_new ();
 
5900
                gtk_widget_show_all (GTK_WIDGET (tool_item));
 
5901
                gtk_toolbar_insert (GTK_TOOLBAR (window->priv->location_bar), tool_item, -1);
 
5902
 
 
5903
                tool_item = gtk_tool_item_new ();
 
5904
                gtk_tool_item_set_expand (tool_item, TRUE);
 
5905
                gtk_container_add (GTK_CONTAINER (tool_item), location_box);
 
5906
                gtk_widget_show_all (GTK_WIDGET (tool_item));
 
5907
                gtk_toolbar_insert (GTK_TOOLBAR (window->priv->location_bar), tool_item, -1);
 
5908
        }
 
5909
 
 
5910
        fr_window_attach (FR_WINDOW (window), window->priv->location_bar, FR_WINDOW_AREA_LOCATIONBAR);
 
5911
        if (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT)
 
5912
                gtk_widget_hide (window->priv->location_bar);
 
5913
        else
 
5914
                gtk_widget_show (window->priv->location_bar);
 
5915
 
 
5916
        /* Recent manager */
 
5917
 
 
5918
        window->priv->recent_manager = gtk_recent_manager_get_default ();
 
5919
 
 
5920
        window->priv->recent_chooser_menu = gtk_recent_chooser_menu_new_for_manager (window->priv->recent_manager);
 
5921
        gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (window->priv->recent_chooser_menu), GTK_RECENT_SORT_MRU);
 
5922
        fr_window_init_recent_chooser (window, GTK_RECENT_CHOOSER (window->priv->recent_chooser_menu));
 
5923
        menu_item = gtk_ui_manager_get_widget (ui, "/MenuBar/Archive/OpenRecentMenu");
 
5924
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), window->priv->recent_chooser_menu);
 
5925
 
 
5926
        window->priv->recent_chooser_toolbar = gtk_recent_chooser_menu_new_for_manager (window->priv->recent_manager);
 
5927
        fr_window_init_recent_chooser (window, GTK_RECENT_CHOOSER (window->priv->recent_chooser_toolbar));
 
5928
 
 
5929
        /* Add the recent menu tool item */
 
5930
 
 
5931
        open_recent_tool_item = gtk_menu_tool_button_new_from_stock (GTK_STOCK_OPEN);
 
5932
        gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_recent_tool_item), window->priv->recent_chooser_toolbar);
 
5933
        gtk_tool_item_set_homogeneous (open_recent_tool_item, FALSE);
 
5934
        gtk_widget_set_tooltip_text (GTK_WIDGET (open_recent_tool_item), _("Open archive"));
 
5935
        gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_recent_tool_item), _("Open a recently used archive"));
 
5936
 
 
5937
        window->priv->open_action = gtk_action_new ("Toolbar_Open", _("Open"), _("Open archive"), GTK_STOCK_OPEN);
 
5938
        g_object_set (window->priv->open_action, "is_important", TRUE, NULL);
 
5939
        g_signal_connect (window->priv->open_action,
 
5940
                          "activate",
 
5941
                          G_CALLBACK (activate_action_open),
 
5942
                          window);
 
5943
        gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_recent_tool_item), window->priv->open_action);
 
5944
 
 
5945
        gtk_widget_show (GTK_WIDGET (open_recent_tool_item));
 
5946
        gtk_toolbar_insert (GTK_TOOLBAR (toolbar), open_recent_tool_item, 1);
 
5947
 
 
5948
        /**/
 
5949
 
 
5950
        fr_window_attach (FR_WINDOW (window), window->priv->toolbar, FR_WINDOW_AREA_TOOLBAR);
 
5951
        if (g_settings_get_boolean (window->priv->settings_ui, PREF_UI_VIEW_TOOLBAR))
 
5952
                gtk_widget_show (toolbar);
 
5953
        else
 
5954
                gtk_widget_hide (toolbar);
 
5955
 
 
5956
        window->priv->file_popup_menu = gtk_ui_manager_get_widget (ui, "/FilePopupMenu");
 
5957
        window->priv->folder_popup_menu = gtk_ui_manager_get_widget (ui, "/FolderPopupMenu");
 
5958
        window->priv->sidebar_folder_popup_menu = gtk_ui_manager_get_widget (ui, "/SidebarFolderPopupMenu");
 
5959
 
 
5960
        /* Create the statusbar. */
 
5961
 
 
5962
        window->priv->statusbar = gtk_statusbar_new ();
 
5963
        window->priv->help_message_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar), "help_message");
 
5964
        window->priv->list_info_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar), "list_info");
 
5965
        window->priv->progress_cid = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->priv->statusbar), "progress");
 
5966
 
 
5967
        statusbar = GTK_STATUSBAR (window->priv->statusbar);
 
5968
#if GTK_CHECK_VERSION (2, 19, 1)
 
5969
        statusbar_box = gtk_statusbar_get_message_area (statusbar);
 
5970
        gtk_box_set_homogeneous (GTK_BOX (statusbar_box), FALSE);
 
5971
        gtk_box_set_spacing (GTK_BOX (statusbar_box), 4);
 
5972
        gtk_box_set_child_packing (GTK_BOX (statusbar_box), gtk_statusbar_get_message_area (statusbar), TRUE, TRUE, 0, GTK_PACK_START );
 
5973
#else
 
5974
        statusbar_box = gtk_hbox_new (FALSE, 4);
 
5975
        g_object_ref (statusbar->label);
 
5976
        gtk_container_remove (GTK_CONTAINER (statusbar->frame), statusbar->label);
 
5977
        gtk_box_pack_start (GTK_BOX (statusbar_box), statusbar->label, TRUE, TRUE, 0);
 
5978
        g_object_unref (statusbar->label);
 
5979
        gtk_container_add (GTK_CONTAINER (statusbar->frame), statusbar_box);
 
5980
#endif
 
5981
 
 
5982
        window->priv->progress_bar = gtk_progress_bar_new ();
 
5983
        gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (window->priv->progress_bar), ACTIVITY_PULSE_STEP);
 
5984
        gtk_widget_set_size_request (window->priv->progress_bar, -1, PROGRESS_BAR_HEIGHT);
 
5985
        {
 
5986
                GtkWidget *vbox;
 
5987
 
 
5988
                vbox = gtk_vbox_new (FALSE, 0);
 
5989
                gtk_box_pack_start (GTK_BOX (statusbar_box), vbox, FALSE, FALSE, 0);
 
5990
                gtk_box_pack_start (GTK_BOX (vbox), window->priv->progress_bar, TRUE, TRUE, 1);
 
5991
                gtk_widget_show (vbox);
 
5992
        }
 
5993
        gtk_widget_show (statusbar_box);
 
5994
 
 
5995
        fr_window_attach (FR_WINDOW (window), window->priv->statusbar, FR_WINDOW_AREA_STATUSBAR);
 
5996
        if (g_settings_get_boolean (window->priv->settings_ui, PREF_UI_VIEW_STATUSBAR))
 
5997
                gtk_widget_show (window->priv->statusbar);
 
5998
        else
 
5999
                gtk_widget_hide (window->priv->statusbar);
 
6000
 
 
6001
        /**/
 
6002
 
 
6003
        fr_window_update_title (window);
 
6004
        fr_window_update_sensitivity (window);
 
6005
        fr_window_update_file_list (window, FALSE);
 
6006
        fr_window_update_dir_tree (window);
 
6007
        fr_window_update_current_location (window);
 
6008
        fr_window_update_columns_visibility (window);
 
6009
 
 
6010
        /* Add notification callbacks. */
 
6011
 
 
6012
        g_signal_connect (window->priv->settings_ui,
 
6013
                          "changed::" PREF_UI_HISTORY_LEN,
 
6014
                          G_CALLBACK (pref_history_len_changed),
 
6015
                          window);
 
6016
        g_signal_connect (window->priv->settings_ui,
 
6017
                          "changed::" PREF_UI_VIEW_TOOLBAR,
 
6018
                          G_CALLBACK (pref_view_toolbar_changed),
 
6019
                          window);
 
6020
        g_signal_connect (window->priv->settings_ui,
 
6021
                          "changed::" PREF_UI_VIEW_STATUSBAR,
 
6022
                          G_CALLBACK (pref_view_statusbar_changed),
 
6023
                          window);
 
6024
        g_signal_connect (window->priv->settings_ui,
 
6025
                          "changed::" PREF_UI_VIEW_FOLDERS,
 
6026
                          G_CALLBACK (pref_view_folders_changed),
 
6027
                          window);
 
6028
        g_signal_connect (window->priv->settings_listing,
 
6029
                          "changed::" PREF_LISTING_SHOW_TYPE,
 
6030
                          G_CALLBACK (pref_show_field_changed),
 
6031
                          window);
 
6032
        g_signal_connect (window->priv->settings_listing,
 
6033
                          "changed::" PREF_LISTING_SHOW_SIZE,
 
6034
                          G_CALLBACK (pref_show_field_changed),
 
6035
                          window);
 
6036
        g_signal_connect (window->priv->settings_listing,
 
6037
                          "changed::" PREF_LISTING_SHOW_TIME,
 
6038
                          G_CALLBACK (pref_show_field_changed),
 
6039
                          window);
 
6040
        g_signal_connect (window->priv->settings_listing,
 
6041
                          "changed::" PREF_LISTING_SHOW_PATH,
 
6042
                          G_CALLBACK (pref_show_field_changed),
 
6043
                          window);
 
6044
        g_signal_connect (window->priv->settings_listing,
 
6045
                          "changed::" PREF_LISTING_USE_MIME_ICONS,
 
6046
                          G_CALLBACK (pref_use_mime_icons_changed),
 
6047
                          window);
 
6048
        g_signal_connect (window->priv->settings_nautilus,
 
6049
                          "changed::" NAUTILUS_CLICK_POLICY,
 
6050
                          G_CALLBACK (pref_click_policy_changed),
 
6051
                          window);
 
6052
 
 
6053
        /* Give focus to the list. */
 
6054
 
 
6055
        gtk_widget_grab_focus (window->priv->list_view);
 
6056
}
 
6057
 
 
6058
 
 
6059
GtkWidget *
 
6060
fr_window_new (void)
 
6061
{
 
6062
        GtkWidget *window;
 
6063
 
 
6064
        window = g_object_new (FR_TYPE_WINDOW, NULL);
 
6065
        fr_window_construct ((FrWindow*) window);
 
6066
 
 
6067
        return window;
 
6068
}
 
6069
 
 
6070
 
 
6071
static void
 
6072
fr_window_set_archive_uri (FrWindow   *window,
 
6073
                           const char *uri)
 
6074
{
 
6075
        if (window->priv->archive_uri != NULL)
 
6076
                        g_free (window->priv->archive_uri);
 
6077
                window->priv->archive_uri = g_strdup (uri);
 
6078
}
 
6079
 
 
6080
 
 
6081
gboolean
 
6082
fr_window_archive_new (FrWindow   *window,
 
6083
                       const char *uri)
 
6084
{
 
6085
        g_return_val_if_fail (window != NULL, FALSE);
 
6086
 
 
6087
        if (! fr_archive_create (window->archive, uri)) {
 
6088
                GtkWindow *file_sel = g_object_get_data (G_OBJECT (window), "fr_file_sel");
 
6089
 
 
6090
                window->priv->load_error_parent_window = file_sel;
 
6091
                fr_archive_action_completed (window->archive,
 
6092
                                             FR_ACTION_CREATING_NEW_ARCHIVE,
 
6093
                                             FR_PROC_ERROR_GENERIC,
 
6094
                                             _("Archive type not supported."));
 
6095
 
 
6096
                return FALSE;
 
6097
        }
 
6098
 
 
6099
        fr_window_set_archive_uri (window, uri);
 
6100
        window->priv->archive_present = TRUE;
 
6101
        window->priv->archive_new = TRUE;
 
6102
 
 
6103
        fr_archive_action_completed (window->archive,
 
6104
                                     FR_ACTION_CREATING_NEW_ARCHIVE,
 
6105
                                     FR_PROC_ERROR_NONE,
 
6106
                                     NULL);
 
6107
 
 
6108
        return TRUE;
 
6109
}
 
6110
 
 
6111
 
 
6112
FrWindow *
 
6113
fr_window_archive_open (FrWindow   *current_window,
 
6114
                        const char *uri,
 
6115
                        GtkWindow  *parent)
 
6116
{
 
6117
        FrWindow *window = current_window;
 
6118
 
 
6119
        if (current_window->priv->archive_present)
 
6120
                window = (FrWindow *) fr_window_new ();
 
6121
 
 
6122
        g_return_val_if_fail (window != NULL, FALSE);
 
6123
 
 
6124
        fr_window_archive_close (window);
 
6125
 
 
6126
        fr_window_set_archive_uri (window, uri);
 
6127
        window->priv->archive_present = FALSE;
 
6128
        window->priv->give_focus_to_the_list = TRUE;
 
6129
        window->priv->load_error_parent_window = parent;
 
6130
 
 
6131
        fr_window_set_current_batch_action (window,
 
6132
                                            FR_BATCH_ACTION_LOAD,
 
6133
                                            g_strdup (window->priv->archive_uri),
 
6134
                                            (GFreeFunc) g_free);
 
6135
 
 
6136
        fr_archive_load (window->archive, window->priv->archive_uri, window->priv->password);
 
6137
 
 
6138
        return window;
 
6139
}
 
6140
 
 
6141
 
 
6142
void
 
6143
fr_window_archive_close (FrWindow *window)
 
6144
{
 
6145
        g_return_if_fail (window != NULL);
 
6146
 
 
6147
        if (! window->priv->archive_new && ! window->priv->archive_present)
 
6148
                return;
 
6149
 
 
6150
        fr_window_free_open_files (window);
 
6151
        fr_clipboard_data_unref (window->priv->copy_data);
 
6152
        window->priv->copy_data = NULL;
 
6153
 
 
6154
        fr_window_set_password (window, NULL);
 
6155
        fr_window_set_volume_size(window, 0);
 
6156
        fr_window_history_clear (window);
 
6157
 
 
6158
        window->priv->archive_new = FALSE;
 
6159
        window->priv->archive_present = FALSE;
 
6160
 
 
6161
        fr_window_update_title (window);
 
6162
        fr_window_update_sensitivity (window);
 
6163
        fr_window_update_file_list (window, FALSE);
 
6164
        fr_window_update_dir_tree (window);
 
6165
        fr_window_update_current_location (window);
 
6166
        fr_window_update_statusbar_list_info (window);
 
6167
}
 
6168
 
 
6169
 
 
6170
const char *
 
6171
fr_window_get_archive_uri (FrWindow *window)
 
6172
{
 
6173
        g_return_val_if_fail (window != NULL, NULL);
 
6174
 
 
6175
        return window->priv->archive_uri;
 
6176
}
 
6177
 
 
6178
 
 
6179
const char *
 
6180
fr_window_get_paste_archive_uri (FrWindow *window)
 
6181
{
 
6182
        g_return_val_if_fail (window != NULL, NULL);
 
6183
 
 
6184
        if (window->priv->clipboard_data != NULL)
 
6185
                return window->priv->clipboard_data->archive_filename;
 
6186
        else
 
6187
                return NULL;
 
6188
}
 
6189
 
 
6190
 
 
6191
gboolean
 
6192
fr_window_archive_is_present (FrWindow *window)
 
6193
{
 
6194
        g_return_val_if_fail (window != NULL, FALSE);
 
6195
 
 
6196
        return window->priv->archive_present;
 
6197
}
 
6198
 
 
6199
 
 
6200
typedef struct {
 
6201
        char     *uri;
 
6202
        char     *password;
 
6203
        gboolean  encrypt_header;
 
6204
        guint     volume_size;
 
6205
} SaveAsData;
 
6206
 
 
6207
 
 
6208
static SaveAsData *
 
6209
save_as_data_new (const char *uri,
 
6210
                  const char *password,
 
6211
                  gboolean    encrypt_header,
 
6212
                  guint       volume_size)
 
6213
{
 
6214
        SaveAsData *sdata;
 
6215
 
 
6216
        sdata = g_new0 (SaveAsData, 1);
 
6217
        if (uri != NULL)
 
6218
                sdata->uri = g_strdup (uri);
 
6219
        if (password != NULL)
 
6220
                sdata->password = g_strdup (password);
 
6221
        sdata->encrypt_header = encrypt_header;
 
6222
        sdata->volume_size = volume_size;
 
6223
 
 
6224
        return sdata;
 
6225
}
 
6226
 
 
6227
 
 
6228
static void
 
6229
save_as_data_free (SaveAsData *sdata)
 
6230
{
 
6231
        if (sdata == NULL)
 
6232
                return;
 
6233
        g_free (sdata->uri);
 
6234
        g_free (sdata->password);
 
6235
        g_free (sdata);
 
6236
}
 
6237
 
 
6238
 
 
6239
void
 
6240
fr_window_archive_save_as (FrWindow   *window,
 
6241
                           const char *uri,
 
6242
                           const char *password,
 
6243
                           gboolean    encrypt_header,
 
6244
                           guint       volume_size)
 
6245
{
 
6246
        g_return_if_fail (window != NULL);
 
6247
        g_return_if_fail (uri != NULL);
 
6248
        g_return_if_fail (window->archive != NULL);
 
6249
 
 
6250
        fr_window_convert_data_free (window, TRUE);
 
6251
        window->priv->convert_data.new_file = g_strdup (uri);
 
6252
 
 
6253
        /* create the new archive */
 
6254
 
 
6255
        window->priv->convert_data.new_archive = fr_archive_new ();
 
6256
        if (! fr_archive_create (window->priv->convert_data.new_archive, uri)) {
 
6257
                GtkWidget *d;
 
6258
                char      *utf8_name;
 
6259
                char      *message;
 
6260
 
 
6261
                utf8_name = g_uri_display_basename (uri);
 
6262
                message = g_strdup_printf (_("Could not save the archive \"%s\""), utf8_name);
 
6263
                g_free (utf8_name);
 
6264
 
 
6265
                d = _gtk_error_dialog_new (GTK_WINDOW (window),
 
6266
                                           GTK_DIALOG_DESTROY_WITH_PARENT,
 
6267
                                           NULL,
 
6268
                                           message,
 
6269
                                           "%s",
 
6270
                                           _("Archive type not supported."));
 
6271
                gtk_dialog_run (GTK_DIALOG (d));
 
6272
                gtk_widget_destroy (d);
 
6273
 
 
6274
                g_free (message);
 
6275
 
 
6276
                g_object_unref (window->priv->convert_data.new_archive);
 
6277
                window->priv->convert_data.new_archive = NULL;
 
6278
 
 
6279
                return;
 
6280
        }
 
6281
 
 
6282
        g_return_if_fail (window->priv->convert_data.new_archive->command != NULL);
 
6283
 
 
6284
        if (password != NULL) {
 
6285
                window->priv->convert_data.password = g_strdup (password);
 
6286
                window->priv->convert_data.encrypt_header = encrypt_header;
 
6287
        }
 
6288
        else
 
6289
                window->priv->convert_data.encrypt_header = FALSE;
 
6290
        window->priv->convert_data.volume_size = volume_size;
 
6291
 
 
6292
        fr_window_set_current_batch_action (window,
 
6293
                                            FR_BATCH_ACTION_SAVE_AS,
 
6294
                                            save_as_data_new (uri, password, encrypt_header, volume_size),
 
6295
                                            (GFreeFunc) save_as_data_free);
 
6296
 
 
6297
        g_signal_connect (G_OBJECT (window->priv->convert_data.new_archive),
 
6298
                          "start",
 
6299
                          G_CALLBACK (action_started),
 
6300
                          window);
 
6301
        g_signal_connect (G_OBJECT (window->priv->convert_data.new_archive),
 
6302
                          "done",
 
6303
                          G_CALLBACK (convert__action_performed),
 
6304
                          window);
 
6305
        g_signal_connect (G_OBJECT (window->priv->convert_data.new_archive),
 
6306
                          "progress",
 
6307
                          G_CALLBACK (fr_window_progress_cb),
 
6308
                          window);
 
6309
        g_signal_connect (G_OBJECT (window->priv->convert_data.new_archive),
 
6310
                          "message",
 
6311
                          G_CALLBACK (fr_window_message_cb),
 
6312
                          window);
 
6313
        g_signal_connect (G_OBJECT (window->priv->convert_data.new_archive),
 
6314
                          "stoppable",
 
6315
                          G_CALLBACK (fr_window_stoppable_cb),
 
6316
                          window);
 
6317
 
 
6318
        window->priv->convert_data.converting = TRUE;
 
6319
        window->priv->convert_data.temp_dir = get_temp_work_dir (NULL);
 
6320
 
 
6321
        fr_process_clear (window->archive->process);
 
6322
        fr_archive_extract_to_local (window->archive,
 
6323
                                     NULL,
 
6324
                                     window->priv->convert_data.temp_dir,
 
6325
                                     NULL,
 
6326
                                     TRUE,
 
6327
                                     FALSE,
 
6328
                                     FALSE,
 
6329
                                     window->priv->password);
 
6330
        fr_process_start (window->archive->process);
 
6331
}
 
6332
 
 
6333
 
 
6334
void
 
6335
fr_window_archive_reload (FrWindow *window)
 
6336
{
 
6337
        g_return_if_fail (window != NULL);
 
6338
 
 
6339
        if (window->priv->activity_ref > 0)
 
6340
                return;
 
6341
        if (window->priv->archive_new)
 
6342
                return;
 
6343
 
 
6344
        fr_archive_reload (window->archive, window->priv->password);
 
6345
}
 
6346
 
 
6347
 
 
6348
void
 
6349
fr_window_archive_rename (FrWindow   *window,
 
6350
                          const char *uri)
 
6351
{
 
6352
        g_return_if_fail (window != NULL);
 
6353
 
 
6354
        if (window->priv->archive_new) {
 
6355
                fr_window_archive_new (window, uri);
 
6356
                return;
 
6357
        }
 
6358
 
 
6359
        fr_archive_rename (window->archive, uri);
 
6360
        fr_window_set_archive_uri (window, uri);
 
6361
 
 
6362
        fr_window_update_title (window);
 
6363
        fr_window_add_to_recent_list (window, window->priv->archive_uri);
 
6364
}
 
6365
 
 
6366
 
 
6367
/**/
 
6368
 
 
6369
 
 
6370
void
 
6371
fr_window_archive_add_files (FrWindow *window,
 
6372
                             GList    *file_list, /* GFile list */
 
6373
                             gboolean  update)
 
6374
{
 
6375
        GFile *base;
 
6376
        char  *base_dir;
 
6377
        int    base_len;
 
6378
        GList *files = NULL;
 
6379
        GList *scan;
 
6380
        char  *base_uri;
 
6381
 
 
6382
        base = g_file_get_parent ((GFile *) file_list->data);
 
6383
        base_dir = g_file_get_path (base);
 
6384
        base_len = 0;
 
6385
        if (strcmp (base_dir, "/") != 0)
 
6386
                base_len = strlen (base_dir);
 
6387
 
 
6388
        for (scan = file_list; scan; scan = scan->next) {
 
6389
                GFile *file = scan->data;
 
6390
                char  *path;
 
6391
                char  *rel_path;
 
6392
 
 
6393
                path = g_file_get_path (file);
 
6394
                rel_path = g_strdup (path + base_len + 1);
 
6395
                files = g_list_prepend (files, rel_path);
 
6396
 
 
6397
                g_free (path);
 
6398
        }
 
6399
 
 
6400
        base_uri = g_file_get_uri (base);
 
6401
 
 
6402
        fr_archive_add_files (window->archive,
 
6403
                              files,
 
6404
                              base_uri,
 
6405
                              fr_window_get_current_location (window),
 
6406
                              update,
 
6407
                              window->priv->password,
 
6408
                              window->priv->encrypt_header,
 
6409
                              window->priv->compression,
 
6410
                              window->priv->volume_size);
 
6411
 
 
6412
        g_free (base_uri);
 
6413
        path_list_free (files);
 
6414
        g_free (base_dir);
 
6415
        g_object_unref (base);
 
6416
}
 
6417
 
 
6418
 
 
6419
void
 
6420
fr_window_archive_add_with_wildcard (FrWindow      *window,
 
6421
                                     const char    *include_files,
 
6422
                                     const char    *exclude_files,
 
6423
                                     const char    *exclude_folders,
 
6424
                                     const char    *base_dir,
 
6425
                                     const char    *dest_dir,
 
6426
                                     gboolean       update,
 
6427
                                     gboolean       follow_links)
 
6428
{
 
6429
        fr_archive_add_with_wildcard (window->archive,
 
6430
                                      include_files,
 
6431
                                      exclude_files,
 
6432
                                      exclude_folders,
 
6433
                                      base_dir,
 
6434
                                      (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
 
6435
                                      update,
 
6436
                                      follow_links,
 
6437
                                      window->priv->password,
 
6438
                                      window->priv->encrypt_header,
 
6439
                                      window->priv->compression,
 
6440
                                      window->priv->volume_size);
 
6441
}
 
6442
 
 
6443
 
 
6444
void
 
6445
fr_window_archive_add_directory (FrWindow      *window,
 
6446
                                 const char    *directory,
 
6447
                                 const char    *base_dir,
 
6448
                                 const char    *dest_dir,
 
6449
                                 gboolean       update)
 
6450
{
 
6451
        fr_archive_add_directory (window->archive,
 
6452
                                  directory,
 
6453
                                  base_dir,
 
6454
                                  (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
 
6455
                                  update,
 
6456
                                  window->priv->password,
 
6457
                                  window->priv->encrypt_header,
 
6458
                                  window->priv->compression,
 
6459
                                  window->priv->volume_size);
 
6460
}
 
6461
 
 
6462
 
 
6463
void
 
6464
fr_window_archive_add_items (FrWindow      *window,
 
6465
                             GList         *item_list,
 
6466
                             const char    *base_dir,
 
6467
                             const char    *dest_dir,
 
6468
                             gboolean       update)
 
6469
{
 
6470
        fr_archive_add_items (window->archive,
 
6471
                              item_list,
 
6472
                              base_dir,
 
6473
                              (dest_dir == NULL)? fr_window_get_current_location (window): dest_dir,
 
6474
                              update,
 
6475
                              window->priv->password,
 
6476
                              window->priv->encrypt_header,
 
6477
                              window->priv->compression,
 
6478
                              window->priv->volume_size);
 
6479
}
 
6480
 
 
6481
 
 
6482
void
 
6483
fr_window_archive_add_dropped_items (FrWindow *window,
 
6484
                                     GList    *item_list,
 
6485
                                     gboolean  update)
 
6486
{
 
6487
        fr_archive_add_dropped_items (window->archive,
 
6488
                                      item_list,
 
6489
                                      fr_window_get_current_location (window),
 
6490
                                      fr_window_get_current_location (window),
 
6491
                                      update,
 
6492
                                      window->priv->password,
 
6493
                                      window->priv->encrypt_header,
 
6494
                                      window->priv->compression,
 
6495
                                      window->priv->volume_size);
 
6496
}
 
6497
 
 
6498
 
 
6499
void
 
6500
fr_window_archive_remove (FrWindow      *window,
 
6501
                          GList         *file_list)
 
6502
{
 
6503
        fr_window_clipboard_remove_file_list (window, file_list);
 
6504
 
 
6505
        fr_process_clear (window->archive->process);
 
6506
        fr_archive_remove (window->archive, file_list, window->priv->compression);
 
6507
        fr_process_start (window->archive->process);
 
6508
}
 
6509
 
 
6510
 
 
6511
/* -- window_archive_extract -- */
 
6512
 
 
6513
 
 
6514
static ExtractData*
 
6515
extract_data_new (GList      *file_list,
 
6516
                  const char *extract_to_dir,
 
6517
                  const char *base_dir,
 
6518
                  gboolean    skip_older,
 
6519
                  gboolean    overwrite,
 
6520
                  gboolean    junk_paths,
 
6521
                  gboolean    extract_here)
 
6522
{
 
6523
        ExtractData *edata;
 
6524
 
 
6525
        edata = g_new0 (ExtractData, 1);
 
6526
        edata->file_list = path_list_dup (file_list);
 
6527
        if (extract_to_dir != NULL)
 
6528
                edata->extract_to_dir = g_strdup (extract_to_dir);
 
6529
        edata->skip_older = skip_older;
 
6530
        edata->overwrite = overwrite;
 
6531
        edata->junk_paths = junk_paths;
 
6532
        if (base_dir != NULL)
 
6533
                edata->base_dir = g_strdup (base_dir);
 
6534
        edata->extract_here = extract_here;
 
6535
 
 
6536
        return edata;
 
6537
}
 
6538
 
 
6539
 
 
6540
static ExtractData*
 
6541
extract_to_data_new (const char *extract_to_dir)
 
6542
{
 
6543
        return extract_data_new (NULL,
 
6544
                                 extract_to_dir,
 
6545
                                 NULL,
 
6546
                                 FALSE,
 
6547
                                 TRUE,
 
6548
                                 FALSE,
 
6549
                                 FALSE);
 
6550
}
 
6551
 
 
6552
 
 
6553
static void
 
6554
extract_data_free (ExtractData *edata)
 
6555
{
 
6556
        g_return_if_fail (edata != NULL);
 
6557
 
 
6558
        path_list_free (edata->file_list);
 
6559
        g_free (edata->extract_to_dir);
 
6560
        g_free (edata->base_dir);
 
6561
 
 
6562
        g_free (edata);
 
6563
}
 
6564
 
 
6565
 
 
6566
static gboolean
 
6567
archive_is_encrypted (FrWindow *window,
 
6568
                      GList    *file_list)
 
6569
{
 
6570
        gboolean encrypted = FALSE;
 
6571
 
 
6572
        if (file_list == NULL) {
 
6573
                int i;
 
6574
 
 
6575
                for (i = 0; ! encrypted && i < window->archive->command->files->len; i++) {
 
6576
                        FileData *fdata = g_ptr_array_index (window->archive->command->files, i);
 
6577
 
 
6578
                        if (fdata->encrypted)
 
6579
                                encrypted = TRUE;
 
6580
                }
 
6581
        }
 
6582
        else {
 
6583
 
 
6584
                GHashTable *file_hash;
 
6585
                int         i;
 
6586
                GList      *scan;
 
6587
 
 
6588
                file_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
6589
                for (i = 0; i < window->archive->command->files->len; i++) {
 
6590
                        FileData *fdata = g_ptr_array_index (window->archive->command->files, i);
 
6591
                        g_hash_table_insert (file_hash, fdata->original_path, fdata);
 
6592
                }
 
6593
 
 
6594
                for (scan = file_list; ! encrypted && scan; scan = scan->next) {
 
6595
                        char     *filename = scan->data;
 
6596
                        FileData *fdata;
 
6597
 
 
6598
                        fdata = g_hash_table_lookup (file_hash, filename);
 
6599
                        g_return_val_if_fail (fdata != NULL, FALSE);
 
6600
 
 
6601
                        if (fdata->encrypted)
 
6602
                                encrypted = TRUE;
 
6603
                }
 
6604
 
 
6605
                g_hash_table_destroy (file_hash);
 
6606
        }
 
6607
 
 
6608
        return encrypted;
 
6609
}
 
6610
 
 
6611
 
 
6612
void
 
6613
fr_window_archive_extract_here (FrWindow   *window,
 
6614
                                gboolean    skip_older,
 
6615
                                gboolean    overwrite,
 
6616
                                gboolean    junk_paths)
 
6617
{
 
6618
        ExtractData *edata;
 
6619
 
 
6620
        edata = extract_data_new (NULL,
 
6621
                                  NULL,
 
6622
                                  NULL,
 
6623
                                  skip_older,
 
6624
                                  overwrite,
 
6625
                                  junk_paths,
 
6626
                                  TRUE);
 
6627
        fr_window_set_current_batch_action (window,
 
6628
                                            FR_BATCH_ACTION_EXTRACT,
 
6629
                                            edata,
 
6630
                                            (GFreeFunc) extract_data_free);
 
6631
 
 
6632
        if (archive_is_encrypted (window, NULL) && (window->priv->password == NULL)) {
 
6633
                dlg_ask_password (window);
 
6634
                return;
 
6635
        }
 
6636
 
 
6637
        window->priv->ask_to_open_destination_after_extraction = FALSE;
 
6638
 
 
6639
        fr_process_clear (window->archive->process);
 
6640
        if (fr_archive_extract_here (window->archive,
 
6641
                                     edata->skip_older,
 
6642
                                     edata->overwrite,
 
6643
                                     edata->junk_paths,
 
6644
                                     window->priv->password))
 
6645
        {
 
6646
                fr_process_start (window->archive->process);
 
6647
        }
 
6648
}
 
6649
 
 
6650
 
 
6651
void
 
6652
fr_window_archive_extract (FrWindow   *window,
 
6653
                           GList      *file_list,
 
6654
                           const char *extract_to_dir,
 
6655
                           const char *base_dir,
 
6656
                           gboolean    skip_older,
 
6657
                           gboolean    overwrite,
 
6658
                           gboolean    junk_paths,
 
6659
                           gboolean    ask_to_open_destination)
 
6660
{
 
6661
        ExtractData *edata;
 
6662
        gboolean     do_not_extract = FALSE;
 
6663
        GError      *error = NULL;
 
6664
 
 
6665
        edata = extract_data_new (file_list,
 
6666
                                  extract_to_dir,
 
6667
                                  base_dir,
 
6668
                                  skip_older,
 
6669
                                  overwrite,
 
6670
                                  junk_paths,
 
6671
                                  FALSE);
 
6672
 
 
6673
        fr_window_set_current_batch_action (window,
 
6674
                                            FR_BATCH_ACTION_EXTRACT,
 
6675
                                            edata,
 
6676
                                            (GFreeFunc) extract_data_free);
 
6677
 
 
6678
        if (archive_is_encrypted (window, edata->file_list) && (window->priv->password == NULL)) {
 
6679
                dlg_ask_password (window);
 
6680
                return;
 
6681
        }
 
6682
 
 
6683
        if (! uri_is_dir (edata->extract_to_dir)) {
 
6684
                if (! ForceDirectoryCreation) {
 
6685
                        GtkWidget *d;
 
6686
                        int        r;
 
6687
                        char      *folder_name;
 
6688
                        char      *msg;
 
6689
 
 
6690
                        folder_name = g_filename_display_name (edata->extract_to_dir);
 
6691
                        msg = g_strdup_printf (_("Destination folder \"%s\" does not exist.\n\nDo you want to create it?"), folder_name);
 
6692
                        g_free (folder_name);
 
6693
 
 
6694
                        d = _gtk_message_dialog_new (GTK_WINDOW (window),
 
6695
                                                     GTK_DIALOG_MODAL,
 
6696
                                                     GTK_STOCK_DIALOG_QUESTION,
 
6697
                                                     msg,
 
6698
                                                     NULL,
 
6699
                                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
6700
                                                     _("Create _Folder"), GTK_RESPONSE_YES,
 
6701
                                                     NULL);
 
6702
 
 
6703
                        gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_YES);
 
6704
                        r = gtk_dialog_run (GTK_DIALOG (d));
 
6705
                        gtk_widget_destroy (GTK_WIDGET (d));
 
6706
 
 
6707
                        g_free (msg);
 
6708
 
 
6709
                        if (r != GTK_RESPONSE_YES)
 
6710
                                do_not_extract = TRUE;
 
6711
                }
 
6712
 
 
6713
                if (! do_not_extract && ! ensure_dir_exists (edata->extract_to_dir, 0755, &error)) {
 
6714
                        GtkWidget *d;
 
6715
                        char      *details;
 
6716
 
 
6717
                        details = g_strdup_printf (_("Could not create the destination folder: %s."), error->message);
 
6718
                        d = _gtk_error_dialog_new (GTK_WINDOW (window),
 
6719
                                                   0,
 
6720
                                                   NULL,
 
6721
                                                   _("Extraction not performed"),
 
6722
                                                   "%s",
 
6723
                                                   details);
 
6724
                        g_clear_error (&error);
 
6725
                        fr_window_show_error_dialog (window, d, GTK_WINDOW (window), details);
 
6726
                        fr_window_stop_batch (window);
 
6727
 
 
6728
                        g_free (details);
 
6729
 
 
6730
                        return;
 
6731
                }
 
6732
        }
 
6733
 
 
6734
        if (do_not_extract) {
 
6735
                GtkWidget *d;
 
6736
 
 
6737
                d = _gtk_message_dialog_new (GTK_WINDOW (window),
 
6738
                                             0,
 
6739
                                             GTK_STOCK_DIALOG_WARNING,
 
6740
                                             _("Extraction not performed"),
 
6741
                                             NULL,
 
6742
                                             GTK_STOCK_OK, GTK_RESPONSE_OK,
 
6743
                                             NULL);
 
6744
                gtk_dialog_set_default_response (GTK_DIALOG (d), GTK_RESPONSE_OK);
 
6745
                fr_window_show_error_dialog (window, d, GTK_WINDOW (window), _("Extraction not performed"));
 
6746
                fr_window_stop_batch (window);
 
6747
 
 
6748
                return;
 
6749
        }
 
6750
 
 
6751
        window->priv->ask_to_open_destination_after_extraction = ask_to_open_destination;
 
6752
 
 
6753
        fr_process_clear (window->archive->process);
 
6754
        fr_archive_extract (window->archive,
 
6755
                            edata->file_list,
 
6756
                            edata->extract_to_dir,
 
6757
                            edata->base_dir,
 
6758
                            edata->skip_older,
 
6759
                            edata->overwrite,
 
6760
                            edata->junk_paths,
 
6761
                            window->priv->password);
 
6762
        fr_process_start (window->archive->process);
 
6763
}
 
6764
 
 
6765
 
 
6766
void
 
6767
fr_window_archive_test (FrWindow *window)
 
6768
{
 
6769
        fr_window_set_current_batch_action (window,
 
6770
                                            FR_BATCH_ACTION_TEST,
 
6771
                                            NULL,
 
6772
                                            NULL);
 
6773
        fr_archive_test (window->archive, window->priv->password);
 
6774
}
 
6775
 
 
6776
 
 
6777
void
 
6778
fr_window_set_password (FrWindow   *window,
 
6779
                        const char *password)
 
6780
{
 
6781
        g_return_if_fail (window != NULL);
 
6782
 
 
6783
        if (window->priv->password != NULL) {
 
6784
                g_free (window->priv->password);
 
6785
                window->priv->password = NULL;
 
6786
        }
 
6787
 
 
6788
        if ((password != NULL) && (password[0] != '\0'))
 
6789
                window->priv->password = g_strdup (password);
 
6790
}
 
6791
 
 
6792
void
 
6793
fr_window_set_password_for_paste (FrWindow   *window,
 
6794
                                  const char *password)
 
6795
{
 
6796
        g_return_if_fail (window != NULL);
 
6797
 
 
6798
        if (window->priv->password_for_paste != NULL) {
 
6799
                g_free (window->priv->password_for_paste);
 
6800
                window->priv->password_for_paste = NULL;
 
6801
        }
 
6802
 
 
6803
        if ((password != NULL) && (password[0] != '\0'))
 
6804
                window->priv->password_for_paste = g_strdup (password);
 
6805
}
 
6806
 
 
6807
const char *
 
6808
fr_window_get_password (FrWindow *window)
 
6809
{
 
6810
        g_return_val_if_fail (window != NULL, NULL);
 
6811
 
 
6812
        return window->priv->password;
 
6813
}
 
6814
 
 
6815
 
 
6816
void
 
6817
fr_window_set_encrypt_header (FrWindow *window,
 
6818
                              gboolean  encrypt_header)
 
6819
{
 
6820
        g_return_if_fail (window != NULL);
 
6821
 
 
6822
        window->priv->encrypt_header = encrypt_header;
 
6823
}
 
6824
 
 
6825
 
 
6826
gboolean
 
6827
fr_window_get_encrypt_header (FrWindow *window)
 
6828
{
 
6829
        return window->priv->encrypt_header;
 
6830
}
 
6831
 
 
6832
 
 
6833
void
 
6834
fr_window_set_compression (FrWindow      *window,
 
6835
                           FrCompression  compression)
 
6836
{
 
6837
        g_return_if_fail (window != NULL);
 
6838
 
 
6839
        window->priv->compression = compression;
 
6840
}
 
6841
 
 
6842
 
 
6843
FrCompression
 
6844
fr_window_get_compression (FrWindow *window)
 
6845
{
 
6846
        return window->priv->compression;
 
6847
}
 
6848
 
 
6849
 
 
6850
void
 
6851
fr_window_set_volume_size (FrWindow *window,
 
6852
                           guint     volume_size)
 
6853
{
 
6854
        g_return_if_fail (window != NULL);
 
6855
 
 
6856
        window->priv->volume_size = volume_size;
 
6857
}
 
6858
 
 
6859
 
 
6860
guint
 
6861
fr_window_get_volume_size (FrWindow *window)
 
6862
{
 
6863
        return window->priv->volume_size;
 
6864
}
 
6865
 
 
6866
 
 
6867
void
 
6868
fr_window_go_to_location (FrWindow   *window,
 
6869
                          const char *path,
 
6870
                          gboolean    force_update)
 
6871
{
 
6872
        char *dir;
 
6873
 
 
6874
        g_return_if_fail (window != NULL);
 
6875
        g_return_if_fail (path != NULL);
 
6876
 
 
6877
        if (force_update) {
 
6878
                g_free (window->priv->last_location);
 
6879
                window->priv->last_location = NULL;
 
6880
        }
 
6881
 
 
6882
        if (path[strlen (path) - 1] != '/')
 
6883
                dir = g_strconcat (path, "/", NULL);
 
6884
        else
 
6885
                dir = g_strdup (path);
 
6886
 
 
6887
        if ((window->priv->last_location == NULL) || (strcmp (window->priv->last_location, dir) != 0)) {
 
6888
                g_free (window->priv->last_location);
 
6889
                window->priv->last_location = dir;
 
6890
 
 
6891
                fr_window_history_add (window, dir);
 
6892
                fr_window_update_file_list (window, TRUE);
 
6893
                fr_window_update_current_location (window);
 
6894
        }
 
6895
        else
 
6896
                g_free (dir);
 
6897
}
 
6898
 
 
6899
 
 
6900
const char *
 
6901
fr_window_get_current_location (FrWindow *window)
 
6902
{
 
6903
        if (window->priv->history_current == NULL) {
 
6904
                fr_window_history_add (window, "/");
 
6905
                return window->priv->history_current->data;
 
6906
        }
 
6907
        else
 
6908
                return (const char*) window->priv->history_current->data;
 
6909
}
 
6910
 
 
6911
 
 
6912
void
 
6913
fr_window_go_up_one_level (FrWindow *window)
 
6914
{
 
6915
        char *parent_dir;
 
6916
 
 
6917
        g_return_if_fail (window != NULL);
 
6918
 
 
6919
        parent_dir = get_parent_dir (fr_window_get_current_location (window));
 
6920
        fr_window_go_to_location (window, parent_dir, FALSE);
 
6921
        g_free (parent_dir);
 
6922
}
 
6923
 
 
6924
 
 
6925
void
 
6926
fr_window_go_back (FrWindow *window)
 
6927
{
 
6928
        g_return_if_fail (window != NULL);
 
6929
 
 
6930
        if (window->priv->history == NULL)
 
6931
                return;
 
6932
        if (window->priv->history_current == NULL)
 
6933
                return;
 
6934
        if (window->priv->history_current->next == NULL)
 
6935
                return;
 
6936
        window->priv->history_current = window->priv->history_current->next;
 
6937
 
 
6938
        fr_window_go_to_location (window, window->priv->history_current->data, FALSE);
 
6939
}
 
6940
 
 
6941
 
 
6942
void
 
6943
fr_window_go_forward (FrWindow *window)
 
6944
{
 
6945
        g_return_if_fail (window != NULL);
 
6946
 
 
6947
        if (window->priv->history == NULL)
 
6948
                return;
 
6949
        if (window->priv->history_current == NULL)
 
6950
                return;
 
6951
        if (window->priv->history_current->prev == NULL)
 
6952
                return;
 
6953
        window->priv->history_current = window->priv->history_current->prev;
 
6954
 
 
6955
        fr_window_go_to_location (window, window->priv->history_current->data, FALSE);
 
6956
}
 
6957
 
 
6958
 
 
6959
void
 
6960
fr_window_set_list_mode (FrWindow         *window,
 
6961
                         FrWindowListMode  list_mode)
 
6962
{
 
6963
        g_return_if_fail (window != NULL);
 
6964
 
 
6965
        window->priv->list_mode = window->priv->last_list_mode = list_mode;
 
6966
        if (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT) {
 
6967
                fr_window_history_clear (window);
 
6968
                fr_window_history_add (window, "/");
 
6969
        }
 
6970
 
 
6971
        g_settings_set_enum (window->priv->settings_listing, PREF_LISTING_LIST_MODE, window->priv->last_list_mode);
 
6972
        g_settings_set_boolean (window->priv->settings_listing, PREF_LISTING_SHOW_PATH, (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT));
 
6973
 
 
6974
        fr_window_update_file_list (window, TRUE);
 
6975
        fr_window_update_dir_tree (window);
 
6976
        fr_window_update_current_location (window);
 
6977
}
 
6978
 
 
6979
 
 
6980
GtkTreeModel *
 
6981
fr_window_get_list_store (FrWindow *window)
 
6982
{
 
6983
        return GTK_TREE_MODEL (window->priv->list_store);
 
6984
}
 
6985
 
 
6986
 
 
6987
void
 
6988
fr_window_find (FrWindow *window)
 
6989
{
 
6990
        window->priv->filter_mode = TRUE;
 
6991
        gtk_widget_show (window->priv->filter_bar);
 
6992
        gtk_widget_grab_focus (window->priv->filter_entry);
 
6993
}
 
6994
 
 
6995
 
 
6996
void
 
6997
fr_window_select_all (FrWindow *window)
 
6998
{
 
6999
        gtk_tree_selection_select_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view)));
 
7000
}
 
7001
 
 
7002
 
 
7003
void
 
7004
fr_window_unselect_all (FrWindow *window)
 
7005
{
 
7006
        gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (window->priv->list_view)));
 
7007
}
 
7008
 
 
7009
 
 
7010
void
 
7011
fr_window_set_sort_type (FrWindow     *window,
 
7012
                         GtkSortType   sort_type)
 
7013
{
 
7014
        window->priv->sort_type = sort_type;
 
7015
        fr_window_update_list_order (window);
 
7016
}
 
7017
 
 
7018
 
 
7019
void
 
7020
fr_window_stop (FrWindow *window)
 
7021
{
 
7022
        if (! window->priv->stoppable)
 
7023
                return;
 
7024
 
 
7025
        if (window->priv->activity_ref > 0)
 
7026
                fr_archive_stop (window->archive);
 
7027
 
 
7028
        if (window->priv->convert_data.converting)
 
7029
                fr_window_convert_data_free (window, TRUE);
 
7030
}
 
7031
 
 
7032
 
 
7033
/* -- start/stop activity mode -- */
 
7034
 
 
7035
 
 
7036
static int
 
7037
activity_cb (gpointer data)
 
7038
{
 
7039
        FrWindow *window = data;
 
7040
 
 
7041
        if ((window->priv->pd_progress_bar != NULL) && window->priv->progress_pulse)
 
7042
                gtk_progress_bar_pulse (GTK_PROGRESS_BAR (window->priv->pd_progress_bar));
 
7043
        if (window->priv->progress_pulse)
 
7044
                gtk_progress_bar_pulse (GTK_PROGRESS_BAR (window->priv->progress_bar));
 
7045
 
 
7046
        return TRUE;
 
7047
}
 
7048
 
 
7049
 
 
7050
void
 
7051
fr_window_start_activity_mode (FrWindow *window)
 
7052
{
 
7053
        g_return_if_fail (window != NULL);
 
7054
 
 
7055
        if (window->priv->activity_ref++ > 0)
 
7056
                return;
 
7057
 
 
7058
        window->priv->activity_timeout_handle = g_timeout_add (ACTIVITY_DELAY,
 
7059
                                                               activity_cb,
 
7060
                                                               window);
 
7061
        fr_window_update_sensitivity (window);
 
7062
}
 
7063
 
 
7064
 
 
7065
void
 
7066
fr_window_stop_activity_mode (FrWindow *window)
 
7067
{
 
7068
        g_return_if_fail (window != NULL);
 
7069
 
 
7070
        if (window->priv->activity_ref == 0)
 
7071
                return;
 
7072
 
 
7073
        window->priv->activity_ref--;
 
7074
 
 
7075
        if (window->priv->activity_ref > 0)
 
7076
                return;
 
7077
 
 
7078
        if (window->priv->activity_timeout_handle == 0)
 
7079
                return;
 
7080
 
 
7081
        g_source_remove (window->priv->activity_timeout_handle);
 
7082
        window->priv->activity_timeout_handle = 0;
 
7083
 
 
7084
        if (! gtk_widget_get_realized (GTK_WIDGET (window)))
 
7085
                return;
 
7086
 
 
7087
        if (window->priv->progress_dialog != NULL)
 
7088
                gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->pd_progress_bar), 0.0);
 
7089
 
 
7090
        if (! window->priv->batch_mode) {
 
7091
                if (window->priv->progress_bar != NULL)
 
7092
                        gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress_bar), 0.0);
 
7093
                fr_window_update_sensitivity (window);
 
7094
        }
 
7095
}
 
7096
 
 
7097
 
 
7098
static gboolean
 
7099
last_output_window__unrealize_cb (GtkWidget  *widget,
 
7100
                                  gpointer    data)
 
7101
{
 
7102
        pref_util_save_window_geometry (GTK_WINDOW (widget), LAST_OUTPUT_SCHEMA_NAME);
 
7103
        return FALSE;
 
7104
}
 
7105
 
 
7106
 
 
7107
void
 
7108
fr_window_view_last_output (FrWindow   *window,
 
7109
                            const char *title)
 
7110
{
 
7111
        GtkWidget     *dialog;
 
7112
        GtkWidget     *vbox;
 
7113
        GtkWidget     *text_view;
 
7114
        GtkWidget     *scrolled;
 
7115
        GtkTextBuffer *text_buffer;
 
7116
        GtkTextIter    iter;
 
7117
        GList         *scan;
 
7118
 
 
7119
        if (title == NULL)
 
7120
                title = _("Last Output");
 
7121
 
 
7122
        dialog = gtk_dialog_new_with_buttons (title,
 
7123
                                              GTK_WINDOW (window),
 
7124
                                              GTK_DIALOG_DESTROY_WITH_PARENT,
 
7125
                                              GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
 
7126
                                              NULL);
 
7127
        gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
 
7128
        gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
 
7129
        gtk_widget_set_size_request (dialog, 500, 300);
 
7130
 
 
7131
        /* Add text */
 
7132
 
 
7133
        scrolled = gtk_scrolled_window_new (NULL, NULL);
 
7134
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
 
7135
                                        GTK_POLICY_AUTOMATIC,
 
7136
                                        GTK_POLICY_AUTOMATIC);
 
7137
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
 
7138
                                             GTK_SHADOW_ETCHED_IN);
 
7139
 
 
7140
        text_buffer = gtk_text_buffer_new (NULL);
 
7141
        gtk_text_buffer_create_tag (text_buffer, "monospace",
 
7142
                                    "family", "monospace", NULL);
 
7143
 
 
7144
        text_view = gtk_text_view_new_with_buffer (text_buffer);
 
7145
        g_object_unref (text_buffer);
 
7146
        gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);
 
7147
        gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (text_view), FALSE);
 
7148
 
 
7149
        /**/
 
7150
 
 
7151
        vbox = gtk_vbox_new (FALSE, 6);
 
7152
        gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
 
7153
 
 
7154
        gtk_container_add (GTK_CONTAINER (scrolled), text_view);
 
7155
        gtk_box_pack_start (GTK_BOX (vbox), scrolled,
 
7156
                            TRUE, TRUE, 0);
 
7157
 
 
7158
        gtk_widget_show_all (vbox);
 
7159
        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
 
7160
                            vbox,
 
7161
                            TRUE, TRUE, 0);
 
7162
 
 
7163
        /* signals */
 
7164
 
 
7165
        g_signal_connect (G_OBJECT (dialog),
 
7166
                          "response",
 
7167
                          G_CALLBACK (gtk_widget_destroy),
 
7168
                          NULL);
 
7169
 
 
7170
        g_signal_connect (G_OBJECT (dialog),
 
7171
                          "unrealize",
 
7172
                          G_CALLBACK (last_output_window__unrealize_cb),
 
7173
                          NULL);
 
7174
 
 
7175
        /**/
 
7176
 
 
7177
        gtk_text_buffer_get_iter_at_offset (text_buffer, &iter, 0);
 
7178
        scan = window->archive->process->out.raw;
 
7179
        for (; scan; scan = scan->next) {
 
7180
                char        *line = scan->data;
 
7181
                char        *utf8_line;
 
7182
                gsize        bytes_written;
 
7183
 
 
7184
                utf8_line = g_locale_to_utf8 (line, -1, NULL, &bytes_written, NULL);
 
7185
                gtk_text_buffer_insert_with_tags_by_name (text_buffer,
 
7186
                                                          &iter,
 
7187
                                                          utf8_line,
 
7188
                                                          bytes_written,
 
7189
                                                          "monospace", NULL);
 
7190
                g_free (utf8_line);
 
7191
                gtk_text_buffer_insert (text_buffer, &iter, "\n", 1);
 
7192
        }
 
7193
 
 
7194
        /**/
 
7195
 
 
7196
        pref_util_restore_window_geometry (GTK_WINDOW (dialog), LAST_OUTPUT_SCHEMA_NAME);
 
7197
}
 
7198
 
 
7199
 
 
7200
/* -- fr_window_rename_selection -- */
 
7201
 
 
7202
 
 
7203
typedef struct {
 
7204
        char     *path_to_rename;
 
7205
        char     *old_name;
 
7206
        char     *new_name;
 
7207
        char     *current_dir;
 
7208
        gboolean  is_dir;
 
7209
        gboolean  dir_in_archive;
 
7210
        char     *original_path;
 
7211
} RenameData;
 
7212
 
 
7213
 
 
7214
static RenameData*
 
7215
rename_data_new (const char *path_to_rename,
 
7216
                 const char *old_name,
 
7217
                 const char *new_name,
 
7218
                 const char *current_dir,
 
7219
                 gboolean    is_dir,
 
7220
                 gboolean    dir_in_archive,
 
7221
                 const char *original_path)
 
7222
{
 
7223
        RenameData *rdata;
 
7224
 
 
7225
        rdata = g_new0 (RenameData, 1);
 
7226
        rdata->path_to_rename = g_strdup (path_to_rename);
 
7227
        if (old_name != NULL)
 
7228
                rdata->old_name = g_strdup (old_name);
 
7229
        if (new_name != NULL)
 
7230
                rdata->new_name = g_strdup (new_name);
 
7231
        if (current_dir != NULL)
 
7232
                rdata->current_dir = g_strdup (current_dir);
 
7233
        rdata->is_dir = is_dir;
 
7234
        rdata->dir_in_archive = dir_in_archive;
 
7235
        if (original_path != NULL)
 
7236
                rdata->original_path = g_strdup (original_path);
 
7237
 
 
7238
        return rdata;
 
7239
}
 
7240
 
 
7241
 
 
7242
static void
 
7243
rename_data_free (RenameData *rdata)
 
7244
{
 
7245
        g_return_if_fail (rdata != NULL);
 
7246
 
 
7247
        g_free (rdata->path_to_rename);
 
7248
        g_free (rdata->old_name);
 
7249
        g_free (rdata->new_name);
 
7250
        g_free (rdata->current_dir);
 
7251
        g_free (rdata->original_path);
 
7252
        g_free (rdata);
 
7253
}
 
7254
 
 
7255
 
 
7256
static void
 
7257
rename_selection (FrWindow   *window,
 
7258
                  const char *path_to_rename,
 
7259
                  const char *old_name,
 
7260
                  const char *new_name,
 
7261
                  const char *current_dir,
 
7262
                  gboolean    is_dir,
 
7263
                  gboolean    dir_in_archive,
 
7264
                  const char *original_path)
 
7265
{
 
7266
        FrArchive  *archive = window->archive;
 
7267
        RenameData *rdata;
 
7268
        char       *tmp_dir;
 
7269
        GList      *file_list;
 
7270
        gboolean    added_dir;
 
7271
        char       *new_dirname;
 
7272
        GList      *new_file_list;
 
7273
        GList      *scan;
 
7274
 
 
7275
        rdata = rename_data_new (path_to_rename,
 
7276
                                 old_name,
 
7277
                                 new_name,
 
7278
                                 current_dir,
 
7279
                                 is_dir,
 
7280
                                 dir_in_archive,
 
7281
                                 original_path);
 
7282
        fr_window_set_current_batch_action (window,
 
7283
                                            FR_BATCH_ACTION_RENAME,
 
7284
                                            rdata,
 
7285
                                            (GFreeFunc) rename_data_free);
 
7286
 
 
7287
        fr_process_clear (archive->process);
 
7288
 
 
7289
        tmp_dir = get_temp_work_dir (NULL);
 
7290
 
 
7291
        if (is_dir)
 
7292
                file_list = get_dir_list_from_path (window, rdata->path_to_rename);
 
7293
        else
 
7294
                file_list = g_list_append (NULL, g_strdup (rdata->path_to_rename));
 
7295
 
 
7296
        fr_archive_extract_to_local (archive,
 
7297
                                     file_list,
 
7298
                                     tmp_dir,
 
7299
                                     NULL,
 
7300
                                     FALSE,
 
7301
                                     TRUE,
 
7302
                                     FALSE,
 
7303
                                     window->priv->password);
 
7304
 
 
7305
        /* temporarily add the dir to rename to the list if it's stored in the
 
7306
         * archive, this way it will be removed from the archive... */
 
7307
        added_dir = FALSE;
 
7308
        if (is_dir && dir_in_archive && ! g_list_find_custom (file_list, original_path, (GCompareFunc) strcmp)) {
 
7309
                file_list = g_list_prepend (file_list, g_strdup (original_path));
 
7310
                added_dir = TRUE;
 
7311
        }
 
7312
 
 
7313
        fr_archive_remove (archive, file_list, window->priv->compression);
 
7314
        fr_window_clipboard_remove_file_list (window, file_list);
 
7315
 
 
7316
        /* ...and remove it from the list again */
 
7317
        if (added_dir) {
 
7318
                GList *tmp;
 
7319
 
 
7320
                tmp = file_list;
 
7321
                file_list = g_list_remove_link (file_list, tmp);
 
7322
 
 
7323
                g_free (tmp->data);
 
7324
                g_list_free (tmp);
 
7325
        }
 
7326
 
 
7327
        /* rename the files. */
 
7328
 
 
7329
        new_dirname = g_build_filename (rdata->current_dir + 1, rdata->new_name, "/", NULL);
 
7330
        new_file_list = NULL;
 
7331
        if (rdata->is_dir) {
 
7332
                char *old_path;
 
7333
                char *new_path;
 
7334
 
 
7335
                old_path = g_build_filename (tmp_dir, rdata->current_dir, rdata->old_name, NULL);
 
7336
                new_path = g_build_filename (tmp_dir, rdata->current_dir, rdata->new_name, NULL);
 
7337
 
 
7338
                fr_process_begin_command (archive->process, "mv");
 
7339
                fr_process_add_arg (archive->process, "-f");
 
7340
                fr_process_add_arg (archive->process, old_path);
 
7341
                fr_process_add_arg (archive->process, new_path);
 
7342
                fr_process_end_command (archive->process);
 
7343
 
 
7344
                g_free (old_path);
 
7345
                g_free (new_path);
 
7346
        }
 
7347
 
 
7348
        for (scan = file_list; scan; scan = scan->next) {
 
7349
                const char *current_dir_relative = rdata->current_dir + 1;
 
7350
                const char *filename = (char*) scan->data;
 
7351
                char       *old_path = NULL, *common = NULL, *new_path = NULL;
 
7352
                char       *new_filename;
 
7353
 
 
7354
                old_path = g_build_filename (tmp_dir, filename, NULL);
 
7355
 
 
7356
                if (strlen (filename) > (strlen (rdata->current_dir) + strlen (rdata->old_name)))
 
7357
                        common = g_strdup (filename + strlen (rdata->current_dir) + strlen (rdata->old_name));
 
7358
                new_path = g_build_filename (tmp_dir, rdata->current_dir, rdata->new_name, common, NULL);
 
7359
 
 
7360
                if (! rdata->is_dir) {
 
7361
                        fr_process_begin_command (archive->process, "mv");
 
7362
                        fr_process_add_arg (archive->process, "-f");
 
7363
                        fr_process_add_arg (archive->process, old_path);
 
7364
                        fr_process_add_arg (archive->process, new_path);
 
7365
                        fr_process_end_command (archive->process);
 
7366
                }
 
7367
 
 
7368
                new_filename = g_build_filename (current_dir_relative, rdata->new_name, common, NULL);
 
7369
                new_file_list = g_list_prepend (new_file_list, new_filename);
 
7370
 
 
7371
                g_free (old_path);
 
7372
                g_free (common);
 
7373
                g_free (new_path);
 
7374
        }
 
7375
        new_file_list = g_list_reverse (new_file_list);
 
7376
 
 
7377
        /* FIXME: this is broken for tar archives.
 
7378
        if (is_dir && dir_in_archive && ! g_list_find_custom (new_file_list, new_dirname, (GCompareFunc) strcmp))
 
7379
                new_file_list = g_list_prepend (new_file_list, g_build_filename (rdata->current_dir + 1, rdata->new_name, NULL));
 
7380
        */
 
7381
 
 
7382
        fr_archive_add (archive,
 
7383
                        new_file_list,
 
7384
                        tmp_dir,
 
7385
                        NULL,
 
7386
                        FALSE,
 
7387
                        FALSE,
 
7388
                        window->priv->password,
 
7389
                        window->priv->encrypt_header,
 
7390
                        window->priv->compression,
 
7391
                        window->priv->volume_size);
 
7392
 
 
7393
        g_free (new_dirname);
 
7394
        path_list_free (new_file_list);
 
7395
        path_list_free (file_list);
 
7396
 
 
7397
        /* remove the tmp dir */
 
7398
 
 
7399
        fr_process_begin_command (archive->process, "rm");
 
7400
        fr_process_set_working_dir (archive->process, g_get_tmp_dir ());
 
7401
        fr_process_set_sticky (archive->process, TRUE);
 
7402
        fr_process_add_arg (archive->process, "-rf");
 
7403
        fr_process_add_arg (archive->process, tmp_dir);
 
7404
        fr_process_end_command (archive->process);
 
7405
 
 
7406
        fr_process_start (archive->process);
 
7407
 
 
7408
        g_free (tmp_dir);
 
7409
}
 
7410
 
 
7411
 
 
7412
static gboolean
 
7413
valid_name (const char  *new_name,
 
7414
            const char  *old_name,
 
7415
            char       **reason)
 
7416
{
 
7417
        char     *utf8_new_name;
 
7418
        gboolean  retval = TRUE;
 
7419
 
 
7420
        new_name = eat_spaces (new_name);
 
7421
        utf8_new_name = g_filename_display_name (new_name);
 
7422
 
 
7423
        if (*new_name == '\0') {
 
7424
                /* Translators: the name references to a filename.  This message can appear when renaming a file. */
 
7425
                *reason = g_strdup_printf ("%s\n\n%s", _("The new name is void."), _("Please use a different name."));
 
7426
                retval = FALSE;
 
7427
        }
 
7428
        else if (strcmp (new_name, old_name) == 0) {
 
7429
                /* Translators: the name references to a filename.  This message can appear when renaming a file. */
 
7430
                *reason = g_strdup_printf ("%s\n\n%s", _("The new name is equal to the old one."), _("Please use a different name."));
 
7431
                retval = FALSE;
 
7432
        }
 
7433
        else if (strchrs (new_name, BAD_CHARS)) {
 
7434
                /* Translators: the name references to a filename.  This message can appear when renaming a file. */
 
7435
                *reason = g_strdup_printf (_("The name \"%s\" is not valid because it cannot contain the characters: %s\n\n%s"), utf8_new_name, BAD_CHARS, _("Please use a different name."));
 
7436
                retval = FALSE;
 
7437
        }
 
7438
 
 
7439
        g_free (utf8_new_name);
 
7440
 
 
7441
        return retval;
 
7442
}
 
7443
 
 
7444
 
 
7445
static gboolean
 
7446
name_is_present (FrWindow    *window,
 
7447
                 const char  *current_dir,
 
7448
                 const char  *new_name,
 
7449
                 char       **reason)
 
7450
{
 
7451
        gboolean  retval = FALSE;
 
7452
        int       i;
 
7453
        char     *new_filename;
 
7454
        int       new_filename_l;
 
7455
 
 
7456
        *reason = NULL;
 
7457
 
 
7458
        new_filename = g_build_filename (current_dir, new_name, NULL);
 
7459
        new_filename_l = strlen (new_filename);
 
7460
 
 
7461
        for (i = 0; i < window->archive->command->files->len; i++) {
 
7462
                FileData   *fdata = g_ptr_array_index (window->archive->command->files, i);
 
7463
                const char *filename = fdata->full_path;
 
7464
 
 
7465
                if ((strncmp (filename, new_filename, new_filename_l) == 0)
 
7466
                    && ((filename[new_filename_l] == '\0')
 
7467
                        || (filename[new_filename_l] == G_DIR_SEPARATOR))) {
 
7468
                        char *utf8_name = g_filename_display_name (new_name);
 
7469
 
 
7470
                        if (filename[new_filename_l] == G_DIR_SEPARATOR)
 
7471
                                *reason = g_strdup_printf (_("A folder named \"%s\" already exists.\n\n%s"), utf8_name, _("Please use a different name."));
 
7472
                        else
 
7473
                                *reason = g_strdup_printf (_("A file named \"%s\" already exists.\n\n%s"), utf8_name, _("Please use a different name."));
 
7474
 
 
7475
                        retval = TRUE;
 
7476
                        break;
 
7477
                }
 
7478
        }
 
7479
 
 
7480
        g_free (new_filename);
 
7481
 
 
7482
        return retval;
 
7483
}
 
7484
 
 
7485
 
 
7486
void
 
7487
fr_window_rename_selection (FrWindow *window,
 
7488
                            gboolean  from_sidebar)
 
7489
{
 
7490
        char     *path_to_rename;
 
7491
        char     *parent_dir;
 
7492
        char     *old_name;
 
7493
        gboolean  renaming_dir = FALSE;
 
7494
        gboolean  dir_in_archive = FALSE;
 
7495
        char     *original_path = NULL;
 
7496
        char     *utf8_old_name;
 
7497
        char     *utf8_new_name;
 
7498
 
 
7499
        if (from_sidebar) {
 
7500
                path_to_rename = fr_window_get_selected_folder_in_tree_view (window);
 
7501
                if (path_to_rename == NULL)
 
7502
                        return;
 
7503
                parent_dir = remove_level_from_path (path_to_rename);
 
7504
                old_name = g_strdup (file_name_from_path (path_to_rename));
 
7505
                renaming_dir = TRUE;
 
7506
        }
 
7507
        else {
 
7508
                FileData *selected_item;
 
7509
 
 
7510
                selected_item = fr_window_get_selected_item_from_file_list (window);
 
7511
                if (selected_item == NULL)
 
7512
                        return;
 
7513
 
 
7514
                renaming_dir = file_data_is_dir (selected_item);
 
7515
                dir_in_archive = selected_item->dir;
 
7516
                original_path = g_strdup (selected_item->original_path);
 
7517
 
 
7518
                if (renaming_dir && ! dir_in_archive) {
 
7519
                        parent_dir = g_strdup (fr_window_get_current_location (window));
 
7520
                        old_name = g_strdup (selected_item->list_name);
 
7521
                        path_to_rename = g_build_filename (parent_dir, old_name, NULL);
 
7522
                }
 
7523
                else {
 
7524
                        if (renaming_dir) {
 
7525
                                path_to_rename = remove_ending_separator (selected_item->full_path);
 
7526
                                parent_dir = remove_level_from_path (path_to_rename);
 
7527
                        }
 
7528
                        else {
 
7529
                                path_to_rename = g_strdup (selected_item->original_path);
 
7530
                                parent_dir = remove_level_from_path (selected_item->full_path);
 
7531
                        }
 
7532
                        old_name = g_strdup (selected_item->name);
 
7533
                }
 
7534
 
 
7535
                file_data_free (selected_item);
 
7536
        }
 
7537
 
 
7538
 retry__rename_selection:
 
7539
        utf8_old_name = g_locale_to_utf8 (old_name, -1 ,0 ,0 ,0);
 
7540
        utf8_new_name = _gtk_request_dialog_run (GTK_WINDOW (window),
 
7541
                                                 (GTK_DIALOG_DESTROY_WITH_PARENT
 
7542
                                                  | GTK_DIALOG_MODAL),
 
7543
                                                 _("Rename"),
 
7544
                                                 (renaming_dir ? _("New folder name") : _("New file name")),
 
7545
                                                 utf8_old_name,
 
7546
                                                 1024,
 
7547
                                                 GTK_STOCK_CANCEL,
 
7548
                                                 _("_Rename"));
 
7549
        g_free (utf8_old_name);
 
7550
 
 
7551
        if (utf8_new_name != NULL) {
 
7552
                char *new_name;
 
7553
                char *reason = NULL;
 
7554
 
 
7555
                new_name = g_filename_from_utf8 (utf8_new_name, -1, 0, 0, 0);
 
7556
                g_free (utf8_new_name);
 
7557
 
 
7558
                if (! valid_name (new_name, old_name, &reason)) {
 
7559
                        char      *utf8_name = g_filename_display_name (new_name);
 
7560
                        GtkWidget *dlg;
 
7561
 
 
7562
                        dlg = _gtk_error_dialog_new (GTK_WINDOW (window),
 
7563
                                                     GTK_DIALOG_DESTROY_WITH_PARENT,
 
7564
                                                     NULL,
 
7565
                                                     (renaming_dir ? _("Could not rename the folder") : _("Could not rename the file")),
 
7566
                                                     "%s",
 
7567
                                                     reason);
 
7568
                        gtk_dialog_run (GTK_DIALOG (dlg));
 
7569
                        gtk_widget_destroy (dlg);
 
7570
 
 
7571
                        g_free (reason);
 
7572
                        g_free (utf8_name);
 
7573
                        g_free (new_name);
 
7574
 
 
7575
                        goto retry__rename_selection;
 
7576
                }
 
7577
 
 
7578
                if (name_is_present (window, parent_dir, new_name, &reason)) {
 
7579
                        GtkWidget *dlg;
 
7580
                        int        r;
 
7581
 
 
7582
                        dlg = _gtk_message_dialog_new (GTK_WINDOW (window),
 
7583
                                                       GTK_DIALOG_MODAL,
 
7584
                                                       GTK_STOCK_DIALOG_QUESTION,
 
7585
                                                       (renaming_dir ? _("Could not rename the folder") : _("Could not rename the file")),
 
7586
                                                       reason,
 
7587
                                                       GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
 
7588
                                                       NULL);
 
7589
                        r = gtk_dialog_run (GTK_DIALOG (dlg));
 
7590
                        gtk_widget_destroy (dlg);
 
7591
                        g_free (reason);
 
7592
                        g_free (new_name);
 
7593
                        goto retry__rename_selection;
 
7594
                }
 
7595
 
 
7596
                rename_selection (window,
 
7597
                                  path_to_rename,
 
7598
                                  old_name,
 
7599
                                  new_name,
 
7600
                                  parent_dir,
 
7601
                                  renaming_dir,
 
7602
                                  dir_in_archive,
 
7603
                                  original_path);
 
7604
 
 
7605
                g_free (new_name);
 
7606
        }
 
7607
 
 
7608
        g_free (old_name);
 
7609
        g_free (parent_dir);
 
7610
        g_free (path_to_rename);
 
7611
        g_free (original_path);
 
7612
}
 
7613
 
 
7614
 
 
7615
static void
 
7616
fr_clipboard_get (GtkClipboard     *clipboard,
 
7617
                  GtkSelectionData *selection_data,
 
7618
                  guint             info,
 
7619
                  gpointer          user_data_or_owner)
 
7620
{
 
7621
        FrWindow *window = user_data_or_owner;
 
7622
        char     *data;
 
7623
 
 
7624
        if (gtk_selection_data_get_target (selection_data) != FR_SPECIAL_URI_LIST)
 
7625
                return;
 
7626
 
 
7627
        data = get_selection_data_from_clipboard_data (window, window->priv->copy_data);
 
7628
        gtk_selection_data_set (selection_data,
 
7629
                                gtk_selection_data_get_target (selection_data),
 
7630
                                8,
 
7631
                                (guchar *) data,
 
7632
                                strlen (data));
 
7633
        g_free (data);
 
7634
}
 
7635
 
 
7636
 
 
7637
static void
 
7638
fr_clipboard_clear (GtkClipboard *clipboard,
 
7639
                    gpointer      user_data_or_owner)
 
7640
{
 
7641
        FrWindow *window = user_data_or_owner;
 
7642
 
 
7643
        if (window->priv->copy_data != NULL) {
 
7644
                fr_clipboard_data_unref (window->priv->copy_data);
 
7645
                window->priv->copy_data = NULL;
 
7646
        }
 
7647
}
 
7648
 
 
7649
 
 
7650
GList *
 
7651
fr_window_get_selection (FrWindow   *window,
 
7652
                         gboolean    from_sidebar,
 
7653
                         char      **return_base_dir)
 
7654
{
 
7655
        GList *files;
 
7656
        char  *base_dir;
 
7657
 
 
7658
        if (from_sidebar) {
 
7659
                char *selected_folder;
 
7660
                char *parent_folder;
 
7661
 
 
7662
                files = fr_window_get_folder_tree_selection (window, TRUE, NULL);
 
7663
                selected_folder = fr_window_get_selected_folder_in_tree_view (window);
 
7664
                parent_folder = remove_level_from_path (selected_folder);
 
7665
                if (parent_folder == NULL)
 
7666
                        base_dir = g_strdup ("/");
 
7667
                else if (parent_folder[strlen (parent_folder) - 1] == '/')
 
7668
                        base_dir = g_strdup (parent_folder);
 
7669
                else
 
7670
                        base_dir = g_strconcat (parent_folder, "/", NULL);
 
7671
                g_free (selected_folder);
 
7672
                g_free (parent_folder);
 
7673
        }
 
7674
        else {
 
7675
                files = fr_window_get_file_list_selection (window, TRUE, NULL);
 
7676
                base_dir = g_strdup (fr_window_get_current_location (window));
 
7677
        }
 
7678
 
 
7679
        if (return_base_dir)
 
7680
                *return_base_dir = base_dir;
 
7681
        else
 
7682
                g_free (base_dir);
 
7683
 
 
7684
        return files;
 
7685
}
 
7686
 
 
7687
 
 
7688
static void
 
7689
fr_window_copy_or_cut_selection (FrWindow      *window,
 
7690
                                 FRClipboardOp  op,
 
7691
                                 gboolean       from_sidebar)
 
7692
{
 
7693
        GList        *files;
 
7694
        char         *base_dir;
 
7695
        GtkClipboard *clipboard;
 
7696
 
 
7697
        files = fr_window_get_selection (window, from_sidebar, &base_dir);
 
7698
 
 
7699
        if (window->priv->copy_data != NULL)
 
7700
                fr_clipboard_data_unref (window->priv->copy_data);
 
7701
        window->priv->copy_data = fr_clipboard_data_new ();
 
7702
        window->priv->copy_data->files = files;
 
7703
        window->priv->copy_data->op = op;
 
7704
        window->priv->copy_data->base_dir = base_dir;
 
7705
 
 
7706
        clipboard = gtk_clipboard_get (FR_CLIPBOARD);
 
7707
        gtk_clipboard_set_with_owner (clipboard,
 
7708
                                      clipboard_targets,
 
7709
                                      G_N_ELEMENTS (clipboard_targets),
 
7710
                                      fr_clipboard_get,
 
7711
                                      fr_clipboard_clear,
 
7712
                                      G_OBJECT (window));
 
7713
 
 
7714
        fr_window_update_sensitivity (window);
 
7715
}
 
7716
 
 
7717
 
 
7718
void
 
7719
fr_window_copy_selection (FrWindow *window,
 
7720
                          gboolean  from_sidebar)
 
7721
{
 
7722
        fr_window_copy_or_cut_selection (window, FR_CLIPBOARD_OP_COPY, from_sidebar);
 
7723
}
 
7724
 
 
7725
 
 
7726
void
 
7727
fr_window_cut_selection (FrWindow *window,
 
7728
                         gboolean  from_sidebar)
 
7729
{
 
7730
        fr_window_copy_or_cut_selection (window, FR_CLIPBOARD_OP_CUT, from_sidebar);
 
7731
}
 
7732
 
 
7733
 
 
7734
static gboolean
 
7735
always_fake_load (FrArchive *archive,
 
7736
                  gpointer   data)
 
7737
{
 
7738
        return TRUE;
 
7739
}
 
7740
 
 
7741
 
 
7742
static void
 
7743
add_pasted_files (FrWindow        *window,
 
7744
                  FrClipboardData *data)
 
7745
{
 
7746
        const char *current_dir_relative = data->current_dir + 1;
 
7747
        GList      *scan;
 
7748
        GList      *new_file_list = NULL;
 
7749
 
 
7750
        if (window->priv->password_for_paste != NULL) {
 
7751
                g_free (window->priv->password_for_paste);
 
7752
                window->priv->password_for_paste = NULL;
 
7753
        }
 
7754
 
 
7755
        fr_process_clear (window->archive->process);
 
7756
        for (scan = data->files; scan; scan = scan->next) {
 
7757
                const char *old_name = (char*) scan->data;
 
7758
                char       *new_name = g_build_filename (current_dir_relative, old_name + strlen (data->base_dir) - 1, NULL);
 
7759
 
 
7760
                /* skip folders */
 
7761
 
 
7762
                if ((strcmp (old_name, new_name) != 0)
 
7763
                    && (old_name[strlen (old_name) - 1] != '/'))
 
7764
                {
 
7765
                        fr_process_begin_command (window->archive->process, "mv");
 
7766
                        fr_process_set_working_dir (window->archive->process, data->tmp_dir);
 
7767
                        fr_process_add_arg (window->archive->process, "-f");
 
7768
                        fr_process_add_arg (window->archive->process, old_name);
 
7769
                        fr_process_add_arg (window->archive->process, new_name);
 
7770
                        fr_process_end_command (window->archive->process);
 
7771
                }
 
7772
 
 
7773
                new_file_list = g_list_prepend (new_file_list, new_name);
 
7774
        }
 
7775
 
 
7776
        fr_archive_add (window->archive,
 
7777
                        new_file_list,
 
7778
                        data->tmp_dir,
 
7779
                        NULL,
 
7780
                        FALSE,
 
7781
                        FALSE,
 
7782
                        window->priv->password,
 
7783
                        window->priv->encrypt_header,
 
7784
                        window->priv->compression,
 
7785
                        window->priv->volume_size);
 
7786
 
 
7787
        path_list_free (new_file_list);
 
7788
 
 
7789
        /* remove the tmp dir */
 
7790
 
 
7791
        fr_process_begin_command (window->archive->process, "rm");
 
7792
        fr_process_set_working_dir (window->archive->process, g_get_tmp_dir ());
 
7793
        fr_process_set_sticky (window->archive->process, TRUE);
 
7794
        fr_process_add_arg (window->archive->process, "-rf");
 
7795
        fr_process_add_arg (window->archive->process, data->tmp_dir);
 
7796
        fr_process_end_command (window->archive->process);
 
7797
 
 
7798
        fr_process_start (window->archive->process);
 
7799
}
 
7800
 
 
7801
 
 
7802
static void
 
7803
copy_from_archive_action_performed_cb (FrArchive   *archive,
 
7804
                                       FrAction     action,
 
7805
                                       FrProcError *error,
 
7806
                                       gpointer     data)
 
7807
{
 
7808
        FrWindow *window = data;
 
7809
        gboolean  continue_batch = FALSE;
 
7810
 
 
7811
#ifdef DEBUG
 
7812
        debug (DEBUG_INFO, "%s [DONE] (FR::Window)\n", action_names[action]);
 
7813
#endif
 
7814
 
 
7815
        fr_window_stop_activity_mode (window);
 
7816
        fr_window_pop_message (window);
 
7817
        close_progress_dialog (window, FALSE);
 
7818
 
 
7819
        if (error->type == FR_PROC_ERROR_ASK_PASSWORD) {
 
7820
                dlg_ask_password_for_paste_operation (window);
 
7821
                return;
 
7822
        }
 
7823
 
 
7824
        continue_batch = handle_errors (window, archive, action, error);
 
7825
 
 
7826
        if (error->type != FR_PROC_ERROR_NONE) {
 
7827
                fr_clipboard_data_unref (window->priv->clipboard_data);
 
7828
                window->priv->clipboard_data = NULL;
 
7829
                return;
 
7830
        }
 
7831
 
 
7832
        switch (action) {
 
7833
        case FR_ACTION_LISTING_CONTENT:
 
7834
                fr_process_clear (window->priv->copy_from_archive->process);
 
7835
                fr_archive_extract_to_local (window->priv->copy_from_archive,
 
7836
                                             window->priv->clipboard_data->files,
 
7837
                                             window->priv->clipboard_data->tmp_dir,
 
7838
                                             NULL,
 
7839
                                             FALSE,
 
7840
                                             TRUE,
 
7841
                                             FALSE,
 
7842
                                             window->priv->clipboard_data->archive_password);
 
7843
                fr_process_start (window->priv->copy_from_archive->process);
 
7844
                break;
 
7845
 
 
7846
        case FR_ACTION_EXTRACTING_FILES:
 
7847
                if (window->priv->clipboard_data->op == FR_CLIPBOARD_OP_CUT) {
 
7848
                        fr_process_clear (window->priv->copy_from_archive->process);
 
7849
                        fr_archive_remove (window->priv->copy_from_archive,
 
7850
                                           window->priv->clipboard_data->files,
 
7851
                                           window->priv->compression);
 
7852
                        fr_process_start (window->priv->copy_from_archive->process);
 
7853
                }
 
7854
                else
 
7855
                        add_pasted_files (window, window->priv->clipboard_data);
 
7856
                break;
 
7857
 
 
7858
        case FR_ACTION_DELETING_FILES:
 
7859
                add_pasted_files (window, window->priv->clipboard_data);
 
7860
                break;
 
7861
 
 
7862
        default:
 
7863
                break;
 
7864
        }
 
7865
}
 
7866
 
 
7867
 
 
7868
static void
 
7869
fr_window_paste_from_clipboard_data (FrWindow        *window,
 
7870
                                     FrClipboardData *data)
 
7871
{
 
7872
        const char *current_dir_relative;
 
7873
        GHashTable *created_dirs;
 
7874
        GList      *scan;
 
7875
 
 
7876
        if (window->priv->password_for_paste != NULL)
 
7877
                fr_clipboard_data_set_password (data, window->priv->password_for_paste);
 
7878
 
 
7879
        if (window->priv->clipboard_data != data) {
 
7880
                fr_clipboard_data_unref (window->priv->clipboard_data);
 
7881
                window->priv->clipboard_data = data;
 
7882
        }
 
7883
 
 
7884
        fr_window_set_current_batch_action (window,
 
7885
                                            FR_BATCH_ACTION_PASTE,
 
7886
                                            fr_clipboard_data_ref (data),
 
7887
                                            (GFreeFunc) fr_clipboard_data_unref);
 
7888
 
 
7889
        current_dir_relative = data->current_dir + 1;
 
7890
 
 
7891
        data->tmp_dir = get_temp_work_dir (NULL);
 
7892
        created_dirs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
7893
        for (scan = data->files; scan; scan = scan->next) {
 
7894
                const char *old_name = (char*) scan->data;
 
7895
                char       *new_name = g_build_filename (current_dir_relative, old_name + strlen (data->base_dir) - 1, NULL);
 
7896
                char       *dir = remove_level_from_path (new_name);
 
7897
 
 
7898
                if ((dir != NULL) && (g_hash_table_lookup (created_dirs, dir) == NULL)) {
 
7899
                        char *dir_path;
 
7900
 
 
7901
                        dir_path = g_build_filename (data->tmp_dir, dir, NULL);
 
7902
                        debug (DEBUG_INFO, "mktree %s\n", dir_path);
 
7903
                        make_directory_tree_from_path (dir_path, 0700, NULL);
 
7904
 
 
7905
                        g_free (dir_path);
 
7906
                        g_hash_table_replace (created_dirs, g_strdup (dir), "1");
 
7907
                }
 
7908
 
 
7909
                g_free (dir);
 
7910
                g_free (new_name);
 
7911
        }
 
7912
        g_hash_table_destroy (created_dirs);
 
7913
 
 
7914
        /**/
 
7915
 
 
7916
        if (window->priv->copy_from_archive == NULL) {
 
7917
                window->priv->copy_from_archive = fr_archive_new ();
 
7918
                g_signal_connect (G_OBJECT (window->priv->copy_from_archive),
 
7919
                                  "start",
 
7920
                                  G_CALLBACK (action_started),
 
7921
                                  window);
 
7922
                g_signal_connect (G_OBJECT (window->priv->copy_from_archive),
 
7923
                                  "done",
 
7924
                                  G_CALLBACK (copy_from_archive_action_performed_cb),
 
7925
                                  window);
 
7926
                g_signal_connect (G_OBJECT (window->priv->copy_from_archive),
 
7927
                                  "progress",
 
7928
                                  G_CALLBACK (fr_window_progress_cb),
 
7929
                                  window);
 
7930
                g_signal_connect (G_OBJECT (window->priv->copy_from_archive),
 
7931
                                  "message",
 
7932
                                  G_CALLBACK (fr_window_message_cb),
 
7933
                                  window);
 
7934
                g_signal_connect (G_OBJECT (window->priv->copy_from_archive),
 
7935
                                  "stoppable",
 
7936
                                  G_CALLBACK (fr_window_stoppable_cb),
 
7937
                                  window);
 
7938
                fr_archive_set_fake_load_func (window->priv->copy_from_archive, always_fake_load, NULL);
 
7939
        }
 
7940
        fr_archive_load_local (window->priv->copy_from_archive,
 
7941
                               data->archive_filename,
 
7942
                               data->archive_password);
 
7943
}
 
7944
 
 
7945
 
 
7946
static void
 
7947
fr_window_paste_selection_to (FrWindow   *window,
 
7948
                              const char *current_dir)
 
7949
{
 
7950
        GtkClipboard     *clipboard;
 
7951
        GtkSelectionData *selection_data;
 
7952
        FrClipboardData  *paste_data;
 
7953
 
 
7954
        clipboard = gtk_clipboard_get (FR_CLIPBOARD);
 
7955
        selection_data = gtk_clipboard_wait_for_contents (clipboard, FR_SPECIAL_URI_LIST);
 
7956
        if (selection_data == NULL)
 
7957
                return;
 
7958
 
 
7959
        paste_data = get_clipboard_data_from_selection_data (window, (char*) gtk_selection_data_get_data (selection_data));
 
7960
        paste_data->current_dir = g_strdup (current_dir);
 
7961
        fr_window_paste_from_clipboard_data (window, paste_data);
 
7962
 
 
7963
        gtk_selection_data_free (selection_data);
 
7964
}
 
7965
 
 
7966
 
 
7967
void
 
7968
fr_window_paste_selection (FrWindow *window,
 
7969
                           gboolean  from_sidebar)
 
7970
{
 
7971
        char *utf8_path, *utf8_old_path, *destination;
 
7972
        char *current_dir;
 
7973
 
 
7974
        if (window->priv->list_mode == FR_WINDOW_LIST_MODE_FLAT)
 
7975
                return;
 
7976
 
 
7977
        /**/
 
7978
 
 
7979
        utf8_old_path = g_filename_to_utf8 (fr_window_get_current_location (window), -1, NULL, NULL, NULL);
 
7980
        utf8_path = _gtk_request_dialog_run (GTK_WINDOW (window),
 
7981
                                               (GTK_DIALOG_DESTROY_WITH_PARENT
 
7982
                                                | GTK_DIALOG_MODAL),
 
7983
                                               _("Paste Selection"),
 
7984
                                               _("Destination folder"),
 
7985
                                               utf8_old_path,
 
7986
                                               1024,
 
7987
                                               GTK_STOCK_CANCEL,
 
7988
                                               GTK_STOCK_PASTE);
 
7989
        g_free (utf8_old_path);
 
7990
        if (utf8_path == NULL)
 
7991
                return;
 
7992
 
 
7993
        destination = g_filename_from_utf8 (utf8_path, -1, NULL, NULL, NULL);
 
7994
        g_free (utf8_path);
 
7995
 
 
7996
        if (destination[0] != '/')
 
7997
                current_dir = build_uri (fr_window_get_current_location (window), destination, NULL);
 
7998
        else
 
7999
                current_dir = g_strdup (destination);
 
8000
        g_free (destination);
 
8001
 
 
8002
        fr_window_paste_selection_to (window, current_dir);
 
8003
 
 
8004
        g_free (current_dir);
 
8005
}
 
8006
 
 
8007
 
 
8008
/* -- fr_window_open_files -- */
 
8009
 
 
8010
 
 
8011
void
 
8012
fr_window_open_files_with_command (FrWindow *window,
 
8013
                                   GList    *file_list,
 
8014
                                   char     *command)
 
8015
{
 
8016
        GAppInfo *app;
 
8017
        GError   *error = NULL;
 
8018
 
 
8019
        app = g_app_info_create_from_commandline (command, NULL, G_APP_INFO_CREATE_NONE, &error);
 
8020
        if (error != NULL) {
 
8021
                _gtk_error_dialog_run (GTK_WINDOW (window),
 
8022
                                       _("Could not perform the operation"),
 
8023
                                       "%s",
 
8024
                                       error->message);
 
8025
                g_clear_error (&error);
 
8026
                return;
 
8027
        }
 
8028
 
 
8029
        fr_window_open_files_with_application (window, file_list, app);
 
8030
}
 
8031
 
 
8032
 
 
8033
void
 
8034
fr_window_open_files_with_application (FrWindow *window,
 
8035
                                       GList    *file_list,
 
8036
                                       GAppInfo *app)
 
8037
{
 
8038
        GList               *uris;
 
8039
        GList               *scan;
 
8040
        GdkAppLaunchContext *context;
 
8041
        GError              *error = NULL;
 
8042
 
 
8043
        if (window->priv->activity_ref > 0)
 
8044
                return;
 
8045
 
 
8046
        uris = NULL;
 
8047
        for (scan = file_list; scan; scan = scan->next)
 
8048
                uris = g_list_prepend (uris, g_filename_to_uri (scan->data, NULL, NULL));
 
8049
 
 
8050
        context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (window)));
 
8051
        gdk_app_launch_context_set_screen (context, gtk_widget_get_screen (GTK_WIDGET (window)));
 
8052
        gdk_app_launch_context_set_timestamp (context, 0);
 
8053
 
 
8054
        if (! g_app_info_launch_uris (app, uris, G_APP_LAUNCH_CONTEXT (context), &error)) {
 
8055
                _gtk_error_dialog_run (GTK_WINDOW (window),
 
8056
                                       _("Could not perform the operation"),
 
8057
                                       "%s",
 
8058
                                       error->message);
 
8059
                g_clear_error (&error);
 
8060
        }
 
8061
 
 
8062
        g_object_unref (context);
 
8063
        path_list_free (uris);
 
8064
}
 
8065
 
 
8066
 
 
8067
typedef struct {
 
8068
        FrWindow    *window;
 
8069
        GList       *file_list;
 
8070
        gboolean     ask_application;
 
8071
        CommandData *cdata;
 
8072
} OpenFilesData;
 
8073
 
 
8074
 
 
8075
static OpenFilesData*
 
8076
open_files_data_new (FrWindow *window,
 
8077
                     GList    *file_list,
 
8078
                     gboolean  ask_application)
 
8079
 
 
8080
{
 
8081
        OpenFilesData *odata;
 
8082
        GList         *scan;
 
8083
 
 
8084
        odata = g_new0 (OpenFilesData, 1);
 
8085
        odata->window = window;
 
8086
        odata->file_list = path_list_dup (file_list);
 
8087
        odata->ask_application = ask_application;
 
8088
        odata->cdata = g_new0 (CommandData, 1);
 
8089
        odata->cdata->temp_dir = get_temp_work_dir (NULL);
 
8090
        odata->cdata->file_list = NULL;
 
8091
        for (scan = file_list; scan; scan = scan->next) {
 
8092
                char *file = scan->data;
 
8093
                char *filename;
 
8094
 
 
8095
                filename = g_strconcat (odata->cdata->temp_dir,
 
8096
                                        "/",
 
8097
                                        file,
 
8098
                                        NULL);
 
8099
                odata->cdata->file_list = g_list_prepend (odata->cdata->file_list, filename);
 
8100
        }
 
8101
 
 
8102
        /* Add to CommandList so the cdata is released on exit. */
 
8103
        CommandList = g_list_prepend (CommandList, odata->cdata);
 
8104
 
 
8105
        return odata;
 
8106
}
 
8107
 
 
8108
 
 
8109
static void
 
8110
open_files_data_free (OpenFilesData *odata)
 
8111
{
 
8112
        g_return_if_fail (odata != NULL);
 
8113
 
 
8114
        path_list_free (odata->file_list);
 
8115
        g_free (odata);
 
8116
}
 
8117
 
 
8118
 
 
8119
void
 
8120
fr_window_update_dialog_closed (FrWindow *window)
 
8121
{
 
8122
        window->priv->update_dialog = NULL;
 
8123
}
 
8124
 
 
8125
 
 
8126
gboolean
 
8127
fr_window_update_files (FrWindow *window,
 
8128
                        GList    *file_list)
 
8129
{
 
8130
        GList *scan;
 
8131
 
 
8132
        if (window->priv->activity_ref > 0)
 
8133
                return FALSE;
 
8134
 
 
8135
        if (window->archive->read_only)
 
8136
                return FALSE;
 
8137
 
 
8138
        fr_process_clear (window->archive->process);
 
8139
 
 
8140
        for (scan = file_list; scan; scan = scan->next) {
 
8141
                OpenFile *file = scan->data;
 
8142
                GList    *local_file_list;
 
8143
 
 
8144
                local_file_list = g_list_append (NULL, file->path);
 
8145
                fr_archive_add (window->archive,
 
8146
                                local_file_list,
 
8147
                                file->temp_dir,
 
8148
                                "/",
 
8149
                                FALSE,
 
8150
                                FALSE,
 
8151
                                window->priv->password,
 
8152
                                window->priv->encrypt_header,
 
8153
                                window->priv->compression,
 
8154
                                window->priv->volume_size);
 
8155
                g_list_free (local_file_list);
 
8156
        }
 
8157
 
 
8158
        fr_process_start (window->archive->process);
 
8159
 
 
8160
        return TRUE;
 
8161
}
 
8162
 
 
8163
 
 
8164
static void
 
8165
open_file_modified_cb (GFileMonitor     *monitor,
 
8166
                       GFile            *monitor_file,
 
8167
                       GFile            *other_file,
 
8168
                       GFileMonitorEvent event_type,
 
8169
                       gpointer          user_data)
 
8170
{
 
8171
        FrWindow *window = user_data;
 
8172
        char     *monitor_uri;
 
8173
        OpenFile *file;
 
8174
        GList    *scan;
 
8175
 
 
8176
        if ((event_type != G_FILE_MONITOR_EVENT_CHANGED)
 
8177
            && (event_type != G_FILE_MONITOR_EVENT_CREATED))
 
8178
        {
 
8179
                return;
 
8180
        }
 
8181
 
 
8182
        monitor_uri = g_file_get_uri (monitor_file);
 
8183
        file = NULL;
 
8184
        for (scan = window->priv->open_files; scan; scan = scan->next) {
 
8185
                OpenFile *test = scan->data;
 
8186
                if (uricmp (test->extracted_uri, monitor_uri) == 0) {
 
8187
                        file = test;
 
8188
                        break;
 
8189
                }
 
8190
        }
 
8191
        g_free (monitor_uri);
 
8192
 
 
8193
        g_return_if_fail (file != NULL);
 
8194
 
 
8195
        if (window->priv->update_dialog == NULL)
 
8196
                window->priv->update_dialog = dlg_update (window);
 
8197
        dlg_update_add_file (window->priv->update_dialog, file);
 
8198
}
 
8199
 
 
8200
 
 
8201
static void
 
8202
fr_window_monitor_open_file (FrWindow *window,
 
8203
                             OpenFile *file)
 
8204
{
 
8205
        GFile *f;
 
8206
 
 
8207
        window->priv->open_files = g_list_prepend (window->priv->open_files, file);
 
8208
        f = g_file_new_for_uri (file->extracted_uri);
 
8209
        file->monitor = g_file_monitor_file (f, 0, NULL, NULL);
 
8210
        g_signal_connect (file->monitor,
 
8211
                          "changed",
 
8212
                          G_CALLBACK (open_file_modified_cb),
 
8213
                          window);
 
8214
        g_object_unref (f);
 
8215
}
 
8216
 
 
8217
 
 
8218
static void
 
8219
monitor_extracted_files (OpenFilesData *odata)
 
8220
{
 
8221
        FrWindow *window = odata->window;
 
8222
        GList    *scan1, *scan2;
 
8223
 
 
8224
        for (scan1 = odata->file_list, scan2 = odata->cdata->file_list;
 
8225
             scan1 && scan2;
 
8226
             scan1 = scan1->next, scan2 = scan2->next)
 
8227
        {
 
8228
                OpenFile   *ofile;
 
8229
                const char *file = scan1->data;
 
8230
                const char *extracted_path = scan2->data;
 
8231
 
 
8232
                ofile = open_file_new (file, extracted_path, odata->cdata->temp_dir);
 
8233
                if (ofile != NULL)
 
8234
                        fr_window_monitor_open_file (window, ofile);
 
8235
        }
 
8236
}
 
8237
 
 
8238
 
 
8239
static gboolean
 
8240
fr_window_open_extracted_files (OpenFilesData *odata)
 
8241
{
 
8242
        GList               *file_list = odata->cdata->file_list;
 
8243
        const char          *first_file;
 
8244
        const char          *first_mime_type;
 
8245
        GAppInfo            *app;
 
8246
        GList               *files_to_open = NULL;
 
8247
        GdkAppLaunchContext *context;
 
8248
        gboolean             result;
 
8249
        GError              *error = NULL;
 
8250
 
 
8251
        g_return_val_if_fail (file_list != NULL, FALSE);
 
8252
 
 
8253
        first_file = (char*) file_list->data;
 
8254
        if (first_file == NULL)
 
8255
                return FALSE;
 
8256
 
 
8257
        if (! odata->window->archive->read_only)
 
8258
                monitor_extracted_files (odata);
 
8259
 
 
8260
        if (odata->ask_application) {
 
8261
                dlg_open_with (odata->window, file_list);
 
8262
                return FALSE;
 
8263
        }
 
8264
 
 
8265
        first_mime_type = get_file_mime_type_for_path (first_file, FALSE);
 
8266
        app = g_app_info_get_default_for_type (first_mime_type, FALSE);
 
8267
 
 
8268
        if (app == NULL) {
 
8269
                dlg_open_with (odata->window, file_list);
 
8270
                return FALSE;
 
8271
        }
 
8272
 
 
8273
        files_to_open = g_list_append (files_to_open, g_filename_to_uri (first_file, NULL, NULL));
 
8274
 
 
8275
        if (g_app_info_supports_files (app)) {
 
8276
                GList *scan;
 
8277
 
 
8278
                for (scan = file_list->next; scan; scan = scan->next) {
 
8279
                        const char *path = scan->data;
 
8280
                        const char *mime_type;
 
8281
 
 
8282
                        mime_type = get_file_mime_type_for_path (path, FALSE);
 
8283
                        if (mime_type == NULL)
 
8284
                                continue;
 
8285
 
 
8286
                        if (strcmp (mime_type, first_mime_type) == 0) {
 
8287
                                files_to_open = g_list_append (files_to_open, g_filename_to_uri (path, NULL, NULL));
 
8288
                        }
 
8289
                        else {
 
8290
                                GAppInfo *app2;
 
8291
 
 
8292
                                app2 = g_app_info_get_default_for_type (mime_type, FALSE);
 
8293
                                if (g_app_info_equal (app, app2))
 
8294
                                        files_to_open = g_list_append (files_to_open, g_filename_to_uri (path, NULL, NULL));
 
8295
                                g_object_unref (app2);
 
8296
                        }
 
8297
                }
 
8298
        }
 
8299
 
 
8300
        context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (odata->window)));
 
8301
        gdk_app_launch_context_set_screen (context, gtk_widget_get_screen (GTK_WIDGET (odata->window)));
 
8302
        gdk_app_launch_context_set_timestamp (context, 0);
 
8303
        result = g_app_info_launch_uris (app, files_to_open, G_APP_LAUNCH_CONTEXT (context), &error);
 
8304
        if (! result) {
 
8305
                _gtk_error_dialog_run (GTK_WINDOW (odata->window),
 
8306
                                       _("Could not perform the operation"),
 
8307
                                       "%s",
 
8308
                                       error->message);
 
8309
                g_clear_error (&error);
 
8310
        }
 
8311
 
 
8312
        g_object_unref (context);
 
8313
        g_object_unref (app);
 
8314
        path_list_free (files_to_open);
 
8315
 
 
8316
        return result;
 
8317
}
 
8318
 
 
8319
 
 
8320
static void
 
8321
fr_window_open_files__extract_done_cb (FrArchive   *archive,
 
8322
                                       FrAction     action,
 
8323
                                       FrProcError *error,
 
8324
                                       gpointer     callback_data)
 
8325
{
 
8326
        OpenFilesData *odata = callback_data;
 
8327
 
 
8328
        g_signal_handlers_disconnect_matched (G_OBJECT (archive),
 
8329
                                              G_SIGNAL_MATCH_DATA,
 
8330
                                              0,
 
8331
                                              0, NULL,
 
8332
                                              0,
 
8333
                                              odata);
 
8334
 
 
8335
        if (error->type == FR_PROC_ERROR_NONE)
 
8336
                fr_window_open_extracted_files (odata);
 
8337
}
 
8338
 
 
8339
 
 
8340
void
 
8341
fr_window_open_files (FrWindow *window,
 
8342
                      GList    *file_list,
 
8343
                      gboolean  ask_application)
 
8344
{
 
8345
        OpenFilesData *odata;
 
8346
 
 
8347
        if (window->priv->activity_ref > 0)
 
8348
                return;
 
8349
 
 
8350
        odata = open_files_data_new (window, file_list, ask_application);
 
8351
        fr_window_set_current_batch_action (window,
 
8352
                                            FR_BATCH_ACTION_OPEN_FILES,
 
8353
                                            odata,
 
8354
                                            (GFreeFunc) open_files_data_free);
 
8355
 
 
8356
        g_signal_connect (G_OBJECT (window->archive),
 
8357
                          "done",
 
8358
                          G_CALLBACK (fr_window_open_files__extract_done_cb),
 
8359
                          odata);
 
8360
 
 
8361
        fr_process_clear (window->archive->process);
 
8362
        fr_archive_extract_to_local (window->archive,
 
8363
                                     odata->file_list,
 
8364
                                     odata->cdata->temp_dir,
 
8365
                                     NULL,
 
8366
                                     FALSE,
 
8367
                                     TRUE,
 
8368
                                     FALSE,
 
8369
                                     window->priv->password);
 
8370
        fr_process_start (window->archive->process);
 
8371
}
 
8372
 
 
8373
 
 
8374
/**/
 
8375
 
 
8376
 
 
8377
static char*
 
8378
get_default_dir (const char *dir)
 
8379
{
 
8380
        if (! is_temp_dir (dir))
 
8381
                return g_strdup (dir);
 
8382
        else
 
8383
                return NULL;
 
8384
}
 
8385
 
 
8386
 
 
8387
void
 
8388
fr_window_set_open_default_dir (FrWindow   *window,
 
8389
                                const char *default_dir)
 
8390
{
 
8391
        g_return_if_fail (window != NULL);
 
8392
        g_return_if_fail (default_dir != NULL);
 
8393
 
 
8394
        if (window->priv->open_default_dir != NULL)
 
8395
                g_free (window->priv->open_default_dir);
 
8396
        window->priv->open_default_dir = get_default_dir (default_dir);
 
8397
}
 
8398
 
 
8399
 
 
8400
const char *
 
8401
fr_window_get_open_default_dir (FrWindow *window)
 
8402
{
 
8403
        if (window->priv->open_default_dir == NULL)
 
8404
                return get_home_uri ();
 
8405
        else
 
8406
                return  window->priv->open_default_dir;
 
8407
}
 
8408
 
 
8409
 
 
8410
void
 
8411
fr_window_set_add_default_dir (FrWindow   *window,
 
8412
                               const char *default_dir)
 
8413
{
 
8414
        g_return_if_fail (window != NULL);
 
8415
        g_return_if_fail (default_dir != NULL);
 
8416
 
 
8417
        if (window->priv->add_default_dir != NULL)
 
8418
                g_free (window->priv->add_default_dir);
 
8419
        window->priv->add_default_dir = get_default_dir (default_dir);
 
8420
}
 
8421
 
 
8422
 
 
8423
const char *
 
8424
fr_window_get_add_default_dir (FrWindow *window)
 
8425
{
 
8426
        if (window->priv->add_default_dir == NULL)
 
8427
                return get_home_uri ();
 
8428
        else
 
8429
                return  window->priv->add_default_dir;
 
8430
}
 
8431
 
 
8432
 
 
8433
void
 
8434
fr_window_set_extract_default_dir (FrWindow   *window,
 
8435
                                   const char *default_dir,
 
8436
                                   gboolean    freeze)
 
8437
{
 
8438
        g_return_if_fail (window != NULL);
 
8439
        g_return_if_fail (default_dir != NULL);
 
8440
 
 
8441
        /* do not change this dir while it's used by the non-interactive
 
8442
         * extraction operation. */
 
8443
        if (window->priv->extract_interact_use_default_dir)
 
8444
                return;
 
8445
 
 
8446
        window->priv->extract_interact_use_default_dir = freeze;
 
8447
 
 
8448
        if (window->priv->extract_default_dir != NULL)
 
8449
                g_free (window->priv->extract_default_dir);
 
8450
        window->priv->extract_default_dir = get_default_dir (default_dir);
 
8451
}
 
8452
 
 
8453
 
 
8454
const char *
 
8455
fr_window_get_extract_default_dir (FrWindow *window)
 
8456
{
 
8457
        if (window->priv->extract_default_dir == NULL)
 
8458
                return get_home_uri ();
 
8459
        else
 
8460
                return  window->priv->extract_default_dir;
 
8461
}
 
8462
 
 
8463
 
 
8464
void
 
8465
fr_window_set_default_dir (FrWindow   *window,
 
8466
                           const char *default_dir,
 
8467
                           gboolean    freeze)
 
8468
{
 
8469
        g_return_if_fail (window != NULL);
 
8470
        g_return_if_fail (default_dir != NULL);
 
8471
 
 
8472
        window->priv->freeze_default_dir = freeze;
 
8473
 
 
8474
        fr_window_set_open_default_dir (window, default_dir);
 
8475
        fr_window_set_add_default_dir (window, default_dir);
 
8476
        fr_window_set_extract_default_dir (window, default_dir, FALSE);
 
8477
}
 
8478
 
 
8479
 
 
8480
void
 
8481
fr_window_update_columns_visibility (FrWindow *window)
 
8482
{
 
8483
        GtkTreeView       *tree_view = GTK_TREE_VIEW (window->priv->list_view);
 
8484
        GtkTreeViewColumn *column;
 
8485
 
 
8486
        column = gtk_tree_view_get_column (tree_view, 1);
 
8487
        gtk_tree_view_column_set_visible (column, g_settings_get_boolean (window->priv->settings_listing, PREF_LISTING_SHOW_SIZE));
 
8488
 
 
8489
        column = gtk_tree_view_get_column (tree_view, 2);
 
8490
        gtk_tree_view_column_set_visible (column, g_settings_get_boolean (window->priv->settings_listing, PREF_LISTING_SHOW_TYPE));
 
8491
 
 
8492
        column = gtk_tree_view_get_column (tree_view, 3);
 
8493
        gtk_tree_view_column_set_visible (column, g_settings_get_boolean (window->priv->settings_listing, PREF_LISTING_SHOW_TIME));
 
8494
 
 
8495
        column = gtk_tree_view_get_column (tree_view, 4);
 
8496
        gtk_tree_view_column_set_visible (column, g_settings_get_boolean (window->priv->settings_listing, PREF_LISTING_SHOW_PATH));
 
8497
}
 
8498
 
 
8499
 
 
8500
void
 
8501
fr_window_set_toolbar_visibility (FrWindow *window,
 
8502
                                  gboolean  visible)
 
8503
{
 
8504
        g_return_if_fail (window != NULL);
 
8505
 
 
8506
        if (visible)
 
8507
                gtk_widget_show (window->priv->toolbar);
 
8508
        else
 
8509
                gtk_widget_hide (window->priv->toolbar);
 
8510
 
 
8511
        set_active (window, "ViewToolbar", visible);
 
8512
}
 
8513
 
 
8514
 
 
8515
void
 
8516
fr_window_set_statusbar_visibility  (FrWindow *window,
 
8517
                                     gboolean  visible)
 
8518
{
 
8519
        g_return_if_fail (window != NULL);
 
8520
 
 
8521
        if (visible)
 
8522
                gtk_widget_show (window->priv->statusbar);
 
8523
        else
 
8524
                gtk_widget_hide (window->priv->statusbar);
 
8525
 
 
8526
        set_active (window, "ViewStatusbar", visible);
 
8527
}
 
8528
 
 
8529
 
 
8530
void
 
8531
fr_window_set_folders_visibility (FrWindow   *window,
 
8532
                                  gboolean    value)
 
8533
{
 
8534
        g_return_if_fail (window != NULL);
 
8535
 
 
8536
        window->priv->view_folders = value;
 
8537
        fr_window_update_dir_tree (window);
 
8538
 
 
8539
        set_active (window, "ViewFolders", window->priv->view_folders);
 
8540
}
 
8541
 
 
8542
 
 
8543
void
 
8544
fr_window_use_progress_dialog (FrWindow *window,
 
8545
                               gboolean  value)
 
8546
{
 
8547
        window->priv->use_progress_dialog = value;
 
8548
}
 
8549
 
 
8550
 
 
8551
/* -- batch mode procedures -- */
 
8552
 
 
8553
 
 
8554
static void fr_window_exec_current_batch_action (FrWindow *window);
 
8555
 
 
8556
 
 
8557
static void
 
8558
fr_window_exec_batch_action (FrWindow      *window,
 
8559
                             FRBatchAction *action)
 
8560
{
 
8561
        ExtractData   *edata;
 
8562
        RenameData    *rdata;
 
8563
        OpenFilesData *odata;
 
8564
        SaveAsData    *sdata;
 
8565
 
 
8566
        switch (action->type) {
 
8567
        case FR_BATCH_ACTION_LOAD:
 
8568
                debug (DEBUG_INFO, "[BATCH] LOAD\n");
 
8569
 
 
8570
                if (! uri_exists ((char*) action->data))
 
8571
                        fr_window_archive_new (window, (char*) action->data);
 
8572
                else
 
8573
                        fr_window_archive_open (window, (char*) action->data, GTK_WINDOW (window));
 
8574
                break;
 
8575
 
 
8576
        case FR_BATCH_ACTION_ADD:
 
8577
                debug (DEBUG_INFO, "[BATCH] ADD\n");
 
8578
 
 
8579
                fr_window_archive_add_dropped_items (window, (GList*) action->data, FALSE);
 
8580
                break;
 
8581
 
 
8582
        case FR_BATCH_ACTION_OPEN:
 
8583
                debug (DEBUG_INFO, "[BATCH] OPEN\n");
 
8584
 
 
8585
                fr_window_push_message (window, _("Add files to an archive"));
 
8586
                dlg_batch_add_files (window, (GList*) action->data);
 
8587
                break;
 
8588
 
 
8589
        case FR_BATCH_ACTION_EXTRACT:
 
8590
                debug (DEBUG_INFO, "[BATCH] EXTRACT\n");
 
8591
 
 
8592
                edata = action->data;
 
8593
                fr_window_archive_extract (window,
 
8594
                                           edata->file_list,
 
8595
                                           edata->extract_to_dir,
 
8596
                                           edata->base_dir,
 
8597
                                           edata->skip_older,
 
8598
                                           edata->overwrite,
 
8599
                                           edata->junk_paths,
 
8600
                                           TRUE);
 
8601
                break;
 
8602
 
 
8603
        case FR_BATCH_ACTION_EXTRACT_HERE:
 
8604
                debug (DEBUG_INFO, "[BATCH] EXTRACT HERE\n");
 
8605
 
 
8606
                edata = action->data;
 
8607
                fr_window_archive_extract_here (window,
 
8608
                                                FALSE,
 
8609
                                                TRUE,
 
8610
                                                FALSE);
 
8611
                break;
 
8612
 
 
8613
        case FR_BATCH_ACTION_EXTRACT_INTERACT:
 
8614
                debug (DEBUG_INFO, "[BATCH] EXTRACT_INTERACT\n");
 
8615
 
 
8616
                if (window->priv->extract_interact_use_default_dir
 
8617
                    && (window->priv->extract_default_dir != NULL))
 
8618
                {
 
8619
                        fr_window_archive_extract (window,
 
8620
                                                   NULL,
 
8621
                                                   window->priv->extract_default_dir,
 
8622
                                                   NULL,
 
8623
                                                   FALSE,
 
8624
                                                   TRUE,
 
8625
                                                   FALSE,
 
8626
                                                   TRUE);
 
8627
                }
 
8628
                else {
 
8629
                        fr_window_push_message (window, _("Extract archive"));
 
8630
                        dlg_extract (NULL, window);
 
8631
                }
 
8632
                break;
 
8633
 
 
8634
        case FR_BATCH_ACTION_RENAME:
 
8635
                debug (DEBUG_INFO, "[BATCH] RENAME\n");
 
8636
 
 
8637
                rdata = action->data;
 
8638
                rename_selection (window,
 
8639
                                  rdata->path_to_rename,
 
8640
                                  rdata->old_name,
 
8641
                                  rdata->new_name,
 
8642
                                  rdata->current_dir,
 
8643
                                  rdata->is_dir,
 
8644
                                  rdata->dir_in_archive,
 
8645
                                  rdata->original_path);
 
8646
                break;
 
8647
 
 
8648
        case FR_BATCH_ACTION_PASTE:
 
8649
                debug (DEBUG_INFO, "[BATCH] PASTE\n");
 
8650
 
 
8651
                fr_window_paste_from_clipboard_data (window, (FrClipboardData*) action->data);
 
8652
                break;
 
8653
 
 
8654
        case FR_BATCH_ACTION_OPEN_FILES:
 
8655
                debug (DEBUG_INFO, "[BATCH] OPEN FILES\n");
 
8656
 
 
8657
                odata = action->data;
 
8658
                fr_window_open_files (window, odata->file_list, odata->ask_application);
 
8659
                break;
 
8660
 
 
8661
        case FR_BATCH_ACTION_SAVE_AS:
 
8662
                debug (DEBUG_INFO, "[BATCH] SAVE_AS\n");
 
8663
 
 
8664
                sdata = action->data;
 
8665
                fr_window_archive_save_as (window,
 
8666
                                           sdata->uri,
 
8667
                                           sdata->password,
 
8668
                                           sdata->encrypt_header,
 
8669
                                           sdata->volume_size);
 
8670
                break;
 
8671
 
 
8672
        case FR_BATCH_ACTION_TEST:
 
8673
                debug (DEBUG_INFO, "[BATCH] TEST\n");
 
8674
 
 
8675
                fr_window_archive_test (window);
 
8676
                break;
 
8677
 
 
8678
        case FR_BATCH_ACTION_CLOSE:
 
8679
                debug (DEBUG_INFO, "[BATCH] CLOSE\n");
 
8680
 
 
8681
                fr_window_archive_close (window);
 
8682
                fr_window_exec_next_batch_action (window);
 
8683
                break;
 
8684
 
 
8685
        case FR_BATCH_ACTION_QUIT:
 
8686
                debug (DEBUG_INFO, "[BATCH] QUIT\n");
 
8687
 
 
8688
                g_signal_emit (window,
 
8689
                               fr_window_signals[READY],
 
8690
                               0,
 
8691
                               NULL);
 
8692
 
 
8693
                if ((window->priv->progress_dialog != NULL) && (gtk_widget_get_parent (window->priv->progress_dialog) != GTK_WIDGET (window)))
 
8694
                        gtk_widget_destroy (window->priv->progress_dialog);
 
8695
                gtk_widget_destroy (GTK_WIDGET (window));
 
8696
                break;
 
8697
 
 
8698
        default:
 
8699
                break;
 
8700
        }
 
8701
}
 
8702
 
 
8703
 
 
8704
void
 
8705
fr_window_reset_current_batch_action (FrWindow *window)
 
8706
{
 
8707
        FRBatchAction *adata = &window->priv->current_batch_action;
 
8708
 
 
8709
        if ((adata->data != NULL) && (adata->free_func != NULL))
 
8710
                (*adata->free_func) (adata->data);
 
8711
        adata->type = FR_BATCH_ACTION_NONE;
 
8712
        adata->data = NULL;
 
8713
        adata->free_func = NULL;
 
8714
}
 
8715
 
 
8716
 
 
8717
void
 
8718
fr_window_set_current_batch_action (FrWindow          *window,
 
8719
                                    FrBatchActionType  action,
 
8720
                                    void              *data,
 
8721
                                    GFreeFunc          free_func)
 
8722
{
 
8723
        FRBatchAction *adata = &window->priv->current_batch_action;
 
8724
 
 
8725
        fr_window_reset_current_batch_action (window);
 
8726
 
 
8727
        adata->type = action;
 
8728
        adata->data = data;
 
8729
        adata->free_func = free_func;
 
8730
}
 
8731
 
 
8732
 
 
8733
void
 
8734
fr_window_restart_current_batch_action (FrWindow *window)
 
8735
{
 
8736
        fr_window_exec_batch_action (window, &window->priv->current_batch_action);
 
8737
}
 
8738
 
 
8739
 
 
8740
void
 
8741
fr_window_append_batch_action (FrWindow          *window,
 
8742
                               FrBatchActionType  action,
 
8743
                               void              *data,
 
8744
                               GFreeFunc          free_func)
 
8745
{
 
8746
        FRBatchAction *a_desc;
 
8747
 
 
8748
        g_return_if_fail (window != NULL);
 
8749
 
 
8750
        a_desc = g_new0 (FRBatchAction, 1);
 
8751
        a_desc->type = action;
 
8752
        a_desc->data = data;
 
8753
        a_desc->free_func = free_func;
 
8754
 
 
8755
        window->priv->batch_action_list = g_list_append (window->priv->batch_action_list, a_desc);
 
8756
}
 
8757
 
 
8758
 
 
8759
static void
 
8760
fr_window_exec_current_batch_action (FrWindow *window)
 
8761
{
 
8762
        FRBatchAction *action;
 
8763
 
 
8764
        if (window->priv->batch_action == NULL) {
 
8765
                window->priv->batch_mode = FALSE;
 
8766
                return;
 
8767
        }
 
8768
        action = (FRBatchAction *) window->priv->batch_action->data;
 
8769
        fr_window_exec_batch_action (window, action);
 
8770
}
 
8771
 
 
8772
 
 
8773
static void
 
8774
fr_window_exec_next_batch_action (FrWindow *window)
 
8775
{
 
8776
        if (window->priv->batch_action != NULL)
 
8777
                window->priv->batch_action = g_list_next (window->priv->batch_action);
 
8778
        else
 
8779
                window->priv->batch_action = window->priv->batch_action_list;
 
8780
        fr_window_exec_current_batch_action (window);
 
8781
}
 
8782
 
 
8783
 
 
8784
void
 
8785
fr_window_start_batch (FrWindow *window)
 
8786
{
 
8787
        g_return_if_fail (window != NULL);
 
8788
 
 
8789
        if (window->priv->batch_mode)
 
8790
                return;
 
8791
 
 
8792
        if (window->priv->batch_action_list == NULL)
 
8793
                return;
 
8794
 
 
8795
        window->priv->batch_mode = TRUE;
 
8796
        window->priv->batch_action = window->priv->batch_action_list;
 
8797
        window->archive->can_create_compressed_file = window->priv->batch_adding_one_file;
 
8798
 
 
8799
        fr_window_exec_current_batch_action (window);
 
8800
}
 
8801
 
 
8802
 
 
8803
void
 
8804
fr_window_stop_batch (FrWindow *window)
 
8805
{
 
8806
        if (! window->priv->non_interactive)
 
8807
                return;
 
8808
 
 
8809
        window->priv->extract_interact_use_default_dir = FALSE;
 
8810
        window->archive->can_create_compressed_file = FALSE;
 
8811
 
 
8812
        if (window->priv->batch_mode) {
 
8813
                if (! window->priv->showing_error_dialog) {
 
8814
                        gtk_widget_destroy (GTK_WIDGET (window));
 
8815
                        return;
 
8816
                }
 
8817
        }
 
8818
        else {
 
8819
                gtk_window_present (GTK_WINDOW (window));
 
8820
                fr_window_archive_close (window);
 
8821
        }
 
8822
 
 
8823
        window->priv->batch_mode = FALSE;
 
8824
}
 
8825
 
 
8826
 
 
8827
void
 
8828
fr_window_resume_batch (FrWindow *window)
 
8829
{
 
8830
        fr_window_exec_current_batch_action (window);
 
8831
}
 
8832
 
 
8833
 
 
8834
gboolean
 
8835
fr_window_is_batch_mode (FrWindow *window)
 
8836
{
 
8837
        return window->priv->batch_mode;
 
8838
}
 
8839
 
 
8840
 
 
8841
void
 
8842
fr_window_new_batch (FrWindow *window)
 
8843
{
 
8844
        fr_window_free_batch_data (window);
 
8845
        window->priv->non_interactive = TRUE;
 
8846
}
 
8847
 
 
8848
 
 
8849
void
 
8850
fr_window_set_batch__extract_here (FrWindow   *window,
 
8851
                                   const char *filename)
 
8852
{
 
8853
        g_return_if_fail (window != NULL);
 
8854
        g_return_if_fail (filename != NULL);
 
8855
 
 
8856
        fr_window_append_batch_action (window,
 
8857
                                       FR_BATCH_ACTION_LOAD,
 
8858
                                       g_strdup (filename),
 
8859
                                       (GFreeFunc) g_free);
 
8860
        fr_window_append_batch_action (window,
 
8861
                                       FR_BATCH_ACTION_EXTRACT_HERE,
 
8862
                                       extract_to_data_new (NULL),
 
8863
                                       (GFreeFunc) extract_data_free);
 
8864
        fr_window_append_batch_action (window,
 
8865
                                       FR_BATCH_ACTION_CLOSE,
 
8866
                                       NULL,
 
8867
                                       NULL);
 
8868
}
 
8869
 
 
8870
 
 
8871
void
 
8872
fr_window_set_batch__extract (FrWindow   *window,
 
8873
                              const char *filename,
 
8874
                              const char *dest_dir)
 
8875
{
 
8876
        g_return_if_fail (window != NULL);
 
8877
        g_return_if_fail (filename != NULL);
 
8878
 
 
8879
        fr_window_append_batch_action (window,
 
8880
                                       FR_BATCH_ACTION_LOAD,
 
8881
                                       g_strdup (filename),
 
8882
                                       (GFreeFunc) g_free);
 
8883
        if (dest_dir != NULL)
 
8884
                fr_window_append_batch_action (window,
 
8885
                                               FR_BATCH_ACTION_EXTRACT,
 
8886
                                               extract_to_data_new (dest_dir),
 
8887
                                               (GFreeFunc) extract_data_free);
 
8888
        else
 
8889
                fr_window_append_batch_action (window,
 
8890
                                               FR_BATCH_ACTION_EXTRACT_INTERACT,
 
8891
                                               NULL,
 
8892
                                               NULL);
 
8893
        fr_window_append_batch_action (window,
 
8894
                                       FR_BATCH_ACTION_CLOSE,
 
8895
                                       NULL,
 
8896
                                       NULL);
 
8897
}
 
8898
 
 
8899
 
 
8900
void
 
8901
fr_window_set_batch__add (FrWindow   *window,
 
8902
                          const char *archive,
 
8903
                          GList      *file_list)
 
8904
{
 
8905
        window->priv->batch_adding_one_file = (file_list->next == NULL) && (uri_is_file (file_list->data));
 
8906
 
 
8907
        if (archive != NULL)
 
8908
                fr_window_append_batch_action (window,
 
8909
                                               FR_BATCH_ACTION_LOAD,
 
8910
                                               g_strdup (archive),
 
8911
                                               (GFreeFunc) g_free);
 
8912
        else
 
8913
                fr_window_append_batch_action (window,
 
8914
                                               FR_BATCH_ACTION_OPEN,
 
8915
                                               file_list,
 
8916
                                               NULL);
 
8917
        fr_window_append_batch_action (window,
 
8918
                                       FR_BATCH_ACTION_ADD,
 
8919
                                       file_list,
 
8920
                                       NULL);
 
8921
        fr_window_append_batch_action (window,
 
8922
                                       FR_BATCH_ACTION_CLOSE,
 
8923
                                       NULL,
 
8924
                                       NULL);
 
8925
}