ui/qt/menu.cpp

changeset 103
6606616eca9f
parent 0
2483f517c562
child 108
77254bd6dccb
--- a/ui/qt/menu.cpp	Tue Feb 25 21:11:00 2025 +0100
+++ b/ui/qt/menu.cpp	Sat Apr 05 16:46:11 2025 +0200
@@ -35,391 +35,203 @@
 #include "menu.h"
 #include "toolkit.h"
 #include "../common/context.h"
+#include "../common/menu.h"
 #include "../ui/properties.h"
 #include "../ui/window.h"
 #include "stock.h"
 #include "container.h"
 
-static UcxList *menus;
-static UcxList *current;
-
-/* -------------------------- UiMenu -------------------------- */
-
-UiMenu::UiMenu(char* label) {
-    this->items = NULL;
-    this->label = label;
-}
 
-void UiMenu::addMenuItem(UiMenuItemI* item) {
-    items = ucx_list_append(items, item);
-}
+static ui_menu_add_f createMenuItem[] = {
+    /* UI_MENU                 */ add_menu_widget,
+    /* UI_MENU_ITEM            */ add_menuitem_widget,
+    /* UI_MENU_CHECK_ITEM      */ add_checkitem_widget,
+    /* UI_MENU_RADIO_ITEM      */ add_radioitem_widget,
+    /* UI_MENU_ITEM_LIST       */ add_menuitem_list_widget,
+    /* UI_MENU_CHECKITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_RADIOITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_SEPARATOR       */ add_menuseparator_widget
+};
 
-void UiMenu::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) {
-    QMenu *m = NULL;
-    if(menubar) {
-        m = menubar->addMenu(label);
-    } else {
-        m = menu->addMenu(label);
-    }
-    
-    UCX_FOREACH(elm, items) {
-        UiMenuItemI *item = (UiMenuItemI*)elm->data;
-        item->addTo(obj, NULL, m);
+/*
+ * create all menu child items
+ */
+static void add_menu_items(QMenu *parent, int i, UiMenu *menu, UiObject *obj) {
+    UiMenuItemI *it = menu->items_begin;
+    int index = 0;
+    while(it) {
+        createMenuItem[it->type](parent, index, it, obj);
+        it = it->next;
+        index++;
     }
 }
 
-
-/* -------------------------- UiMenuItem -------------------------- */
-
-UiMenuItem::UiMenuItem(char* label, ui_callback f, void* userdata) {
-    this->label = label;
-    this->callback = f;
-    this->userdata = userdata;
-    this->groups = NULL;
+void add_menu_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenu *m = (UiMenu*)item;
+    QMenu *menu = parent->addMenu(m->label);
+    add_menu_items(menu, i, m, obj);
 }
 
-void UiMenuItem::addGroup(int group) {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-void UiMenuItem::setCheckable(bool c) {
-    checkable = c;
-}
-
-void UiMenuItem::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) {
+static UiAction* create_action(
+        UiObject *obj,
+        const char *icon,
+        const char *label,
+        ui_callback callback,
+        void *userdata,
+        int *states)
+{
     QString str = QString::fromUtf8(label);
     UiAction *action = new UiAction(obj, str, callback, userdata);
-    action->setCheckable(checkable);
-    if(checkable) {
-        action->setChecked(false);
+    if(icon) {
+        action->setIcon(QIcon::fromTheme(icon));
+        action->setIconVisibleInMenu(true);
     }
-    menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
+    
+    if(states) {
+        size_t nstates = uic_group_array_size(states);
+        uic_add_group_widget_i(obj->ctx, action, (ui_enablefunc)ui_action_enable, states, nstates);
+        action->setEnabled(false);
+    }
+    
+    return action;
 }
 
-
-/* -------------------------- UiStMenuItem -------------------------- */
-
-UiStMenuItem::UiStMenuItem(char* stockid, ui_callback f, void* userdata) {
-    this->stockid = stockid;
-    this->callback = f;
-    this->userdata = userdata;
-    this->groups = NULL;
-}
-
-void UiStMenuItem::addGroup(int group) {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-void UiStMenuItem::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) {
-    UiStockItem *stockItem = ui_get_stock_item(stockid);
-    
-    QString str = QString::fromUtf8(stockItem->label);
-    UiAction *action = new UiAction(obj, str, callback, userdata);
-    action->setIcon(QIcon::fromTheme(stockItem->icon_name));
-    action->setIconVisibleInMenu(true);
-    menu->addAction(action);
-    //UiEventWrapper *ev = new UiEventWrapper(callback, userdata);
+void add_menuitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItem *it = (UiMenuItem*)item;
+    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->groups);
+    parent->addAction(action);
     QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
 }
 
-
-/* -------------------------- UiMenuSeparator -------------------------- */
-
-void UiMenuSeparator::addTo(UiObject* obj, QMenuBar* menubar, QMenu* menu) {
-    menu->addSeparator();
+void add_menuseparator_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    parent->addSeparator();
 }
 
-
-/* -------------------------- UiCheckItemNV -------------------------- */
-
-UiCheckItemNV::UiCheckItemNV(char* label, char* varname) {
-    this->label = label;
-    this->varname = varname;
+void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuCheckItem *it = (UiMenuCheckItem*)item;
+    
+    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->groups);
+    parent->addAction(action);
+    action->setCheckable(true);
+    action->prepare_event = ui_checkableaction_prepare_event;
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, NULL, it->varname, UI_VAR_INTEGER);
+    if(var) {
+        UiInteger *value = (UiInteger*)var->value;
+        value->obj = action;
+        value->get = ui_checkableaction_get;
+        value->set = ui_checkableaction_set;
+        
+        action->setChecked((bool)value->value);
+    }
+    action->var = var;
 }
 
-void UiCheckItemNV::addTo(UiObject* obj, QMenuBar* menubar, QMenu* menu) {
-    QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, NULL, NULL);
+void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuRadioItem *it = (UiMenuRadioItem*)item;
+    
+    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->groups);
+    parent->addAction(action);
     action->setCheckable(true);
