remove deleted resources from the browser list

Sun, 11 Feb 2024 13:59:02 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 11 Feb 2024 13:59:02 +0100
changeset 27
c254ed644edf
parent 26
40d6af793c1a
child 28
1ecc1183f046

remove deleted resources from the browser list

application/application.c file | annotate | diff | comparison | revisions
application/davcontroller.c file | annotate | diff | comparison | revisions
ui/common/types.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
ui/ui/window.h file | annotate | diff | comparison | revisions
ui/winui/util.h file | annotate | diff | comparison | revisions
ui/winui/window.cpp file | annotate | diff | comparison | revisions
--- a/application/application.c	Fri Feb 09 16:50:23 2024 +0100
+++ b/application/application.c	Sun Feb 11 13:59:02 2024 +0100
@@ -41,6 +41,7 @@
 
 void application_init(void) {
 	davctx = dav_context_new();
+	dav_context_set_mtsafe(davctx, true);
 
 	application_create_menu();
 }
--- a/application/davcontroller.c	Fri Feb 09 16:50:23 2024 +0100
+++ b/application/davcontroller.c	Sun Feb 11 13:59:02 2024 +0100
@@ -669,41 +669,117 @@
 // ------------------------------------- Path Operation (DELETE, MKCOL) -------------------------------------
 
 enum DavPathOpType {
-    DAV_PATH_OP_DELETE = 0
+    DAV_PATH_OP_DELETE = 0,
+    DAV_PATH_OP_MKCOL
 };
 
 typedef struct DavPathOp {
+    UiObject *ui;
+    DavBrowser *browser;
+
+    // operation type (delete, mkcol, ...)
     enum DavPathOpType op;
+    // clone of the browser's DavSession
     DavSession *sn;
+    // path array
     char **path;
+    // browser->resources indices
     size_t *list_indices;
+    // number of path/list_indices elements
     size_t nelm;
+
+    // browser->current ptr when the PathOp started
+    // used in combination with collection_ctn to check if the browser list changed
     DavResource *collection;
     int64_t collection_ctn;
 } DavPathOp;
 
+typedef struct DavPathOpResult {
+    UiObject *ui;
+    DavBrowser *browser;
+    DavResource *collection;
+    int64_t collection_ctn;
+
+    char *path;
+    int res_index;
+    int result;
+    char *errormsg;
+} DavPathOpResult;
+
+static int uithr_pathop_delete_error(void *data) {
+    DavPathOpResult *result = data;
+
+    cxmutstr msg = cx_asprintf("Cannot delete resource %s", result->path);
+    ui_dialog(result->ui, .title = "Error", .content = msg.ptr, .button1_label = "OK");
+    free(msg.ptr);
+
+    if (result->errormsg) {
+        free(result->errormsg);
+    }
+    free(result->path);
+    free(result);
+    return 0;
+}
+
+static int uithr_pathop_delete_sucess(void *data) {
+    DavPathOpResult *result = data;
+
+    if (result->browser->current == result->collection && result->browser->res_counter == result->collection_ctn) {
+        ui_list_remove(result->browser->resources, result->res_index);
+        result->browser->resources->update(result->browser->resources, 0);
+    }
+
+    free(result->path);
+    free(result);
+    return 0;
+}
+
 static int jobthr_path_op(void *data) {
     DavPathOp *op = data;
 
-    for (int i = 0; i < op->nelm; i++) {
+
+    for (int i = op->nelm-1; i >= 0; i--) {
         if (op->path[i]) {
             DavResource *res = dav_resource_new(op->sn, op->path[i]);
 
-            int ret = 0;
+            DavPathOpResult *result = malloc(sizeof(DavPathOpResult));
+            result->ui = op->ui;
+            result->browser = op->browser;
+            result->collection = op->collection;
+            result->collection_ctn = op->collection_ctn;
+            result->path = strdup(res->path);
+            result->result = 0;
+            result->res_index = op->list_indices[i];
+            result->errormsg = NULL;
+    
             if (op->op == DAV_PATH_OP_DELETE) {
-                ret = dav_delete(res);
+                ui_threadfunc result_callback = uithr_pathop_delete_sucess;
+                if (dav_delete(res)) {
+                    result->errormsg = op->sn->errorstr ? strdup(op->sn->errorstr) : NULL;
+                    result_callback = uithr_pathop_delete_error;
+                }
+                ui_call_mainthread(result_callback, result);
             }
 
             dav_resource_free(res);
+            free(op->path[i]);
         }
     }
 
+    dav_session_destroy(op->sn);
+    free(op->path);
+    free(op->list_indices);
+    free(op);
 
     return 0;
 }
 
+
+
 void davbrowser_delete(UiObject *ui, DavBrowser *browser, UiListSelection selection) {
     DavPathOp *op = malloc(sizeof(DavPathOp));
+    op->ui = ui;
+    op->browser = browser;
     op->op = DAV_PATH_OP_DELETE;
     op->sn = dav_session_clone(browser->sn);
     op->path = calloc(selection.count, sizeof(char*));
--- a/ui/common/types.c	Fri Feb 09 16:50:23 2024 +0100
+++ b/ui/common/types.c	Sun Feb 11 13:59:02 2024 +0100
@@ -150,6 +150,10 @@
     cxListInsert(list->data, 0, data);
 }
 
+void ui_list_remove(UiList *list, int i) {
+    cxListRemove(list->data, i);
+}
+
 void ui_list_clear(UiList *list) {
     cxListClear(list->data);
 }
--- a/ui/ui/toolkit.h	Fri Feb 09 16:50:23 2024 +0100
+++ b/ui/ui/toolkit.h	Sun Feb 11 13:59:02 2024 +0100
@@ -474,6 +474,7 @@
 UIEXPORT int   ui_list_count(UiList *list);
 UIEXPORT void  ui_list_append(UiList *list, void *data);
 UIEXPORT void  ui_list_prepend(UiList *list, void *data);
+UIEXPORT void ui_list_remove(UiList *list, int i);
 UIEXPORT void ui_list_clear(UiList *list);
 UIEXPORT void  ui_list_addobsv(UiList *list, ui_callback f, void *data);
 UIEXPORT void  ui_list_notify(UiList *list);
--- a/ui/ui/window.h	Fri Feb 09 16:50:23 2024 +0100
+++ b/ui/ui/window.h	Sun Feb 11 13:59:02 2024 +0100
@@ -39,11 +39,25 @@
 #define UI_FILEDIALOG_SELECT_MULTI        1
 #define UI_FILEDIALOG_SELECT_FOLDER       2
 
+typedef struct UiDialogArgs {
+    const char *title;
+    const char *content;
+    const char *button1_label;
+    const char *button2_label;
+    const char *closebutton_label;
+    ui_callback result;
+    void *resultdata;
+} UiDialogArgs;
+
 UIEXPORT UiObject* ui_window(const char *title, void *window_data);
 UIEXPORT UiObject* ui_simple_window(const char *title, void *window_data);
 
 UIEXPORT void ui_window_size(UiObject *obj, int width, int height);
 
+#define ui_dialog(parent, ...) ui_dialog_create(parent, (UiDialogArgs){ __VA_ARGS__ } )
+
+UIEXPORT void ui_dialog_create(UiObject *parent, UiDialogArgs args);
+
 UIEXPORT void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata);
 UIEXPORT void ui_savefiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata);
 
