1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2013 Hiroyuki Yamamoto and the Claws Mail team
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 3 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, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #include "claws-features.h"
23 #endif
24
25 #include <glib.h>
26 #include <gdk/gdkkeysyms.h>
27 #include <gtk/gtk.h>
28
29 #include "claws.h"
30 #include "filesel.h"
31 #include "manage_window.h"
32 #include "gtkutils.h"
33 #include "utils.h"
34 #include "codeconv.h"
35 #include "procmime.h"
36 #include "prefs_common.h"
37
38 static void
update_preview_cb(GtkFileChooser * file_chooser,gpointer data)39 update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
40 {
41 GtkWidget *preview;
42 char *filename = NULL, *type = NULL;
43 GdkPixbuf *pixbuf = NULL;
44 gboolean have_preview = FALSE;
45
46 preview = GTK_WIDGET (data);
47 filename = gtk_file_chooser_get_preview_filename (file_chooser);
48
49 if (filename == NULL) {
50 gtk_file_chooser_set_preview_widget_active (file_chooser, FALSE);
51 return;
52 }
53 type = procmime_get_mime_type(filename);
54
55 if (type && !strncmp(type, "image/", 6))
56 pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL);
57
58 g_free(type);
59 g_free (filename);
60
61 if (pixbuf) {
62 have_preview = TRUE;
63 gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
64 g_object_unref(G_OBJECT(pixbuf));
65 }
66
67 gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
68 }
69
filesel_create(const gchar * title,const gchar * path,gboolean multiple_files,gboolean open,gboolean folder_mode,const gchar * filter)70 static GList *filesel_create(const gchar *title, const gchar *path,
71 gboolean multiple_files,
72 gboolean open, gboolean folder_mode,
73 const gchar *filter)
74 {
75 GSList *slist = NULL, *slist_orig = NULL;
76 GList *list = NULL;
77
78 gint action = (open == TRUE) ?
79 (folder_mode == TRUE ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
80 GTK_FILE_CHOOSER_ACTION_OPEN):
81 (folder_mode == TRUE ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
82 GTK_FILE_CHOOSER_ACTION_SAVE);
83
84 gchar * action_btn = (open == TRUE) ? GTK_STOCK_OPEN:GTK_STOCK_SAVE;
85 GtkWidget *chooser = gtk_file_chooser_dialog_new
86 (title, NULL, action,
87 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
88 action_btn, GTK_RESPONSE_ACCEPT,
89 NULL);
90
91 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(chooser), FALSE);
92
93 if (filter != NULL) {
94 GtkFileFilter *file_filter = gtk_file_filter_new();
95 gtk_file_filter_add_pattern(file_filter, filter);
96 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(chooser),
97 file_filter);
98 }
99
100 if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
101 GtkImage *preview;
102 preview = GTK_IMAGE(gtk_image_new ());
103 gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER(chooser), GTK_WIDGET(preview));
104 g_signal_connect (chooser, "update-preview",
105 G_CALLBACK (update_preview_cb), preview);
106
107 }
108
109 if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
110 gtk_dialog_set_default_response(GTK_DIALOG(chooser), GTK_RESPONSE_ACCEPT);
111 }
112
113 manage_window_set_transient (GTK_WINDOW(chooser));
114 gtk_window_set_modal(GTK_WINDOW(chooser), TRUE);
115
116 gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(chooser), multiple_files);
117
118 if (path && strlen(path) > 0) {
119 char *filename = NULL;
120 char *realpath = g_strdup(path);
121 char *tmp = NULL;
122 if (path[strlen(path)-1] == G_DIR_SEPARATOR) {
123 filename = "";
124 } else if ((filename = strrchr(path, G_DIR_SEPARATOR)) != NULL) {
125 filename++;
126 *(strrchr(realpath, G_DIR_SEPARATOR)+1) = '\0';
127 } else {
128 filename = (char *) path;
129 g_free(realpath);
130 realpath = g_strdup(get_home_dir());
131 }
132 if (g_utf8_validate(realpath, -1, NULL))
133 tmp = g_filename_from_utf8(realpath, -1, NULL, NULL, NULL);
134 if (tmp == NULL)
135 tmp = g_strdup(realpath);
136 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), tmp);
137 g_free(tmp);
138 if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
139 if (g_utf8_validate(filename, -1, NULL))
140 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser),
141 filename);
142 }
143 g_free(realpath);
144 } else {
145 gchar *tmp = NULL;
146 if (!prefs_common.attach_load_dir || !*prefs_common.attach_load_dir)
147 prefs_common.attach_load_dir = g_strdup_printf("%s%c", get_home_dir(), G_DIR_SEPARATOR);
148 if (g_utf8_validate(prefs_common.attach_load_dir, -1, NULL))
149 tmp = g_filename_from_utf8(prefs_common.attach_load_dir, -1, NULL, NULL, NULL);
150 if (tmp == NULL)
151 tmp = g_strdup(prefs_common.attach_load_dir);
152 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), tmp);
153 g_free(tmp);
154 }
155
156 if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
157 slist = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser));
158
159 manage_window_focus_out(chooser, NULL, NULL);
160 gtk_widget_destroy (chooser);
161
162 slist_orig = slist;
163
164 if (slist) {
165 gchar *tmp = g_strdup(slist->data);
166
167 if (!path && prefs_common.attach_load_dir)
168 g_free(prefs_common.attach_load_dir);
169
170 if (strrchr(tmp, G_DIR_SEPARATOR))
171 *(strrchr(tmp, G_DIR_SEPARATOR)+1) = '\0';
172
173 if (!path)
174 prefs_common.attach_load_dir = g_filename_to_utf8(tmp, -1, NULL, NULL, NULL);
175
176 g_free(tmp);
177 }
178
179 while (slist) {
180 list = g_list_append(list, slist->data);
181 slist = slist->next;
182 }
183
184 if (slist_orig)
185 g_slist_free(slist_orig);
186
187 return list;
188 }
189
190 /**
191 * This function lets the user select multiple files.
192 * This opens an Open type dialog.
193 * @param title the title of the dialog
194 */
filesel_select_multiple_files_open(const gchar * title,const gchar * path)195 GList *filesel_select_multiple_files_open(const gchar *title, const gchar *path)
196 {
197 return filesel_create(title, path, TRUE, TRUE, FALSE, NULL);
198 }
199
filesel_select_multiple_files_open_with_filter(const gchar * title,const gchar * path,const gchar * filter)200 GList *filesel_select_multiple_files_open_with_filter( const gchar *title,
201 const gchar *path,
202 const gchar *filter)
203 {
204 return filesel_create (title, path, TRUE, TRUE, FALSE, filter);
205 }
206
207 /**
208 * This function lets the user select one file.
209 * This opens an Open type dialog if "file" is NULL,
210 * Save dialog if "file" contains a path.
211 * @param title the title of the dialog
212 * @param path the optional path to save to
213 */
filesel_select_file(const gchar * title,const gchar * path,gboolean open,gboolean folder_mode,const gchar * filter)214 static gchar *filesel_select_file(const gchar *title, const gchar *path,
215 gboolean open, gboolean folder_mode,
216 const gchar *filter)
217 {
218 GList * list = filesel_create(title, path, FALSE, open, folder_mode, filter);
219 gchar * result = NULL;
220 if (list) {
221 result = g_strdup(list->data);
222 }
223 g_list_free(list);
224 return result;
225 }
filesel_select_file_open(const gchar * title,const gchar * path)226 gchar *filesel_select_file_open(const gchar *title, const gchar *path)
227 {
228 return filesel_select_file (title, path, TRUE, FALSE, NULL);
229 }
230
filesel_select_file_open_with_filter(const gchar * title,const gchar * path,const gchar * filter)231 gchar *filesel_select_file_open_with_filter(const gchar *title, const gchar *path,
232 const gchar *filter)
233 {
234 return filesel_select_file (title, path, TRUE, FALSE, filter);
235 }
236
filesel_select_file_save(const gchar * title,const gchar * path)237 gchar *filesel_select_file_save(const gchar *title, const gchar *path)
238 {
239 return filesel_select_file (title, path, FALSE, FALSE, NULL);
240 }
241
filesel_select_file_open_folder(const gchar * title,const gchar * path)242 gchar *filesel_select_file_open_folder(const gchar *title, const gchar *path)
243 {
244 return filesel_select_file (title, path, TRUE, TRUE, NULL);
245 }
246
filesel_select_file_save_folder(const gchar * title,const gchar * path)247 gchar *filesel_select_file_save_folder(const gchar *title, const gchar *path)
248 {
249 return filesel_select_file (title, path, FALSE, TRUE, NULL);
250 }
251
252