implement resourceviewer textfile save button

Mon, 11 Nov 2024 22:42:09 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 11 Nov 2024 22:42:09 +0100
changeset 78
ad7ced6cf00b
parent 77
5de33c2d94c6
child 79
483d7342b439

implement resourceviewer textfile save button

application/application.h file | annotate | diff | comparison | revisions
application/davcontroller.c file | annotate | diff | comparison | revisions
application/davcontroller.h file | annotate | diff | comparison | revisions
application/window.c file | annotate | diff | comparison | revisions
application/window.h file | annotate | diff | comparison | revisions
ui/gtk/text.c file | annotate | diff | comparison | revisions
ui/gtk/text.h file | annotate | diff | comparison | revisions
--- a/application/application.h	Mon Nov 11 20:45:34 2024 +0100
+++ b/application/application.h	Mon Nov 11 22:42:09 2024 +0100
@@ -47,6 +47,8 @@
 #define APP_STATE_BROWSER_SESSION 100
 #define APP_STATE_BROWSER_SELECTION 110
     
+#define RESOURCEVIEWER_STATE_MODIFIED 2000
+    
 typedef struct DavApp {
     DavConfig *dav_config;
     UiList *repos;
--- a/application/davcontroller.c	Mon Nov 11 20:45:34 2024 +0100
+++ b/application/davcontroller.c	Mon Nov 11 22:42:09 2024 +0100
@@ -1433,7 +1433,6 @@
 
 static void resourceviewer_load_finished(UiEvent *event, void *data) {
     DavResourceViewer *doc = data;
-    doc->loaded = TRUE;
     
     if(doc->window_closed) {
         dav_resourceviewer_destroy(doc);
@@ -1450,6 +1449,8 @@
     }
       
     ui_set(doc->tabview, 1);
+    
+    doc->loaded = TRUE;
 }
 
 void dav_resourceviewer_load(UiObject *ui, DavResourceViewer *res) {
@@ -1460,6 +1461,57 @@
     ui_job(ui, jobthr_resourceviewer_load, res, resourceviewer_load_finished, res);
 }
 
+
+typedef struct ResourceViewerUploadFile {
+    UiObject *ui;
+    DavSession *sn;
+    char *path;
+    cxmutstr text;
+    int error;
+} ResourceViewerUploadFile;
+
+static int jobthr_upload_text(void *data) {
+    ResourceViewerUploadFile *upload = data;
+    
+    DavResource *res = dav_resource_new(upload->sn, upload->path);
+    dav_set_content_data(res, upload->text.ptr, upload->text.length);
+    upload->error = dav_store(res);
+    dav_resource_free(res);
+    
+    return 0;
+}
+
+static void uithr_upload_text_finished(UiEvent *event, void *data) {
+    ResourceViewerUploadFile *upload = data;
+    
+    if(upload->error) {
+        cxmutstr errormsg = cx_asprintf("Upload failed: %d", upload->sn->error); // TODO: add full error message
+        ui_dialog(event->obj, .title = "Error", .content = errormsg.ptr, .closebutton_label = "OK");
+        free(errormsg.ptr);
+        ui_set_group(event->obj->ctx, RESOURCEVIEWER_STATE_MODIFIED);
+    }
+    
+    dav_session_destroy(upload->sn);
+    free(upload->path);
+    free(upload->text.ptr);
+    free(upload);
+}
+
+void dav_resourceviewer_save(UiObject *ui, DavResourceViewer *res) {
+    if(res->type == DAV_RESOURCE_VIEW_TEXT) {
+        DavSession *newsn = dav_session_clone(res->current->session);
+        ResourceViewerUploadFile *upload = malloc(sizeof(ResourceViewerUploadFile));
+        upload->ui = ui;
+        upload->sn = newsn;
+        upload->path = strdup(res->current->path);
+        char *text = ui_get(res->text);
+        size_t textlen = strlen(text);
+        upload->text = cx_strdup(cx_strn(text, textlen));
+        ui_job(ui, jobthr_upload_text, upload, uithr_upload_text_finished, upload);
+        ui_unset_group(ui->ctx, RESOURCEVIEWER_STATE_MODIFIED);
+    }
+}
+
 void dav_resourceviewer_destroy(DavResourceViewer *res) {
     
 }
--- a/application/davcontroller.h	Mon Nov 11 20:45:34 2024 +0100
+++ b/application/davcontroller.h	Mon Nov 11 22:42:09 2024 +0100
@@ -80,6 +80,8 @@
 
 void dav_resourceviewer_load(UiObject *ui, DavResourceViewer *res);
 
+void dav_resourceviewer_save(UiObject *ui, DavResourceViewer *res);
+
 void dav_resourceviewer_destroy(DavResourceViewer *res);
 
 #ifdef	__cplusplus
--- a/application/window.c	Mon Nov 11 20:45:34 2024 +0100
+++ b/application/window.c	Mon Nov 11 22:42:09 2024 +0100
@@ -129,6 +129,16 @@
     UiObject *win = ui_simple_window(name, NULL);
     ui_window_size(win, 600, 600);
     
+    // TODO: when properties can be modified, always add the headerbar
+    if(type == DAV_RESOURCE_VIEW_TEXT) {
+        ui_headerbar(win, .showtitle = TRUE) {
+            ui_headerbar_start(win) {
+                ui_button(win, .label = "Save", .style_class = "suggested-action", .onclick = action_resourceviewer_save, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_MODIFIED));
+            }
+        }
+    }
+    
+    
     DavResourceViewer *doc = dav_resourceviewer_create(browser->sn, path, type);
     ui_attach_document(win->ctx, doc);
     ui_context_closefunc(win->ctx, resourceviewer_close, doc);
