ui/gtk/window.c

changeset 45
ab71409644b0
parent 44
473954dc6b74
--- a/ui/gtk/window.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/window.c	Sun Sep 29 20:25:41 2024 +0200
@@ -119,11 +119,13 @@
     GtkWidget *toolbar_view = adw_toolbar_view_new();
     adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view);
     adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox);
-    
+
     GtkWidget *headerbar = adw_header_bar_new();
     adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar);
     
-    ui_fill_headerbar(obj, headerbar);
+    if(!simple) {
+        ui_fill_headerbar(obj, headerbar);
+    }
 #elif GTK_MAJOR_VERSION >= 4
     WINDOW_SET_CONTENT(obj->widget, vbox);
 #else
@@ -259,12 +261,176 @@
 }
 
 
-#if GTK_MAJOR_VERSION >= 4
-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();
+    if(name) {
+        gtk_file_dialog_set_initial_name(dialog, name);
+    }
+    
+    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
-static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
+
+
+
+static void filechooser_response(GtkDialog* self, gint response_id, UiEventData *data) {
+    UiEvent evt;
+    evt.obj = data->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(response_id == GTK_RESPONSE_ACCEPT) {
+#if GTK_CHECK_VERSION(4, 0, 0)
+        GListModel *selection = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(self));
+        flist = flist = listmodel2filelist(selection);
+        g_object_unref(selection);
+#else
+        GSList *selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(self));
+        flist.nfiles = g_slist_length(selection);
+        flist.files = calloc(flist.nfiles, sizeof(char*));
+        int i = 0;
+        while(selection) {
+            char *file = selection->data;
+            flist.files[i] = strdup(file);
+            g_free(file);
+            selection = selection->next;
+            i++;
+        }
+        g_slist_free(selection);
+#endif
+    }
+    
+    
+    if(data->callback) {
+        data->callback(&evt, data->userdata);
+    }
+    
+    for(int i=0;i<flist.nfiles;i++) {
+        free(flist.files[i]);
+    }
+    
+    WINDOW_DESTROY(GTK_WIDGET(self));
+}
+
+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;
     
@@ -305,6 +471,25 @@
         gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
     }
     
+    UiEventData *event = malloc(sizeof(UiEventData));
+    event->obj = obj;
+    event->userdata = cbdata;
+    event->callback = file_selected_callback;
+    event->value = 0;
+    event->customdata = NULL;
+    
+    g_signal_connect(
+                dialog,
+                "response",
+                G_CALLBACK(filechooser_response),
+                event);
+    g_signal_connect(
+                dialog,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
+    
+    
     UiEvent evt;
     evt.obj = obj;
     evt.document = evt.obj->ctx->document;
@@ -316,39 +501,15 @@
     flist.nfiles = 0;
     evt.eventdata = &flist;
     
-    int result = gtk_dialog_run(GTK_DIALOG (dialog));
-    GSList *selection = NULL;
-    if(result == GTK_RESPONSE_ACCEPT) {
-        selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
-        flist.nfiles = g_slist_length(selection);
-        flist.files = calloc(flist.nfiles, sizeof(char*));
-        int i = 0;
-        while(selection) {
-            flist.files[i] = selection->data;
-            selection = selection->next;
-            i++;
-        }
-    }
-    
-    if(file_selected_callback) {
-        file_selected_callback(&evt, cbdata);
-    }
-    
-    for(int i=0;i<flist.nfiles;i++) {
-        g_free(flist.files[i]);
-    } 
-    free(flist.files);
-    g_slist_free(selection);
-    
-    gtk_widget_destroy(dialog);
+    gtk_widget_show(dialog);
 }
 #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