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
Forum Updated to NodeBB v4.3 + New Features

DelegateChooser creates delegates in other context

Scheduled Pinned Locked Moved Solved QML and Qt Quick
delegatechoosertableviewqt 5.12
7 Posts 2 Posters 1.6k Views 1 Watching
  • 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.
  • SebastianMS Offline
    SebastianMS Offline
    SebastianM
    wrote on last edited by SebastianM
    #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
    • SebastianMS Offline
      SebastianMS Offline
      SebastianM
      wrote on 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
      0
      • SebastianMS SebastianM

        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 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
        • SebastianMS Offline
          SebastianMS Offline
          SebastianM
          wrote on last edited by SebastianM
          #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
          • SebastianMS Offline
            SebastianMS Offline
            SebastianM
            wrote on 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
            • SebastianMS Offline
              SebastianMS Offline
              SebastianM
              wrote on last edited by SebastianM
              #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
              1
              • SebastianMS SebastianM

                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 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

                • Login

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