Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSqlTableModel proxy not working
Forum Updated to NodeBB v4.3 + New Features

QSqlTableModel proxy not working

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 3 Posters 588 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.
  • S Offline
    S Offline
    SergeyK12
    wrote on last edited by
    #1

    Hi.

    I collide with an issue i couldnt understand.

    I have proxy which translate row into a tree.
    Its worked well with QStandardItemModel.
    But its broken with QSqlTableModel.

    Both models could be shown via QTableView. But Sql couldnt in QTreeView (no childs found)

    Is there any difference between models which i should care with proxy?
    I thought that there shouldnt. (both could be viewed in table, so functions for dhow is same)

    Thanks for any impulse in any direction (no idea what to do)

    Here is my code, just in case ...

    struct StandartProxyInternal{
        int row;
    };
    
    class StandardTreeProxy : public QAbstractProxyModel {
    
        // QAbstractItemModel interface
    public:
        QModelIndex index(int row, int column, const QModelIndex &parent) const
        {
            if(!parent.isValid()) {
                return createIndex(row, column, nullptr);
            }
    
            return createIndex(row, column, new StandartProxyInternal{parent.row()});
        }
    
        QModelIndex parent(const QModelIndex &child) const
        {
            if(!child.isValid()) {
                return QModelIndex();
            }
    
            auto *internal = static_cast<StandartProxyInternal*>(child.internalPointer());
            if(!internal) {
                return QModelIndex();
            }
    
            return index(internal->row, 0, QModelIndex());
        }
    
        int rowCount(const QModelIndex &parent) const
        {
            if(!parent.isValid()) {
                return sourceModel()->rowCount();
            }
    
            return sourceModel()->columnCount() - 1;
        }
    
        int columnCount(const QModelIndex &parent) const { return 1; }
    
    
        // QAbstractProxyModel interface
    public:
        QModelIndex mapToSource(const QModelIndex &proxyIndex) const
        {
            auto *internal = static_cast<StandartProxyInternal*>(proxyIndex.internalPointer());
    
            if(!internal) {
                return sourceModel()->index(proxyIndex.row(), 0);
            }
    
            int row = internal->row;
            int col = proxyIndex.row() + 1;
            return sourceModel()->index(row, col);
        }
    
    
        QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
        {
            if(sourceIndex.column() == 0) {
                return index(sourceIndex.row(), 0, QModelIndex());
            }
    
            return index(sourceIndex.column() - 1, 0, createIndex(sourceIndex.row(), 0));
        }
    
        // QAbstractItemModel interface
    public:
        bool hasChildren(const QModelIndex &parent) const
        {
            if(!parent.isValid()) {
                return sourceModel()->columnCount() > 0 ? true : false;
            }
    
            auto *internal = static_cast<StandartProxyInternal*>(parent.internalPointer());
    
            if(!internal) {
                return true;
            }
    
            return false;
        }
    
        // QAbstractProxyModel interface
    public:
        void setSourceModel(QAbstractItemModel *sourceModel)
        {
            QAbstractProxyModel::setSourceModel(sourceModel);
            connect(sourceModel, &QAbstractItemModel::dataChanged, this, &QAbstractProxyModel::dataChanged);
            connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &QAbstractProxyModel::rowsInserted);
        }
    };
    
    Pl45m4P 1 Reply Last reply
    0
    • S Offline
      S Offline
      SergeyK12
      wrote on last edited by SergeyK12
      #7

      Here is a debug log i got for sql version:

      hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
      hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
      rowCount QModelIndex(-1,-1,0x0,QObject(0x0))
      index 0 0 QModelIndex(-1,-1,0x0,QObject(0x0))
      parent QModelIndex(0,0,0x0,QAbstractProxyModel(0x2acd5fa1d90))
      0x0
      

      And same log for standard:

      hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
      hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
      rowCount QModelIndex(-1,-1,0x0,QObject(0x0))
      index 0 0 QModelIndex(-1,-1,0x0,QObject(0x0))
      hasChild QModelIndex(0,0,0x0,QAbstractProxyModel(0x2096f6e1660))
      parent QModelIndex(0,0,0x0,QAbstractProxyModel(0x2096f6e1660))
      0x0
      

      Third hasChildren not called.
      How could that happened? All i did is switch model. (I understand that its difficult to understand without the code of logging)

      1 Reply Last reply
      0
      • S SergeyK12

        Hi.

        I collide with an issue i couldnt understand.

        I have proxy which translate row into a tree.
        Its worked well with QStandardItemModel.
        But its broken with QSqlTableModel.

        Both models could be shown via QTableView. But Sql couldnt in QTreeView (no childs found)

        Is there any difference between models which i should care with proxy?
        I thought that there shouldnt. (both could be viewed in table, so functions for dhow is same)

        Thanks for any impulse in any direction (no idea what to do)

        Here is my code, just in case ...

        struct StandartProxyInternal{
            int row;
        };
        
        class StandardTreeProxy : public QAbstractProxyModel {
        
            // QAbstractItemModel interface
        public:
            QModelIndex index(int row, int column, const QModelIndex &parent) const
            {
                if(!parent.isValid()) {
                    return createIndex(row, column, nullptr);
                }
        
                return createIndex(row, column, new StandartProxyInternal{parent.row()});
            }
        
            QModelIndex parent(const QModelIndex &child) const
            {
                if(!child.isValid()) {
                    return QModelIndex();
                }
        
                auto *internal = static_cast<StandartProxyInternal*>(child.internalPointer());
                if(!internal) {
                    return QModelIndex();
                }
        
                return index(internal->row, 0, QModelIndex());
            }
        
            int rowCount(const QModelIndex &parent) const
            {
                if(!parent.isValid()) {
                    return sourceModel()->rowCount();
                }
        
                return sourceModel()->columnCount() - 1;
            }
        
            int columnCount(const QModelIndex &parent) const { return 1; }
        
        
            // QAbstractProxyModel interface
        public:
            QModelIndex mapToSource(const QModelIndex &proxyIndex) const
            {
                auto *internal = static_cast<StandartProxyInternal*>(proxyIndex.internalPointer());
        
                if(!internal) {
                    return sourceModel()->index(proxyIndex.row(), 0);
                }
        
                int row = internal->row;
                int col = proxyIndex.row() + 1;
                return sourceModel()->index(row, col);
            }
        
        
            QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
            {
                if(sourceIndex.column() == 0) {
                    return index(sourceIndex.row(), 0, QModelIndex());
                }
        
                return index(sourceIndex.column() - 1, 0, createIndex(sourceIndex.row(), 0));
            }
        
            // QAbstractItemModel interface
        public:
            bool hasChildren(const QModelIndex &parent) const
            {
                if(!parent.isValid()) {
                    return sourceModel()->columnCount() > 0 ? true : false;
                }
        
                auto *internal = static_cast<StandartProxyInternal*>(parent.internalPointer());
        
                if(!internal) {
                    return true;
                }
        
                return false;
            }
        
            // QAbstractProxyModel interface
        public:
            void setSourceModel(QAbstractItemModel *sourceModel)
            {
                QAbstractProxyModel::setSourceModel(sourceModel);
                connect(sourceModel, &QAbstractItemModel::dataChanged, this, &QAbstractProxyModel::dataChanged);
                connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &QAbstractProxyModel::rowsInserted);
            }
        };
        
        Pl45m4P Offline
        Pl45m4P Offline
        Pl45m4
        wrote on last edited by
        #2

        @SergeyK12

        Hi,

        I found related threads, maybe it helps.

        • https://www.qtcentre.org/threads/69098-Viewing-QSqlTableModel-in-QTreeView-through-a-proxy-model
        • https://stackoverflow.com/questions/68145427/issues-with-mapping-qsqltablemodel-to-qtreeview-using-qabstractproxymodel

        And here is an example:
        (can't tell if this still works, since it's pretty old)

        • https://github.com/Al-/QXTreeProxyModel

        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

        ~E. W. Dijkstra

        1 Reply Last reply
        1
        • S Offline
          S Offline
          SergeyK12
          wrote on last edited by SergeyK12
          #3

          Thanks. Try to compare with my solution.
          My misunderstand is that:
          (StandardModel is worked, but SqlModel isnt, but TableView in both cases is ok)

          image.png

          image.png

          so there is an internal difference between them?

          I though that every view should work for every model (as TableView)

          My example work for only single row in model and not support anything, just try to use proxy.

          1 Reply Last reply
          0
          • Christian EhrlicherC Online
            Christian EhrlicherC Online
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #4

            How would you map a table to a tree? You most likely did something wrong in your model.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SergeyK12
              wrote on last edited by SergeyK12
              #5

              I found out that all QModelIndexes is Invalid when its an sql one.
              But since my first column is a root indexes for other columns - thew added in the view.

                  QModelIndex mapToSource(const QModelIndex &proxyIndex) const
                  {
                      auto *internal = static_cast<StandartProxyInternal*>(proxyIndex.internalPointer());
              
                      if(!internal) {
                          return sourceModel()->index(proxyIndex.row(), 0);
                      }
              
                      int row = internal->row;
                      int col = proxyIndex.row() + 1;
                      return sourceModel()->index(row, col);
                  }
              
              
                  QModelIndex mapFromSource(const QModelIndex &sourceIndex) const
                  {
                      if(sourceIndex.column() == 0) {
                          return index(sourceIndex.row(), 0, QModelIndex());
                      }
              
                      return index(sourceIndex.column() - 1, 0, createIndex(sourceIndex.row(), 0));
                  }
              

              But it exactly same for standardmodel, which work

              1 Reply Last reply
              0
              • S Offline
                S Offline
                SergeyK12
                wrote on last edited by
                #6

                Seems like function hasChildren didnt call for root item

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SergeyK12
                  wrote on last edited by SergeyK12
                  #7

                  Here is a debug log i got for sql version:

                  hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
                  hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
                  rowCount QModelIndex(-1,-1,0x0,QObject(0x0))
                  index 0 0 QModelIndex(-1,-1,0x0,QObject(0x0))
                  parent QModelIndex(0,0,0x0,QAbstractProxyModel(0x2acd5fa1d90))
                  0x0
                  

                  And same log for standard:

                  hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
                  hasChild QModelIndex(-1,-1,0x0,QObject(0x0))
                  rowCount QModelIndex(-1,-1,0x0,QObject(0x0))
                  index 0 0 QModelIndex(-1,-1,0x0,QObject(0x0))
                  hasChild QModelIndex(0,0,0x0,QAbstractProxyModel(0x2096f6e1660))
                  parent QModelIndex(0,0,0x0,QAbstractProxyModel(0x2096f6e1660))
                  0x0
                  

                  Third hasChildren not called.
                  How could that happened? All i did is switch model. (I understand that its difficult to understand without the code of logging)

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    SergeyK12
                    wrote on last edited by SergeyK12
                    #8

                    @Christian Ehrlicher Thanks for your links, from which i found out about flags existance.

                    It happened because of this check insede Qt:

                    if (parent.flags() & Qt::ItemNeverHasChildren)
                    

                    and it flag always in my QModelIndex

                    QFlags<Qt::ItemFlag>(ItemIsSelectable|ItemIsEditable|ItemIsEnabled|ItemNeverHasChildren)
                    

                    1751d8e5-b6f8-47ca-bf9d-59290e64cbb6-image.png

                    Default flags settings is a key difference between QStandardModel and QSqlTabbleModel!

                    1 Reply Last reply
                    0
                    • S SergeyK12 has marked this topic as solved on
                    • S SergeyK12 has marked this topic as solved on
                    • S SergeyK12 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