Statistics
| Revision:

root / src / filesel.c @ 3070

History | View | Annotate | Download (8.8 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2012 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19
20
#include <glib.h>
21
#include <glib/gi18n.h>
22
#include <gdk/gdkkeysyms.h>
23
#include <gtk/gtkversion.h>
24
#include <gtk/gtkfilechooserdialog.h>
25
#include <gtk/gtkexpander.h>
26
#include <gtk/gtkstock.h>
27
28
#include "main.h"
29
#include "filesel.h"
30
#include "manage_window.h"
31
#include "alertpanel.h"
32
#include "utils.h"
33
#include "prefs_common.h"
34
#include "inc.h"
35
36
37
static GSList *filesel_select_file_full        (const gchar                *title,
38
                                         const gchar                *file,
39
                                         GtkFileChooserAction         action,
40
                                         gboolean                 multiple);
41
42
static GtkWidget *filesel_create        (const gchar                *title,
43
                                         GtkFileChooserAction         action);
44
45
static void filesel_save_expander_set_expanded           (GtkWidget        *dialog,
46
                                                    gboolean         expanded);
47
static gboolean filesel_save_expander_get_expanded (GtkWidget        *dialog);
48
49
#if GTK_CHECK_VERSION(2, 8, 0)
50
static GtkFileChooserConfirmation filesel_confirm_overwrite_cb
51
                                        (GtkFileChooser                *chooser,
52
                                         gpointer                 data);
53
#endif
54
55
56
gchar *filesel_select_file(const gchar *title, const gchar *file,
57
                           GtkFileChooserAction action)
58
{
59
        GSList *list;
60
        gchar *selected = NULL;
61
62
        list = filesel_select_file_full(title, file, action, FALSE);
63
        if (list) {
64
                selected = (gchar *)list->data;
65
                slist_free_strings(list->next);
66
        }
67
        g_slist_free(list);
68
69
        return selected;
70
}
71
72
GSList *filesel_select_files(const gchar *title, const gchar *file,
73
                             GtkFileChooserAction action)
74
{
75
        return filesel_select_file_full(title, file, action, TRUE);
76
}
77
78
static void filesel_change_dir_for_action(GtkFileChooserAction action)
79
{
80
        const gchar *cwd = NULL;
81
82
        switch (action) {
83
        case GTK_FILE_CHOOSER_ACTION_OPEN:
84
                if (prefs_common.prev_open_dir &&
85
                    is_dir_exist(prefs_common.prev_open_dir))
86
                        cwd = prefs_common.prev_open_dir;
87
                else {
88
                        g_free(prefs_common.prev_open_dir);
89
                        prefs_common.prev_open_dir = NULL;
90
                }
91
                break;
92
        case GTK_FILE_CHOOSER_ACTION_SAVE:
93
                if (prefs_common.prev_save_dir &&
94
                    is_dir_exist(prefs_common.prev_save_dir))
95
                        cwd = prefs_common.prev_save_dir;
96
                else {
97
                        g_free(prefs_common.prev_save_dir);
98
                        prefs_common.prev_save_dir = NULL;
99
                }
100
                break;
101
        case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
102
                if (prefs_common.prev_folder_dir &&
103
                    is_dir_exist(prefs_common.prev_folder_dir))
104
                        cwd = prefs_common.prev_folder_dir;
105
                else {
106
                        g_free(prefs_common.prev_folder_dir);
107
                        prefs_common.prev_folder_dir = NULL;
108
                }
109
                break;
110
        default:
111
                break;
112
        }
113
114
        if (cwd)
115
                change_dir(cwd);
116
        else
117
                change_dir(get_document_dir());
118
}
119
120
static void filesel_save_dir_for_action(GtkFileChooserAction action,
121
                                        const gchar *cwd)
122
{
123
        switch (action) {
124
        case GTK_FILE_CHOOSER_ACTION_OPEN:
125
                g_free(prefs_common.prev_open_dir);
126
                prefs_common.prev_open_dir = g_strdup(cwd);
127
                break;
128
        case GTK_FILE_CHOOSER_ACTION_SAVE:
129
                g_free(prefs_common.prev_save_dir);
130
                prefs_common.prev_save_dir = g_strdup(cwd);
131
                break;
132
        case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
133
                g_free(prefs_common.prev_folder_dir);
134
                prefs_common.prev_folder_dir = g_strdup(cwd);
135
                break;
136
        default:
137
                break;
138
        }
139
}
140
141
static GSList *filesel_select_file_full(const gchar *title, const gchar *file,
142
                                        GtkFileChooserAction action,
143
                                        gboolean multiple)
144
{
145
        gchar *cwd;
146
        GtkWidget *dialog;
147
        gchar *prev_dir;
148
        static gboolean save_expander_expanded = FALSE;
149
        GSList *list = NULL;
150
151
        prev_dir = g_get_current_dir();
152
153
        filesel_change_dir_for_action(action);
154
155
        dialog = filesel_create(title, action);
156
157
        manage_window_set_transient(GTK_WINDOW(dialog));
158
159
        if (file)
160
                gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
161
                                                  file);
162
163
        gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog),
164
                                             multiple);
165
166
        if (action == GTK_FILE_CHOOSER_ACTION_SAVE && save_expander_expanded) {
167
                filesel_save_expander_set_expanded
168
                        (dialog, save_expander_expanded);
169
        }
170
171
#if GTK_CHECK_VERSION(2, 8, 0)
172
        if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
173
                gtk_file_chooser_set_do_overwrite_confirmation
174
                        (GTK_FILE_CHOOSER(dialog), TRUE);
175
                g_signal_connect(GTK_FILE_CHOOSER(dialog), "confirm-overwrite",
176
                                 G_CALLBACK(filesel_confirm_overwrite_cb),
177
                                 NULL);
