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