Skip to content

Commit 91fb885

Browse files
committed
Use GtkFileChooserNative depending on user configuration
1 parent de4f029 commit 91fb885

File tree

8 files changed

+239
-145
lines changed

8 files changed

+239
-145
lines changed

data/geany.glade

+16
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,22 @@
13111311
<property name="position">3</property>
13121312
</packing>
13131313
</child>
1314+
<child>
1315+
<object class="GtkCheckButton" id="check_native_dialogs">
1316+
<property name="label" translatable="yes">Use platform-native file dialogs</property>
1317+
<property name="visible">True</property>
1318+
<property name="can-focus">True</property>
1319+
<property name="receives-default">False</property>
1320+
<property name="tooltip-text" translatable="yes">Defines whether to use the platform-native file dialogs or whether to use the GTK default dialogs</property>
1321+
<property name="use-underline">True</property>
1322+
<property name="draw-indicator">True</property>
1323+
</object>
1324+
<packing>
1325+
<property name="expand">False</property>
1326+
<property name="fill">False</property>
1327+
<property name="position">4</property>
1328+
</packing>
1329+
</child>
13141330
</object>
13151331
</child>
13161332
</object>

src/dialogs.c

+117-80
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static void file_chooser_set_filter_idx(GtkFileChooser *chooser, guint idx)
122122
}
123123

124124

125-
static gboolean open_file_dialog_handle_response(GtkWidget *dialog, gint response)
125+
static gboolean open_file_dialog_handle_response(GtkFileChooser *dialog, gint response)
126126
{
127127
gboolean ret = TRUE;
128128

@@ -131,24 +131,28 @@ static gboolean open_file_dialog_handle_response(GtkWidget *dialog, gint respons
131131
GSList *filelist;
132132
GeanyFiletype *ft = NULL;
133133
const gchar *charset = NULL;
134-
GtkWidget *expander = ui_lookup_widget(dialog, "more_options_expander");
135-
GtkWidget *filetype_combo = ui_lookup_widget(dialog, "filetype_combo");
136-
GtkWidget *encoding_combo = ui_lookup_widget(dialog, "encoding_combo");
137134
gboolean ro = (response == GEANY_RESPONSE_VIEW); /* View clicked */
138135

139-
filesel_state.open.more_options_visible = gtk_expander_get_expanded(GTK_EXPANDER(expander));
140-
filesel_state.open.filter_idx = file_chooser_get_filter_idx(GTK_FILE_CHOOSER(dialog));
141-
filesel_state.open.filetype_idx = filetype_combo_box_get_active_filetype(GTK_COMBO_BOX(filetype_combo));
136+
if (GTK_IS_WIDGET(dialog))
137+
{
138+
GtkWidget *expander = ui_lookup_widget(GTK_WIDGET(dialog), "more_options_expander");
139+
GtkWidget *filetype_combo = ui_lookup_widget(GTK_WIDGET(dialog), "filetype_combo");
140+
GtkWidget *encoding_combo = ui_lookup_widget(GTK_WIDGET(dialog), "encoding_combo");
141+
142+
filesel_state.open.more_options_visible = gtk_expander_get_expanded(GTK_EXPANDER(expander));
143+
filesel_state.open.filter_idx = file_chooser_get_filter_idx(GTK_FILE_CHOOSER(dialog));
144+
filesel_state.open.filetype_idx = filetype_combo_box_get_active_filetype(GTK_COMBO_BOX(filetype_combo));
145+
filesel_state.open.encoding_idx = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(encoding_combo));
146+
}
142147

143148
/* ignore detect from file item */
144149
if (filesel_state.open.filetype_idx >= 0)
145150
ft = filetypes_index(filesel_state.open.filetype_idx);
146151

147-
filesel_state.open.encoding_idx = ui_encodings_combo_box_get_active_encoding(GTK_COMBO_BOX(encoding_combo));
148152
if (filesel_state.open.encoding_idx >= 0 && filesel_state.open.encoding_idx < GEANY_ENCODINGS_MAX)
149153
charset = encodings[filesel_state.open.encoding_idx].charset;
150154

151-
filelist = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
155+
filelist = gtk_file_chooser_get_filenames(dialog);
152156
if (filelist != NULL)
153157
{
154158
const gchar *first = filelist->data;
@@ -167,7 +171,7 @@ static gboolean open_file_dialog_handle_response(GtkWidget *dialog, gint respons
167171
}
168172
}
169173
if (app->project && !EMPTY(app->project->base_path))
170-
gtk_file_chooser_remove_shortcut_folder(GTK_FILE_CHOOSER(dialog),
174+
gtk_file_chooser_remove_shortcut_folder(dialog,
171175
app->project->base_path, NULL);
172176
return ret;
173177
}
@@ -365,54 +369,61 @@ static GtkWidget *add_file_open_extra_widget(GtkWidget *dialog)
365369
}
366370

