returning objects from roles
-
Hey,
I'm trying to get a role to return an object. I'm running into undefined errors when I try to access display.blockNumber and display.time
here's my code
blockdisplay.h:
#ifndef BLOCKDISPLAY_H #define BLOCKDISPLAY_H #include <QMetaType> class BlockDisplay { public: BlockDisplay(); BlockDisplay(int blocknum, long time); BlockDisplay(const BlockDisplay &other); int blockNumber() const; long time() const; private: int m_blocknumber; long m_time; }; Q_DECLARE_METATYPE(BlockDisplay) #endif // BLOCKDISPLAY_H
blockdisplay.cpp:
#include "blockdisplay.h" BlockDisplay::BlockDisplay() { } BlockDisplay::BlockDisplay(int blocknum, long time) { this->m_blocknumber = blocknum; this->m_time = time; } BlockDisplay::BlockDisplay(const BlockDisplay &other) { this->m_blocknumber = other.blockNumber(); this->m_time = other.time(); } int BlockDisplay::blockNumber() const { return this->m_blocknumber; } long BlockDisplay::time() const { return this->m_time; }
modelclass.h:
#ifndef MODELCLASS_H #define MODELCLASS_H #include <QObject> #include <QAbstractListModel> #include <QStringListModel> #include <blockchain.h> class ModelClass : public QAbstractListModel { Q_OBJECT Q_PROPERTY(qint32 blockheight READ blockheight) protected: Blockchain bc{}; int first; public: ModelClass(); qint32 blockheight(); void init(); int rowCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; }; #endif // MODELCLASS_H
modelclass.cpp:
#include "modelclass.h" #include <string.h> #include <qdebug> #include "blockdisplay.h" using namespace std; ModelClass::ModelClass() { } void ModelClass::init() { bc.init(); if ( !bc.Valid() ) qDebug() << "invalid"; else { bc.SeekToFirst(); bc.Next(); if ( !bc.Valid() ) qDebug() << "invalid"; else first = bc.GetCurrentBlock().signedhead().head().num(); } //setProperty("blockheight",bc.GetBlockHeight()); } qint32 ModelClass::blockheight() { return bc.GetBlockHeight(); } int ModelClass::rowCount(const QModelIndex &parent) const { //qInfo() << " 0test " << bc.GetBlockHeight(); return bc.GetBlockHeight() - first; } QVariant ModelClass::data(const QModelIndex & index, int role) const { qInfo() << " 1test " << index; int row = bc.GetBlockHeight() - index.row();// + 1 + first; if (index.isValid()) { bc.Seek(row); if (bc.Valid()) { if (role == Qt::DisplayRole) { int blocknum = bc.GetCurrentBlock().signedhead().head().num(); long timestamp = bc.GetCurrentBlock().signedhead().head().timestamp(); BlockDisplay dsply{blocknum, timestamp}; QVariant var; var.setValue(dsply); return var; } } } return QVariant(); }
snippet from blocks.qml:
Component { id: gridComp Row { Text { text: display.blockNumber + " " MouseArea { anchors.fill: parent onClicked: { list.currentIndex = index; ld.setSource("detail.qml") } } } Text { text: display.time + " " } } }
[edit: fixed missing coding tags SGaist]
-
Hi,
You should take a look at the Using C++ Models with Qt Quick Views chapter of Qt's documentation. It should get you started.
-
@SGaist I'm a little confused. Perhaps I'm going in the wrong direction. All of the examples I've seen use roles with one value for example QString. I was thinking I can return an object and access it's properties via display.propertyname. Is this even possible?
Thanks!
-
If you take the QObjectList based example you'll see that you can access your object properties.
-
@jpnurmi from docs I read that I can use a list of QObject* as model data, but this model doesn't know if list content changes I have to reset the model. haven't tested yet but doesn't sound flexible.
In BlackBerry Cascades implementation I can fill a data model with a list of QObject* and use the properties of QObject* data classes in list view items. editing properties in QML the C++ QObject* was changed and changes automatically proposed to QML. very convenient: have a list, tap on row, push details page, change values, pop page and list values are automagically also changed.
...reading through the docs and examples to find out how to do this with Qt 5.6 ... landing in this thread.
from your answer I have the hope that there's a way to deal with QObject* data from C++ in QML, but perhaps I misunderstood. -
@ekkescorner QObjectList is indeed not great for dynamic lists, because there's no way to monitor for changes. Here's a dummy example of using QAbstractListModel + QObject:
// main.cpp #include <QtGui> #include <QtQml> class ExampleModel : public QAbstractListModel { Q_OBJECT public: ExampleModel(QObject *parent = 0) : QAbstractListModel(parent) { for (int i = 0; i < 10; ++i) { QObject *object = new QObject(this); object->setObjectName(QString::number(i) + QString::number(i)); m_objects.append(object); } } int rowCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; return m_objects.count(); } QVariant data(const QModelIndex &index, int role) const { if (!index.isValid() || role != Qt::UserRole) return QVariant(); return QVariant::fromValue(m_objects.at(index.row())); } QHash<int, QByteArray> roleNames() const { QHash<int, QByteArray> roles; roles.insert(Qt::UserRole, "example"); return roles; } private: QObjectList m_objects; }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); qmlRegisterType<ExampleModel>("example", 1, 0, "ExampleModel"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } #include "main.moc"
// main.qml import QtQuick 2.5 import QtQuick.Window 2.2 import example 1.0 Window { visible: true ListView { spacing: 20 anchors.fill: parent model: ExampleModel { } delegate: Text { text: example.objectName } } }
-
@jpnurmi thanks. sounds great - will try it out soon.
-
@jpnurmi cool :)
did some first tests with QAbstractListModel filled with some Customer* (QObject)
inserted customers, removed customers, changed properties via C++
all correct refreshed in QML ListViewseems I can "port" most of my data model logic / UI from BlackBerry Cascades to Qt 5.6 :)