implement listview (QT)

Mon, 21 Apr 2025 11:03:17 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 21 Apr 2025 11:03:17 +0200
changeset 579
810b848e2e4f
parent 578
950d2e38957b
child 580
9b8d61227169

implement listview (QT)

application/main.c file | annotate | diff | comparison | revisions
ui/qt/list.cpp file | annotate | diff | comparison | revisions
ui/qt/model.cpp file | annotate | diff | comparison | revisions
ui/qt/model.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Sun Apr 20 10:56:50 2025 +0200
+++ b/application/main.c	Mon Apr 21 11:03:17 2025 +0200
@@ -915,8 +915,21 @@
 
 #ifdef UI_QT
 
+static void list_activate(UiEvent *event, void *userdata) {
+    UiListSelection *sel = event->eventdata;
+    printf("selection [%d]\n", sel->rows[0]);
+}
+
 void application_startup(UiEvent *event, void *data) {
     UiObject *obj = ui_window("My Window", NULL);
+    
+    UiList *list = ui_list_new(obj->ctx, "mylist");
+    ui_list_append(list, "Entry 1");
+    ui_list_append(list, "Entry 2");
+    ui_list_append(list, "Entry 3");
+    ui_list_append(list, "Entry 4");
+    ui_list_append(list, "Entry 5");
+    
     ui_grid(obj, .margin = 10, .columnspacing = 10, .rowspacing = 10) {
         ui_button(obj, .label = "Button 1");
         ui_button(obj, .label = "Button 2", .hexpand = TRUE, .hfill = TRUE);
@@ -924,6 +937,7 @@
         ui_newline(obj);
         
         ui_textarea(obj, .vexpand = TRUE, .vfill = TRUE);
+        ui_listview(obj, .varname = "mylist", .colspan = 2, .fill = TRUE, .onactivate = list_activate);
         ui_newline(obj);
         
         ui_button(obj, .label = "Button Y");
--- a/ui/qt/list.cpp	Sun Apr 20 10:56:50 2025 +0200
+++ b/ui/qt/list.cpp	Mon Apr 21 11:03:17 2025 +0200
@@ -33,4 +33,43 @@
 #include <QTreeWidgetItem>
 #include <QListView>
 
+extern "C" void* ui_strmodel_getvalue(void *elm, int column) {
+    return column == 0 ? elm : NULL;
+}
 
+
+UIWIDGET ui_listview_create(UiObject* obj, UiListArgs args) {
+    UiContainerPrivate *ctn = ui_obj_container(obj);
+    UI_APPLY_LAYOUT(ctn->layout, args);
+    
+    QListView *view = new QListView();
+    
+    ui_getvaluefunc getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST);
+    
+    ListModel *model = new ListModel(obj, view, var, getvalue);
+    view->setModel(model);
+    
+    if(var) {
+        UiList *list = (UiList*)var->value;
+        list->update = ui_listmodel_update;
+        list->getselection = ui_listmodel_getselection;
+        list->setselection = ui_listmodel_setselection;
+        list->obj = model;
+    }
+    
+    model->setActivationCallback(args.onactivate, args.onactivatedata);
+    model->setSelectionCallback(args.onselection, args.onselectiondata);
+    
+    QItemSelectionModel *s = view->selectionModel();
+    QObject::connect(
+            s,
+            SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+            model,
+            SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
+    
+    
+    ctn->add(view, false);
+    
+    return view;
+}
--- a/ui/qt/model.cpp	Sun Apr 20 10:56:50 2025 +0200
+++ b/ui/qt/model.cpp	Mon Apr 21 11:03:17 2025 +0200
@@ -29,13 +29,34 @@
 #include "model.h"
 
 
-ListModel::ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *userdata){
+ListModel::ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc getvalue){
     this->obj = obj;
     this->view = view;
     this->var = var;
     this->getvalue = getvalue;
-    this->callback = f;
-    this->userdata = userdata;
+    this->onactivate = nullptr;
+    this->onactivatedata = nullptr;
+    this->onselection = nullptr;
+    this->onselectiondata = nullptr;
+}
+
+void ListModel::setActivationCallback(ui_callback f, void *userdata) {
+    onactivate = f;
+    onactivatedata = userdata;
+}
+
+void ListModel::setSelectionCallback(ui_callback f, void *userdata) {
+    onselection = f;
+    onselectiondata = userdata;
+}
+
+void ListModel::update(int row) {
+    if(row >= 0) {
+        this->update(row);
+    } else {
+        this->beginResetModel();
+        this->endResetModel();
+    }
 }
 
 int ListModel::rowCount(const QModelIndex& parent) const {
@@ -56,7 +77,66 @@
 }
 
 void ListModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
+    UiListSelection sel = ui_selection_model_to_selection(view->selectionModel());
     
+    UiEvent event;
+    event.obj = obj;
+    event.window = obj->window;
+    event.document = obj->ctx->document;
+    event.eventdata = &sel;
+    event.intval = sel.count;
+    event.set = ui_get_setop();
+    
+    if(onactivate) {
+        onactivate(&event, onactivatedata);
+    }
+    if(onselection) {
+        onselection(&event, onselectiondata);
+    }
+    
+    free(sel.rows);
 }
 
 
