UNIXworkcode

/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2024 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "application.h" #include <string.h> #include <stdbool.h> #include <libidav/webdav.h> #include "window.h" #include "config.h" #include "davcontroller.h" #include "settings.h" #include "appsettings.h" static DavContext* davctx; static DavApp *app; void application_init(void) { davctx = dav_context_new(); dav_context_set_mtsafe(davctx, true); application_create_menu(); } DavApp* get_application(void) { return app; } void application_startup(UiEvent* event, void* data) { if (load_config(davctx)) { // TODO: error exit(-1); } appsettings_init(); window_init(); // create document for global settings (repolist, ...) app = application_create_app_document(); UiContext *global = ui_global_context(); ui_attach_document(global, app); // create new window UiObject *win = window_create(); // create new browser document and attach it to the main window DavBrowser *doc = davbrowser_create(win); ui_attach_document(win->ctx, doc); ui_show(win); } static void* davrepo_getname(void *elm, int unused) { DavCfgRepository *repo = elm; return repo->name.value.ptr; } void application_create_menu(void) { // menu ui_menu("File") { ui_menuitem(.label = "New Window", .onclick = action_window_new); ui_menuseparator(); ui_menuitem(.label = "New Folder", .onclick = action_mkcol, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem(.label = "New File", .onclick = action_newfile, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem(.label = "Delete", .onclick = action_delete, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuseparator(); ui_menuitem(.label = "Upload File", .onclick = action_upload_file, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem(.label = "Upload Folder", .onclick = action_upload_dir, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem(.label = "Download", .onclick = action_download, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_menuitem("Open Properties", .onclick = action_open_properties, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_menuitem("Open as Text File", .onclick = action_open_properties, .onclickdata = "text/plain", .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_menuseparator(); ui_menuitem(.label = "Close", .onclick = action_window_close); } ui_menu("Edit") { ui_menuitem(.label = "Preferences", .onclick = action_open_settings); } ui_menu("Go") { ui_menuitem(.label = "Parent", .onclick = action_go_parent, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem(.label = "Back", .onclick = action_go_back, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem(.label = "Forward", .onclick = action_go_forward, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuseparator(); ui_menu("Repositories") { ui_menu_itemlist(.varname = "repolist", .getvalue = davrepo_getname, .onselect = action_repo_selected); } } ui_menu("View") { ui_menu_itemlist(.varname = "transferlist", .getvalue = transfers_getlabel, .onselect = action_transfer_selected); } // toolbar ui_toolbar_item("Home", .icon = UI_ICON_HOME); ui_toolbar_item("NewWindow", .icon = UI_ICON_NEW_WINDOW, .onclick = action_window_new); ui_toolbar_item("Refresh", .icon = UI_ICON_REFRESH, .onclick = action_refresh, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_toolbar_menu("Repo", .label = "Repository") { ui_menu_itemlist(.varname = "repolist", .getvalue = davrepo_getname, .onselect = action_repo_selected); } ui_toolbar_item("NewFolder", .icon = UI_ICON_NEW_FOLDER, .onclick = action_mkcol, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_toolbar_item("NewFile", .icon = UI_ICON_ADD, .onclick = action_newfile, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_toolbar_item("Upload", .label = "Upload", .icon = UI_ICON_UPLOAD, .onclick = action_upload_file, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_toolbar_item("Download", .icon = UI_ICON_SAVE_LOCAL, .onclick = action_download, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_toolbar_item("Remove", .icon = UI_ICON_DELETE, .onclick = action_delete, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_toolbar_toggleitem("LocalBrowser", .icon = UI_ICON_DOCK_LEFT, .label = "Local Browser"); ui_toolbar_toggleitem("PreviewPane", .icon = UI_ICON_DOCK_RIGHT); ui_toolbar_appmenu() { ui_menuitem("New Window", .onclick = action_window_new); ui_menuseparator(); ui_menuitem("Download", .onclick = action_download, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_menuitem("Upload Files", .onclick = action_upload_file, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem("Upload Directory", .onclick = action_upload_dir, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION)); ui_menuitem("Open Properties", .onclick = action_open_properties, .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_menuitem("Open as Text File", .onclick = action_open_properties, .onclickdata = "text/plain", .groups = UI_GROUPS(APP_STATE_BROWSER_SESSION, APP_STATE_BROWSER_SELECTION)); ui_menuseparator(); ui_menu("Downloads/Uploads") { ui_menu_itemlist(.varname = "transferlist", .getvalue = transfers_getlabel, .onselect = action_transfer_selected); } ui_menuseparator(); ui_menuitem("Preferences", .onclick = action_open_settings); } //ui_toolbar_add_default("Home", UI_TOOLBAR_LEFT); //ui_toolbar_add_default("NewWindow", UI_TOOLBAR_LEFT); //ui_toolbar_add_default("Refresh", UI_TOOLBAR_LEFT); ui_toolbar_add_default("Repo", UI_TOOLBAR_LEFT); ui_toolbar_add_default("NewFolder", UI_TOOLBAR_CENTER); ui_toolbar_add_default("NewFile", UI_TOOLBAR_CENTER); ui_toolbar_add_default("Remove", UI_TOOLBAR_CENTER); ui_toolbar_add_default("Download", UI_TOOLBAR_CENTER); ui_toolbar_add_default("Upload", UI_TOOLBAR_CENTER); //ui_toolbar_add_default("LocalBrowser", UI_TOOLBAR_RIGHT); //ui_toolbar_add_default("PreviewPane", UI_TOOLBAR_RIGHT); } DavApp* application_create_app_document(void) { DavApp *doc = ui_document_new(sizeof(DavApp)); UiContext *ctx = ui_document_context(doc); doc->repos = ui_list_new(ctx, "repolist"); doc->transfers = ui_list_new(ctx, "transferlist"); CxList *transfers = doc->transfers->data; transfers->collection.cmpfunc = cx_cmp_ptr; // create repo list application_update_repolist(doc); return doc; } void application_update_repolist(DavApp *app) { DavConfig *config = get_config(); ui_list_clear(app->repos); for (DavCfgRepository *repo = config->repositories; repo; repo = repo->next) { ui_list_append(app->repos, repo); } ui_notify(app->repos->observers, NULL); } DavContext* application_dav_context(void) { return davctx; } void* transfers_getlabel(void *data, int col) { DavTransfer *trans = data; return trans->label; } void application_register_transfer(DavTransfer *trans) { DavApp *app = get_application(); ui_list_append(app->transfers, trans); application_update_transferlist(); } void application_remove_transfer(DavTransfer *trans) { DavApp *app = get_application(); CxList *transfers = app->transfers->data; cxListFindRemove(transfers, trans); application_update_transferlist(); } /* static int transfers_cmp(const DavTransfer *left, const DavTransfer *right) { return cx_cmp_double(&right->progress, &left->progress); } */ void application_update_transferlist(void) { DavApp *app = get_application(); /* CxList *transfers = app->transfers->data; transfers->collection.cmpfunc = (cx_compare_func)transfers_cmp; cxListSort(transfers); transfers->collection.cmpfunc = cx_cmp_ptr; */ ui_list_update(app->transfers); ui_list_notify(app->transfers); } void action_window_new(UiEvent *event, void *data) { UiObject *win = window_create(); // create new browser document and attach it to the main window DavBrowser *doc = davbrowser_create(win); ui_attach_document(win->ctx, doc); ui_show(win); } void action_window_close(UiEvent *event, void *data) { ui_close(event->obj); } void action_refresh(UiEvent *event, void *data) { DavBrowser *browser = event->document; if (browser->current) { davbrowser_query_path(event->obj, browser, browser->current->path); } } void action_repo_selected(UiEvent *event, void *data) { DavCfgRepository *repo = event->eventdata; DavBrowser *browser = event->document; davbrowser_connect2repo(event->obj, browser, repo, ""); } static void file_selected(UiEvent *event, void *data) { UiFileList *files = event->eventdata; if (files && files->nfiles > 0) { // files will be freed by the filedialog handler, therefore we need a copy UiFileList uploadList = ui_filelist_copy(*files); // uploadList will be freed by davbrowser_upload_files davbrowser_upload_files(event->obj, event->document, uploadList); } } static void download_location_selected(UiEvent *event, void *data) { DavBrowser *browser = event->document; DavResource *reslist = data; UiFileList *flist = event->eventdata; if (flist && flist->nfiles > 0) { davbrowser_download(event->obj, browser, reslist, flist->files[0]); } else { dav_session_destroy(reslist->session); } } void action_download(UiEvent *event, void *data) { DavBrowser *browser = event->document; UiListSelection sel = ui_list_getselection(browser->resources); if (sel.count > 0) {; const char *initialFileName = NULL; if (sel.count == 1) { DavResource *res = ui_list_get(browser->resources, sel.rows[0]); if (res && !res->iscollection) { initialFileName = res->name; } } // create a copy of the current session and all selected resources DavSession *sn = dav_session_clone(browser->sn); DavResource *first = NULL; DavResource *last = NULL; for (int i = 0; i < sel.count; i++) { // get selected resource DavResource *res = ui_list_get(browser->resources, sel.rows[i]); // copy resource DavResource *res_copy = dav_resource_new(sn, res->path); res_copy->iscollection = res->iscollection; res_copy->contentlength = res->contentlength; res_copy->lastmodified = res->lastmodified; res_copy->creationdate = res->creationdate; // link resources if (!first) { first = res_copy; } if (last) { res_copy->prev = last; last->next = res_copy; } last = res_copy; } if (initialFileName) { ui_savefiledialog(event->obj, initialFileName, download_location_selected, first); } else { ui_openfiledialog(event->obj, UI_FILEDIALOG_SELECT_FOLDER, download_location_selected, first); } ui_listselection_free(sel); } } void action_upload_file(UiEvent *event, void *data) { DavBrowser *browser = event->document; if(!browser->sn) { return; } ui_openfiledialog(event->obj, UI_FILEDIALOG_SELECT_MULTI, file_selected, NULL); } void action_upload_dir(UiEvent *event, void *data) { DavBrowser *browser = event->document; if(!browser->sn) { return; } ui_openfiledialog(event->obj, UI_FILEDIALOG_SELECT_FOLDER|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); } void action_selectall(UiEvent *event, void *data) { DavBrowser *browser = event->document; int nres = ui_list_count(browser->resources); for(int i=0;i<nres;i++) { ui_list_setselection(browser->resources, i); } } void action_rename(UiEvent *event, void *data) { DavBrowser *browser = event->document; UiListSelection sel = ui_list_getselection(browser->resources); if (sel.count == 1) { davbrowser_rename(event->obj, browser, sel); } else if(sel.count > 1) { fprintf(stderr, "Renaming multiple resources is not implemented yet\n"); } } static void newfiledialog_result(UiEvent *event, void *data) { DavBrowser *browser = event->document; char *path = event->eventdata; if (event->intval == 1) { davbrowser_newfile(event->obj, browser, path); } } void action_newfile(UiEvent *event, void *data) { DavBrowser *browser = event->document; if(!browser->sn) { return; } ui_dialog(event->obj, .content = "New File", .input = TRUE, .button1_label = "Create File", .button2_label = "Cancel", .result = newfiledialog_result); } static void newfolderdialog_result(UiEvent *event, void *data) { DavBrowser *browser = event->document; char *path = event->eventdata; if (event->intval == 1) { davbrowser_mkcol(event->obj, browser, path); } } void action_mkcol(UiEvent *event, void *data) { DavBrowser *browser = event->document; if(!browser->sn) { return; } ui_dialog(event->obj, .content = "New Folder", .input = TRUE, .button1_label = "Create Folder", .button2_label = "Cancel", .result = newfolderdialog_result); } void action_open_settings(UiEvent *event, void *data) { settings_window_open(); } void action_open_properties(UiEvent *event, void *data) { char *type = data; DavBrowser *browser = event->document; UiListSelection sel = ui_list_getselection(browser->resources); for(int i=0;i<sel.count;i++) { DavResource *res = ui_list_get(browser->resources, sel.rows[i]); if(res) { davbrowser_open_resource(event->obj, browser, res, type); } } ui_listselection_free(sel); } void action_transfer_selected(UiEvent *event, void *data) { DavApp *app = get_application(); DavTransfer *trans = ui_list_get(app->transfers, event->intval); if(trans) { ui_show(trans->window); } }