Fri, 09 Feb 2024 16:50:23 +0100
implement resource deletion
application/application.c | file | annotate | diff | comparison | revisions | |
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 | |
ui/common/context.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/tree.h | file | annotate | diff | comparison | revisions | |
ui/winui/table.cpp | file | annotate | diff | comparison | revisions | |
ui/winui/table.h | file | annotate | diff | comparison | revisions |
--- a/application/application.c Thu Feb 08 10:35:07 2024 +0100 +++ b/application/application.c Fri Feb 09 16:50:23 2024 +0100 @@ -88,7 +88,7 @@ ui_toolbar_item("NewFile", .icon = "Add"); ui_toolbar_item("Upload", .label = "Upload", .icon = "Upload", .onclick = action_upload_file); ui_toolbar_item("Download", .icon = "SaveLocal"); - ui_toolbar_item("Remove", .icon = "Delete"); + ui_toolbar_item("Remove", .icon = "Delete", .onclick = action_delete ); ui_toolbar_toggleitem("LocalBrowser", .icon = "DockLeft", .label = "Local Browser"); ui_toolbar_toggleitem("PreviewPane", .icon = "DockRight"); @@ -177,3 +177,12 @@ void action_upload_file(UiEvent *event, void *data) { ui_openfiledialog(event->obj, UI_FILEDIALOG_SELECT_MULTI, file_selected, NULL); } + +void action_delete(UiEvent *event, void *data) { + DavBrowser *browser = event->document; + UiListSelection sel = ui_list_getselection(browser->resources); + if (sel.count > 0) { + davbrowser_delete(event->obj, browser, sel); + } + ui_listselection_free(sel); +}
--- a/application/application.h Thu Feb 08 10:35:07 2024 +0100 +++ b/application/application.h Fri Feb 09 16:50:23 2024 +0100 @@ -62,6 +62,11 @@ DavResource *current; + /* + * incremented every time current is updated + */ + uint64_t res_counter; + CxList *navigation_stack; bool navstack_enabled; int navstack_pos; @@ -104,6 +109,8 @@ void action_upload_file(UiEvent *event, void *data); +void action_delete(UiEvent *event, void *data); + #ifdef __cplusplus } #endif
--- a/application/davcontroller.c Thu Feb 08 10:35:07 2024 +0100 +++ b/application/davcontroller.c Fri Feb 09 16:50:23 2024 +0100 @@ -63,6 +63,7 @@ ui_list_clear(browser->resources); browser->current = collection; + browser->res_counter++; for (DavResource *res = collection->children; res; res = res->next) { ui_list_append(browser->resources, res); } @@ -267,6 +268,19 @@ UiString *label_top_right; UiString *label_bottom_left; UiString *label_bottom_right; + + // The collection, the files are uploaded to + // It is only safe to access the collection ptr, if + // collection == browser->current && collection_ctn == browser->res_counter + // and obviously it can only be accessed from the UI thread + DavResource *collection; + + // copy of browser->res_counter, used for integrity check + int64_t collection_ctn; + + // current uploaded resource, created as part of the browser session + // only if collection == browser->current && collection_ctn == browser->res_counter + DavResource *current_resource; } DavFileUpload; typedef struct DUFile { @@ -348,6 +362,8 @@ typedef struct FileNameUpdate { DavFileUpload *upload; char *name; + char *path; + DavBool iscollection; } FileNameUpdate; static int uithr_update_file_label(FileNameUpdate *update) { @@ -359,6 +375,37 @@ ui_set(update->upload->label_top_right, update->name); + DavFileUpload *upload = update->upload; + DavBrowser *browser = upload->browser; + // update the resource list in the browser, if the current collection has not changed + if (upload->collection == browser->current && upload->collection_ctn == browser->res_counter) { + char *parent = util_parent_path(update->path); + cxstring parent_s = cx_str(parent); + cxstring colpath_s = cx_str(upload->collection->path); + if (parent_s.length > 0 && parent_s.ptr[parent_s.length - 1] == '/') { + parent_s.length--; + } + if (colpath_s.length > 0 && colpath_s.ptr[colpath_s.length - 1] == '/') { + colpath_s.length--; + } + + // only update, if the added resource has the current collection as parent + if (!cx_strcmp(parent_s, colpath_s)) { + DavResource *ui_res = dav_resource_new(upload->collection->session, update->path); + ui_res->iscollection = update->iscollection; + ui_res->lastmodified = time(NULL); + ui_res->creationdate = time(NULL); + upload->current_resource = ui_res; + + ui_list_append(browser->resources, ui_res); + browser->resources->update(browser->resources, 0); + } else { + upload->current_resource = NULL; // maybe not necessary + } + free(parent); + } + + free(update->path); free(update); return 0; } @@ -383,6 +430,8 @@ FileNameUpdate *ui_update = malloc(sizeof(FileNameUpdate)); ui_update->upload = upload; ui_update->name = strdup(res->name); + ui_update->path = strdup(res->path); + ui_update->iscollection = FALSE; ui_call_mainthread((ui_threadfunc)uithr_update_file_label, ui_update); dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); @@ -410,6 +459,16 @@ update_upload_labels(upload); + // update resource content length in the browser + DavBrowser *browser = upload->browser; + if (upload->collection == browser->current && upload->collection_ctn == browser->res_counter) { + if (upload->current_resource) { + upload->current_resource->contentlength = upload->current_file_upload; + browser->resources->update(browser->resources, 0); + } + } + upload->current_resource = NULL; + free(file->path); free(file->upload_path); } @@ -425,6 +484,8 @@ FileNameUpdate *ui_update = malloc(sizeof(FileNameUpdate)); ui_update->upload = upload; ui_update->name = strdup(res->name); + ui_update->path = strdup(res->path); + ui_update->iscollection = TRUE; ui_call_mainthread((ui_threadfunc)uithr_update_file_label, ui_update); if (dav_create(res)) { @@ -444,6 +505,8 @@ update_upload_labels(upload); + upload->current_resource = NULL; + free(file->path); free(file->upload_path); } @@ -561,6 +624,9 @@ upload->base_path = strdup(browser->current->path); upload->queue = ui_threadpool_create(1); + upload->collection = browser->current; + upload->collection_ctn = browser->res_counter; + // create upload progress window cxmutstr wtitle = cx_asprintf("Upload to: %s", ui_get(browser->path)); UiObject *dialog = ui_simple_window(wtitle.ptr, upload); @@ -598,3 +664,62 @@ // start upload and stat threads ui_job(ui, jobthr_upload_scan, upload, uithr_upload_scan_finished, upload); } + + +// ------------------------------------- Path Operation (DELETE, MKCOL) ------------------------------------- + +enum DavPathOpType { + DAV_PATH_OP_DELETE = 0 +}; + +typedef struct DavPathOp { + enum DavPathOpType op; + DavSession *sn; + char **path; + size_t *list_indices; + size_t nelm; + DavResource *collection; + int64_t collection_ctn; +} DavPathOp; + +static int jobthr_path_op(void *data) { + DavPathOp *op = data; + + for (int i = 0; i < op->nelm; i++) { + if (op->path[i]) { + DavResource *res = dav_resource_new(op->sn, op->path[i]); + + int ret = 0; + if (op->op == DAV_PATH_OP_DELETE) { + ret = dav_delete(res); + } + + dav_resource_free(res); + } + } + + + return 0; +} + +void davbrowser_delete(UiObject *ui, DavBrowser *browser, UiListSelection selection) { + DavPathOp *op = malloc(sizeof(DavPathOp)); + op->op = DAV_PATH_OP_DELETE; + op->sn = dav_session_clone(browser->sn); + op->path = calloc(selection.count, sizeof(char*)); + op->list_indices = calloc(selection.count, sizeof(size_t)); + op->nelm = selection.count; + + op->collection = browser->current; + op->collection_ctn = browser->res_counter; + + for (int i = 0; i < selection.count; i++) { + DavResource *res = ui_list_get(browser->resources, selection.rows[i]); + if (res) { + op->path[i] = strdup(res->path); + op->list_indices[i] = selection.rows[i]; + } + } + + ui_job(ui, jobthr_path_op, op, NULL, NULL); +}
--- a/application/davcontroller.h Thu Feb 08 10:35:07 2024 +0100 +++ b/application/davcontroller.h Fri Feb 09 16:50:23 2024 +0100 @@ -58,6 +58,7 @@ void davbrowser_upload_files(UiObject *ui, DavBrowser *browser, UiFileList files); +void davbrowser_delete(UiObject *ui, DavBrowser *browser, UiListSelection selection); #ifdef __cplusplus }
--- a/application/window.c Thu Feb 08 10:35:07 2024 +0100 +++ b/application/window.c Fri Feb 09 16:50:23 2024 +0100 @@ -221,6 +221,6 @@ UiListDnd *listdnd = event->eventdata; UiDnD *dnd = listdnd->dnd; UiFileList files = ui_selection_geturis(dnd); - + davbrowser_upload_files(event->obj, event->document, files); }
--- a/ui/common/context.c Thu Feb 08 10:35:07 2024 +0100 +++ b/ui/common/context.c Fri Feb 09 16:50:23 2024 +0100 @@ -321,6 +321,7 @@ if (f->obj) { t->obj = f->obj; t->update = f->update; + t->getselection = f->getselection; } UiVar tmp = *from;
--- a/ui/common/types.c Thu Feb 08 10:35:07 2024 +0100 +++ b/ui/common/types.c Fri Feb 09 16:50:23 2024 +0100 @@ -104,6 +104,7 @@ list->iter = NULL; list->update = NULL; + list->getselection = NULL; list->obj = NULL; if(name) { @@ -458,6 +459,18 @@ } +UIEXPORT UiListSelection ui_list_getselection(UiList *list) { + if (list->getselection) { + return list->getselection(list); + } + return (UiListSelection){ 0, NULL }; +} + +UIEXPORT void ui_listselection_free(UiListSelection selection) { + if (selection.rows) { + free(selection.rows); + } +} UIEXPORT UiStr ui_str(char *cstr) { return (UiStr) { cstr, NULL };
--- a/ui/ui/toolkit.h Thu Feb 08 10:35:07 2024 +0100 +++ b/ui/ui/toolkit.h Fri Feb 09 16:50:23 2024 +0100 @@ -157,6 +157,8 @@ typedef struct UiFileList UiFileList; +typedef struct UiListSelection UiListSelection; + /* begin opaque types */ typedef struct UiContext UiContext; typedef struct UiContainer UiContainer; @@ -329,8 +331,9 @@ /* private - implementation dependent */ void *data; - /* binding function */ + /* binding functions */ void (*update)(UiList *list, int i); + UiListSelection (*getselection)(UiList *list); /* binding object */ void *obj; @@ -338,6 +341,19 @@ UiObserver *observers; }; + +struct UiListSelection { + /* + * number of selected items + */ + int count; + + /* + * indices of selected rows + */ + int *rows; +}; + struct UiRange { double (*get)(UiRange *range); void (*set)(UiRange *range, double value); @@ -462,6 +478,8 @@ UIEXPORT void ui_list_addobsv(UiList *list, ui_callback f, void *data); UIEXPORT void ui_list_notify(UiList *list); +UIEXPORT UiListSelection ui_list_getselection(UiList *list); + UIEXPORT UiFileList ui_filelist_copy(UiFileList list); UIEXPORT void ui_filelist_free(UiFileList list); @@ -477,7 +495,7 @@ - +UIEXPORT void ui_listselection_free(UiListSelection selection); UIEXPORT UiIcon* ui_icon(const char* name, size_t size); UIEXPORT UiIcon* ui_imageicon(const char* file);
--- a/ui/ui/tree.h Thu Feb 08 10:35:07 2024 +0100 +++ b/ui/ui/tree.h Fri Feb 09 16:50:23 2024 +0100 @@ -37,7 +37,6 @@ typedef struct UiModel UiModel; typedef struct UiListCallbacks UiListCallbacks; -typedef struct UiListSelection UiListSelection; typedef struct UiListDnd UiListDnd; typedef struct UiListArgs UiListArgs; @@ -95,18 +94,6 @@ void *userdata; }; -struct UiListSelection { - /* - * number of selected items - */ - int count; - - /* - * indices of selected rows - */ - int *rows; -}; - struct UiListDnd { UiListSelection selection; UiDnD *dnd; @@ -150,11 +137,10 @@ UIEXPORT UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs args); UIEXPORT UIWIDGET ui_breadcrumbbar_create(UiObject* obj, UiListArgs args); - -void ui_table_dragsource(UIWIDGET tablewidget, int actions, char *target0, ...); -void ui_table_dragsource_a(UIWIDGET tablewidget, int actions, char **targets, int nelm); -void ui_table_dragdest(UIWIDGET tablewidget, int actions, char *target0, ...); -void ui_table_dragdest_a(UIWIDGET tablewidget, int actions, char **targets, int nelm); +void ui_table_dragsource_deprecated(UIWIDGET tablewidget, int actions, char *target0, ...); +void ui_table_dragsource_a_deprecated(UIWIDGET tablewidget, int actions, char **targets, int nelm); +void ui_table_dragdest_deprecated(UIWIDGET tablewidget, int actions, char *target0, ...); +void ui_table_dragdest_a_deprecated(UIWIDGET tablewidget, int actions, char **targets, int nelm); #ifdef __cplusplus
--- a/ui/winui/table.cpp Thu Feb 08 10:35:07 2024 +0100 +++ b/ui/winui/table.cpp Fri Feb 09 16:50:23 2024 +0100 @@ -111,6 +111,7 @@ if (var) { UiList* list = (UiList*)var->value; list->update = ui_table_update; + list->getselection = ui_table_selection; list->obj = uitable; uitable->update(list, 0); } @@ -134,6 +135,11 @@ table->update(list, i); } +extern "C" UiListSelection ui_table_selection(UiList * list) { + UiTable* table = (UiTable*)list->obj; + return table->uiselection(); +} + UiTable::UiTable(UiObject *obj, winrt::Microsoft::UI::Xaml::Controls::ScrollViewer scrollW, winrt::Microsoft::UI::Xaml::Controls::Grid grid) { this->obj = obj;