Sun, 29 Sep 2024 18:51:03 +0200
use GtkFileDialog on newer gtk4 versions
application/main.c | file | annotate | diff | comparison | revisions | |
ui/gtk/window.c | file | annotate | diff | comparison | revisions |
--- a/application/main.c Sun Sep 29 15:55:56 2024 +0200 +++ b/application/main.c Sun Sep 29 18:51:03 2024 +0200 @@ -60,7 +60,7 @@ } void action_button(UiEvent *event, void *userdata) { - ui_openfiledialog(event->obj, UI_FILEDIALOG_SELECT_SINGLE, action_file_selected, NULL); + ui_openfiledialog(event->obj, 0, action_file_selected, NULL); } void action_switch(UiEvent *event, void *userdata) {
--- a/ui/gtk/window.c Sun Sep 29 15:55:56 2024 +0200 +++ b/ui/gtk/window.c Sun Sep 29 18:51:03 2024 +0200 @@ -259,9 +259,122 @@ } -#if GTK_MAJOR_VERSION >= 40 -static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { - // TODO +#if GTK_MAJOR_VERSION >= 3 +UiFileList listmodel2filelist(GListModel *selection) { + UiFileList flist; + flist.files = NULL; + flist.nfiles = 0; + flist.nfiles = g_list_model_get_n_items(selection); + flist.files = calloc(flist.nfiles, sizeof(char*)); + for(int i=0;i<flist.nfiles;i++) { + GFile *file = g_list_model_get_item(selection, i); + char *path = g_file_get_path(file); + flist.files[i] = path ? strdup(path) : NULL; + g_object_unref(file); + } + return flist; +} +#endif + + +#if GTK_CHECK_VERSION(4, 10, 0) + +#define UI_GTK_FILEDIALOG_OPEN 16 +#define UI_GTK_FILEDIALOG_SAVE 32 + +static void filechooser_opened(GObject *source, GAsyncResult *result, void *data) { + UiEventData *event = data; + + GFile *file = NULL; + GListModel *selection = NULL; + GError *error = NULL; + + int mode = event->value; + int multi = mode & UI_FILEDIALOG_SELECT_MULTI; + if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { + if(multi) { + selection = gtk_file_dialog_select_multiple_folders_finish(GTK_FILE_DIALOG(source), result, &error); + } else { + file = gtk_file_dialog_select_folder_finish(GTK_FILE_DIALOG(source), result, &error); + } + } else if((mode & UI_GTK_FILEDIALOG_OPEN) == UI_GTK_FILEDIALOG_OPEN) { + if(multi) { + selection = gtk_file_dialog_open_multiple_finish(GTK_FILE_DIALOG(source), result, &error); + } else { + file = gtk_file_dialog_open_finish(GTK_FILE_DIALOG(source), result, &error); + } + } else { + file = gtk_file_dialog_save_finish(GTK_FILE_DIALOG(source), result, &error); + } + + UiEvent evt; + evt.obj = event->obj; + evt.document = evt.obj->ctx->document; + evt.window = evt.obj->window; + evt.intval = 0; + + UiFileList flist; + flist.files = NULL; + flist.nfiles = 0; + evt.eventdata = &flist; + + if(selection) { + flist = listmodel2filelist(selection); + g_object_unref(selection); + } else if(file) { + char *path = g_file_get_path(file); + if(path) { + flist.nfiles = 1; + flist.files = calloc(flist.nfiles, sizeof(char*)); + flist.files[0] = strdup(path); + } + g_object_unref(file); + } + + if(event->callback) { + event->callback(&evt, event->userdata); + } + + for(int i=0;i<flist.nfiles;i++) { + free(flist.files[i]); + } +} + +static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) { + if(action == GTK_FILE_CHOOSER_ACTION_OPEN) { + mode |= UI_GTK_FILEDIALOG_OPEN; + } else { + mode |= UI_GTK_FILEDIALOG_SAVE; + } + + UiEventData *event = malloc(sizeof(UiEventData)); + event->callback = file_selected_callback; + event->userdata = cbdata; + event->customdata = NULL; + event->value = mode; + event->obj = obj; + + GtkWindow *parent = GTK_WINDOW(gtk_widget_get_root(obj->widget)); + GtkFileDialog *dialog = gtk_file_dialog_new(); + + int multi = mode & UI_FILEDIALOG_SELECT_MULTI; + if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { + if(multi) { + gtk_file_dialog_select_multiple_folders(dialog, parent, NULL, filechooser_opened, event); + } else { + gtk_file_dialog_select_folder(dialog, parent, NULL, filechooser_opened, event); + } + } else if(action == GTK_FILE_CHOOSER_ACTION_OPEN) { + if(multi) { + gtk_file_dialog_open_multiple(dialog, parent, NULL, filechooser_opened, event); + } else { + gtk_file_dialog_open(dialog, parent, NULL, filechooser_opened, event); + } + } else { + gtk_file_dialog_save(dialog, parent, NULL, filechooser_opened, event); + } + + g_object_unref(dialog); } #else @@ -282,14 +395,7 @@ if(response_id == GTK_RESPONSE_ACCEPT) { #if GTK_CHECK_VERSION(4, 0, 0) GListModel *selection = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(self)); - flist.nfiles = g_list_model_get_n_items(selection); - flist.files = calloc(flist.nfiles, sizeof(char*)); - for(int i=0;i<flist.nfiles;i++) { - GFile *file = g_list_model_get_item(selection, i); - char *path = g_file_get_path(file); - flist.files[i] = strdup(path ? path : ""); - g_object_unref(file); - } + flist = flist = listmodel2filelist(selection); g_object_unref(selection); #else GSList *selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(self)); @@ -319,7 +425,7 @@ WINDOW_DESTROY(GTK_WIDGET(self)); } -static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { +static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) { char *button; char *title; @@ -395,10 +501,10 @@ #endif void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { - ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, file_selected_callback, cbdata); + ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, NULL, file_selected_callback, cbdata); } void ui_savefiledialog(UiObject *obj, const char *name, ui_callback file_selected_callback, void *cbdata) { - ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, file_selected_callback, cbdata); + ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, name, file_selected_callback, cbdata); }