Merge pull request #733 from hexchat/filedialog

Improve file dialogs
This commit is contained in:
TingPing 2013-09-06 17:00:55 -07:00
commit 703316ace6
7 changed files with 64 additions and 113 deletions

View File

@ -125,11 +125,12 @@ void fe_get_str (char *prompt, char *def, void *callback, void *ud);
void fe_get_int (char *prompt, int 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_WRITE 1 /* save file */
#define FRF_MULTIPLE 2 /* multi-select */ #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_CHOOSEFOLDER 8 /* choosing a folder only */
#define FRF_FILTERISINITIAL 16 /* filter is initial directory */ #define FRF_FILTERISINITIAL 16 /* filter is initial directory */
#define FRF_NOASKOVERWRITE 32 /* don't ask to overwrite existing files */ #define FRF_NOASKOVERWRITE 32 /* don't ask to overwrite existing files */
#define FRF_EXTENSIONS 64 /* specify file extensions to be displayed */ #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 fe_get_file (const char *title, char *initial,
void (*callback) (void *userdata, char *file), void *userdata, void (*callback) (void *userdata, char *file), void *userdata,
int flags); int flags);

View File

@ -908,10 +908,15 @@ fe_confirm (const char *message, void (*yesproc)(void *), void (*noproc)(void *)
{ {
/* warning, assuming fe_confirm is used by DCC only! */ /* warning, assuming fe_confirm is used by DCC only! */
struct DCC *dcc = ud; struct DCC *dcc = ud;
char *filepath;
if (dcc->file) 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 int

View File

@ -51,7 +51,6 @@
extern void path_part (char *file, char *path, int pathlen); extern void path_part (char *file, char *path, int pathlen);
struct file_req struct file_req
{ {
GtkWidget *dialog; GtkWidget *dialog;
@ -69,9 +68,6 @@ struct file_req
#endif #endif
}; };
static char last_dir[256] = "";
static void static void
gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq) 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; struct stat st;
int axs = FALSE; 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 */ /* check if the file is readable or writable */
if (freq->flags & FRF_WRITE) if (freq->flags & FRF_WRITE)
{ {
if (access (last_dir, W_OK) == 0) if (access (temp, W_OK) == 0)
axs = TRUE; axs = TRUE;
} else } else
{ {
@ -179,60 +176,6 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
char *token; char *token;
char *tokenbuffer; 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) if (flags & FRF_WRITE)
{ {
dialog = gtk_file_chooser_dialog_new (title, NULL, 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_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
NULL); 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)) if (!(flags & FRF_NOASKOVERWRITE))
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
@ -257,41 +193,28 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
NULL); 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) if (flags & FRF_MULTIPLE)
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE); 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) if (flags & FRF_CHOOSEFOLDER)
{
gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); 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) if ((flags & FRF_EXTENSIONS || flags & FRF_MIMETYPES) && extensions != NULL)
{ {
filefilter = gtk_file_filter_new (); filefilter = gtk_file_filter_new ();
tokenbuffer = g_strdup (extensions); tokenbuffer = g_strdup (extensions);
@ -299,7 +222,10 @@ gtkutil_file_req (const char *title, void *callback, void *userdata, char *filte
while (token != NULL) 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, ";"); token = strtok (NULL, ";");
} }
@ -307,6 +233,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_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 = malloc (sizeof (struct file_req));
freq->dialog = dialog; freq->dialog = dialog;
freq->flags = flags; freq->flags = flags;

View File

@ -21,16 +21,10 @@
#define HEXCHAT_GTKUTIL_H #define HEXCHAT_GTKUTIL_H
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "../common/fe.h"
typedef void (*filereqcallback) (void *, char *file); 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_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 (GtkWidget * igad, GtkWidget * dgad);
void gtkutil_destroy_on_esc (GtkWidget *win); void gtkutil_destroy_on_esc (GtkWidget *win);

View File

@ -162,9 +162,9 @@ plugingui_load (void)
gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess, gtkutil_file_req (_("Select a Plugin or Script to load"), plugingui_load_cb, current_sess,
#ifdef WIN32 #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 #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 #endif
g_free (sub_dir); g_free (sub_dir);

View File

@ -1059,7 +1059,19 @@ setup_filereq_cb (GtkWidget *entry, char *file)
static void static void
setup_browsefile_cb (GtkWidget *button, GtkWidget *entry) 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 */
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, filter, filter_type|FRF_RECENTLYUSED);
} }
static void static void
@ -1659,7 +1671,18 @@ static void
setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry) setup_snd_browse_cb (GtkWidget *button, GtkEntry *entry)
{ {
char *sounds_dir = g_build_filename (get_xdir (), HEXCHAT_SOUND_DIR, NULL); 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 *filter = NULL;
int filter_type;
#ifdef WIN32 /* win32 only supports wav, others could support anything */
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, filter, FRF_FILTERISINITIAL|filter_type);
g_free (sounds_dir); g_free (sounds_dir);
} }

View File

@ -146,7 +146,7 @@ static void
url_button_save (void) url_button_save (void)
{ {
gtkutil_file_req (_("Select an output filename"), 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 void