367371

368-
static GtkWidget *create_open_file_dialog(void)
372+
static GtkFileChooser *create_open_file_dialog(void)
369373
{
370-
GtkWidget *dialog;
374+
GtkFileChooser *dialog;
371375
GtkWidget *viewbtn;
372376
GSList *node;
373377

374-
dialog = gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window),
375-
GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
376-
gtk_widget_set_name(dialog, "GeanyDialog");
377-
378-
viewbtn = gtk_dialog_add_button(GTK_DIALOG(dialog), C_("Open dialog action", "_View"), GEANY_RESPONSE_VIEW);
379-
gtk_widget_set_tooltip_text(viewbtn,
380-
_("Opens the file in read-only mode. If you choose more than one file to open, all files will be opened read-only."));
381-
382-
gtk_dialog_add_buttons(GTK_DIALOG(dialog),
383-
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
384-
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
385-
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
386-
387-
gtk_widget_set_size_request(dialog, -1, 460);
388-
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
389-
gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
390-
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
391-
gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
392-
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window));
393-
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
394-
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE);
395-
396-
/* add checkboxes and filename entry */
397-
gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), add_file_open_extra_widget(dialog));
378+
if (interface_prefs.use_native_windows_dialogs)
379+
dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Open File"),
380+
GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel"));
381+
else
382+
{
383+
dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Open File"), GTK_WINDOW(main_widgets.window),
384+
GTK_FILE_CHOOSER_ACTION_OPEN, NULL, NULL));
385+
gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialog");
386+
387+
viewbtn = gtk_dialog_add_button(GTK_DIALOG(dialog), C_("Open dialog action", "_View"), GEANY_RESPONSE_VIEW);
388+
gtk_widget_set_tooltip_text(viewbtn,
389+
_("Opens the file in read-only mode. If you choose more than one file to open, all files will be opened read-only."));
390+
391+
gtk_dialog_add_buttons(GTK_DIALOG(dialog),
392+
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
393+
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
394+
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
395+
396+
gtk_widget_set_size_request(GTK_WIDGET(dialog), -1, 460);
397+
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
398+
gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
399+
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
400+
gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
401+
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window));
402+
403+
/* add checkboxes and filename entry */
404+
gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(dialog), add_file_open_extra_widget(GTK_WIDGET(dialog)));
405+
406+
g_signal_connect(dialog, "notify::show-hidden",
407+
G_CALLBACK(on_file_open_show_hidden_notify), NULL);
408+
}
398409

399410
/* add FileFilters(start with "All Files") */
400-
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),
411+
gtk_file_chooser_add_filter(dialog,
401412
filetypes_create_file_filter(filetypes[GEANY_FILETYPES_NONE]));
402413
/* now create meta filter "All Source" */
403-
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog),
414+
gtk_file_chooser_add_filter(dialog,
404415
filetypes_create_file_filter_all_source());
405416
foreach_slist(node, filetypes_by_title)
406417
{
407418
GeanyFiletype *ft = node->data;
408419

409420
if (G_UNLIKELY(ft->id == GEANY_FILETYPES_NONE))
410421
continue;
411-
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filetypes_create_file_filter(ft));
422+
gtk_file_chooser_add_filter(dialog, filetypes_create_file_filter(ft));
412423
}
413424

414-
g_signal_connect(dialog, "notify::show-hidden",
415-
G_CALLBACK(on_file_open_show_hidden_notify), NULL);
425+
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
426+
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE);
416427

417428
return dialog;
418429
}
@@ -444,11 +455,29 @@ static void open_file_dialog_apply_settings(GtkWidget *dialog)
444455
}
445456

446457

