How to add QComboBox and TextField inside TreeView with delegate QML?
-
Hi, I had implement TreeView following this tutorial, But I had implement with Qt Quick Control (does not has .ui file). tutorial here. With load text and show on TreeView, it work fine. But I had another problem:
I know that a row is a TreeItem and the model is TreeModel extend from QAbstractItemModel.
-
My TreeView has four columns and I set data for TreeItem with its itemData, each itemData has 4 element.
-
On Value Column (column 2) I want to add dynamic component (QComboBox and TextField), it depend on value of TreeItem the TreeModel. [The figure below] 2.
-
I set data for TreeItem and TreeModel from .cpp file, and set model for TreeView in .qml file.
-
I have a objectA with 8 element (name, value, data to assign component for column 2, current index of Combobox if have Combobox, data1,...) with second element maybe QStringList or QString. My TreeItem get data from objectA with TreeItem (name,value,data1,data2).
I have 3 problems need to be solve:
- First problem, I had delegate the column 2 to all ComboBox or all TextField ok, But I cannot mix them together. When the value of TreeItem is a QStringList, I want delegate for Combobox, and when it is QString I want delegate for TextField. But I cannot access to the return data, I dont know that I need to define it on .cpp file or .qml file. I know that "styleData.value" is the value for a cell data, access from .qml file. But I cant to know data Type of "styleData.value" .
- Second problem, Another problem that I dont know how to set current index for Combobox on load data. For example: the value(second element) of TreeItem is: [item1, item2, item3] and the current Index is at item 2.
- Third problem, when data is loaded, I change data for ComboBox. How to get current Data of the TreeItem, current Index of Combobox.
Sorry for long question, and a lot of problem.
Please help me if you know any my problem. Thank in advance -
-
My TreeModel.h
class TreeModel : public QAbstractItemModel { Q_OBJECT enum DelegateEnum { NameEnum = 0, ValueEnum, DeviceEnum, UnitEnum }; public: explicit TreeModel(QObject *parent = 0); TreeModel(const QStringList &headers,const QList<PlcView *> &plcViewList, const QString &topIO, QObject *parent = 0); ~TreeModel(); int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; bool insertColumns(int position, int columns, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; bool insertRows(int position, int rows, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; bool removeColumns(int position, int columns, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE; private: void setupModelData(const QStringList &lines, TreeItem *parent); void setupModelData2(const QList<PlcView *> &plcViewList, TreeItem *parent, const QString &topIO); TreeItem *getItem(const QModelIndex &index) const; TreeItem *rootItem; };
roleNames() function:
QHash<int, QByteArray> TreeModel::roleNames() const { QHash<int, QByteArray> roles; roles[NameEnum] = "name"; roles[ValueEnum] = "value"; roles[DeviceEnum] = "device"; roles[UnitEnum] = "unit"; return roles; }
-
My mydevice.ui.qml file.
Item { id: content width: 320 height: 480 property alias valueColumnDelegate: valueColumn.delegate TreeView { id: treeView Layout.fillHeight: true Layout.fillWidth: true opacity: 1 highlightOnFocus: true Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter anchors.fill: parent anchors.margins: 2 headerDelegate: Rectangle { height: 60 Layout.fillHeight: true border.width: 1 border.color: "#000000" //color: pallete.altBgColor Text { anchors.fill: parent text: styleData.value renderType: Text.NativeRendering color: "#000000" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter } } TableViewColumn { role: "name" title: "Name" width: parent.width/4 + parent.width/16 delegate: TextDelegate{} } TableViewColumn { id: valueColumn role: "value" title: "Value" width: parent.width/4 - parent.width/12 } TableViewColumn { role: "device" title: "Device" width: parent.width/8 + parent.width/12 delegate: TextDelegate{} } TableViewColumn { role: "unit" title: "Unit" width: parent.width/4 + parent.width/16 delegate: TextDelegate{} } } } }
-
@tamlong0205 I think most of this can be done from C++ side.
-
You can add a function in the model which can return what type is the data for current index. This function will be called from QML and depending upon its value use a
Loader
to load the specific delegate. -
Perhaps setting currentIndex in
Component.onCompleted
handler ? -
Create a C++ function which will store in info in the model itself i.e When you change the index in ComboBox call this function and update the value there and may be maintain a role to store this update.
-