Salvo
Salvo

Reputation: 326

QML TableView get row clicked with QtQuick.Controls 2

I've searched a lot on the net but I didn't find an answer and that's something really strange since I suppose it's a basic functionality most people should use (probably I don't understand how to correctly use TableView with QtQuick.Controls 2).

Tha problem is: I would like to know on which row I clicked and I want to access data of a particular column of that row (something like TableView.get(row, column)). In QtQuick.Controls 1.4 there are functions that allow me to access the rows (like this one) but I cannot find any for QtQuick.Control 2. Also there aren't the selection: and itemDelegate: that would be useful. How can implement these things in QtQuick.Controls 2?

I am using Qt 5.15.0 with MinGw. I have datas from a database that are passed to QML with QAbstractTableModel.

.cpp model

#include "archiviosqlmodel.h"
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlQuery>
#include <QDebug>

ArchivioSqlModel::ArchivioSqlModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    db_4= QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), "def.db");
        db_4.setDatabaseName("def.db");
    if (!db_4.isOpen())
        db_4.open();

    QSqlQuery query(db_4);
    query.exec("CREATE TABLE IF NOT EXISTS A (ID INTEGER PRIMARY KEY AUTOINCREMENT, B INTEGER, C CHAR(5), D CHAR(5), E CHAR(5));");
    query.exec("INSERT INTO A (ID, B, C, D, E) VALUES (1, 2, 'AAAAA', 'BBBBB', 'CCCCC')");
    query.exec("INSERT INTO A (ID, B, C, D, E) VALUES (2, 4, 'DDDDD', 'FFFFF', 'QQQQQ')");
    query.exec("INSERT INTO A (ID, B, C, D, E) VALUES (3, 5, 'EEEEE', 'GGGGG', 'HHHHH')");


    model.setQuery("SELECT * FROM A", db_4);

    qDebug() << "Row Count " << model.rowCount() << "Column count " << model.columnCount();
}

ArchivioSqlModel::~ArchivioSqlModel()
{
    db_4.close();
}

QVariant ArchivioSqlModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role == Qt::DisplayRole)
    {
        if(orientation == Qt::Horizontal)
        {
            switch (section)
            {
            case 0:
                return tr("ID");
            case 1:
                return tr("A");
            case 2:
                return tr("A");
            case 3:
                return tr("A");
            case 4:
                return tr("A");
            }
        }
    }
    return QVariant();
}

int ArchivioSqlModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return model.rowCount();
}

int ArchivioSqlModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;
    return model.columnCount();
}

QVariant ArchivioSqlModel::data(const QModelIndex &index, int role) const
{
    QVariant value;
    if (!index.isValid())
        return QVariant();
    if(role == Qt::DisplayRole && index.row() >= 0 && index.row() < rowCount()
            && index.column() >= 0 && index.column() < columnCount())
    {
        QModelIndex modelIndex = this->index(index.row(), index.column());
        value = model.data(modelIndex, Qt::DisplayRole);
        return value;//QString("data %1-%2").arg(index.row()).arg(index.column());
    }
    return QVariant();
}

.h model

    #include <QSqlQueryModel>


class ArchivioSqlModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    explicit ArchivioSqlModel(QObject *parent = 0);

    Q_INVOKABLE QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    ~ArchivioSqlModel() override;

signals:
    void queryStrChanged();

public slots:

private:
    const static char* COLUMN_NAMES[];
    const static char* SQL_SELECT;

    QSqlDatabase db_4;
    QSqlQueryModel model;

    QHash<int, QByteArray> m_roleNames;

};

main.qml

 import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.4