@@ -147,7 +157,7 @@
             ui_tabview0(win) {
                 if(type == DAV_RESOURCE_VIEW_TEXT) {
                     ui_tab(win, "Content") {
-                        ui_textarea(win, .varname = "text");
+                        ui_textarea(win, .varname = "text", .onchange = action_resourceviewer_text_modified);
                     }
                 } else if(type == DAV_RESOURCE_VIEW_IMAGE) {
                     ui_tab(win, "Preview") {
@@ -405,3 +415,18 @@
 
     davbrowser_upload_files(event->obj, event->document, files);
 }
+
+
+/* ------------------------ resource viewer actions ------------------------ */
+
+void action_resourceviewer_text_modified(UiEvent *event, void *data) {
+    DavResourceViewer *doc = event->document;
+    if(doc->loaded) {
+        ui_set_group(event->obj->ctx, RESOURCEVIEWER_STATE_MODIFIED);
+    }
+}
+
+void action_resourceviewer_save(UiEvent *event, void *data) {
+    DavResourceViewer *doc = event->document;
+    dav_resourceviewer_save(event->obj, doc);
+}
--- a/application/window.h	Mon Nov 11 20:45:34 2024 +0100
+++ b/application/window.h	Mon Nov 11 22:42:09 2024 +0100
@@ -73,6 +73,9 @@
 
 void action_dnd_drop(UiEvent *event, void *data);
 
+void action_resourceviewer_text_modified(UiEvent *event, void *data);
+void action_resourceviewer_save(UiEvent *event, void *data);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/gtk/text.c	Mon Nov 11 20:45:34 2024 +0100
+++ b/ui/gtk/text.c	Mon Nov 11 22:42:09 2024 +0100
@@ -78,9 +78,12 @@
             NULL);
     
     UiTextArea *uitext = malloc(sizeof(UiTextArea));
+    uitext->obj = obj;
     uitext->ctx = obj->ctx;
     uitext->var = var;
     uitext->last_selection_state = 0;
+    uitext->onchange = args.onchange;
+    uitext->onchangedata = args.onchangedata;
     
     g_signal_connect(
                 text_area,
@@ -266,13 +269,19 @@
 
 void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea) {
     UiText *value = textarea->var->value;
+    
+    UiEvent e;
+    e.obj = textarea->obj;
+    e.window = e.obj->window;
+    e.document = textarea->ctx->document;
+    e.eventdata = value;
+    e.intval = 0;
+    
+    if(textarea->onchange) {
+        textarea->onchange(&e, textarea->onchangedata);
+    }
+    
     if(value->observers) {
-        UiEvent e;
-        e.obj = textarea->ctx->obj;
-        e.window = e.obj->window;
-        e.document = textarea->ctx->document;
-        e.eventdata = value;
-        e.intval = 0;
         ui_notify_evt(value->observers, &e);
     }
 }
--- a/ui/gtk/text.h	Mon Nov 11 20:45:34 2024 +0100
+++ b/ui/gtk/text.h	Mon Nov 11 22:42:09 2024 +0100
@@ -61,9 +61,12 @@
 } UiUndoMgr;
 
 typedef struct UiTextArea {
-    UiContext *ctx;
-    UiVar    *var;
-    int       last_selection_state;
+    UiObject    *obj;
+    UiContext   *ctx;
+    UiVar       *var;
+    int         last_selection_state;
+    ui_callback onchange;
+    void        *onchangedata;
 } UiTextArea;
 
 typedef struct UiTextField {

mercurial