458+
gint dialogs_file_chooser_run(GtkFileChooser *dialog)
459+
{
460+
if (GTK_IS_WIDGET(dialog))
461+
return gtk_dialog_run(GTK_DIALOG(dialog));
462+
463+
return gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog));
464+
}
465+
466+
467+
void dialogs_file_chooser_destroy(GtkFileChooser *dialog)
468+
{
469+
if (GTK_IS_WIDGET(dialog))
470+
gtk_widget_destroy(GTK_WIDGET(dialog));
471+
else
472+
g_object_unref(dialog);
473+
}
474+
475+
447476
/* This shows the file selection dialog to open a file. */
448477
void dialogs_show_open_file(void)
449478
{
450479
gchar *initdir;
451-
GtkWidget *dialog;
480+
GtkFileChooser *dialog;
452481

453482
/* set dialog directory to the current file's directory, if present */
454483
initdir = utils_get_current_file_dir_utf8();
@@ -461,18 +490,19 @@ void dialogs_show_open_file(void)
461490
SETPTR(initdir, utils_get_locale_from_utf8(initdir));
462491

463492
dialog = create_open_file_dialog();
464-
open_file_dialog_apply_settings(dialog);
493+
if (GTK_IS_WIDGET(dialog))
494+
open_file_dialog_apply_settings(GTK_WIDGET(dialog));
465495

466496
if (initdir != NULL && g_path_is_absolute(initdir))
467-
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), initdir);
497+
gtk_file_chooser_set_current_folder(dialog, initdir);
468498

469499
if (app->project && !EMPTY(app->project->base_path))
470-
gtk_file_chooser_add_shortcut_folder(GTK_FILE_CHOOSER(dialog),
500+
gtk_file_chooser_add_shortcut_folder(dialog,
471501
app->project->base_path, NULL);
472502

473503
while (!open_file_dialog_handle_response(dialog,
474-
gtk_dialog_run(GTK_DIALOG(dialog))));
475-
gtk_widget_destroy(dialog);
504+
dialogs_file_chooser_run(dialog)));
505+
dialogs_file_chooser_destroy(dialog);
476506

477507
g_free(initdir);
478508
}
@@ -507,11 +537,11 @@ static gboolean handle_save_as(GeanyDocument *doc,
507537

508538

509539
static gboolean save_as_dialog_handle_response(GeanyDocument *doc,
510-
GtkWidget *dialog, gint response)
540+
GtkFileChooser *dialog, gint response)
511541
{
512542
gboolean rename_file = FALSE;
513543
gboolean success = FALSE;
514-
gchar *new_filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
544+
gchar *new_filename = gtk_file_chooser_get_filename(dialog);
515545

516546
switch (response)
517547
{
@@ -549,39 +579,46 @@ static gboolean save_as_dialog_handle_response(GeanyDocument *doc,
549579
}
550580

551581

552-
static GtkWidget *create_save_file_dialog(GeanyDocument *doc)
582+
static GtkFileChooser *create_save_file_dialog(GeanyDocument *doc)
553583
{
554-
GtkWidget *dialog, *rename_btn;
584+
GtkFileChooser *dialog;
585+
GtkWidget *rename_btn;
555586
const gchar *initdir;
556587

557-
dialog = gtk_file_chooser_dialog_new(_("Save File"), GTK_WINDOW(main_widgets.window),
558-
GTK_FILE_CHOOSER_ACTION_SAVE, NULL, NULL);
559-
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
560-
gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
561-
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
562-
gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
563-
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window));
564-
gtk_widget_set_name(dialog, "GeanyDialog");
565-
566-
rename_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), _("R_ename"), GEANY_RESPONSE_RENAME);
567-
gtk_widget_set_tooltip_text(rename_btn, _("Save the file and rename it"));
568-
/* disable rename unless file exists on disk */
569-
gtk_widget_set_sensitive(rename_btn, doc->real_path != NULL);
570-
571-
gtk_dialog_add_buttons(GTK_DIALOG(dialog),
572-
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
573-
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
574-
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
588+
if (interface_prefs.use_native_windows_dialogs)
589+
dialog = GTK_FILE_CHOOSER(gtk_file_chooser_native_new(_("Save File"),
590+
GTK_WINDOW(main_widgets.window), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", "_Cancel"));
591+
else
592+
{
593+
dialog = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(_("Save File"), GTK_WINDOW(main_widgets.window),
594+
GTK_FILE_CHOOSER_ACTION_SAVE, NULL, NULL));
595+
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
596+
gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
597+
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), FALSE);
598+
gtk_window_set_type_hint(GTK_WINDOW(dialog), GDK_WINDOW_TYPE_HINT_DIALOG);
599+
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(main_widgets.window));
600+
gtk_widget_set_name(GTK_WIDGET(dialog), "GeanyDialog");
601+
602+
rename_btn = gtk_dialog_add_button(GTK_DIALOG(dialog), _("R_ename"), GEANY_RESPONSE_RENAME);
603+
gtk_widget_set_tooltip_text(rename_btn, _("Save the file and rename it"));
604+
/* disable rename unless file exists on disk */
605+
gtk_widget_set_sensitive(rename_btn, doc->real_path != NULL);
606+
607+
gtk_dialog_add_buttons(GTK_DIALOG(dialog),
608+
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
609+
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
610+
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
611+
}
575612