import Archive 1.0
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    Rectangle {
        id: rectangle
        x: 62
        y: 106
        width: 200
        height: 200
        color: "#000022"
        border.width: 0
        anchors.fill:parent

        Rectangle {
            id: rectangleBack
            x: 10
            y: 406
            width: 64
            height: 64
            color: "#000033"
            radius: 20
            anchors.left: parent.left
            anchors.leftMargin: 10
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 10
            border.width: 2
            border.color: "#ffffff"

            MouseArea {
                id: mouseAreaBack
                anchors.fill: parent
                onClicked: {
                    if (stackView.depth > 1)
                        stackView.pop()
                }
                onPressed: {
                    rectangleBack.width = 64 - 4
                    rectangleBack.height = 64 - 4
                }
                onReleased: {
                    rectangleBack.width = 64
                    rectangleBack.height = 64
                }
            }
        }

        Text {
            id: textArchive
            height: 25
            color: "#ffffff"
            text: qsTr("Datas:")
            font.family: "Arial"
            verticalAlignment: Text.AlignVCenter
            font.bold: true
            fontSizeMode: Text.Fit
            horizontalAlignment: Text.AlignHCenter
            anchors.right: parent.right
            anchors.rightMargin: 0
            anchors.left: parent.left
            anchors.leftMargin: 0
            anchors.top: parent.top
            anchors.topMargin: 10
            font.pixelSize: 14
        }

        ArchivioSqlModel {
            id: archiviomodel
        }

        Rectangle {
            id: rectangle1
            color: "#000022"
            radius: 10
            border.width: 2
            border.color: "#ffffff"
            anchors.right: parent.right
            anchors.rightMargin: 5
            anchors.left: parent.left
            anchors.leftMargin: 5
            anchors.bottom: rectangleBack.top
            anchors.bottomMargin: 10
            anchors.top: textArchive.bottom
            anchors.topMargin: 10

            TableView {
                id: tableViewid
                anchors.leftMargin: 5
                anchors.bottomMargin: 5
                anchors.rightMargin: 5
                anchors.topMargin: 5

                columnWidthProvider: function (column) { return 100; }
                rowHeightProvider: function (column) { return 60; }
                anchors.fill: parent
                topMargin: columnsHeader.implicitHeight



                model: archiviomodel
                ScrollBar.horizontal: ScrollBar{}
                ScrollBar.vertical: ScrollBar{}
                clip: true



                delegate: Rectangle {
                    Text {
                        id: textId
                        text: display
                        anchors.fill: parent
                        anchors.margins: 10
                        color: 'black'
                        font.pixelSize: 15
                        verticalAlignment: Text.AlignVCenter
                    }

                    MouseArea {
                        anchors.fill: parent
                        onClicked: {
                            console.log("prova:" + textId.text)
                        }
                    }
                }


                Rectangle { // mask the headers
                    z: 3
                    color: "#000033"
                    y: tableViewid.contentY
                    x: tableViewid.contentX
                    width: tableViewid.leftMargin
                    height: tableViewid.topMargin
                }

                Row {
                    id: columnsHeader
                    y: tableViewid.contentY
                    z: 2
                    Repeater {
                        model: tableViewid.columns > 0 ? tableViewid.columns : 1
                        Label {
                            width: tableViewid.columnWidthProvider(modelData)
                            height: 35
                            text: archiviomodel.headerData(modelData, Qt.Horizontal)
                            color: '#ffffff'
                            font.pixelSize: 15
                            padding: 10
                            verticalAlignment: Text.AlignVCenter

                            background: Rectangle {
                                radius: 10
                                color: "#000022"
                            }
                        }
                    }
                }

                ScrollIndicator.horizontal: ScrollIndicator { }
                ScrollIndicator.vertical: ScrollIndicator { }

            }
        }

        Rectangle {
            id: rectangleOpenlap
            x: 10
            y: 406
            width: 64
            height: 64
            color: "#000033"
            radius: 20
            anchors.right: parent.right
            anchors.rightMargin: 10
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 10
            border.width: 2
            border.color: "#ffffff"

            MouseArea {
                id: mouseAreaOpenlap
                anchors.fill: parent
                onClicked: {
                    console.log("Rows")
                }
                onPressed: {
                    rectangleOpenlap.width = 64 - 4
                    rectangleOpenlap.height = 64 - 4
                }
                onReleased: {
                    rectangleOpenlap.width = 64
                    rectangleOpenlap.height = 64
                }
            }
        }
    }
}

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "archiviosqlmodel.h"

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QGuiApplication app(argc, argv);

    qmlRegisterType<ArchivioSqlModel>("Archive", 1, 0, "ArchivioSqlModel");

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

Thanks in advance!

Upvotes: 3

Views: 2263

Answers (1)

Mitch
Mitch

Reputation: 24416

To access data from the model, you can use the model context property and the built-in display role:

MouseArea {
    anchors.fill: parent
    onClicked: {
        console.log(model.display)
    }
}

Model data can be set in a similar way.

The above is basically a shorter way of the following:

MouseArea {
    anchors.fill: parent
    onClicked: {
        console.log(row, column, tableViewid.model.data(tableViewid.model.index(row, column)))
    }
}

The code above uses index() to create an index that can then be passed to data()

The row and column properties are provided to each delegate.

This is also useful if you need to get data from the model from outside the delegate, for whatever reason.

Upvotes: 4

Related Questions