Use C ++ to implement the QML TreeViewModel (1 ). Using C ++ to implement the Data Access Components in the QML TreeViewModel (1) QML, such as ListView, TableView, and GridView, ListModel is usually used as the data provider, this kind of application is quite limited. use C ++ to implement the TreeView Model (1) of QML)
Data Access Components in QML, such as ListView, TableView, and GridView, usually use ListModel as the data provider. such applications have considerable limitations, such as being unable to access the local file system or connect to the traditional SQL database, therefore, data is usually accessed through C ++ and displayed and edited through QML. common data model components include q1_actitemmodel, q1_acttablemodel, and QSQLTableModel. All the advanced Model components are inherited from qiniactitemmodel. as long as you understand the interface functions and operation mechanism of qiniactitemmodel, you can understand the implementation methods of the Model/View mechanism of QT.
Qiniactitemmodel is an abstract class. to instantiate qiniactitemmodel, you must inherit and implement at least the following five methods:
Int rowCount (const QModelIndex & parent = QModelIndex () const;
Int columnCount (const QModelIndex & parent = QModelIndex () const;
QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex () const;
QVariant data (const QModelIndex & index, int role = Qt: DisplayRole) const;
QModelIndex parent (const QModelIndex & child) const;
Unlike the QWidget component, in the QML data model, data is accessed through Role instead of Column. for example:
- TableView {
- Id: tableView1
- Anchors. fill: parent
- TableViewColumn {
- Width: 50
- Title :""
- Role: "tagging"
- }
- TableViewColumn {
- Width: 80
- Title: "Operation"
- Role: "name"
- }
- }
TableViewColumn is the column definition of TableView. TableViewColumn obtains data from the model through the role attribute definition. TableView obtains the available role of the model by calling the roleNames () method of the model. Therefore, in addition to the five virtual functions that must be implemented, you must re-implement roleNames () to tell the View which role is available. the roleNames () prototype is as follows:
- QHash roleNames() const;
The following is a complete definition of the Model class:
- ClassSqlMenuEntry: public q1_actitemmodel, public QQmlParserStatus
- {
- Q_OBJECT
- Public:
- Explicit SqlMenuEntry (QObject * parent = 0 );
- ~ SqlMenuEntry ();
- Enum MenuEntryRoles {idRole = Qt: UserRole + 1, nameRole, defaultEntryRole, customEntryRole, iconRole, iconHoverRole };
- Int rowCount (const QModelIndex & parent = QModelIndex () const;
- Int columnCount (const QModelIndex & parent = QModelIndex () const;
- QModelIndex index (int row, int column, const QModelIndex & parent = QModelIndex () const;
- QVariant data (const QModelIndex & index, int role = Qt: DisplayRole) const;
- QModelIndex parent (const QModelIndex & child) const;
- QHash RoleNames () const;
- Private:
- QHash MRoleNames;
- QList > MRecords; // The actual data is stored here. QList can only store two-dimensional data but cannot store tree nodes. here is just an example.
- };
RoleNames () implementation is quite simple:
- QHash SqlMenuEntry::roleNames() const
- {
- return mRoleNames;
- }
MRoleNames can be initialized in the class constructor:
- SqlMenuEntry::SqlMenuEntry(QObject *parent)
- :QAbstractItemModel(parent)
- {
- mRoleNames[nameRole] = "name";
- mRoleNames[idRole] = "menuid";
- mRoleNames[iconRole] = "icon";
- mRoleNames[defaultEntryRole] = "default";
- mRoleNames[iconHoverRole] = "iconHover";
- }
In QML, you can access data through "name", "menuid", and "icon:
- ListView{
- model:MenuEntryModel{ }
- delegate:Item{
- Column{
- Text{text:name}
- Text{text:icon}
- }
- }
- }
If you only provide data for the tables table, you can simply provide data to the View based on the names of the above interface functions:
- Int SqlMenuEntry: rowCount (const QModelIndex & parent) const
- {
- Return mRecords. size ();
- }
- Int SqlMenuEntry: columnCount (const QModelIndex & parent) const
- {
- Return 1; // QML does not use columns to retrieve data. by default, a column is returned. If no example is returned, the View control considers the table to be empty and does not obtain data.
- }
- QModelIndex SqlMenuEntry: index (int row, int column, const QModelIndex & parent) const
- {
- If (row> = 0) & (row <mRecords. size ()))
- {
- Return createIndex (row, column );
- }
- Return QModelIndex (); // return an invalid empty index.
- }
- QModelIndex SqlMenuEntry: parent (const QModelIndex & child) const
- {
- Return QModelIndex (); // The rows in the tables table do not have parent nodes.
- }
- QVariant SqlMenuEntry: data (const QModelIndex & index, int role) const
- {
- If (index. isValid)
- {
- Return mRecords [index. row ()] [role];
- }
- }
Data in mRecords can be generated as needed. for example, you can use the QSqlQuery component to obtain and add data from the database server:
- QHash row;
- row[nameRole] = "name1";
- row[iconRole] = "icon1";
- mRecords.append(row);
The implemented model class can be passed through
- qmlRegisterType ("com.limutech.tv",1,0,"MenuEntryModel");
Register. the registered class can generate an instance in QML:
- import com.limutech.tv 1.0
- MenuEntryModel{
- id:menuEntryModel
- }
- ListView{
- model:menuEntryModel
- ...
- }
The process for the View component to obtain data is as follows:
1. View calls rowCount (constQModelIndex & parent) and passes an empty parent to get the number of rows of the root node;
2. View calls columnCount (const QModelIndex & parent) and passes an empty parent to get the number of columns of the root node;
3. View calls index (int row, int column, const QModelIndex & parent) for column enumeration to pass row numbers, column numbers, and empty parent to obtain the root node QModelIndex;
4. continue to use the returned modelIndex as the parent to obtain the rowCount and columnCount of each row. if the value is greater than 0, the node has subnodes;
5. call roleNames to return the available role list
6. with the returned modelIndex and role as parameters, call data to obtain data and use the corresponding delegate for display.
Therefore, to display a tree-like list, you need to improve the two-dimensional table model to handle situations where the parent is not empty. at the same time, the model should be able to store tree-like data, in the next section, I will continue to share the implementation of the layered model and some implementations that involve data modification.
The Data Access Components in batch Model (1) QML, such as ListView, TableView, and GridView, usually use ListModel as the data provider. such applications have considerable limitations...