From 4c406bce171db7086e394f69ae3cddd3b4dc8a87 Mon Sep 17 00:00:00 2001 From: TingPing Date: Fri, 30 Aug 2013 20:19:10 -0400 Subject: [PATCH 1/3] Improve file dialogs - Fixes #314 - Adds file extensions to sound and image browsing - Some options no longer default to our config dir - Always add a shortcut to our config dir - Remove broken 'last_dir' functionality, gtk already knows recent --- src/common/fe.h | 2 +- src/fe-gtk/fe-gtk.c | 9 +++- src/fe-gtk/gtkutil.c | 117 ++++++++--------------------------------- src/fe-gtk/gtkutil.h | 8 +-- src/fe-gtk/plugingui.c | 4 +- src/fe-gtk/setup.c | 11 +++- src/fe-gtk/urlgrab.c | 2 +- 7 files changed, 42 insertions(+), 111 deletions(-) diff --git a/src/common/fe.h b/src/common/fe.h index 22db38df..eee4ad0c 100644 --- a/src/common/fe.h +++ b/src/common/fe.h @@ -125,7 +125,7 @@ void fe_get_str (char *prompt, char *def, void *callback, void *ud); void fe_get_int (char *prompt, int def, void *callback, void *ud); #define FRF_WRITE 1 /* save file */ #define FRF_MULTIPLE 2 /* multi-select */ -#define FRF_ADDFOLDER 4 /* add ~/.config/hexchat to favourites */ +#define FRF_RECENTLYUSED 4 /* let gtk decide start dir instead of our config */ #define FRF_CHOOSEFOLDER 8 /* choosing a folder only */ #define FRF_FILTERISINITIAL 16 /* filter is initial directory */ #define FRF_NOASKOVERWRITE 32 /* don't ask to overwrite existing files */ diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c index acba80a5..3469569e 100644 --- a/src/fe-gtk/fe-gtk.c +++ b/src/fe-gtk/fe-gtk.c @@ -908,10 +908,15 @@ fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *) { /* warning, assuming fe_confirm is used by DCC only! */ struct DCC *dcc = ud; + char *filepath; if (dcc->file) - gtkutil_file_req (message, dcc_saveas_cb, ud, dcc->file, NULL, - FRF_WRITE|FRF_NOASKOVERWRITE); + { + filepath = g_build_filename (prefs.hex_dcc_dir, dcc->file, NULL); + gtkutil_file_req (message, dcc_saveas_cb, ud, filepath, NULL, + FRF_WRITE|FRF_NOASKOVERWRITE|FRF_FILTERISINITIAL); + g_free (filepath); + } } int diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c index 8a3de06f..55ae2c76 100644 --- a/src/fe-gtk/gtkutil.c +++ b/src/fe-gtk/gtkutil.c @@ -51,7 +51,6 @@ extern void path_part (char *file, char *path, int pathlen); - struct file_req { GtkWidget *dialog; @@ -69,9 +68,6 @@ struct file_req #endif }; -static char last_dir[256] = ""; - - static void gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq) { @@ -84,13 +80,14 @@ gtkutil_check_file (char *file, struct file_req *freq) { struct stat st; int axs = FALSE; + char temp[256]; - path_part (file, last_dir, sizeof (last_dir)); + path_part (file, temp, sizeof (temp)); /* check if the file is readable or writable */ if (freq->flags & FRF_WRITE) { - if (access (last_dir, W_OK) == 0) + if (access (temp, W_OK) == 0) axs = TRUE; } else { @@ -179,60 +176,6 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte char *token; char *tokenbuffer; -#if 0 /* native file dialogs */ -#ifdef WIN32 - if (!(flags & FRF_WRITE)) - { - freq = malloc (sizeof (struct file_req)); - freq->th = thread_new (); - freq->flags = 0; - freq->multiple = (flags & FRF_MULTIPLE); - freq->callback = callback; - freq->userdata = userdata; - freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0); - if (!filter) - { - freq->filter = "All files\0*.*\0" - "Executables\0*.exe\0" - "ZIP files\0*.zip\0\0"; - } - else - { - freq->filter = filter; - } - - thread_start (freq->th, win32_thread, freq); - fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq); - - return; - - } - - else { - freq = malloc (sizeof (struct file_req)); - freq->th = thread_new (); - freq->flags = 0; - freq->multiple = (flags & FRF_MULTIPLE); - freq->callback = callback; - freq->userdata = userdata; - freq->title = g_locale_from_utf8 (title, -1, 0, 0, 0); - if (!filter) - { - freq->filter = "All files\0*.*\0\0"; - } - else - { - freq->filter = filter; - } - - thread_start (freq->th, win32_thread2, freq); - fe_input_add (freq->th->pipe_fd[0], FIA_FD|FIA_READ, win32_read_thread, freq); - - return; - } -#endif -#endif - if (flags & FRF_WRITE) { dialog = gtk_file_chooser_dialog_new (title, NULL, @@ -240,13 +183,6 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); - if (filter && filter[0]) /* filter becomes initial name when saving */ - { - char temp[1024]; - path_part (filter, temp, sizeof (temp)); - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), temp); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), file_part (filter)); - } if (!(flags & FRF_NOASKOVERWRITE)) gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); @@ -257,39 +193,26 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); + + if (filter && filter[0] && (flags & FRF_FILTERISINITIAL)) + { + if (flags & FRF_WRITE) + { + char temp[1024]; + path_part (filter, temp, sizeof (temp)); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), temp); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), file_part (filter)); + } + else + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), filter); + } + else if (!(flags & FRF_RECENTLYUSED)) + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), get_xdir ()); + if (flags & FRF_MULTIPLE) gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE); - if (last_dir[0]) - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_dir); - if (flags & FRF_ADDFOLDER) - gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), - get_xdir (), NULL); if (flags & FRF_CHOOSEFOLDER) - { gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), filter); - } - else - { - if (filter && (flags & FRF_FILTERISINITIAL)) - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), filter); - } - /* With DCC, we can't rely on filter as initial folder since filter already contains - * the filename upon DCC RECV. Thus we have no better option than to check for the message - * which will be the title of the window. For DCC it always contains the "offering" word. - * This method is really ugly but it works so we'll stick with it for now. - */ - else if (strstr (title, "offering") != NULL) - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), prefs.hex_dcc_dir); - } - /* by default, open the config folder */ - else - { - gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), get_xdir ()); - } - } if (flags & FRF_EXTENSIONS && extensions != NULL) { @@ -307,6 +230,8 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filefilter); } + gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), get_xdir (), NULL); + freq = malloc (sizeof (struct file_req)); freq->dialog = dialog; freq->flags = flags; diff --git a/src/fe-gtk/gtkutil.h b/src/fe-gtk/gtkutil.h index e3f59a29..2ecbe3c2 100644 --- a/src/fe-gtk/gtkutil.h +++ b/src/fe-gtk/gtkutil.h @@ -21,16 +21,10 @@ #define HEXCHAT_GTKUTIL_H #include +#include "../common/fe.h" typedef void (*filereqcallback) (void *, char *file); -#define FRF_WRITE 1 -#define FRF_MULTIPLE 2 -#define FRF_ADDFOLDER 4 -#define FRF_CHOOSEFOLDER 8 -#define FRF_FILTERISINITIAL 16 -#define FRF_NOASKOVERWRITE 32 - void gtkutil_file_req (const char *title, void *callback, void *userdata, char *filter, char *extensions, int flags); void gtkutil_destroy (GtkWidget * igad, GtkWidget * dgad); void gtkutil_destroy_on_esc (GtkWidget *win); diff --git a/src/fe-gtk/plugingui.c b/src/fe-gtk/plugingui.c index 745c6d83..c6d90e2f 100644 --- a/src/fe-gtk/plugingui.c +++ b/src/fe-gtk/plugingui.c @@ -162,9 +162,9 @@ plugingui_load (void) gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess, #ifdef WIN32 - sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl;*.js", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS); + sub_dir, "*.dll;*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS); #else - sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl;*.js", FRF_ADDFOLDER|FRF_FILTERISINITIAL|FRF_EXTENSIONS); + sub_dir, "*.so;*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS); #endif g_free (sub_dir); diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 2d46b95f..9923f654 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -1059,7 +1059,9 @@ setup_filereq_cb (GtkWidget *entry, char *file) static void setup_browsefile_cb (GtkWidget *button, GtkWidget *entry) { - gtkutil_file_req (_("Select an Image File"), setup_filereq_cb, entry, NULL, NULL, 0); + /* used for background image only */ + gtkutil_file_req (_("Select an Image File"), setup_filereq_cb, + entry, NULL, "*.jpg;*.png;*.tif;*.gif", FRF_EXTENSIONS|FRF_RECENTLYUSED); } static void @@ -1659,7 +1661,12 @@ static void setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry) { char *sounds_dir = g_build_filename (get_xdir (), HEXCHAT_SOUND_DIR, NULL); - gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry, sounds_dir, NULL, FRF_FILTERISINITIAL); + char *extensions = NULL; +#ifdef WIN32 /* win32 only supports wav, others could support anything */ + extensions = "*.wav"; +#endif + + gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry, sounds_dir, extensions, FRF_FILTERISINITIAL|FRF_EXTENSIONS); g_free (sounds_dir); } diff --git a/src/fe-gtk/urlgrab.c b/src/fe-gtk/urlgrab.c index cefa51c8..79a6d5f5 100644 --- a/src/fe-gtk/urlgrab.c +++ b/src/fe-gtk/urlgrab.c @@ -146,7 +146,7 @@ static void url_button_save (void) { gtkutil_file_req (_("Select an output filename"), - url_save_callback, NULL, get_xdir (), NULL, FRF_WRITE|FRF_FILTERISINITIAL); + url_save_callback, NULL, NULL, NULL, FRF_WRITE); } void From 755932c3bc976d9a95e0b1b330efed31f7e48d9b Mon Sep 17 00:00:00 2001 From: TingPing Date: Sat, 31 Aug 2013 15:31:22 -0400 Subject: [PATCH 2/3] Use mimetypes for audio and images --- src/common/fe.h | 1 + src/fe-gtk/gtkutil.c | 7 +++++-- src/fe-gtk/setup.c | 14 ++++++++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/common/fe.h b/src/common/fe.h index eee4ad0c..91bf0a5b 100644 --- a/src/common/fe.h +++ b/src/common/fe.h @@ -130,6 +130,7 @@ void fe_get_int (char *prompt, int def, void *callback, void *ud); #define FRF_FILTERISINITIAL 16 /* filter is initial directory */ #define FRF_NOASKOVERWRITE 32 /* don't ask to overwrite existing files */ #define FRF_EXTENSIONS 64 /* specify file extensions to be displayed */ +#define FRF_MIMETYPES 128 /* specify file mimetypes to be displayed */ void fe_get_file (const char *title, char *initial, void (*callback) (void *userdata, char *file), void *userdata, int flags); diff --git a/src/fe-gtk/gtkutil.c b/src/fe-gtk/gtkutil.c index 55ae2c76..985a2f78 100644 --- a/src/fe-gtk/gtkutil.c +++ b/src/fe-gtk/gtkutil.c @@ -214,7 +214,7 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte if (flags & FRF_CHOOSEFOLDER) gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - if (flags & FRF_EXTENSIONS && extensions != NULL) + if ((flags & FRF_EXTENSIONS || flags & FRF_MIMETYPES) && extensions != NULL) { filefilter = gtk_file_filter_new (); tokenbuffer = g_strdup (extensions); @@ -222,7 +222,10 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte while (token != NULL) { - gtk_file_filter_add_pattern (filefilter, token); + if (flags & FRF_EXTENSIONS) + gtk_file_filter_add_pattern (filefilter, token); + else + gtk_file_filter_add_mime_type (filefilter, token); token = strtok (NULL, ";"); } diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index 9923f654..f86c1eaa 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -1061,7 +1061,7 @@ setup_browsefile_cb (GtkWidget *button, GtkWidget *entry) { /* used for background image only */ gtkutil_file_req (_("Select an Image File"), setup_filereq_cb, - entry, NULL, "*.jpg;*.png;*.tif;*.gif", FRF_EXTENSIONS|FRF_RECENTLYUSED); + entry, NULL, "image/*", FRF_MIMETYPES|FRF_RECENTLYUSED); } static void @@ -1661,12 +1661,18 @@ static void setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry) { char *sounds_dir = g_build_filename (get_xdir (), HEXCHAT_SOUND_DIR, NULL); - char *extensions = NULL; + char *filter = NULL; + int filter_type; #ifdef WIN32 /* win32 only supports wav, others could support anything */ - extensions = "*.wav"; + filter = "*.wav"; + filter_type = FRF_EXTENSIONS; +#else + filter = "audio/*"; + filter_type = FRF_MIMETYPES; #endif - gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry, sounds_dir, extensions, FRF_FILTERISINITIAL|FRF_EXTENSIONS); + gtkutil_file_req (_("Select a sound file"), setup_snd_filereq_cb, entry, + sounds_dir, filter, FRF_FILTERISINITIAL|filter_type); g_free (sounds_dir); } From bf269d2e0386a54650b3b9e860eeb2e2f05a3fde Mon Sep 17 00:00:00 2001 From: TingPing Date: Sat, 31 Aug 2013 15:38:29 -0400 Subject: [PATCH 3/3] Of course mimetype doesn't work on Windows.. --- src/fe-gtk/setup.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c index f86c1eaa..4abc584f 100644 --- a/src/fe-gtk/setup.c +++ b/src/fe-gtk/setup.c @@ -1060,8 +1060,18 @@ static void setup_browsefile_cb (GtkWidget *button, GtkWidget *entry) { /* used for background image only */ + char *filter; + int filter_type; + +#ifdef WIN32 + filter = "*png;*.tiff;*.gif;*.jpeg;*.jpg"; + filter_type = FRF_EXTENSIONS; +#else + filter = "image/*"; + filter_type = FRF_MIMETYPES; +#endif gtkutil_file_req (_("Select an Image File"), setup_filereq_cb, - entry, NULL, "image/*", FRF_MIMETYPES|FRF_RECENTLYUSED); + entry, NULL, filter, filter_type|FRF_RECENTLYUSED); } static void