use GtkFileDialog on newer gtk4 versions newapi

Sun, 29 Sep 2024 18:51:03 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 29 Sep 2024 18:51:03 +0200
branch
newapi
changeset 315
144c2b4683cb
parent 314
d96ba820083a
child 316
e15ff2183b43

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);
 }
 

mercurial