+
+
+UiListSelection ui_selection_model_to_selection(QItemSelectionModel *model) {
+    UiListSelection sel;
+    sel.rows = NULL;
+    sel.count = 0;
+    
+    if(model->hasSelection()) {
+        QModelIndexList indices = model->selectedIndexes();
+        sel.count = indices.count();
+        sel.rows = (int*)calloc(sel.count, sizeof(int));
+        
+        int i = 0;
+        for (const QModelIndex &index : indices) {
+            sel.rows[i++] = index.row();
+        }
+    }
+    
+    return sel;
+}
+
+/* ---------------------- UiList implementation -----------------------------*/
+
+void ui_listmodel_update(UiList *list, int row) {
+    ListModel *model = (ListModel*)list->obj;
+    model->update(row);
+}
+
+void ui_listmodel_setselection(UiList *list, UiListSelection sel) {
+    ListModel *model = (ListModel*)list->obj;
+    QItemSelection selection;
+    for (int i=0;i<sel.count;i++) {
+        QModelIndex index = model->index(sel.rows[i]);
+        selection.select(index, index);
+    }
+    model->view->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
+}
+
+UiListSelection ui_listmodel_getselection(UiList *list) {
+    ListModel *model = (ListModel*)list->obj;
+    return ui_selection_model_to_selection(model->view->selectionModel());
+}
--- a/ui/qt/model.h	Sun Apr 20 10:56:50 2025 +0200
+++ b/ui/qt/model.h	Mon Apr 21 11:03:17 2025 +0200
@@ -44,15 +44,23 @@
 class ListModel : public QAbstractListModel {
     Q_OBJECT
     
+    ui_getvaluefunc getvalue;
+    ui_callback onactivate;
+    void        *onactivatedata;
+    ui_callback onselection;
+    void        *onselectiondata;
+    
+public:
     UiObject    *obj;
     UiVar       *var;
-    ui_getvaluefunc getvalue;
-    ui_callback callback;
-    void        *userdata;
     QListView   *view;
     
-public:
-    ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *userdata);
+    ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc getvalue);
+    
+    void setActivationCallback(ui_callback f, void *userdata);
+    void setSelectionCallback(ui_callback f, void *userdata);
+    
+    void update(int row);
     
     int rowCount(const QModelIndex &parent = QModelIndex()) const;
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
@@ -64,6 +72,15 @@
 };
 
 
+UiListSelection ui_selection_model_to_selection(QItemSelectionModel *model);
+
+extern "C" {
+    
+    void ui_listmodel_update(UiList *list, int row);
+    void ui_listmodel_setselection(UiList *list, UiListSelection sel);
+    UiListSelection ui_listmodel_getselection(UiList *list);
+
+}
 
 #endif	/* MODEL_H */
 

mercurial