# HG changeset patch # User Olaf Wintermann # Date 1707656342 -3600 # Node ID c254ed644edf13367014d068540001360e4c5327 # Parent 40d6af793c1a9da424be651a108f2e3f8477cb6c remove deleted resources from the browser list diff -r 40d6af793c1a -r c254ed644edf application/application.c --- 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(); } diff -r 40d6af793c1a -r c254ed644edf application/davcontroller.c --- 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*)); diff -r 40d6af793c1a -r c254ed644edf ui/common/types.c --- 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); } diff -r 40d6af793c1a -r c254ed644edf ui/ui/toolkit.h --- 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); diff -r 40d6af793c1a -r c254ed644edf ui/ui/window.h --- 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); diff -r 40d6af793c1a -r c254ed644edf ui/winui/util.h --- 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 + wchar_t* str2wstr(const char* str, int* newlen); wchar_t* str2wstr_len(const char* str, size_t len, int* newlen); diff -r 40d6af793c1a -r c254ed644edf ui/winui/window.cpp --- 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 @@ -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,