talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

filesel.c (7284B)


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