Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. DelegateChooser creates delegates in other context

DelegateChooser creates delegates in other context

Scheduled Pinned Locked Moved Solved QML and Qt Quick
delegatechoosertableviewqt 5.12
7 Posts 2 Posters 1.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    SebastianM
    wrote on 4 Nov 2019, 10:14 last edited by SebastianM 11 Apr 2019, 14:20
    #1

    Hi,
    I'm using model created and populated in C++. I'm using 3 additional roles (names provided in roleNames())

    import QtQuick 2.0
    import QtQuick.Controls 1.4
    import Qt.labs.qmlmodels 1.0
    
    TableView {
    	id: propertiesTableView
    	anchors.fill : parent
    	TableViewColumn{
    		title: "Name"
    		role: "display"
    		movable: false
    	}
    	TableViewColumn{
    		title: "Value"
    		role: "propertyValue"
    		movable: false
    		delegate: DelegateChooser {
    			role: "propertyType"
    			DelegateChoice { 
    				roleValue: "1"
    				delegate: Rectangle {
    					CheckBox {
    						checked: styleData.value
    					}
    				}
    			}
    		}
    	}
    	Component {
    		id: boolDelegate
    		CheckBox {
    			checked: styleData.value
    		}
    	}
    }
    

    When I run this code - I'm spammed with QQmlComponent: Must create component in context from the same QQmlEngine warning.
    Where's the problem? How to solve it?

    PS: I've debug a little and problem is with instantiation of DelegateChooser.
    *void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, QQmlContext forContext)
    and inside QQuickLoaderPrivate::_q_sourceLoaded
    creationContext()/itemContext() from stored/incubated component has engine property set inside, but component doesn't.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SebastianM
      wrote on 5 Nov 2019, 11:46 last edited by
      #2

      Minimal reproducing project
      main.cpp

      #include <QtQml/QQmlContext>
      #include <table_model.h>
      
      #include <QApplication>
      
      int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        TableModel model;
      
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("externalModel", &model);
      
        engine.load(QUrl(QLatin1String("qrc:/main.qml")));
        QList<QObject *> rootObjects = engine.rootObjects();
        if (rootObjects.size() == 0)
          return -1;
        model.populateWithTestData(); 
        return a.exec();
      }
      

      table_model.h

      #ifndef TABLE_MODEL_H
      #define TABLE_MODEL_H
      
      #include <QStandardItemModel>
      #include <memory>
      
      enum TableModelTypes {
        kFloatValue = 1,
        kIntValue = 2,
        kBoolValue = 3,
        kColorValue = 4,
        kVector2Value = 5,
        kVector3Value = 6,
        kStringValue = 7,
        kResourceValue = 8,
        VALUE_NOT_SET = 0,
      };
      
      enum TableModelRoles {
        PropertyType = Qt::UserRole,
        PropertyValue = Qt::UserRole + 1,
      };
      
      class TableModel : public QStandardItemModel {
        Q_OBJECT
      public:
        TableModel() {
          QHash<int, QByteArray> roleNames = QStandardItemModel::roleNames();
          roleNames[Qt::DisplayRole] = "display";
          roleNames[TableModelRoles::PropertyType] = "propertyType";
          roleNames[TableModelRoles::PropertyValue] = "propertyValue";
          setItemRoleNames(roleNames);
        }
      
        ~TableModel() = default;
      
        Qt::ItemFlags flags(const QModelIndex &index) const override {
          if (index.isValid()) {
            if (index.column() == 0)
              return Qt::ItemIsEnabled;
          }
          return QStandardItemModel::flags(index);
        }
      
        QVariant data(const QModelIndex &index, int role) const {
          if (!index.isValid())
            return QVariant();
      
          switch (role) {
          case TableModelRoles::PropertyValue: {
            return QStandardItemModel::data(createIndex(index.row(), 1, index.internalId()));
          }
          }
      
          return QStandardItemModel::data(index, role);
        }
      
        void populateWithTestData() {
          auto row = 0;
          setRowCount(9);
          setColumnCount(2);
          addModelRow(row++, "Actual Width", 1232, TableModelTypes::kFloatValue);
          addModelRow(row++, "Actual Height", 1032, TableModelTypes::kFloatValue);
          addModelRow(row++, "Visible", true, TableModelTypes::kBoolValue);
          addModelRow(row++, "Enable Click", false, TableModelTypes::kBoolValue);
          addModelRow(row++, "Enabled", false, TableModelTypes::kBoolValue);
          addModelRow(row++, "Horizontal Alignment", 1, TableModelTypes::kIntValue);
          addModelRow(row++, "Vertical Alignment", 2, TableModelTypes::kIntValue);
          addModelRow(row++, "Locale", "", TableModelTypes::kStringValue);
          addModelRow(row++, "Name", "Node from Outer Space", TableModelTypes::kStringValue);
          emit modelAcquired(this);
        }
      signals:
        void modelAcquired(QAbstractItemModel *_model);
      
      protected:
        void addModelRow(int row, QString name, QVariant value, TableModelTypes type) {
          QModelIndex nameIndex = index(row, 0);
          QModelIndex valueIndex = index(row, 1);
          setData(nameIndex, name);
          setData(valueIndex, value);
          setData(nameIndex, type, TableModelRoles::PropertyType);
        }
      };
      
      #endif  // TABLE_MODEL_H
      

      main.qml

      import QtQuick 2.12
      import QtQuick.Window 2.12
      import QtQuick.Controls 1.4
      import Qt.labs.qmlmodels 1.0
      
      Window {
      	visible: true
      	width: 600
      	height: 500
      
      	TableView {	
      		id: propertiesTableView
      		anchors.fill : parent
      		
      		TableViewColumn{
      			title: "Name"
      			role: "display"
      			movable: false
      		}
      		TableViewColumn{ title: "Type nr"; role: "propertyType";  movable: false; }
      	
      		DelegateChooser {
      			id: propertyValueDelegate
      			role: "propertyType"
      			DelegateChoice { 
      				roleValue: 3
      				delegate: Rectangle {
      					CheckBox {
      						checked: styleData.value
      					}
      				}
      			}
      			DelegateChoice {
      				delegate: Rectangle {
      					color: "blue"
      					Text {
      						text: "Default delegate"
      					}
      				}
      			}
      		}
      		
      		TableViewColumn{
      			title: "Value"
      			role: "propertyValue"
      			movable: false
      			delegate: propertyValueDelegate
      		}
      		
      		Connections {
      			target: externalModel
      			onModelAcquired : {
      				console.log("Setting model ("+_model.columnCount()+","+_model.rowCount()+")" )
      				propertiesTableView.model = _model
      				console.log("Setting model completed" )
      			}
      		}
      	
      	}
      
      	onClosing: {
      		console.log("Closing QML window ");
      		Qt.quit();
      	}
      }
      
      J.HilkJ 1 Reply Last reply 5 Nov 2019, 12:46
      0
      • S SebastianM
        5 Nov 2019, 11:46

        Minimal reproducing project
        main.cpp

        #include <QtQml/QQmlContext>
        #include <table_model.h>
        
        #include <QApplication>
        
        int main(int argc, char *argv[]) {
          QApplication a(argc, argv);
          TableModel model;
        
          QQmlApplicationEngine engine;
          engine.rootContext()->setContextProperty("externalModel", &model);
        
          engine.load(QUrl(QLatin1String("qrc:/main.qml")));
          QList<QObject *> rootObjects = engine.rootObjects();
          if (rootObjects.size() == 0)
            return -1;
          model.populateWithTestData(); 
          return a.exec();
        }
        

        table_model.h

        #ifndef TABLE_MODEL_H
        #define TABLE_MODEL_H
        
        #include <QStandardItemModel>
        #include <memory>
        
        enum TableModelTypes {
          kFloatValue = 1,
          kIntValue = 2,
          kBoolValue = 3,
          kColorValue = 4,
          kVector2Value = 5,
          kVector3Value = 6,
          kStringValue = 7,
          kResourceValue = 8,
          VALUE_NOT_SET = 0,
        };
        
        enum TableModelRoles {
          PropertyType = Qt::UserRole,
          PropertyValue = Qt::UserRole + 1,
        };
        
        class TableModel : public QStandardItemModel {
          Q_OBJECT
        public:
          TableModel() {
            QHash<int, QByteArray> roleNames = QStandardItemModel::roleNames();
            roleNames[Qt::DisplayRole] = "display";
            roleNames[TableModelRoles::PropertyType] = "propertyType";
            roleNames[TableModelRoles::PropertyValue] = "propertyValue";
            setItemRoleNames(roleNames);
          }
        
          ~TableModel() = default;
        
          Qt::ItemFlags flags(const QModelIndex &index) const override {
            if (index.isValid()) {
              if (index.column() == 0)
                return Qt::ItemIsEnabled;
            }
            return QStandardItemModel::flags(index);
          }
        
          QVariant data(const QModelIndex &index, int role) const {
            if (!index.isValid())
              return QVariant();
        
            switch (role) {
            case TableModelRoles::PropertyValue: {
              return QStandardItemModel::data(createIndex(index.row(), 1, index.internalId()));
            }
            }
        
            return QStandardItemModel::data(index, role);
          }
        
          void populateWithTestData() {
            auto row = 0;
            setRowCount(9);
            setColumnCount(2);
            addModelRow(row++, "Actual Width", 1232, TableModelTypes::kFloatValue);
            addModelRow(row++, "Actual Height", 1032, TableModelTypes::kFloatValue);
            addModelRow(row++, "Visible", true, TableModelTypes::kBoolValue);
            addModelRow(row++, "Enable Click", false, TableModelTypes::kBoolValue);
            addModelRow(row++, "Enabled", false, TableModelTypes::kBoolValue);
            addModelRow(row++, "Horizontal Alignment", 1, TableModelTypes::kIntValue);
            addModelRow(row++, "Vertical Alignment", 2, TableModelTypes::kIntValue);
            addModelRow(row++, "Locale", "", TableModelTypes::kStringValue);
            addModelRow(row++, "Name", "Node from Outer Space", TableModelTypes::kStringValue);
            emit modelAcquired(this);
          }
        signals:
          void modelAcquired(QAbstractItemModel *_model);
        
        protected:
          void addModelRow(int row, QString name, QVariant value, TableModelTypes type) {
            QModelIndex nameIndex = index(row, 0);
            QModelIndex valueIndex = index(row, 1);
            setData(nameIndex, name);
            setData(valueIndex, value);
            setData(nameIndex, type, TableModelRoles::PropertyType);
          }
        };
        
        #endif  // TABLE_MODEL_H
        

        main.qml

        import QtQuick 2.12
        import QtQuick.Window 2.12
        import QtQuick.Controls 1.4
        import Qt.labs.qmlmodels 1.0
        
        Window {
        	visible: true
        	width: 600
        	height: 500
        
        	TableView {	
        		id: propertiesTableView
        		anchors.fill : parent
        		
        		TableViewColumn{
        			title: "Name"
        			role: "display"
        			movable: false
        		}
        		TableViewColumn{ title: "Type nr"; role: "propertyType";  movable: false; }
        	
        		DelegateChooser {
        			id: propertyValueDelegate
        			role: "propertyType"
        			DelegateChoice { 
        				roleValue: 3
        				delegate: Rectangle {
        					CheckBox {
        						checked: styleData.value
        					}
        				}
        			}
        			DelegateChoice {
        				delegate: Rectangle {
        					color: "blue"
        					Text {
        						text: "Default delegate"
        					}
        				}
        			}
        		}
        		
        		TableViewColumn{
        			title: "Value"
        			role: "propertyValue"
        			movable: false
        			delegate: propertyValueDelegate
        		}
        		
        		Connections {
        			target: externalModel
        			onModelAcquired : {
        				console.log("Setting model ("+_model.columnCount()+","+_model.rowCount()+")" )
        				propertiesTableView.model = _model
        				console.log("Setting model completed" )
        			}
        		}
        	
        	}
        
        	onClosing: {
        		console.log("Closing QML window ");
        		Qt.quit();
        	}
        }
        
        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on 5 Nov 2019, 12:46 last edited by
        #3

        @SebastianM
        Hi
        I haben’s used Tableview jet, so correct me if I am wrong
        But in the minimal example you do Not expose your model to the qml engine nor do you assign any model inside the qml file, I don‘t think this can work


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SebastianM
          wrote on 5 Nov 2019, 14:11 last edited by SebastianM 11 May 2019, 14:11
          #4

          Model is created:

            TableModel model;
          
            QQmlApplicationEngine engine;
            engine.rootContext()->setContextProperty("externalModel", &model);
          

          and attached to TableView

          		Connections {
          			target: externalModel
          			onModelAcquired : {
          				console.log("Setting model ("+_model.columnCount()+","+_model.rowCount()+")" )
          				propertiesTableView.model = _model
          				console.log("Setting model completed" )
          			}
          		}
          

          I've got logs like

          qml: Setting model (2,9)
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          QQmlComponent: Must create component in context from the same QQmlEngine
          qml: Setting model completed
          

          which shows that custom model change signal is received by TableView and assigned.

          However, I just made test with this ListModel assigned statically inside main.qml. The same set of warnings about incorrect context.
          So it's not a model problem.

          	ListModel {
          		id: listModel_1
          		ListElement { name: "Actual Width"; propertyValue: 1232; propertyType: 1; }
          		ListElement { name: "Actual Height"; propertyValue: 1032; propertyType: 1; }
          		ListElement { name: "Visible"; propertyValue: 1; propertyType: 3; }
          		ListElement { name: "Enable click"; propertyValue: 0; propertyType: 3; }
          		ListElement { name: "Enabled"; propertyValue: 0; propertyType: 3; }
          		ListElement { name: "Horizontal Alignment"; propertyValue: 1; propertyType: 2; }
          		ListElement { name: "Vertical Alignment"; propertyValue: 2; propertyType: 2; }
          		ListElement { name: "Locale"; propertyValue: 1; propertyType: 7; }
          		ListElement { name: "Name"; propertyValue: 12; propertyType: 7; }
          	}
          
          1 Reply Last reply
          0
          • S Offline
            S Offline
            SebastianM
            wrote on 5 Nov 2019, 14:39 last edited by
            #5

            Even simplier - all in one QML. No selection for delegate - always and for everything display one delegate.

            import QtQuick 2.12
            import QtQuick.Window 2.12
            import QtQuick.Controls 1.4
            import Qt.labs.qmlmodels 1.0
            
            Rectangle {
            	visible: true
            	width: 600
            	height: 500
            	ListModel {
            		id: listModel_1
            		ListElement { display: "Actual Width"; propertyValue: 1232; propertyType: 1; }
            		ListElement { display: "Actual Height"; propertyValue: 1032; propertyType: 1; }
            		ListElement { display: "Visible"; propertyValue: 1; propertyType: 3; }
            		ListElement { display: "Enable click"; propertyValue: 0; propertyType: 3; }
            		ListElement { display: "Enabled"; propertyValue: 0; propertyType: 3; }
            		ListElement { display: "Horizontal Alignment"; propertyValue: 1; propertyType: 2; }
            		ListElement { display: "Vertical Alignment"; propertyValue: 2; propertyType: 2; }
            		ListElement { display: "Locale"; propertyValue: 1; propertyType: 7; }
            		ListElement { display: "Name"; propertyValue: 12; propertyType: 7; }
            	}
            	
            	DelegateChooser {
            		id: propertyValueDelegate
            		DelegateChoice {
            			delegate: Rectangle {
            				color: "blue"
            				Text {
            					text: "Default delegate"
            				}
            			}
            		}
            	}
            	
            	TableView {
            		id: propertiesTableView
            		anchors.fill : parent
            		model: listModel_1
            		
            		TableViewColumn{ title: "Name"; role: "display"; movable: false; }
            		TableViewColumn{ title: "Type nr"; role: "propertyType";  movable: false; }
            		
            		TableViewColumn{
            			title: "Value"
            			role: "propertyValue"
            			movable: false
            			delegate: propertyValueDelegate
            		}
            	}
            }
            
            1 Reply Last reply
            0
            • S Offline
              S Offline
              SebastianM
              wrote on 6 Nov 2019, 12:49 last edited by SebastianM 11 Jun 2019, 12:50
              #6

              I used Import to QtQuick.Controls 1.4 which added TableView from Quick Controls 1.
              DelegateChooser works with TableView from Quick Controls 2 so only import QtQuick 2.12 should remain

              J.HilkJ 1 Reply Last reply 8 Nov 2019, 09:31
              1
              • S SebastianM
                6 Nov 2019, 12:49

                I used Import to QtQuick.Controls 1.4 which added TableView from Quick Controls 1.
                DelegateChooser works with TableView from Quick Controls 2 so only import QtQuick 2.12 should remain

                J.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on 8 Nov 2019, 09:31 last edited by
                #7

                @SebastianM
                great that you managed to figure it out.

                It's a bit difficult to read all this on a mobile screen so excuse my previous posts 🙈

                Never the less, thanks for charing the answer


                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                1 Reply Last reply
                0

                1/7

                4 Nov 2019, 10:14

                • Login

                • Login or register to search.
                1 out of 7
                • First post
                  1/7
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved