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. TableView with different delegates for its columns (QtQuick 2.15)
Qt 6.11 is out! See what's new in the release blog

TableView with different delegates for its columns (QtQuick 2.15)

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 1.3k 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.
  • SeDiS Offline
    SeDiS Offline
    SeDi
    wrote on last edited by SeDi
    #1

    Hi,
    I want to show a TableView that shows a few of its roles with CheckBoxes or Buttons, other roles as normal text delegates, other roles not at all.
    I am using a c++ model derived from QAbstractTableModel (togethter with a QSortFilterProxyModel). Currently Qt 15.0.

    I am aware of the DelegateChooser , but the fact that it is in qt-labs lets me hesitate to use it.

    I'd hate to lose TableView's goodies (e.g. resizing columns) by using a ListView and I should avoid QtQuick 1 for performance reasons (and being deprecated in the first place).

    I have also contemplated just using a bunch of delegates inside an Item of which only one is visible at a time, depending on the role. But that'd be ugly and very memory-consuming.

    What is a proper way to go? Is it safe to go for a "labs" feature?

    BR
    Sebastian

    B 1 Reply Last reply
    0
    • SeDiS SeDi

      Hi,
      I want to show a TableView that shows a few of its roles with CheckBoxes or Buttons, other roles as normal text delegates, other roles not at all.
      I am using a c++ model derived from QAbstractTableModel (togethter with a QSortFilterProxyModel). Currently Qt 15.0.

      I am aware of the DelegateChooser , but the fact that it is in qt-labs lets me hesitate to use it.

      I'd hate to lose TableView's goodies (e.g. resizing columns) by using a ListView and I should avoid QtQuick 1 for performance reasons (and being deprecated in the first place).

      I have also contemplated just using a bunch of delegates inside an Item of which only one is visible at a time, depending on the role. But that'd be ugly and very memory-consuming.

      What is a proper way to go? Is it safe to go for a "labs" feature?

      BR
      Sebastian

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

      @SeDi the 'classic' way to do this is to use a Loader in your delegate and use a switch or if-else if-... construct to instantiate the appropriate component. This is what I do in a similar situation involving a ListView - but I am stuck on 5.9.6 at the moment. I would use DelegateChooser if I had the option, even if it is a labs component, as I could always switch back to my current approach if it stopped being supported or whatever.

      SeDiS 1 Reply Last reply
      2
      • B Bob64

        @SeDi the 'classic' way to do this is to use a Loader in your delegate and use a switch or if-else if-... construct to instantiate the appropriate component. This is what I do in a similar situation involving a ListView - but I am stuck on 5.9.6 at the moment. I would use DelegateChooser if I had the option, even if it is a labs component, as I could always switch back to my current approach if it stopped being supported or whatever.

        SeDiS Offline
        SeDiS Offline
        SeDi
        wrote on last edited by
        #3

        @Bob64 That sounds convincing - thank you!

        SeDiS 1 Reply Last reply
        0
        • SeDiS SeDi

          @Bob64 That sounds convincing - thank you!

          SeDiS Offline
          SeDiS Offline
          SeDi
          wrote on last edited by
          #4

          @SeDi For posterity, here's my working solution:

          delegate: Rectangle {
                                          width: childrenRect.width
                                          height: childrenRect.height
                                          Loader {
                                              sourceComponent: {
                                                  switch(columnNo) {
                                                  case 0: return firstDelegate;
                                                  case 1: return secondDelegate;
                                                  // ...
                                                  default: return etcDelegate;
                                                  }
                                              }
                                          }
                                          Component {
                                              id: firstDelegate
                                              Rectangle {
                                                  width: childrenRect.width
                                                  height: childrenRect.height
                                                  color: "lightgray"
                                                   Text {
                                                       width: contentWidth + contentHeight
                                                       height: contentHeight * 1.1
                                                       text: "first"
                                                       verticalAlignment: Text.AlignVCenter
                                                       horizontalAlignment: Text.AlignHCenter
                                                   }
                                              }
                                          }
                                          Component {
                                              id: secondDelegate
                                              Rectangle {
                                                  width: childrenRect.width
                                                  height: childrenRect.height
                                                  color: "yellow"
                                                   Text {
                                                       width: contentWidth + contentHeight
                                                       height: contentHeight * 1.1
                                                       text: "second"
                                                       verticalAlignment: Text.AlignVCenter
                                                       horizontalAlignment: Text.AlignHCenter
                                                   }
                                              }
                                          }
                                          Component {
                                              id: etcDelegate
                                              Rectangle {
                                                  width: childrenRect.width
                                                  height: childrenRect.height
                                                  color: "lightgreen"
                                                   Text {
                                                       width: contentWidth + contentHeight
                                                       height: contentHeight * 1.1
                                                       text: foodName
                                                       verticalAlignment: Text.AlignVCenter
                                                       horizontalAlignment: Text.AlignHCenter
                                                   }
                                              }
                                          }
                                      }
          

          To provide the columnNo role I had to do some work in my QAbstractTableModel.
          The roles enum in the header:

          class LogTableModel : public QAbstractTableModel
          {
              enum Role {
                  DisplayRole         = Qt::DisplayRole,
                  DecorationRole      = Qt::DecorationRole,
                  StatusTipRole       = Qt::StatusTipRole,
                  //whatever...
                  ColumnNoRole        = Qt::UserRole+5 // or wherever it suits
          ...
          
          

          In data(...) I have implemented:

          QVariant LogTableModel::data(const QModelIndex &index, int role) const
          {
              if (index.isValid()) {
                  switch(role)
                  {
                  case DisplayRole: return  QVariant::fromValue(m_columns.at(index.column())->at(index.row()));
                  case ColumnNoRole: return QVariant::fromValue(index.column());
          ...
          

          roleNames() must also know it:

          QHash<int, QByteArray> LogTableModel::roleNames() const
          {
              QHash<int, QByteArray> roles;
              roles[DisplayRole] = "display";
              roles[ColumnNoRole] = "columnNo";
          ...
          
          1 Reply Last reply
          1

          • Login

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