576-
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
577-
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), FALSE);
613+
gtk_file_chooser_set_do_overwrite_confirmation(dialog, TRUE);
614+
gtk_file_chooser_set_local_only(dialog, FALSE);
578615

579616
/* set the folder by default to the project base dir or the global pref for opening files */
580617
initdir = utils_get_default_dir_utf8();
581618
if (initdir)
582619
{
583620
gchar *linitdir = utils_get_locale_from_utf8(initdir);
584-
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), linitdir);
621+
gtk_file_chooser_set_current_folder(dialog, linitdir);
585622
g_free(linitdir);
586623
}
587624
return dialog;
@@ -590,7 +627,7 @@ static GtkWidget *create_save_file_dialog(GeanyDocument *doc)
590627

591628
static gboolean show_save_as_gtk(GeanyDocument *doc)
592629
{
593-
GtkWidget *dialog;
630+
GtkFileChooser *dialog;
594631
gint resp;
595632

596633
g_return_val_if_fail(DOC_VALID(doc), FALSE);
@@ -605,15 +642,15 @@ static gboolean show_save_as_gtk(GeanyDocument *doc)
605642
gchar *locale_basename = g_path_get_basename(locale_filename);
606643
gchar *locale_dirname = g_path_get_dirname(locale_filename);
607644

608-
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), locale_dirname);
609-
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), locale_basename);
645+
gtk_file_chooser_set_current_folder(dialog, locale_dirname);
646+
gtk_file_chooser_set_current_name(dialog, locale_basename);
610647

611648
g_free(locale_filename);
612649
g_free(locale_basename);
613650
g_free(locale_dirname);
614651
}
615652
else
616-
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), doc->file_name);
653+
gtk_file_chooser_set_current_name(dialog, doc->file_name);
617654
}
618655
else
619656
{
@@ -625,7 +662,7 @@ static gboolean show_save_as_gtk(GeanyDocument *doc)
625662
else
626663
fname = g_strdup(GEANY_STRING_UNTITLED);
627664

628-
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), fname);
665+
gtk_file_chooser_set_current_name(dialog, fname);
629666

630667
g_free(fname);
631668
}
@@ -637,15 +674,15 @@ static gboolean show_save_as_gtk(GeanyDocument *doc)
637674
/* Run the dialog synchronously, pausing this function call */
638675
do
639676
{
640-
resp = gtk_dialog_run(GTK_DIALOG(dialog));
677+
resp = dialogs_file_chooser_run(dialog);
641678
}
642679
while (! save_as_dialog_handle_response(doc, dialog, resp));
643680

644681
if (app->project && !EMPTY(app->project->base_path))
645-
gtk_file_chooser_remove_shortcut_folder(GTK_FILE_CHOOSER(dialog),
682+
gtk_file_chooser_remove_shortcut_folder(dialog,
646683
app->project->base_path, NULL);
647684

648-
gtk_widget_destroy(dialog);
685+
dialogs_file_chooser_destroy(dialog);
649686

650687
return (resp == GTK_RESPONSE_ACCEPT);
651688
}

src/dialogs.h

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ gint dialogs_show_prompt(GtkWidget *parent,
8080

8181
void dialogs_show_msgbox_with_secondary(GtkMessageType type, const gchar *text, const gchar *secondary);
8282

83+
gint dialogs_file_chooser_run(GtkFileChooser *dialog);
84+
void dialogs_file_chooser_destroy(GtkFileChooser *dialog);
85+
8386
#endif /* GEANY_PRIVATE */
8487

8588
G_END_DECLS

0 commit comments

Comments
 (0)