Mon, 11 Nov 2024 22:42:09 +0100
implement resourceviewer textfile save button
--- 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 {