--- a/ui/winui/util.h	Fri Feb 09 16:50:23 2024 +0100
+++ b/ui/winui/util.h	Sun Feb 11 13:59:02 2024 +0100
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <stdlib.h>
+
 wchar_t* str2wstr(const char* str, int* newlen);
 
 wchar_t* str2wstr_len(const char* str, size_t len, int* newlen);
--- a/ui/winui/window.cpp	Fri Feb 09 16:50:23 2024 +0100
+++ b/ui/winui/window.cpp	Sun Feb 11 13:59:02 2024 +0100
@@ -37,6 +37,7 @@
 #include "util.h"
 
 #include "../common/context.h"
+#include "../common/object.h"
 
 #include <stdlib.h>
 
@@ -204,6 +205,70 @@
 	}
 }
 
+
+
+
+static Windows::Foundation::IAsyncAction create_dialog_async(UiObject *obj, UiDialogArgs args) {
+	UiObject* current = uic_current_obj(obj);
+	Window parentWindow = current->wobj->window;
+
+	ContentDialog dialog = ContentDialog();
+	dialog.XamlRoot(parentWindow.Content().XamlRoot());
+
+	if (args.title) {
+		wchar_t *str = str2wstr(args.title, nullptr);
+		dialog.Title(winrt::box_value(str));
+		free(str);
+	}
+	if (args.content) {
+		wchar_t *str = str2wstr(args.content, nullptr);
+		dialog.Content(winrt::box_value(str));
+		free(str);
+	}
+
+	if (args.button1_label) {
+		wchar_t *str = str2wstr(args.button1_label, nullptr);
+		dialog.PrimaryButtonText(winrt::hstring(str));
+		free(str);
+	}
+	if (args.button2_label) {
+		wchar_t *str = str2wstr(args.button2_label, nullptr);
+		dialog.SecondaryButtonText(winrt::hstring(str));
+		free(str);
+	}
+	if (args.closebutton_label) {
+		wchar_t *str = str2wstr(args.closebutton_label, nullptr);
+		dialog.CloseButtonText(winrt::hstring(str));
+		free(str);
+	}
+
+	ContentDialogResult result = co_await dialog.ShowAsync();
+
+	if (args.result) {
+		UiEvent evt;
+		evt.obj = current;
+		evt.document = current->ctx->document;
+		evt.window = current->window;
+		evt.eventdata = NULL;
+		evt.intval = 0;
+		if (result == ContentDialogResult::Primary) {
+			evt.intval = 1;
+		} else if (result == ContentDialogResult::Secondary) {
+			evt.intval = 2;
+		}
+
+		args.result(&evt, args.resultdata);
+	}
+}
+
+UIEXPORT void ui_dialog_create(UiObject *obj, UiDialogArgs args) {
+	create_dialog_async(obj, args);
+}
+
+
+
+// --------------------------------------- File Dialog ---------------------------------------
+
 static void filedialog_callback(
 	UiObject *obj,
 	ui_callback file_selected_callback,

mercurial