178
        }
179
#endif
180
181
        gtk_widget_show(dialog);
182
183
        change_dir(prev_dir);
184
        g_free(prev_dir);
185
186
        inc_lock();
187
188
        if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
189
                list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
190
                if (list) {
191
                        cwd = gtk_file_chooser_get_current_folder
192
                                (GTK_FILE_CHOOSER(dialog));
193
                        if (cwd) {
194
                                filesel_save_dir_for_action(action, cwd);
195
                                g_free(cwd);
196
                        }
197
                }
198
        }
199
200
        inc_unlock();
201
202
        if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
203
                save_expander_expanded =
204
                        filesel_save_expander_get_expanded(dialog);
205
206
        manage_window_focus_out(dialog, NULL, NULL);
207
        gtk_widget_destroy(dialog);
208
209
        return list;
210
}
211
212
gchar *filesel_save_as(const gchar *file)
213
{
214
        gchar *filename;
215
216
        filename = filesel_select_file(_("Save as"), file,
217
                                       GTK_FILE_CHOOSER_ACTION_SAVE);
218
219
#if !GTK_CHECK_VERSION(2, 8, 0)
220
        if (filename && is_file_exist(filename)) {
221
                AlertValue aval;
222
223
                aval = alertpanel(_("Overwrite existing file"),
224
                                  _("The file already exists. Do you want to replace it?"),
225
                                  GTK_STOCK_YES, GTK_STOCK_NO, NULL);
226
                if (G_ALERTDEFAULT != aval) {
227
                        g_free(filename);
228
                        filename = NULL;
229
                }
230
        }
231
#endif
232
233
        return filename;
234
}
235
236
gchar *filesel_select_dir(const gchar *dir)
237
{
238
        GSList *list;
239
        gchar *selected = NULL;
240
241
        list = filesel_select_file_full(_("Select folder"), dir,
242
                                        GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
243
                                        FALSE);
244
        if (list) {
245
                selected = (gchar *)list->data;
246
                slist_free_strings(list->next);
247
        }
248
        g_slist_free(list);
249
250
        return selected;
251
}
252
253
static GtkWidget *filesel_create(const gchar *title,
254
                                 GtkFileChooserAction action)
255
{
256
        GtkWidget *dialog;
257
258
        if (prefs_common.comply_gnome_hig)
259
                dialog = gtk_file_chooser_dialog_new
260
                        (title, NULL, action,
261
                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
262
                         (action == GTK_FILE_CHOOSER_ACTION_SAVE ||
263
                          action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
264
                         ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
265
                         NULL);
266
        else
267
                dialog = gtk_file_chooser_dialog_new
268
                        (title, NULL, action,
269
                         (action == GTK_FILE_CHOOSER_ACTION_SAVE ||
270
                          action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
271
                         ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
272
                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
273
                         NULL);
274
        gtk_window_set_position(GTK_WINDOW(dialog),
275
                                GTK_WIN_POS_CENTER_ON_PARENT);
276
        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
277
        gtk_window_set_wmclass
278
                (GTK_WINDOW(dialog), "file_selection", "Sylpheed");
279
        gtk_dialog_set_default_response
280
                (GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
281
282
        MANAGE_WINDOW_SIGNALS_CONNECT(dialog);
283
284
        return dialog;
285
}
286
287
static void container_foreach_cb(GtkWidget *widget, gpointer data)
288
{
289
        GtkWidget **expander = (GtkWidget **)data;
290
291
        if (*expander == NULL) {
292
                if (GTK_IS_EXPANDER(widget))
293
                        *expander = widget;
294
                else if (GTK_IS_CONTAINER(widget))
295
                        gtk_container_foreach(GTK_CONTAINER(widget),
296
                                              container_foreach_cb, data);
297
        }
298
}
299
300
static void filesel_save_expander_set_expanded(GtkWidget *dialog,
301
                                               gboolean expanded)
302
{
303
        GtkWidget *expander = NULL;
304
305
        gtk_container_foreach(GTK_CONTAINER(dialog), container_foreach_cb,
306
                              &expander);
307
        if (expander)
308
                gtk_expander_set_expanded(GTK_EXPANDER(expander), expanded);
309
}
310
311
static gboolean filesel_save_expander_get_expanded(GtkWidget *dialog)
312
{
313
        GtkWidget *expander = NULL;
314
315
        gtk_container_foreach(GTK_CONTAINER(dialog), container_foreach_cb,
316
                              &expander);
317
        if (expander)
318
                return gtk_expander_get_expanded(GTK_EXPANDER(expander));
319
        else
320
                return FALSE;
321
}
322
323
#if GTK_CHECK_VERSION(2, 8, 0)
324
static GtkFileChooserConfirmation filesel_confirm_overwrite_cb
325
                                        (GtkFileChooser                *chooser,
326
                                         gpointer                 data)
327
{
328
        gchar *filename;
329
        GtkFileChooserConfirmation ret =
330
                GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
331
332
        filename = gtk_file_chooser_get_filename(chooser);
333
334
        if (filename && is_file_exist(filename)) {
335
                AlertValue aval;
336
337
                aval = alertpanel(_("Overwrite existing file"),
338
                                  _("The file already exists. Do you want to replace it?"),
339
                                  GTK_STOCK_YES, GTK_STOCK_NO, NULL);
340
                if (G_ALERTDEFAULT == aval)
341
                        ret = GTK_FILE_CHOOSER_CONFIRMATION_ACCEPT_FILENAME;
342
                else
343
                        ret = GTK_FILE_CHOOSER_CONFIRMATION_SELECT_AGAIN;
344
        }
345
346
        g_free(filename);
347
348
        return ret;
349
}
350
#endif