Sun, 29 Sep 2024 20:25:41 +0200
update toolkit, fix download/upload progressbar
application/davcontroller.c | file | annotate | diff | comparison | revisions | |
application/window.c | file | annotate | diff | comparison | revisions | |
ui/gtk/button.c | file | annotate | diff | comparison | revisions | |
ui/gtk/container.c | file | annotate | diff | comparison | revisions | |
ui/gtk/display.c | file | annotate | diff | comparison | revisions | |
ui/gtk/entry.c | file | annotate | diff | comparison | revisions | |
ui/gtk/headerbar.c | file | annotate | diff | comparison | revisions | |
ui/gtk/text.c | file | annotate | diff | comparison | revisions | |
ui/gtk/toolkit.c | file | annotate | diff | comparison | revisions | |
ui/gtk/toolkit.h | file | annotate | diff | comparison | revisions | |
ui/gtk/window.c | file | annotate | diff | comparison | revisions | |
ui/ui/button.h | file | annotate | diff | comparison | revisions | |
ui/ui/container.h | file | annotate | diff | comparison | revisions | |
ui/ui/entry.h | file | annotate | diff | comparison | revisions | |
ui/ui/text.h | file | annotate | diff | comparison | revisions |
--- a/application/davcontroller.c Sun Sep 29 13:32:51 2024 +0200 +++ b/application/davcontroller.c Sun Sep 29 20:25:41 2024 +0200 @@ -707,7 +707,7 @@ if (sz_downloaded_end) { *sz_downloaded_end = 0; } - + if (download->total_bytes > 0) { double progress = (double)download->downloaded_bytes / (double)download->total_bytes; ui_set(download->progress, progress*100); @@ -780,7 +780,6 @@ DavResource *res = dav_resource_new(file->download->download_sn, file->path); dav_get_content(res, file, (dav_write_func)ddfile_write); - file->download->downloaded_bytes += ftell(f); file->download->downloaded_files++; ui_call_mainthread(uithr_download_update_progress, file->download); @@ -928,7 +927,7 @@ ui_rlabel(dialog, .value = download->label_top_right); ui_newline(dialog); - ui_progressbar(dialog, .value = download->progress, .colspan = 2, .hexpand = TRUE); + ui_progressbar(dialog, .value = download->progress, .min = 0, .max = 100, .colspan = 2, .hexpand = TRUE); ui_newline(dialog); ui_llabel(dialog, .value = download->label_bottom_left);
--- a/application/window.c Sun Sep 29 13:32:51 2024 +0200 +++ b/application/window.c Sun Sep 29 20:25:41 2024 +0200 @@ -57,11 +57,11 @@ // navigation bar - ui_hbox(obj, .fill = UI_OFF, .margin = 8) { - ui_button(obj, .icon = UI_ICON_GO_BACK, .onclick = action_go_back); - ui_button(obj, .icon = UI_ICON_GO_FORWARD, .onclick = action_go_forward); - - ui_label(obj, .label = " "); // replace when we have a ui_space widget + ui_hbox(obj, .fill = UI_OFF, .margin = 8, .spacing = 8) { + ui_hbox(obj, .fill = UI_OFF, .style_class="linked") { + ui_button(obj, .icon = UI_ICON_GO_BACK, .onclick = action_go_back); + ui_button(obj, .icon = UI_ICON_GO_FORWARD, .onclick = action_go_forward); + } ui_path_textfield(obj, .fill = UI_ON, .getpathelm = dav_get_pathelm, .onactivate = action_path_selected, .varname = "path");
--- a/ui/gtk/button.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/button.c Sun Sep 29 20:25:41 2024 +0200 @@ -90,6 +90,7 @@ UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) { UiObject* current = uic_current_obj(obj); GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata); + ui_set_name_and_style(button, args.name, args.style_class); UI_APPLY_LAYOUT1(current, args); current->container->add(current->container, button, FALSE); return button; @@ -230,6 +231,7 @@ UiObject* current = uic_current_obj(obj); ui_setup_togglebutton(current, widget, args.label, args.icon, args.varname, args.value, args.onchange, args.onchangedata); + ui_set_name_and_style(widget, args.name, args.style_class); UI_APPLY_LAYOUT1(current, args); current->container->add(current->container, widget, FALSE); @@ -340,6 +342,7 @@ } GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args.label); + ui_set_name_and_style(rbutton, args.name, args.style_class); if(rgroup) { #if GTK_MAJOR_VERSION >= 4 if(rg) {
--- a/ui/gtk/container.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/container.c Sun Sep 29 20:25:41 2024 +0200 @@ -266,6 +266,7 @@ UI_APPLY_LAYOUT1(current, args); GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing); + ui_set_name_and_style(box, args.name, args.style_class); GtkWidget *widget = args.margin > 0 ? box_set_margin(box, args.margin) : box; ct->add(ct, widget, TRUE); @@ -303,6 +304,7 @@ GtkWidget *widget; GtkWidget *grid = create_grid(args.columnspacing, args.rowspacing); + ui_set_name_and_style(grid, args.name, args.style_class); widget = box_set_margin(grid, args.margin); current->container->add(current->container, widget, TRUE); @@ -319,6 +321,7 @@ UI_APPLY_LAYOUT1(current, args); GtkWidget *sw = SCROLLEDWINDOW_NEW(); + ui_set_name_and_style(sw, args.name, args.style_class); UiObject *newobj = uic_object_new(obj, sw); newobj->container = ui_scrolledwindow_container(obj, sw); uic_obj_add(obj, newobj);
--- a/ui/gtk/display.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/display.c Sun Sep 29 20:25:41 2024 +0200 @@ -119,10 +119,27 @@ /* ------------------------- progress bar ------------------------- */ +typedef struct UiProgressBarRange { + double min; + double max; +} UiProgressBarRange; + UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) { UiObject* current = uic_current_obj(obj); GtkWidget *progressbar = gtk_progress_bar_new(); + if(args.max > args.min) { + UiProgressBarRange *range = malloc(sizeof(UiProgressBarRange)); + range->min = args.min; + range->max = args.max; + g_signal_connect( + progressbar, + "destroy", + G_CALLBACK(ui_destroy_userdata), + range); + g_object_set_data(G_OBJECT(progressbar), "ui_range", range); + } + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_DOUBLE); if(var && var->value) { @@ -130,7 +147,7 @@ value->get = ui_progressbar_get; value->set = ui_progressbar_set; value->obj = progressbar; - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), 0.5); + ui_progressbar_set(value, value->value); } UI_APPLY_LAYOUT1(current, args); @@ -140,13 +157,22 @@ } double ui_progressbar_get(UiDouble *d) { - d->value = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj)); + UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range"); + double fraction = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj)); + if(range) { + fraction = range->min + (range->max - range->min) * fraction; + } + d->value = fraction; return d->value; } void ui_progressbar_set(UiDouble *d, double value) { + d->value = value; + UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range"); + if(range) { + value = (value - range->min) / (range->max - range->min); + } gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(d->obj), value); - d->value = value; }
--- a/ui/gtk/entry.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/entry.c Sun Sep 29 20:25:41 2024 +0200 @@ -70,6 +70,7 @@ } #endif GtkWidget *spin = gtk_spin_button_new_with_range(min, max, args.step); + ui_set_name_and_style(spin, args.name, args.style_class); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), args.digits); UiObserver **obs = NULL; if(var) {
--- a/ui/gtk/headerbar.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/headerbar.c Sun Sep 29 20:25:41 2024 +0200 @@ -152,19 +152,28 @@ UiObject *obj, enum UiToolbarPos pos) { + + +#if GTK_MAJOR_VERSION >= 4 GtkWidget *menubutton = gtk_menu_button_new(); - if(item->args.label) { gtk_menu_button_set_label(GTK_MENU_BUTTON(menubutton), item->args.label); } if(item->args.icon) { gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(menubutton), item->args.icon); } - + GMenu *menu = g_menu_new(); ui_gmenu_add_menu_items(menu, 0, &item->menu, obj); gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(menubutton), G_MENU_MODEL(menu)); +#else + GtkWidget *menubutton = gtk_menu_button_new(); + + // TODO + + +#endif headerbar_add(headerbar, box, menubutton, pos); }
--- a/ui/gtk/text.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/text.c Sun Sep 29 20:25:41 2024 +0200 @@ -542,6 +542,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool password, UiTextFieldArgs args) { GtkWidget *textfield = gtk_entry_new(); + ui_set_name_and_style(textfield, args.name, args.style_class); UiObject* current = uic_current_obj(obj); UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING); @@ -700,7 +701,6 @@ } static void ui_path_textfield_destroy(GtkWidget *object, UiPathTextField *pathtf) { - free(pathtf->hbox); g_object_unref(pathtf->entry); free(pathtf); }
--- a/ui/gtk/toolkit.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/toolkit.c Sun Sep 29 20:25:41 2024 +0200 @@ -383,4 +383,26 @@ -#endif \ No newline at end of file +#endif + +void ui_set_name_and_style(GtkWidget *widget, const char *name, const char *style_classes) { + if(name) { + gtk_widget_set_name(widget, name); + } + if(style_classes) { + cxstring *cls = NULL; + size_t numClasses = cx_strsplit_a(cxDefaultAllocator, cx_str(style_classes), CX_STR(" "), 128, &cls); + for(int i=0;i<numClasses;i++) { + cxmutstr m = cx_strdup(cls[i]); +#if GTK_MAJOR_VERSION >= 4 + gtk_widget_add_css_class(widget, m.ptr); +#elif GTK_MAJOR_VERSION >= 3 + GtkStyleContext *ctx = gtk_widget_get_style_context(widget); + gtk_style_context_add_class(ctx, m.ptr); +#endif + free(m.ptr); + } + free(cls); + + } +}
--- a/ui/gtk/toolkit.h Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/toolkit.h Sun Sep 29 20:25:41 2024 +0200 @@ -136,6 +136,8 @@ int ui_get_scalefactor(); +void ui_set_name_and_style(GtkWidget *widget, const char *name, const char *style); + void ui_destroy_userdata(GtkWidget *object, void *userdata); void ui_destroy_vardata(GtkWidget *object, UiVarEventData *data); void ui_destroy_boundvar(UiContext *ctx, UiVar *var);
--- a/ui/gtk/window.c Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/gtk/window.c Sun Sep 29 20:25:41 2024 +0200 @@ -119,11 +119,13 @@ GtkWidget *toolbar_view = adw_toolbar_view_new(); adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view); adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox); - + GtkWidget *headerbar = adw_header_bar_new(); adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar); - ui_fill_headerbar(obj, headerbar); + if(!simple) { + ui_fill_headerbar(obj, headerbar); + } #elif GTK_MAJOR_VERSION >= 4 WINDOW_SET_CONTENT(obj->widget, vbox); #else @@ -259,12 +261,176 @@ } -#if GTK_MAJOR_VERSION >= 4 -static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { - // TODO +#if GTK_MAJOR_VERSION >= 3 +UiFileList listmodel2filelist(GListModel *selection) { + UiFileList flist; + flist.files = NULL; + flist.nfiles = 0; + flist.nfiles = g_list_model_get_n_items(selection); + flist.files = calloc(flist.nfiles, sizeof(char*)); + for(int i=0;i<flist.nfiles;i++) { + GFile *file = g_list_model_get_item(selection, i); + char *path = g_file_get_path(file); + flist.files[i] = path ? strdup(path) : NULL; + g_object_unref(file); + } + return flist; +} +#endif + + +#if GTK_CHECK_VERSION(4, 10, 0) + +#define UI_GTK_FILEDIALOG_OPEN 16 +#define UI_GTK_FILEDIALOG_SAVE 32 + +static void filechooser_opened(GObject *source, GAsyncResult *result, void *data) { + UiEventData *event = data; + + GFile *file = NULL; + GListModel *selection = NULL; + GError *error = NULL; + + int mode = event->value; + int multi = mode & UI_FILEDIALOG_SELECT_MULTI; + if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { + if(multi) { + selection = gtk_file_dialog_select_multiple_folders_finish(GTK_FILE_DIALOG(source), result, &error); + } else { + file = gtk_file_dialog_select_folder_finish(GTK_FILE_DIALOG(source), result, &error); + } + } else if((mode & UI_GTK_FILEDIALOG_OPEN) == UI_GTK_FILEDIALOG_OPEN) { + if(multi) { + selection = gtk_file_dialog_open_multiple_finish(GTK_FILE_DIALOG(source), result, &error); + } else { + file = gtk_file_dialog_open_finish(GTK_FILE_DIALOG(source), result, &error); + } + } else { + file = gtk_file_dialog_save_finish(GTK_FILE_DIALOG(source), result, &error); + } + + UiEvent evt; + evt.obj = event->obj; + evt.document = evt.obj->ctx->document; + evt.window = evt.obj->window; + evt.intval = 0; + + UiFileList flist; + flist.files = NULL; + flist.nfiles = 0; + evt.eventdata = &flist; + + if(selection) { + flist = listmodel2filelist(selection); + g_object_unref(selection); + } else if(file) { + char *path = g_file_get_path(file); + if(path) { + flist.nfiles = 1; + flist.files = calloc(flist.nfiles, sizeof(char*)); + flist.files[0] = strdup(path); + } + g_object_unref(file); + } + + if(event->callback) { + event->callback(&evt, event->userdata); + } + + for(int i=0;i<flist.nfiles;i++) { + free(flist.files[i]); + } +} + +static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) { + if(action == GTK_FILE_CHOOSER_ACTION_OPEN) { + mode |= UI_GTK_FILEDIALOG_OPEN; + } else { + mode |= UI_GTK_FILEDIALOG_SAVE; + } + + UiEventData *event = malloc(sizeof(UiEventData)); + event->callback = file_selected_callback; + event->userdata = cbdata; + event->customdata = NULL; + event->value = mode; + event->obj = obj; + + GtkWindow *parent = GTK_WINDOW(gtk_widget_get_root(obj->widget)); + GtkFileDialog *dialog = gtk_file_dialog_new(); + if(name) { + gtk_file_dialog_set_initial_name(dialog, name); + } + + int multi = mode & UI_FILEDIALOG_SELECT_MULTI; + if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) { + if(multi) { + gtk_file_dialog_select_multiple_folders(dialog, parent, NULL, filechooser_opened, event); + } else { + gtk_file_dialog_select_folder(dialog, parent, NULL, filechooser_opened, event); + } + } else if(action == GTK_FILE_CHOOSER_ACTION_OPEN) { + if(multi) { + gtk_file_dialog_open_multiple(dialog, parent, NULL, filechooser_opened, event); + } else { + gtk_file_dialog_open(dialog, parent, NULL, filechooser_opened, event); + } + } else { + gtk_file_dialog_save(dialog, parent, NULL, filechooser_opened, event); + } + + g_object_unref(dialog); } #else -static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { + + + +static void filechooser_response(GtkDialog* self, gint response_id, UiEventData *data) { + UiEvent evt; + evt.obj = data->obj; + evt.document = evt.obj->ctx->document; + evt.window = evt.obj->window; + evt.intval = 0; + + UiFileList flist; + flist.files = NULL; + flist.nfiles = 0; + evt.eventdata = &flist; + + if(response_id == GTK_RESPONSE_ACCEPT) { +#if GTK_CHECK_VERSION(4, 0, 0) + GListModel *selection = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(self)); + flist = flist = listmodel2filelist(selection); + g_object_unref(selection); +#else + GSList *selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(self)); + flist.nfiles = g_slist_length(selection); + flist.files = calloc(flist.nfiles, sizeof(char*)); + int i = 0; + while(selection) { + char *file = selection->data; + flist.files[i] = strdup(file); + g_free(file); + selection = selection->next; + i++; + } + g_slist_free(selection); +#endif + } + + + if(data->callback) { + data->callback(&evt, data->userdata); + } + + for(int i=0;i<flist.nfiles;i++) { + free(flist.files[i]); + } + + WINDOW_DESTROY(GTK_WIDGET(self)); +} + +static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) { char *button; char *title; @@ -305,6 +471,25 @@ gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); } + UiEventData *event = malloc(sizeof(UiEventData)); + event->obj = obj; + event->userdata = cbdata; + event->callback = file_selected_callback; + event->value = 0; + event->customdata = NULL; + + g_signal_connect( + dialog, + "response", + G_CALLBACK(filechooser_response), + event); + g_signal_connect( + dialog, + "destroy", + G_CALLBACK(ui_destroy_userdata), + event); + + UiEvent evt; evt.obj = obj; evt.document = evt.obj->ctx->document; @@ -316,39 +501,15 @@ flist.nfiles = 0; evt.eventdata = &flist; - int result = gtk_dialog_run(GTK_DIALOG (dialog)); - GSList *selection = NULL; - if(result == GTK_RESPONSE_ACCEPT) { - selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); - flist.nfiles = g_slist_length(selection); - flist.files = calloc(flist.nfiles, sizeof(char*)); - int i = 0; - while(selection) { - flist.files[i] = selection->data; - selection = selection->next; - i++; - } - } - - if(file_selected_callback) { - file_selected_callback(&evt, cbdata); - } - - for(int i=0;i<flist.nfiles;i++) { - g_free(flist.files[i]); - } - free(flist.files); - g_slist_free(selection); - - gtk_widget_destroy(dialog); + gtk_widget_show(dialog); } #endif void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { - ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, file_selected_callback, cbdata); + ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, NULL, file_selected_callback, cbdata); } void ui_savefiledialog(UiObject *obj, const char *name, ui_callback file_selected_callback, void *cbdata) { - ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, file_selected_callback, cbdata); + ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, name, file_selected_callback, cbdata); }
--- a/ui/ui/button.h Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/ui/button.h Sun Sep 29 20:25:41 2024 +0200 @@ -41,6 +41,8 @@ UiBool vexpand; int colspan; int rowspan; + const char *name; + const char *style_class; const char* label; const char* stockid; @@ -56,7 +58,9 @@ UiBool vexpand; int colspan; int rowspan; - + const char *name; + const char *style_class; + const char* label; const char* stockid; const char* icon; @@ -66,7 +70,7 @@ ui_callback onchange; void* onchangedata; } UiToggleArgs; - + #define ui_button(obj, ...) ui_button_create(obj, (UiButtonArgs){ __VA_ARGS__ } ) #define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, (UiToggleArgs){ __VA_ARGS__ } ) #define ui_checkbox(obj, ...) ui_checkbox_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
--- a/ui/ui/container.h Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/ui/container.h Sun Sep 29 20:25:41 2024 +0200 @@ -56,6 +56,8 @@ UiBool vexpand; int colspan; int rowspan; + const char *name; + const char *style_class; int margin; int spacing; @@ -69,6 +71,8 @@ UiBool vexpand; int colspan; int rowspan; + const char *name; + const char *style_class; UiSubContainerType subcontainer; @@ -87,6 +91,8 @@ UiBool vexpand; int colspan; int rowspan; + const char *name; + const char *style_class; UiTabViewType tabview;
--- a/ui/ui/entry.h Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/ui/entry.h Sun Sep 29 20:25:41 2024 +0200 @@ -42,6 +42,8 @@ UiBool vexpand; int colspan; int rowspan; + const char *name; + const char *style_class; double step; int digits;
--- a/ui/ui/text.h Sun Sep 29 13:32:51 2024 +0200 +++ b/ui/ui/text.h Sun Sep 29 20:25:41 2024 +0200 @@ -42,6 +42,8 @@ int colspan; int rowspan; int width; + const char *name; + const char *style_class; UiString* value; const char* varname; @@ -66,6 +68,8 @@ UiBool vexpand; int colspan; int rowspan; + const char *name; + const char *style_class; UiString *value; const char* varname;