QML ListView에 C++ QStandardItemModel적용
QML ListView에서 C++에서 작성한 QStandardItemModel을 적용하기 위한 예제 입니다.
- main.cpp
#include "qtquick1applicationviewer.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QDeclarativeEngine>
#include <QDeclarativeContext>
class TestModel : public QStandardItemModel
{
public:
TestModel() : QStandardItemModel()
{
QHash<int, QByteArray> roleNames;
roleNames[Qt::UserRole + 1] = "name";
roleNames[Qt::UserRole + 2] = "option1";
roleNames[Qt::UserRole + 3] = "option2";
setRoleNames(roleNames);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
TestModel* model = new TestModel;
QList<QStandardItem*> columnItems;
QStandardItem *item1 = new QStandardItem("AAA");
item1->setData(QString("AAA"), Qt::UserRole + 1);
item1->setData(QString("111"), Qt::UserRole + 2);
item1->setData(QString("222"), Qt::UserRole + 3);
columnItems << item1;
model->appendRow( columnItems );
columnItems.clear();
QStandardItem *item2 = new QStandardItem();
item2->setData(QString("BBB"), Qt::UserRole + 1);
item2->setData(QString("333"), Qt::UserRole + 2);
item2->setData(QString("444"), Qt::UserRole + 3);
columnItems << item2;
model->appendRow( columnItems );
QtQuick1ApplicationViewer viewer;
viewer.addImportPath(QLatin1String("modules"));
viewer.setOrientation(QtQuick1ApplicationViewer::ScreenOrientationAuto);
viewer.engine()->rootContext()->setContextProperty( "testModel", model );
viewer.setMainQmlFile(QLatin1String("qml/qmllistex/main.qml"));
viewer.showExpanded();
return app.exec();
}
- main.qml
import QtQuick 1.1
Rectangle {
width: 640
height: 480
Component {
id: listRow
Row {
Rectangle {
width:100
height:20
color: "blue"
TextEdit {
anchors.fill: parent
color: "white"
text: name
}
}
Rectangle {
width:100
height:20
color: "red"
TextEdit {
anchors.fill: parent
color: "white"
text: option1
}
}
Rectangle {
width:100
height:20
color: "cyan"
TextEdit {
anchors.fill: parent
color: "white"
text: option2
}
}
}
}
ListView {
model: testModel
delegate: listRow
anchors.fill: parent
interactive: false
}
}
실행결과
위의 예제에서 QML코드에서 C++의 TestModel의 값을 수정하기 위해서는 다음과 같은 방법으로 수정할 수 있습니다.
편의상 주요 수정사항만 발췌 합니다.
- main.cpp
class TestModel : public QStandardItemModel
{
Q_OBJECT
public:
TestModel() : QStandardItemModel()
{
QHash<int, QByteArray> roleNames;
roleNames[Qt::UserRole + 1] = "name";
roleNames[Qt::UserRole + 2] = "option1";
roleNames[Qt::UserRole + 3] = "option2";
setRoleNames(roleNames);
}
Q_INVOKABLE void setModelProperty(int index, QString property, QVariant value)
{
qDebug() << "TestModel::setModelProperty index:" << index << " property:" << property
<< " value:" << value;
if (property == "name")
setData(QStandardItemModel::index(index, 0), value, Qt::UserRole+1);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
....
viewer.setMainQmlFile(QLatin1String("qml/qmllistex/main.qml"));
viewer.showExpanded();
return app.exec();
}
#include "main.moc"
먼저 TestMode의 객체에 setModelProperty라는 함수를 추가하고, 해당 함수에서 property의 값이 “name”인 경우 setData함수를 통해 Qt::UserRole+1 에 해당하는 값을 value로 변경합니다.
Qt::UserRole+1은 앞서 TestMode생성자에서 정의한 “name”의 user role입니다.
setModelProperty함수는 QML에서 접근이 가능하여야 하므로 Q_INVOKABLE 이 추가되어야 하고, Q_INVOKABLE이 제대로 동작하기 위해서는 Q_OBJECT가 TestModel에 선언이 되어야 하기 때문에 이 역시 추가를 하였습니다.
이와 더불어 Q_OBJECT가 추가되고, 해당 코드가 main.cpp 와 같이 source 코드에 기술됨에 따라 main.cpp파일 가장 하단에 main.moc를 include합니다.
이제 QML코드에서 다음과 같이 setModelProperty에 접근하는 코드를 삽입합니다.
....
Component {
id: listRow
Row {
Rectangle {
width:100
height:20
color: "blue"
TextEdit {
anchors.fill: parent
color: "white"
text: name
}
}
Rectangle {
width:100
height:20
color: "red"
TextEdit {
anchors.fill: parent
color: "white"
text: option1
}
}
Rectangle {
width:100
height:20
color: "cyan"
TextEdit {
anchors.fill: parent
color: "white"
text: option2
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("Clicked: "+index)
testModel.setModelProperty(index, "name", "xxxx")
}
}
}
}
}
....
위의 QML코드중 option2의 값을 표시하는 Rectangle에 MouseArea를 추가하고 onClicked를 재정의하여 testModel.setModelProperty(index, “name”, “xxxx”) 를 추가합니다.
이 루틴은 현재 index(즉 row)의 name 필드의 값을 “xxxx”로 변경합니다.
위를 저장하고 실행을 하면 option2의 필드를 클릭하면 첫번재 이름부분이 “xxxx”로 변경됨을 확인할 수 있습니다.
실행결과