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. Passing C++ Data Structure to QML
Forum Update on Monday, May 27th 2025

Passing C++ Data Structure to QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
2 Posts 2 Posters 360 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.
  • I Offline
    I Offline
    ikuris
    wrote on last edited by
    #1

    Hello,
    I am trying to implement Custom Table View in qml to pass to QQucikWidget, I have implemented Custom Model that inherits from QAbstractTableModel, my problem is I do want to pass a whole structure as one column but I couldn't manage to implement the QML part of that. Here is my data that I am using in model

    #include <array>
    #include <QObject>
    
    struct Item
    {
        unsigned int id1;
        unsigned int id2;
        bool flag;
    };
    
    
    
    struct TData
    {
        unsigned int id1;
        unsigned int id2;
        std::array<Item, 4> items;
    };
    
    
    Q_DECLARE_METATYPE(Item)
    

    Here is my CustomModel implementations

    // CustomTable.h
        enum Roles
        {
            ItemRole = Qt::UserRole + 1
        };
    
    // CustomTable.cpp
    QVariant CustomTable::data(const QModelIndex &index, int role) const
    {
        if (!index.isValid())
            return QVariant();
    
        if(role == Qt::DisplayRole)
        {
            switch (index.column())
            {
                case 0: return datas[index.row()].id1;
                case 1: return datas[index.row()].id2;
            }
        }
        else if(role == Roles::ItemRole)
        {
            qDebug() << "item role data called!";
            switch (index.column())
            {
                case 2: return QVariant::fromValue(datas[index.row()].items);
            }
        }
    
        // FIXME: Implement me!
        return QVariant();
    }
    
    QHash<int, QByteArray> CustomTable::roleNames() const
    {
        QHash<int, QByteArray> roles;
        roles.insert(Qt::DisplayRole, "display");
        roles.insert(Roles::ItemRole, "item");
        return roles;
    }
    

    Here is my QML file

    // CustomTableView.qml
    import QtQuick 2.12
    import QtQuick.Window 2.12
    import Qt.labs.qmlmodels 1.0
    import QtQuick.Controls 2.15
    import CustomTable 1.0
    
    
    Item {
        anchors.fill: parent
        HorizontalHeaderView
        {
            syncView: tableView
            id: horizontalHeader
            anchors.left: tableView.left
        }
        TableView
        {
            id: tableView
            anchors.top: horizontalHeader.bottom
            anchors.fill: parent
            clip: true
            model: CustomTable
            {
                id: customTable
            }
            rowSpacing: 5
            onWidthChanged: forceLayout()
            onHeightChanged: forceLayout()
            columnWidthProvider: function(){return tableView.width / tableView.model.columnCount();}
            rowHeightProvider: function(){return tableView.height / 10;}
            topMargin: horizontalHeader.implicitHeight
    
    
            delegate: DelegateChooser {
                DelegateChoice
                {
                    column: 0
                    delegate: Text {
                        id: id1Text
                        text: display
                        horizontalAlignment: Text.AlignHCenter // Center text horizontally
                    }
                }
                DelegateChoice
                {
                    column: 1
                    delegate: Text {
                        id: id3
                        text: display
                        horizontalAlignment: Text.AlignHCenter // Center text horizontally
                    }
                }
                DelegateChoice
                {
                    column: 2
                    delegate: Item {
                        property var itemData: item
                        Row
                        {
                            spacing: 10
                            width: {
                                // Get the column width from the TableView model
                                var columnWidth = tableView.columnWidthProvider(tableView.model, 2);
                                // Subtract the spacing to account for spacing between rectangles
                                return columnWidth - spacing;
                            }
                            Rectangle
                            {
                                id: item1
                                width: parent.width / 5 // Set the width to a fraction of the parent's width
                                height: parent.height
                                color: "red"
                                Text {
                                    id: item1Text
                                    text: item[0].id1
                                    anchors.centerIn: parent
                                }
                            }
                            Rectangle
                            {
                                id: item2
                                width: parent.width / 5 // Set the width to a fraction of the parent's width
                                height: 30
                                color: "blue"
                                Text {
                                    id: item2Text
                                    text: item[1].id1
                                    anchors.centerIn: parent
                                }
                            }
    
                            Rectangle
                            {
                                id: item3
                                width: parent.width / 5 // Set the width to a fraction of the parent's width
                                height: 30
                                color: "green"
                                Text {
                                    id: item3Text
                                    text: item[2].id1
                                    anchors.centerIn: parent
                                }
                            }
    
                            Rectangle
                            {
                                id: item4
                                width: parent.width / 5 // Set the width to a fraction of the parent's width
                                height: 30
                                color: "yellow"
                                Text {
                                    id: item4Text
                                    text: item[3].id1
                                    anchors.centerIn: parent
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    

    As you can see I am trying to get the items in TData in column 2 but I couldn't manage to parse it through, I do get the "TypeError: Cannot read property 'id1' of undefined" error, What should I do, I kinda donot want to make 3 roles for each item and I want to see all 4 of them in 1 column. Is there a way for that? For the second part , since I'm new to QML, any improvements to the code will be very helpful.

    B 1 Reply Last reply
    0
    • I ikuris

      Hello,
      I am trying to implement Custom Table View in qml to pass to QQucikWidget, I have implemented Custom Model that inherits from QAbstractTableModel, my problem is I do want to pass a whole structure as one column but I couldn't manage to implement the QML part of that. Here is my data that I am using in model

      #include <array>
      #include <QObject>
      
      struct Item
      {
          unsigned int id1;
          unsigned int id2;
          bool flag;
      };
      
      
      
      struct TData
      {
          unsigned int id1;
          unsigned int id2;
          std::array<Item, 4> items;
      };
      
      
      Q_DECLARE_METATYPE(Item)
      

      Here is my CustomModel implementations

      // CustomTable.h
          enum Roles
          {
              ItemRole = Qt::UserRole + 1
          };
      
      // CustomTable.cpp
      QVariant CustomTable::data(const QModelIndex &index, int role) const
      {
          if (!index.isValid())
              return QVariant();
      
          if(role == Qt::DisplayRole)
          {
              switch (index.column())
              {
                  case 0: return datas[index.row()].id1;
                  case 1: return datas[index.row()].id2;
              }
          }
          else if(role == Roles::ItemRole)
          {
              qDebug() << "item role data called!";
              switch (index.column())
              {
                  case 2: return QVariant::fromValue(datas[index.row()].items);
              }
          }
      
          // FIXME: Implement me!
          return QVariant();
      }
      
      QHash<int, QByteArray> CustomTable::roleNames() const
      {
          QHash<int, QByteArray> roles;
          roles.insert(Qt::DisplayRole, "display");
          roles.insert(Roles::ItemRole, "item");
          return roles;
      }
      

      Here is my QML file

      // CustomTableView.qml
      import QtQuick 2.12
      import QtQuick.Window 2.12
      import Qt.labs.qmlmodels 1.0
      import QtQuick.Controls 2.15
      import CustomTable 1.0
      
      
      Item {
          anchors.fill: parent
          HorizontalHeaderView
          {
              syncView: tableView
              id: horizontalHeader
              anchors.left: tableView.left
          }
          TableView
          {
              id: tableView
              anchors.top: horizontalHeader.bottom
              anchors.fill: parent
              clip: true
              model: CustomTable
              {
                  id: customTable
              }
              rowSpacing: 5
              onWidthChanged: forceLayout()
              onHeightChanged: forceLayout()
              columnWidthProvider: function(){return tableView.width / tableView.model.columnCount();}
              rowHeightProvider: function(){return tableView.height / 10;}
              topMargin: horizontalHeader.implicitHeight
      
      
              delegate: DelegateChooser {
                  DelegateChoice
                  {
                      column: 0
                      delegate: Text {
                          id: id1Text
                          text: display
                          horizontalAlignment: Text.AlignHCenter // Center text horizontally
                      }
                  }
                  DelegateChoice
                  {
                      column: 1
                      delegate: Text {
                          id: id3
                          text: display
                          horizontalAlignment: Text.AlignHCenter // Center text horizontally
                      }
                  }
                  DelegateChoice
                  {
                      column: 2
                      delegate: Item {
                          property var itemData: item
                          Row
                          {
                              spacing: 10
                              width: {
                                  // Get the column width from the TableView model
                                  var columnWidth = tableView.columnWidthProvider(tableView.model, 2);
                                  // Subtract the spacing to account for spacing between rectangles
                                  return columnWidth - spacing;
                              }
                              Rectangle
                              {
                                  id: item1
                                  width: parent.width / 5 // Set the width to a fraction of the parent's width
                                  height: parent.height
                                  color: "red"
                                  Text {
                                      id: item1Text
                                      text: item[0].id1
                                      anchors.centerIn: parent
                                  }
                              }
                              Rectangle
                              {
                                  id: item2
                                  width: parent.width / 5 // Set the width to a fraction of the parent's width
                                  height: 30
                                  color: "blue"
                                  Text {
                                      id: item2Text
                                      text: item[1].id1
                                      anchors.centerIn: parent
                                  }
                              }
      
                              Rectangle
                              {
                                  id: item3
                                  width: parent.width / 5 // Set the width to a fraction of the parent's width
                                  height: 30
                                  color: "green"
                                  Text {
                                      id: item3Text
                                      text: item[2].id1
                                      anchors.centerIn: parent
                                  }
                              }
      
                              Rectangle
                              {
                                  id: item4
                                  width: parent.width / 5 // Set the width to a fraction of the parent's width
                                  height: 30
                                  color: "yellow"
                                  Text {
                                      id: item4Text
                                      text: item[3].id1
                                      anchors.centerIn: parent
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }
      
      
      

      As you can see I am trying to get the items in TData in column 2 but I couldn't manage to parse it through, I do get the "TypeError: Cannot read property 'id1' of undefined" error, What should I do, I kinda donot want to make 3 roles for each item and I want to see all 4 of them in 1 column. Is there a way for that? For the second part , since I'm new to QML, any improvements to the code will be very helpful.

      B Offline
      B Offline
      Bob64
      wrote on last edited by
      #2

      @ikuris there has been a recent thread here that seems to be about a very similar topic. I don't know if it will answer your question but it might be worth taking a look at it:

      https://forum.qt.io/topic/147232/exposing-entire-c-object-to-qml

      1 Reply Last reply
      0
      • I ikuris has marked this topic as solved on

      • Login

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