-    menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
+    action->prepare_event = ui_actiongroup_prepare_event;
     
-    UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_INTEGER);
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, NULL, it->varname, UI_VAR_INTEGER);
     if(var) {
         UiInteger *value = (UiInteger*)var->value;
-        action->setChecked(value->value);
-        value->obj = action;
-        value->get = ui_checkitem_get;
-        value->set = ui_checkitem_set;
-        value = 0;
-    } else {
-        // TODO: error
+        QActionGroup *group = (QActionGroup*)value->obj;
+        if(!group) {
+            group = new QActionGroup(parent);
+            value->obj = group;
+        }
+        group->addAction(action);
+        value->get = ui_actiongroup_get;
+        value->set = ui_actiongroup_set;
+        if(value->value != 0) {
+            ui_actiongroup_set(value, value->value);
+        }
+    }
+    action->var;
+}
+
+void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action) {
+    if(action->var) {
+        UiInteger *value = (UiInteger*)action->var->value;
+        event->eventdata = value;
+        event->intval = value->get(value);
     }
 }
 
-
-/* -------------------------- UiAction -------------------------- */
-
-UiAction::UiAction(UiObject *obj, QString &label, ui_callback f, void* userdata) : QAction(label, NULL) {
-    //QAction(label, NULL);
-    this->obj = obj;
-    this->callback = f;
-    this->userdata = userdata;
-}
-
-void UiAction::trigger() {
-    if(!callback) {
-        return;
+int64_t ui_actiongroup_get(UiInteger *value) {
+    QActionGroup *group = (QActionGroup*)value->obj;
+    auto actions = group->actions();
+    int i = 1;
+    foreach(const QAction *action, actions) {
+        if(action->isChecked()) {
+            value->value = i;
+            break;
+        }
+        i++;
     }
-    
-    UiEvent e;
-    e.obj = obj;
-    e.window = obj->window;
-    e.document = obj->ctx->document;
-    e.eventdata = NULL;
-    
-    if(isCheckable()) {
-        e.intval = isChecked();
-    } else {
-        e.intval = 0;
-    }
-    
-    callback(&e, userdata);
+    return value->value;
 }
 
-
-void ui_menu(char *label) {
-    // free current menu hierarchy
-    ucx_list_free(current);
-    
-    // create menu
-    UiMenu *menu = new UiMenu(label);
-    
-    current = ucx_list_prepend(NULL, menu);
-    menus = ucx_list_append(menus, menu);
+void ui_actiongroup_set(UiInteger *value, int64_t i) {
+    QActionGroup *group = (QActionGroup*)value->obj;
+    auto actions = group->actions();
+    if(i > 0) {
+        if(i-1 < actions.size()) {
+            actions[i]->setEnabled(true);
+        }
+        value->value = i;
+    } else {
+        foreach(QAction *action, actions) {
+            action->setEnabled(false);
+        }
+        value->value = 0;
+    }
 }
 
-void ui_submenu(char *label) {
-    UiMenu *menu = new UiMenu(label);
-    
-    // add submenu to current menu
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(menu);
+void add_menuitem_list_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     
-    // set the submenu to current menu
-    current = ucx_list_prepend(current, menu);
-}
-
-void ui_submenu_end() {
-    if(ucx_list_size(current) < 2) {
-        return;
-    }
-    current = ucx_list_remove(current, current);
-    //UcxList *c = current;
 }
 
 
-void ui_menuitem(char *label, ui_callback f, void *userdata) {
-    ui_menuitem_gr(label, f, userdata, -1);
-}
-
-void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) {
-    ui_menuitem_stgr(stockid, f, userdata, -1);
-}
-
-void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) {
-    if(!current) {
-        return;
-    }
-    
-    UiMenuItem *item = new UiMenuItem(label, f, userdata);
-    
-    // add groups
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        item->addGroup(group);
-    }
-    va_end(ap);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
-    if(!current) {
+void ui_add_menus(UiObject *obj, QMainWindow *window) {
+    UiMenu *menus_begin = uic_get_menu_list();
+    if(menus_begin == NULL) {
         return;
     }
     
-    UiStMenuItem *item = new UiStMenuItem(stockid, f, userdata);
-    
-    // add groups
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        item->addGroup(group);
-    }
-    va_end(ap);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_menuseparator() {
-    if(!current) {
-        return;
-    }
-    
-    UiMenuSeparator *item = new UiMenuSeparator();
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_checkitem(char *label, ui_callback f, void *userdata) {
-    if(!current) {
-        return;
-    }
-    
-    UiMenuItem *item = new UiMenuItem(label, f, userdata);
-    item->setCheckable(true);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_checkitem_nv(char *label, char *vname) {
-    if(!current) {
-        return;
-    }
-    
-    UiCheckItemNV *item = new UiCheckItemNV(label, vname);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) {
-    
-}
-
-void ui_add_menus(UiObject *obj, QMainWindow *window) {
     QMenuBar *mb = window->menuBar();
     
-    UCX_FOREACH(elm, menus) {
-        UiMenu *menu = (UiMenu*)elm->data;
-        menu->addTo(obj, mb, NULL);        
+    UiMenu *ls = menus_begin;
+    while(ls) {
+        if(ls->item.type == UI_MENU) {
+            QMenu *menu = mb->addMenu(ls->label);
+            add_menu_items(menu, 0, ls, obj);
+        }        
+        ls = (UiMenu*)ls->item.next;
     }
 }
 
-int ui_checkitem_get(UiInteger *i) {
-    QAction *action = (QAction*)i->obj;
-    i->value = action->isChecked();
-    return i->value;
-}
-
-void ui_checkitem_set(UiInteger *i, int value) {
-    QAction *action = (QAction*)i->obj;
-    i->value = value;
-    action->setChecked(value);
-}
-
-
-/*
- * widget menu functions
- */
-
-UiContextMenuHandler::UiContextMenuHandler(QWidget *widget, QMenu* menu) {
-    this->widget = widget;
-    this->menu = menu;
-}
-
-void UiContextMenuHandler::contextMenuEvent(const QPoint & pos) {
-    menu->popup(widget->mapToGlobal(pos));
-}
-UIMENU ui_contextmenu(UiObject *obj) {
-    UiContainer *ct = uic_get_current_container(obj);
-    return ui_contextmenu_w(obj, ct->current);
-}
-
-UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget) {
-    UiContainer *ct = uic_get_current_container(obj);
-    
-    QMenu *menu = new QMenu(widget);
-    widget->setContextMenuPolicy(Qt::CustomContextMenu);
-    
-    UiContextMenuHandler *handler = new UiContextMenuHandler(widget, menu);
-    QObject::connect(
-            widget,
-            SIGNAL(customContextMenuRequested(QPoint)),
-            handler,
-            SLOT(contextMenuEvent(QPoint)));
-    
-    ct->menu = menu;
-    
-    return menu;
-}
-
-void ui_contextmenu_popup(UIMENU menu) {
-    
+void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) {
+    if(action->var) {
+        event->eventdata = action->var->value;
+    }
+    event->intval = action->isChecked();
 }
 
-void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) {
-    ui_widget_menuitem_gr(obj, label, f, userdata, -1);
-}
-
-void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...) {
-    UiContainer *ct = uic_get_current_container(obj);
-    if(!ct->menu) {
-        return;
-    }
-    
-    // add groups
-    UcxList *groups = NULL;
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        ucx_list_append(groups, (void*)(intptr_t)group);
-    }
-    va_end(ap);
-    
-    // create menuitem
-    QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, f, userdata);
-    ct->menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
+int64_t ui_checkableaction_get(UiInteger *value) {
+    UiAction *action= (UiAction*)value->obj;
+    value->value = action->isChecked();
+    return value->value;
 }
 
-void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) {
-    ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1);
+void ui_checkableaction_set(UiInteger *value, int64_t i) {
+    UiAction *action = (UiAction*)value->obj;
+    value->value = i;
+    if(i != 0) {
+        action->setChecked((bool)i);
+    }
 }
 
-void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...) {
-    UiContainer *ct = uic_get_current_container(obj);
-    if(!ct->menu) {
-        return;
-    }
-    
-    // add groups
-    UcxList *groups = NULL;
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        ucx_list_append(groups, (void*)(intptr_t)group);
-    }
-    va_end(ap);
-    
-    // create menuitem
-    UiStockItem *stockItem = ui_get_stock_item(stockid);
-    
-    QString str = QString::fromUtf8(stockItem->label);
-    UiAction *action = new UiAction(obj, str, f, userdata);
-    action->setIcon(QIcon::fromTheme(stockItem->icon_name));
-    action->setIconVisibleInMenu(true);
-    ct->menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
-}

mercurial