diff --git a/data/geany.glade b/data/geany.glade index 98fc6b3ec7..204977e8d4 100644 --- a/data/geany.glade +++ b/data/geany.glade @@ -1311,6 +1311,22 @@ 3 + + + Use platform-native file dialogs + True + True + False + Defines whether to use the platform-native file dialogs or whether to use the GTK default dialogs + True + True + + + False + False + 4 + + diff --git a/src/dialogs.c b/src/dialogs.c index ccb54045ff..3d1fefc293 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -122,7 +122,7 @@ static void file_chooser_set_filter_idx(GtkFileChooser *chooser, guint idx) } -static gboolean open_file_dialog_handle_response(GtkWidget *dialog, gint response) +static gboolean open_file_dialog_handle_response(GtkFileChooser *dialog, gint response) { gboolean ret = TRUE; @@ -131,24 +131,28 @@ static gboolean open_file_dialog_handle_response(GtkWidget *dialog, gint respons GSList *filelist; GeanyFiletype *ft = NULL; const gchar *charset = NULL; - GtkWidget *expander = ui_lookup_widget(dialog, "more_options_expander"); - GtkWidget *filetype_combo = ui_lookup_widget(dialog, "filetype_combo"); - GtkWidget *encoding_combo = ui_lookup_widget(dialog, "encoding_combo"); gboolean ro = (response == GEANY_RESPONSE_VIEW); /* View clicked */ - filesel_state.open.more_options_visible = gtk_expander_get_expanded(GTK_EXPANDER(expander)); - filesel_state.open.filter_idx = file_chooser_get_filter_idx(GTK_FILE_CHOOSER(dialog)); - filesel_state.open.filetype_idx = filetype_combo_box_get_active_filetype(GTK_COMBO_BOX(filetype_combo)); + if (GTK_IS_WIDGET(dialog)) + { + GtkWidget *expander = ui_lookup_widget(GTK_WIDGET(dialog), "more_options_expander"); + GtkWidget *filetype_combo = ui_lookup_widget(GTK_WIDGET(dialog), "filetype_combo"); + GtkWidget *encoding_combo = ui_lookup_widget(GTK_WIDGET(dialog), "encoding_combo"); + + filesel_state.open.more_options_visible = gtk_expander_get_expanded(GTK_EXPANDER(expander)); + filesel_state.open.filter_idx = file_chooser_get_filter_idx(GTK_FILE_CHOOSER(dialog)); + filesel_state.open.filetype_idx = filetype_combo_box_get_active_filetype(GTK_COMBO_BOX(filetype_combo)); + filesel_state.open.encoding_idx = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(encoding_combo)); + } /* ignore detect from file item */ if (filesel_state.open.filetype_idx >= 0) ft = filetypes_index(filesel_state.open.filetype_idx); - filesel_state.open.encoding_idx = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(encoding_combo)); if (filesel_state.open.encoding_idx >= 0 && filesel_state.open.encoding_idx < GEANY_ENCODINGS_MAX) charset = encodings[filesel_state.open.encoding_idx].charset; - filelist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + filelist = gtk_file_chooser_get_filenames(dialog); if (filelist != NULL) { const gchar *first = filelist->data; @@ -167,7 +171,7 @@ static gboolean open_file_dialog_handle_response(GtkWidget *dialog, gint respons } } if (app->project && !EMPTY(app->project->base_path)) - gtk_file_chooser_remove_shortcut_folder(GTK_FILE_CHOOSER(dialog), + gtk_file_chooser_remove_shortcut_folder(dialog, app->project->base_path, NULL); return ret; } @@ -365,42 +369,49 @@ static GtkWidget *add_file_open_extra_widget(GtkWidget *dialog) } -static GtkWidget *create_open_file_dialog(void) +static GtkFileChooser *create_open_file_dialog(void) { - GtkWidget *dialog; + GtkFileChooser *dialog; GtkWidget *viewbtn; GSList *node; - dialog = gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window), - GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL); - gtk_widget_set_name(dialog, "GeanyDialog"); - - viewbtn = gtk_dialog_add_button(GTK_DIALOG(dialog), C_("Open dialog action", "_View"), GEANY_RESPONSE_VIEW); - gtk_widget_set_tooltip_text(viewbtn, - _("Opens the file in read-only mode. If you choose more than one file to open, all files will be opened read-only.")); - - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - - gtk_widget_set_size_request(dialog, -1, 460); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE); - gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window)); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); - gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE); - - /* add checkboxes and filename entry */ - gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), add_file_open_extra_widget(dialog)); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Open File"), + GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel")); + else + { + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window), + GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL)); + gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialog"); + + viewbtn = gtk_dialog_add_button(GTK_DIALOG(dialog), C_("Open dialog action", "_View"), GEANY_RESPONSE_VIEW); + gtk_widget_set_tooltip_text(viewbtn, + _("Opens the file in read-only mode. If you choose more than one file to open, all files will be opened read-only.")); + + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + + gtk_widget_set_size_request(GTK_WIDGET(dialog), -1, 460); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE); + gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window)); + + /* add checkboxes and filename entry */ + gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), add_file_open_extra_widget(GTK_WIDGET(dialog))); + + g_signal_connect(dialog, "notify::show-hidden", + G_CALLBACK(on_file_open_show_hidden_notify), NULL); + } /* add FileFilters(start with "All Files") */ - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), + gtk_file_chooser_add_filter(dialog, filetypes_create_file_filter(filetypes[GEANY_FILETYPES_NONE])); /* now create meta filter "All Source" */ - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), + gtk_file_chooser_add_filter(dialog, filetypes_create_file_filter_all_source()); foreach_slist(node, filetypes_by_title) { @@ -408,11 +419,11 @@ static GtkWidget *create_open_file_dialog(void) if (G_UNLIKELY(ft->id == GEANY_FILETYPES_NONE)) continue; - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filetypes_create_file_filter(ft)); + gtk_file_chooser_add_filter(dialog, filetypes_create_file_filter(ft)); } - g_signal_connect(dialog, "notify::show-hidden", - G_CALLBACK(on_file_open_show_hidden_notify), NULL); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); + gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE); return dialog; } @@ -444,11 +455,29 @@ static void open_file_dialog_apply_settings(GtkWidget *dialog) } +gint dialogs_file_chooser_run(GtkFileChooser *dialog) +{ + if (GTK_IS_WIDGET(dialog)) + return gtk_dialog_run(GTK_DIALOG(dialog)); + + return gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog)); +} + + +void dialogs_file_chooser_destroy(GtkFileChooser *dialog) +{ + if (GTK_IS_WIDGET(dialog)) + gtk_widget_destroy(GTK_WIDGET(dialog)); + else + g_object_unref(dialog); +} + + /* This shows the file selection dialog to open a file. */ void dialogs_show_open_file(void) { gchar *initdir; - GtkWidget *dialog; + GtkFileChooser *dialog; /* set dialog directory to the current file's directory, if present */ initdir = utils_get_current_file_dir_utf8(); @@ -461,18 +490,19 @@ void dialogs_show_open_file(void) SETPTR(initdir, utils_get_locale_from_utf8(initdir)); dialog = create_open_file_dialog(); - open_file_dialog_apply_settings(dialog); + if (GTK_IS_WIDGET(dialog)) + open_file_dialog_apply_settings(GTK_WIDGET(dialog)); if (initdir != NULL && g_path_is_absolute(initdir)) - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), initdir); + gtk_file_chooser_set_current_folder(dialog, initdir); if (app->project && !EMPTY(app->project->base_path)) - gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(dialog), + gtk_file_chooser_add_shortcut_folder(dialog, app->project->base_path, NULL); while (!open_file_dialog_handle_response(dialog, - gtk_dialog_run(GTK_DIALOG(dialog)))); - gtk_widget_destroy(dialog); + dialogs_file_chooser_run(dialog))); + dialogs_file_chooser_destroy(dialog); g_free(initdir); } @@ -507,11 +537,11 @@ static gboolean handle_save_as(GeanyDocument *doc, static gboolean save_as_dialog_handle_response(GeanyDocument *doc, - GtkWidget *dialog, gint response) + GtkFileChooser *dialog, gint response) { gboolean rename_file = FALSE; gboolean success = FALSE; - gchar *new_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + gchar *new_filename = gtk_file_chooser_get_filename(dialog); switch (response) { @@ -549,39 +579,46 @@ static gboolean save_as_dialog_handle_response(GeanyDocument *doc, } -static GtkWidget *create_save_file_dialog(GeanyDocument *doc) +static GtkFileChooser *create_save_file_dialog(GeanyDocument *doc) { - GtkWidget *dialog, *rename_btn; + GtkFileChooser *dialog; + GtkWidget *rename_btn; const gchar *initdir; - dialog = gtk_file_chooser_dialog_new(_("Save File"), GTK_WINDOW(main_widgets.window), - GTK_FILE_CHOOSER_ACTION_SAVE, NULL, NULL); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE); - gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window)); - gtk_widget_set_name(dialog, "GeanyDialog"); - - rename_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), _("R_ename"), GEANY_RESPONSE_RENAME); - gtk_widget_set_tooltip_text(rename_btn, _("Save the file and rename it")); - /* disable rename unless file exists on disk */ - gtk_widget_set_sensitive(rename_btn, doc->real_path != NULL); - - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Save File"), + GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", "_Cancel")); + else + { + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Save File"), GTK_WINDOW(main_widgets.window), + GTK_FILE_CHOOSER_ACTION_SAVE, NULL, NULL)); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE); + gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window)); + gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialog"); + + rename_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), _("R_ename"), GEANY_RESPONSE_RENAME); + gtk_widget_set_tooltip_text(rename_btn, _("Save the file and rename it")); + /* disable rename unless file exists on disk */ + gtk_widget_set_sensitive(rename_btn, doc->real_path != NULL); + + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + } - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); - gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE); + gtk_file_chooser_set_do_overwrite_confirmation(dialog, TRUE); + gtk_file_chooser_set_local_only(dialog, FALSE); /* set the folder by default to the project base dir or the global pref for opening files */ initdir = utils_get_default_dir_utf8(); if (initdir) { gchar *linitdir = utils_get_locale_from_utf8(initdir); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), linitdir); + gtk_file_chooser_set_current_folder(dialog, linitdir); g_free(linitdir); } return dialog; @@ -590,7 +627,7 @@ static GtkWidget *create_save_file_dialog(GeanyDocument *doc) static gboolean show_save_as_gtk(GeanyDocument *doc) { - GtkWidget *dialog; + GtkFileChooser *dialog; gint resp; g_return_val_if_fail(DOC_VALID(doc), FALSE); @@ -605,15 +642,15 @@ static gboolean show_save_as_gtk(GeanyDocument *doc) gchar *locale_basename = g_path_get_basename(locale_filename); gchar *locale_dirname = g_path_get_dirname(locale_filename); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_dirname); - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), locale_basename); + gtk_file_chooser_set_current_folder(dialog, locale_dirname); + gtk_file_chooser_set_current_name(dialog, locale_basename); g_free(locale_filename); g_free(locale_basename); g_free(locale_dirname); } else - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), doc->file_name); + gtk_file_chooser_set_current_name(dialog, doc->file_name); } else { @@ -625,7 +662,7 @@ static gboolean show_save_as_gtk(GeanyDocument *doc) else fname = g_strdup(GEANY_STRING_UNTITLED); - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), fname); + gtk_file_chooser_set_current_name(dialog, fname); g_free(fname); } @@ -637,15 +674,15 @@ static gboolean show_save_as_gtk(GeanyDocument *doc) /* Run the dialog synchronously, pausing this function call */ do { - resp = gtk_dialog_run(GTK_DIALOG(dialog)); + resp = dialogs_file_chooser_run(dialog); } while (! save_as_dialog_handle_response(doc, dialog, resp)); if (app->project && !EMPTY(app->project->base_path)) - gtk_file_chooser_remove_shortcut_folder(GTK_FILE_CHOOSER(dialog), + gtk_file_chooser_remove_shortcut_folder(dialog, app->project->base_path, NULL); - gtk_widget_destroy(dialog); + dialogs_file_chooser_destroy(dialog); return (resp == GTK_RESPONSE_ACCEPT); } diff --git a/src/dialogs.h b/src/dialogs.h index 90ffeb8d89..df328cebba 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -80,6 +80,9 @@ gint dialogs_show_prompt(GtkWidget *parent, void dialogs_show_msgbox_with_secondary(GtkMessageType type, const gchar *text, const gchar *secondary); +gint dialogs_file_chooser_run(GtkFileChooser *dialog); +void dialogs_file_chooser_destroy(GtkFileChooser *dialog); + #endif /* GEANY_PRIVATE */ G_END_DECLS diff --git a/src/keyfile.c b/src/keyfile.c index 43fe7c2893..344dd86a9d 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -79,11 +79,14 @@ #define GEANY_DISK_CHECK_TIMEOUT 30 #define GEANY_DEFAULT_TOOLS_MAKE "make" #ifdef G_OS_WIN32 -#define GEANY_DEFAULT_TOOLS_TERMINAL "cmd.exe /Q /C %c" +# define GEANY_DEFAULT_TOOLS_TERMINAL "cmd.exe /Q /C %c" +# define GEANY_DEFAULT_USE_NATIVE_DLGS TRUE #elif defined(__APPLE__) -#define GEANY_DEFAULT_TOOLS_TERMINAL "open -a terminal %c" +# define GEANY_DEFAULT_TOOLS_TERMINAL "open -a terminal %c" +# define GEANY_DEFAULT_USE_NATIVE_DLGS TRUE #else -#define GEANY_DEFAULT_TOOLS_TERMINAL "xterm -e \"/bin/sh %c\"" +# define GEANY_DEFAULT_TOOLS_TERMINAL "xterm -e \"/bin/sh %c\"" +# define GEANY_DEFAULT_USE_NATIVE_DLGS FALSE #endif #ifdef __APPLE__ #define GEANY_DEFAULT_TOOLS_BROWSER "open -a safari" @@ -545,6 +548,7 @@ static void save_dialog_prefs(GKeyFile *config) g_key_file_set_integer(config, PACKAGE, "tab_pos_editor", interface_prefs.tab_pos_editor); g_key_file_set_integer(config, PACKAGE, "tab_pos_msgwin", interface_prefs.tab_pos_msgwin); g_key_file_set_integer(config, PACKAGE, "tab_label_length", interface_prefs.tab_label_len); + g_key_file_set_boolean(config, PACKAGE, "use_native_dialogs", interface_prefs.use_native_windows_dialogs); /* display */ g_key_file_set_boolean(config, PACKAGE, "show_indent_guide", editor_prefs.show_indent_guide); @@ -895,6 +899,7 @@ static void load_dialog_prefs(GKeyFile *config) interface_prefs.editor_font = utils_get_setting_string(config, PACKAGE, "editor_font", GEANY_DEFAULT_FONT_EDITOR); interface_prefs.tagbar_font = utils_get_setting_string(config, PACKAGE, "tagbar_font", GEANY_DEFAULT_FONT_SYMBOL_LIST); interface_prefs.msgwin_font = utils_get_setting_string(config, PACKAGE, "msgwin_font", GEANY_DEFAULT_FONT_MSG_WINDOW); + interface_prefs.use_native_windows_dialogs = utils_get_setting_boolean(config, PACKAGE, "use_native_dialogs", GEANY_DEFAULT_USE_NATIVE_DLGS); /* display, editor */ editor_prefs.long_line_enabled = utils_get_setting_boolean(config, PACKAGE, "long_line_enabled", TRUE); diff --git a/src/prefs.c b/src/prefs.c index cbb2c01c24..02f51214c0 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -424,6 +424,10 @@ static void prefs_init_dialog(void) widget = ui_lookup_widget(ui_widgets.prefs_dialog, "entry_contextaction"); gtk_entry_set_text(GTK_ENTRY(widget), tool_prefs.context_action_cmd); + widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_dialogs"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), + interface_prefs.use_native_windows_dialogs); + project_setup_prefs(); /* project files path */ @@ -900,6 +904,10 @@ on_prefs_dialog_response(GtkDialog *dialog, gint response, gpointer user_data) g_free(tool_prefs.context_action_cmd); tool_prefs.context_action_cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(widget))); + widget = ui_lookup_widget(ui_widgets.prefs_dialog, "check_native_dialogs"); + interface_prefs.use_native_windows_dialogs = + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + project_apply_prefs(); /* project file path */ diff --git a/src/project.c b/src/project.c index f0c5b2e36f..efe4120da8 100644 --- a/src/project.c +++ b/src/project.c @@ -313,11 +313,11 @@ gboolean project_load_file_with_session(const gchar *locale_file_name) } -static void run_open_dialog(GtkDialog *dialog) +static void run_open_dialog(GtkFileChooser *dialog) { - while (gtk_dialog_run(dialog) == GTK_RESPONSE_ACCEPT) + while (dialogs_file_chooser_run(dialog) == GTK_RESPONSE_ACCEPT) { - gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + gchar *filename = gtk_file_chooser_get_filename(dialog); if (app->project && !project_close(FALSE)) {} /* try to load the config */ @@ -326,7 +326,8 @@ static void run_open_dialog(GtkDialog *dialog) gchar *utf8_filename = utils_get_utf8_from_locale(filename); SHOW_ERR1(_("Project file \"%s\" could not be loaded."), utf8_filename); - gtk_widget_grab_focus(GTK_WIDGET(dialog)); + if (GTK_IS_WIDGET(dialog)) + gtk_widget_grab_focus(GTK_WIDGET(dialog)); g_free(utf8_filename); g_free(filename); continue; @@ -341,45 +342,52 @@ void project_open(void) { const gchar *dir = local_prefs.project_file_path; gchar *locale_path; - GtkWidget *dialog; + GtkFileChooser *dialog; GtkFileFilter *filter; - dialog = gtk_file_chooser_dialog_new(_("Open Project"), GTK_WINDOW(main_widgets.window), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - gtk_widget_set_name(dialog, "GeanyDialogProject"); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Open Project"), + GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel")); + else + { + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Open Project"), GTK_WINDOW(main_widgets.window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL)); + gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialogProject"); + + /* set default Open, so pressing enter can open multiple files */ + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE); + gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window)); + gtk_widget_show_all(GTK_WIDGET(dialog)); + } - /* set default Open, so pressing enter can open multiple files */ - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE); - gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window)); - gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); + gtk_file_chooser_set_select_multiple(dialog, TRUE); /* add FileFilters */ filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, _("All files")); gtk_file_filter_add_pattern(filter, "*"); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_add_filter(dialog, filter); filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, _("Project files")); gtk_file_filter_add_pattern(filter, "*." GEANY_PROJECT_EXT); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); - gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_add_filter(dialog, filter); + gtk_file_chooser_set_filter(dialog, filter); locale_path = utils_get_locale_from_utf8(dir); if (g_file_test(locale_path, G_FILE_TEST_EXISTS) && g_file_test(locale_path, G_FILE_TEST_IS_DIR)) { - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_path); + gtk_file_chooser_set_current_folder(dialog, locale_path); } g_free(locale_path); - gtk_widget_show_all(dialog); - run_open_dialog(GTK_DIALOG(dialog)); - gtk_widget_destroy(GTK_WIDGET(dialog)); + run_open_dialog(dialog); + dialogs_file_chooser_destroy(dialog); } @@ -485,16 +493,20 @@ static void destroy_project(gboolean open_default) static void on_project_properties_base_path_button_clicked(GtkWidget *button, GtkWidget *base_path_entry) { - GtkWidget *dialog; + GtkFileChooser *dialog; g_return_if_fail(base_path_entry != NULL); g_return_if_fail(GTK_IS_WIDGET(base_path_entry)); - dialog = gtk_file_chooser_dialog_new(_("Choose Project Base Path"), - NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, - NULL); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Choose Project Base Path"), + NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, "_Open", "_Cancel")); + else + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Choose Project Base Path"), + NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL)); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { @@ -502,7 +514,7 @@ static void on_project_properties_base_path_button_clicked(GtkWidget *button, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); } - gtk_widget_destroy(dialog); + dialogs_file_chooser_destroy(dialog); } @@ -875,7 +887,7 @@ static gboolean update_config(const PropertyDialogElements *e, gboolean new_proj } -static void run_dialog(GtkWidget *dialog, GtkWidget *entry) +static void run_dialog(GtkFileChooser *dialog, GtkWidget *entry) { /* set filename in the file chooser dialog */ const gchar *utf8_filename = gtk_entry_get_text(GTK_ENTRY(entry)); @@ -889,9 +901,9 @@ static void run_dialog(GtkWidget *dialog, GtkWidget *entry) * gtk_file_chooser_set_current_folder(which expects a locale filename) otherwise * we end up in the parent directory */ if (g_file_test(locale_filename, G_FILE_TEST_IS_DIR)) - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_filename); + gtk_file_chooser_set_current_folder(dialog, locale_filename); else - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), utf8_filename); + gtk_file_chooser_set_filename(dialog, utf8_filename); } else /* if the file doesn't yet exist, use at least the current directory */ { @@ -899,21 +911,21 @@ static void run_dialog(GtkWidget *dialog, GtkWidget *entry) gchar *name = g_path_get_basename(utf8_filename); if (g_file_test(locale_dir, G_FILE_TEST_EXISTS)) - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_dir); - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), name); + gtk_file_chooser_set_current_folder(dialog, locale_dir); + gtk_file_chooser_set_current_name(dialog, name); g_free(name); g_free(locale_dir); } } - else if (gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)) != GTK_FILE_CHOOSER_ACTION_OPEN) + else if (gtk_file_chooser_get_action(dialog) != GTK_FILE_CHOOSER_ACTION_OPEN) { - gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), utf8_filename); + gtk_file_chooser_set_current_name(dialog, utf8_filename); } g_free(locale_filename); /* run it */ - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + if (dialogs_file_chooser_run(dialog) == GTK_RESPONSE_ACCEPT) { gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); gchar *tmp_utf8_filename = utils_get_utf8_from_locale(filename); @@ -923,24 +935,30 @@ static void run_dialog(GtkWidget *dialog, GtkWidget *entry) g_free(tmp_utf8_filename); g_free(filename); } - gtk_widget_destroy(dialog); + dialogs_file_chooser_destroy(dialog); } static void on_file_save_button_clicked(GtkButton *button, PropertyDialogElements *e) { - GtkWidget *dialog; + GtkFileChooser *dialog; /* initialise the dialog */ - dialog = gtk_file_chooser_dialog_new(_("Choose Project Filename"), NULL, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); - gtk_widget_set_name(dialog, "GeanyDialogProject"); - gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE); - gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Choose Project Filename"), + NULL, GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", "_Cancel")); + else + { + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Choose Project Filename"), NULL, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL)); + gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialogProject"); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE); + gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); + } run_dialog(dialog, e->file_name); } diff --git a/src/symbols.c b/src/symbols.c index 244eb40adb..9d05b1227f 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -38,6 +38,7 @@ #include "app.h" #include "callbacks.h" /* FIXME: for ignore_callback */ +#include "dialogs.h" #include "documentprivate.h" #include "editor.h" #include "encodings.h" @@ -1263,23 +1264,29 @@ int symbols_generate_global_tags(int argc, char **argv, gboolean want_preprocess void symbols_show_load_tags_dialog(void) { - GtkWidget *dialog; + GtkFileChooser *dialog; GtkFileFilter *filter; - dialog = gtk_file_chooser_dialog_new(_("Load Tags File"), GTK_WINDOW(main_widgets.window), - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_OK, - NULL); - gtk_widget_set_name(dialog, "GeanyDialog"); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Load Tags File"), + GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel")); + else + { + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Load Tags File"), GTK_WINDOW(main_widgets.window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL)); + gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialog"); + } filter = gtk_file_filter_new(); gtk_file_filter_set_name(filter, _("Geany tags file (*.*.tags)")); gtk_file_filter_add_pattern(filter, "*.*.tags"); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + gtk_file_chooser_add_filter(dialog, filter); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) + if (dialogs_file_chooser_run(dialog) == GTK_RESPONSE_ACCEPT) { - GSList *flist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + GSList *flist = gtk_file_chooser_get_filenames(dialog); GSList *item; for (item = flist; item != NULL; item = g_slist_next(item)) @@ -1303,7 +1310,7 @@ void symbols_show_load_tags_dialog(void) } g_slist_free(flist); } - gtk_widget_destroy(dialog); + dialogs_file_chooser_destroy(dialog); } diff --git a/src/ui_utils.c b/src/ui_utils.c index 68d12f0ff8..f9f54c295f 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -1964,43 +1964,49 @@ void ui_setup_open_button_callback(GtkWidget *open_btn, const gchar *title, } -#ifndef G_OS_WIN32 static gchar *run_file_chooser(const gchar *title, GtkFileChooserAction action, const gchar *utf8_path) { - GtkWidget *dialog = gtk_file_chooser_dialog_new(title, - GTK_WINDOW(main_widgets.window), action, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + GtkFileChooser *dialog; gchar *locale_path; gchar *ret_path = NULL; - gtk_widget_set_name(dialog, "GeanyDialog"); + if (interface_prefs.use_native_windows_dialogs) + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(title, + GTK_WINDOW(main_widgets.window), action, "_Open", "_Cancel")); + else + { + dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(title, + GTK_WINDOW(main_widgets.window), action, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL)); + gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialog"); + } + locale_path = utils_get_locale_from_utf8(utf8_path); if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) { if (g_path_is_absolute(locale_path) && g_file_test(locale_path, G_FILE_TEST_IS_DIR)) - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_path); + gtk_file_chooser_set_current_folder(dialog, locale_path); } else if (action == GTK_FILE_CHOOSER_ACTION_OPEN) { if (g_path_is_absolute(locale_path)) - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), locale_path); + gtk_file_chooser_set_filename(dialog, locale_path); } g_free(locale_path); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) + if (dialogs_file_chooser_run(dialog) == GTK_RESPONSE_ACCEPT) { gchar *dir_locale; - dir_locale = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + dir_locale = gtk_file_chooser_get_filename(dialog); ret_path = utils_get_utf8_from_locale(dir_locale); g_free(dir_locale); } - gtk_widget_destroy(dialog); + dialogs_file_chooser_destroy(dialog); return ret_path; } -#endif gchar *ui_get_project_directory(const gchar *path) @@ -2008,11 +2014,7 @@ gchar *ui_get_project_directory(const gchar *path) gchar *utf8_path; const gchar *title = _("Select Project Base Path"); -#ifdef G_OS_WIN32 - utf8_path = win32_show_folder_dialog(ui_widgets.prefs_dialog, title, path); -#else utf8_path = run_file_chooser(title, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, path); -#endif return utf8_path; } @@ -2035,22 +2037,12 @@ static void ui_path_box_open_clicked(GtkButton *button, gpointer user_data) if (action == GTK_FILE_CHOOSER_ACTION_OPEN) { -#ifdef G_OS_WIN32 - utf8_path = win32_show_file_dialog(GTK_WINDOW(ui_widgets.prefs_dialog), title, - gtk_entry_get_text(GTK_ENTRY(entry))); -#else utf8_path = run_file_chooser(title, action, gtk_entry_get_text(GTK_ENTRY(entry))); -#endif } else if (action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) { gchar *path = g_path_get_dirname(gtk_entry_get_text(GTK_ENTRY(entry))); -#ifdef G_OS_WIN32 - utf8_path = win32_show_folder_dialog(ui_widgets.prefs_dialog, title, - gtk_entry_get_text(GTK_ENTRY(entry))); -#else utf8_path = run_file_chooser(title, action, path); -#endif g_free(path); } diff --git a/src/ui_utils.h b/src/ui_utils.h index 8b71f1779f..51a9ad92b6 100644 --- a/src/ui_utils.h +++ b/src/ui_utils.h @@ -63,7 +63,7 @@ typedef struct GeanyInterfacePrefs gboolean msgwin_compiler_visible; /**< whether message window's compiler tab is visible */ gboolean msgwin_messages_visible; /**< whether message window's messages tab is visible */ gboolean msgwin_scribble_visible; /**< whether message window's scribble tab is visible */ - /** whether to use native Windows' dialogs - ignored and not used anymore */ + /** whether to use platform-native file dialogs */ gboolean use_native_windows_dialogs; /** whether compiler messages window is automatically scrolled to show new messages */ gboolean compiler_tab_autoscroll; diff --git a/src/win32.c b/src/win32.c index 1f737ce584..5d1886ee96 100644 --- a/src/win32.c +++ b/src/win32.c @@ -181,95 +181,6 @@ static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM p } -/* Shows a folder selection dialog. - * initial_dir is expected in UTF-8 - * The selected folder name is returned. */ -gchar *win32_show_folder_dialog(GtkWidget *parent, const gchar *title, const gchar *initial_dir) -{ - BROWSEINFOW bi; - LPITEMIDLIST pidl; - gchar *result = NULL; - wchar_t fname[MAX_PATH]; - wchar_t w_title[512]; - - MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, G_N_ELEMENTS(w_title)); - - if (parent == NULL) - parent = main_widgets.window; - - memset(&bi, 0, sizeof bi); - bi.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(parent)); - bi.pidlRoot = NULL; - bi.lpszTitle = w_title; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM) get_dir_for_path(initial_dir); - bi.ulFlags = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_USENEWUI; - - pidl = SHBrowseForFolderW(&bi); - - /* convert the strange Windows folder list item something into an usual path string ;-) */ - if (pidl != NULL) - { - if (SHGetPathFromIDListW(pidl, fname)) - { - result = g_malloc0(MAX_PATH * 2); - WideCharToMultiByte(CP_UTF8, 0, fname, -1, result, MAX_PATH * 2, NULL, NULL); - } - CoTaskMemFree(pidl); - } - return result; -} - - -/* initial_dir can be NULL to use the current working directory. - * Returns: the selected filename */ -gchar *win32_show_file_dialog(GtkWindow *parent, const gchar *title, const gchar *initial_file) -{ - OPENFILENAMEW of; - gint retval; - gchar tmp[MAX_PATH]; - wchar_t w_file[MAX_PATH]; - wchar_t w_title[512]; - - w_file[0] = '\0'; - - if (initial_file != NULL) - MultiByteToWideChar(CP_UTF8, 0, initial_file, -1, w_file, G_N_ELEMENTS(w_file)); - - MultiByteToWideChar(CP_UTF8, 0, title, -1, w_title, G_N_ELEMENTS(w_title)); - - /* initialise file dialog info struct */ - memset(&of, 0, sizeof of); - of.lStructSize = sizeof of; - of.hwndOwner = GDK_WINDOW_HWND(gtk_widget_get_window(GTK_WIDGET(parent))); - - of.lpstrFile = w_file; - of.nMaxFile = 2048; - of.lpstrFileTitle = NULL; - of.lpstrTitle = w_title; - of.lpstrDefExt = L""; - of.Flags = OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING; - of.lpfnHook = win32_dialog_explorer_hook_proc; - retval = GetOpenFileNameW(&of); - - if (! retval) - { - if (CommDlgExtendedError()) - { - gchar *error = g_strdup_printf( - "File dialog box error (%x)", (gint) CommDlgExtendedError()); - win32_message_dialog(NULL, GTK_MESSAGE_ERROR, error); - g_free(error); - } - return NULL; - } - - WideCharToMultiByte(CP_UTF8, 0, w_file, -1, tmp, sizeof(tmp), NULL, NULL); - - return g_strdup(tmp); -} - - /* Creates a native Windows message box of the given type and returns always TRUE * or FALSE representing th pressed Yes or No button. * If type is not GTK_MESSAGE_QUESTION, it returns always TRUE. */ diff --git a/src/win32.h b/src/win32.h index d944587e45..b0bc339de9 100644 --- a/src/win32.h +++ b/src/win32.h @@ -30,15 +30,11 @@ G_BEGIN_DECLS -gchar *win32_show_file_dialog(GtkWindow *parent, const gchar *title, const gchar *initial_dir); - gboolean win32_message_dialog(GtkWidget *parent, GtkMessageType type, const gchar *msg); void win32_open_browser(const gchar *uri); -gchar *win32_show_folder_dialog(GtkWidget *parent, const gchar *title, const gchar *initial_dir); - gint win32_check_write_permission(const gchar *dir); void win32_init_debug_code(void);