--- a/application/davcontroller.c Sun Feb 11 15:59:56 2024 +0100 +++ b/application/davcontroller.c Mon Feb 12 17:32:02 2024 +0100 @@ -666,6 +666,143 @@ } +// ------------------------------------- File Download ------------------------------------- + +typedef struct DavFileDownload { + UiObject *ui; + DavBrowser *browser; + + DavSession *sn; + DavResource *reslist; + char *local_path; + DavBool isdirectory; + + UiThreadpool *queue; + + size_t total_bytes; + size_t total_files; + size_t total_directories; + size_t downloaded_bytes; + size_t downloaded_files; + size_t downloaded_directories; + + UiObject *dialog; + UiDouble *progress; + UiString *label_top_left; + UiString *label_top_right; + UiString *label_bottom_left; + UiString *label_bottom_right; +} DavFileDownload; + +// dav download file +typedef struct DDFile { + DavFileDownload *download; + DavResource *res; + char *to; +} DDFile; + +static int qthr_download_resource(void *data) { + DDFile *file = data; + + FILE *f = fopen(file->to, "wb"); + if (!f) { + return 0; + } + + dav_get_content(file->res, f, (dav_write_func)fwrite); + + fclose(f); +} + +static int jobthr_download_scan(void *data) { + DavFileDownload *download = data; + DavBrowser *browser = download->browser; + + // check if the specified local location is a directory + SYS_STAT s; + if (!sys_stat(download->local_path, &s)) { + if (S_ISDIR(s.st_mode)) { + download->isdirectory = TRUE; + } + } + + // add selected files to the download queue + DavResource *res = download->reslist; + while (res) { + DDFile *file = malloc(sizeof(DDFile)); + file->download = download; + file->res = res; + if (download->isdirectory) { + file->to = util_concat_path(download->local_path, res->name); + } else { + file->to = strdup(download->local_path); + } + + ui_threadpool_job(download->queue, download->ui, qthr_download_resource, file, NULL, NULL); + + res = res->next; + } +} + +static void uithr_download_scan_finished(UiEvent *event, void *data) { + +} + +static void download_window_closed(UiEvent *event, void *data) { + +} + + +void davbrowser_download(UiObject *ui, DavBrowser *browser, DavResource *reslist, const char *local_path) { + DavFileDownload *download = malloc(sizeof(DavFileDownload)); + memset(download, 0, sizeof(DavFileDownload)); + + download->browser = browser; + download->sn = reslist->session; + download->reslist = reslist; + download->local_path = strdup(local_path); + + download->queue = ui_threadpool_create(1); + + // create download progress window + cxmutstr wtitle = cx_asprintf("Download to: %s", local_path); + UiObject *dialog = ui_simple_window(wtitle.ptr, download); + ui_context_closefunc(dialog->ctx, download_window_closed, NULL); + free(wtitle.ptr); + download->dialog = dialog; + ui_window_size(dialog, 550, 120); + download->progress = ui_double_new(dialog->ctx, NULL); + download->label_top_left = ui_string_new(dialog->ctx, NULL); + download->label_top_right = ui_string_new(dialog->ctx, NULL); + download->label_bottom_left = ui_string_new(dialog->ctx, NULL); + download->label_bottom_right = ui_string_new(dialog->ctx, NULL); + + ui_grid(dialog, .margin = 10, .spacing = 10, .fill = TRUE) { + ui_llabel(dialog, .value = download->label_top_left, .hexpand = TRUE); + ui_rlabel(dialog, .value = download->label_top_right); + ui_newline(dialog); + + ui_progressbar(dialog, .value = download->progress, .colspan = 2, .hexpand = TRUE); + ui_newline(dialog); + + ui_llabel(dialog, .value = download->label_bottom_left); + ui_rlabel(dialog, .value = download->label_bottom_right); + ui_newline(dialog); + } + + ui_set(download->label_top_left, ""); + ui_set(download->label_top_right, ""); + ui_set(download->label_bottom_left, ""); + ui_set(download->label_bottom_right, ""); + ui_set(download->progress, 0); + + ui_show(dialog); + + // start upload and stat threads + ui_job(ui, jobthr_download_scan, download, uithr_download_scan_finished, download); +} + + // ------------------------------------- Path Operation (DELETE, MKCOL) ------------------------------------- enum DavPathOpType { @@ -812,8 +949,6 @@ return 0; } - - void davbrowser_delete(UiObject *ui, DavBrowser *browser, UiListSelection selection) { DavPathOp *op = malloc(sizeof(DavPathOp)); op->ui = ui;