# HG changeset patch # User Olaf Wintermann # Date 1707242512 -3600 # Node ID 813c97c5b6d3405397eb6edb3eace1714054821f # Parent af411868ab9ba678d53ddbb07b855ab1dac3b61c add a very basic upload progress bar diff -r af411868ab9b -r 813c97c5b6d3 application/davcontroller.c --- a/application/davcontroller.c Tue Feb 06 14:17:22 2024 +0100 +++ b/application/davcontroller.c Tue Feb 06 19:01:52 2024 +0100 @@ -246,6 +246,14 @@ DavSession *sn; UiFileList files; char *base_path; + UiThreadpool *queue; + + size_t total_bytes; + size_t total_files; + size_t total_directories; + size_t uploaded_bytes; + size_t uploaded_files; + size_t uploaded_directories; UiObject *dialog; UiDouble *progress; @@ -256,30 +264,119 @@ typedef struct DUFile { char *path; char *upload_path; + size_t bytes; + DavBool isdirectory; + DavFileUpload *upload; + DavError error; } DUFile; -static int jobthr_file_upload(void *data) { +static double upload_progress(DavFileUpload *upload) { + return ((double)upload->uploaded_bytes / (double)upload->total_bytes) * 100; +} + +static int qthr_file_upload(void *data) { + DUFile *f = data; + DavFileUpload *upload = f->upload; + DavSession *sn = upload->sn; + + FILE *in = sys_fopen(f->path, "rb"); + if (!in) { + // TODO: error msg + return 0; + } + + DavResource *res = dav_resource_new(sn, f->upload_path); + dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); + if (dav_store(res)) { + f->error = sn->error; + } + dav_resource_free(res); + + fclose(in); + + return 0; +} + +static void uithr_file_uploaded(UiEvent *event, void *data) { + DUFile *file = data; + DavFileUpload *upload = file->upload; + + upload->uploaded_files++; + upload->uploaded_bytes += file->bytes; + + double progress = upload_progress(upload); + ui_set(upload->progress, upload_progress(upload)); + + free(file->path); + free(file->upload_path); +} + +static int qthr_dir_upload(void *data) { + DUFile *f = data; + DavFileUpload *upload = f->upload; + DavSession *sn = upload->sn; + + DavResource *res = dav_resource_new(sn, f->upload_path); + res->iscollection = TRUE; + + if (dav_create(res)) { + f->error = sn->error; + } + + dav_resource_free(res); + + return 0; +} + +static void uithr_dir_uploaded(UiEvent *event, void *data) { + DUFile *file = data; + DavFileUpload *upload = file->upload; + + upload->uploaded_directories++; + + free(file->path); + free(file->upload_path); +} + +static int qthr_upload_finished(void *data) { + return 0; +} + +static void uithr_upload_finished(UiEvent *event, void *data) { + DavFileUpload *upload = data; + ui_threadpool_destroy(upload->queue); + + free(upload->base_path); + dav_session_destroy(upload->sn); +} + +static int jobthr_upload_scan(void *data) { DavFileUpload *upload = data; - CxList *stack = cxLinkedListCreateSimple(sizeof(DUFile)); + CxList *stack = cxLinkedListCreateSimple(CX_STORE_POINTERS); for (int i = 0; i < upload->files.nfiles; i++) { - DUFile f; - f.path = upload->files.files[i]; - f.upload_path = util_path_file_name(f.path); - cxListInsert(stack, 0, &f); + DUFile *f = malloc(sizeof(DUFile)); + f->path = strdup(upload->files.files[i]); + f->upload_path = util_concat_path(upload->base_path, util_path_file_name(f->path)); + f->isdirectory = FALSE; + f->bytes = 0; + f->upload = upload; + f->error = 0; + cxListInsert(stack, 0, f); } while (stack->size > 0) { DUFile *f = cxListAt(stack, 0); char *path = util_concat_path(upload->base_path, f->upload_path); - DavResource *res = dav_resource_new(upload->sn, path); + cxListRemove(stack, 0); SYS_STAT s; if (!stat(f->path, &s)) { if (S_ISDIR(s.st_mode)) { - res->iscollection = 1; - dav_create(res); + f->isdirectory = TRUE; + upload->total_directories++; + ui_threadpool_job(upload->queue, upload->ui, qthr_dir_upload, f, uithr_dir_uploaded, f); SYS_DIR dir = sys_opendir(f->path); if (dir) { @@ -289,43 +386,40 @@ if(!strcmp(entry->name, ".") || !strcmp(entry->name, "..")) { continue; } - + cxmutstr newpath = util_concat_sys_path(cx_str(f->path), cx_str(entry->name)); char *new_upload_path = util_concat_path(f->upload_path, entry->name); - DUFile child; - child.path = newpath.ptr; - child.upload_path = new_upload_path; - cxListAdd(stack, &child); + DUFile *child = malloc(sizeof(DUFile)); + child->path = newpath.ptr; + child->upload_path = new_upload_path; + child->isdirectory = FALSE; + child->bytes = 0; + child->upload = upload; + child->error = 0; + cxListAdd(stack, child); } sys_closedir(dir); } } else if (S_ISREG(s.st_mode)) { - FILE *in = sys_fopen(f->path, "rb"); - if (in) { - dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); - //dav_set_content_length(res, s.st_size); - int err = dav_store(res); - if (err) { - // TODO: error + f->isdirectory = FALSE; + f->bytes = s.st_size; + upload->total_files++; + upload->total_bytes += s.st_size; + ui_threadpool_job(upload->queue, upload->ui, qthr_file_upload, f, uithr_file_uploaded, f); + } + } + } // TODO: else error msg - } - fclose(in); - } - } - } // TODO: else error msg + ui_threadpool_job(upload->queue, upload->ui, qthr_upload_finished, upload, uithr_upload_finished, upload); - dav_resource_free(res); - free(path); - - cxListRemove(stack, 0); - } + ui_filelist_free(upload->files); return 0; } -static void uithr_file_upload_finished(UiEvent *event, void *data) { +static void uithr_upload_scan_finished(UiEvent *event, void *data) { DavFileUpload *upload = data; } @@ -341,11 +435,14 @@ // create upload obj, that contains all relevant data for the upload DavFileUpload *upload = malloc(sizeof(DavFileUpload)); + memset(upload, 0, sizeof(DavFileUpload)); + upload->ui = ui; upload->browser = browser; upload->sn = upload_session; upload->files = files; upload->base_path = strdup(browser->current->path); + upload->queue = ui_threadpool_create(1); // create upload progress window UiObject *dialog = ui_simple_window("Upload", upload); @@ -365,8 +462,8 @@ ui_set(upload->speed_label, ""); ui_set(upload->progress, 0); - //ui_show(dialog); + ui_show(dialog); // start upload and stat threads - ui_job(ui, jobthr_file_upload, upload, uithr_file_upload_finished, upload); + ui_job(ui, jobthr_upload_scan, upload, uithr_upload_scan_finished, upload); } diff -r af411868ab9b -r 813c97c5b6d3 ui/common/types.c --- a/ui/common/types.c Tue Feb 06 14:17:22 2024 +0100 +++ b/ui/common/types.c Tue Feb 06 19:01:52 2024 +0100 @@ -459,16 +459,16 @@ -UiStr ui_str(char *cstr) { +UIEXPORT UiStr ui_str(char *cstr) { return (UiStr) { cstr, NULL }; } -UiStr ui_str_free(char *str, void (*freefunc)(void *v)) { +UIEXPORT UiStr ui_str_free(char *str, void (*freefunc)(void *v)) { return (UiStr) { str, freefunc }; } -UiFileList ui_filelist_copy(UiFileList list) { +UIEXPORT UiFileList ui_filelist_copy(UiFileList list) { char **newlist = calloc(sizeof(char*), list.nfiles); for (int i = 0; i < list.nfiles; i++) { newlist[i] = strdup(list.files[i]); @@ -476,7 +476,7 @@ return (UiFileList) { newlist, list.nfiles }; } -void ui_filelist_free(UiFileList list) { +UIEXPORT void ui_filelist_free(UiFileList list) { for (int i = 0; i < list.nfiles; i++) { free(list.files[i]); } diff -r af411868ab9b -r 813c97c5b6d3 ui/ui/toolkit.h --- a/ui/ui/toolkit.h Tue Feb 06 14:17:22 2024 +0100 +++ b/ui/ui/toolkit.h Tue Feb 06 19:01:52 2024 +0100 @@ -460,8 +460,8 @@ UIEXPORT void ui_list_addobsv(UiList *list, ui_callback f, void *data); UIEXPORT void ui_list_notify(UiList *list); -UiFileList ui_filelist_copy(UiFileList list); -void ui_filelist_free(UiFileList list); +UIEXPORT UiFileList ui_filelist_copy(UiFileList list); +UIEXPORT void ui_filelist_free(UiFileList list); UIEXPORT void ui_clipboard_set(char *str); UIEXPORT char* ui_clipboard_get(); @@ -485,8 +485,8 @@ UIEXPORT UiIcon* ui_fileicon(size_t size); -UiStr ui_str(char *cstr); -UiStr ui_str_free(char *str, void (*free)(void *v)); +UIEXPORT UiStr ui_str(char *cstr); +UIEXPORT UiStr ui_str_free(char *str, void (*free)(void *v)); #ifdef __cplusplus }