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. [SOLVED] Use of QIdentityProxyModel and QTableView (Qt5.2)
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] Use of QIdentityProxyModel and QTableView (Qt5.2)

Scheduled Pinned Locked Moved General and Desktop
15 Posts 2 Posters 5.1k 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.
  • B Offline
    B Offline
    bizut
    wrote on last edited by
    #1

    Hi all,

    I'd like to use QIdentityProxyModel to add a special line in my tableview in order to avoid adding a button for inserting new data (i use the proxy for not adding fake data in my database for graphic purpose...).
    I have as a sourcemodel, a QSqlTableModel.
    With the following code, i have a line yes, but the text is blank. It seems that the data() function is not called for index.row=0! (that is where i want the special line). The data corresponding to the sourcemodel is well displayed.
    Would you have an explanation what is wrong in my code ? Many thanks!

    @class ProxyModelForTablePers : public QIdentityProxyModel {
    public :
    ProxyModelForTablePers(QObject* parent = 0);
    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
    virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    virtual Qt::ItemFlags flags(const QModelIndex &index) const;
    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
    };

    ProxyModelForTablePers::ProxyModelForTablePers (QObject* parent)
    : QIdentityProxyModel (parent) {
    }

    int ProxyModelForTablePers::rowCount(const QModelIndex &parent) const {

    return (this->sourceModel()->rowCount()+1);//for adding a fake line
    

    }

    QVariant ProxyModelForTablePers::data(const QModelIndex &proxyIndex, int role) const {

    if (!proxyIndex.isValid())
        return QVariant ();
    
    if (proxyIndex.row() == 0) {
        return QVariant ("NEW");
    } else
        return QIdentityProxyModel::data(proxyIndex, role);
    

    }

    bool ProxyModelForTablePers::setData(const QModelIndex &index, const QVariant &value, int role) {

    if (index.row() == 0) {
        return true;//not yet imlemented will do the insert
    }
    else
        return QIdentityProxyModel::setData (index, value, role);
    

    }

    Qt::ItemFlags ProxyModelForTablePers::flags(const QModelIndex &index) const {

    Qt::ItemFlags flags = QIdentityProxyModel::flags(index);
    flags |= Qt::ItemIsEditable;
    return flags;
    

    }

    QModelIndex ProxyModelForTablePers::index(int row, int column, const QModelIndex &parent) const {

    if (row == 0) {
        return QModelIndex(parent);
    } else
        return this->sourceModel()->index(row-1, column, parent);
    

    }

    and the code called for the QTableview :

    _SourceModel = new QSqlTableModel (this);
    FillSourceModelViewPers();
    
    ProxyModelForTablePers * lProxy = new ProxyModelForTablePers (this);
    lProxy->setSourceModel(_SourceModel);
    
    this->setModel(lProxy); ("this" is a subclass of QTableView)
    

    @

    1 Reply Last reply
    0
    • B Offline
      B Offline
      bizut
      wrote on last edited by
      #2

      Anyone has an experience of this proxy ? Thanks.

      [quote author="bizut" date="1390287425"]Hi all,

      I'd like to use QIdentityProxyModel to add a special line in my tableview in order to avoid adding a button for inserting new data (i use the proxy for not adding fake data in my database for graphic purpose...).
      I have as a sourcemodel, a QSqlTableModel.
      With the following code, i have a line yes, but the text is blank. It seems that the data() function is not called for index.row=0! (that is where i want the special line). The data corresponding to the sourcemodel is well displayed.
      Would you have an explanation what is wrong in my code ? Many thanks!

      @class ProxyModelForTablePers : public QIdentityProxyModel {
      public :
      ProxyModelForTablePers(QObject* parent = 0);
      virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
      virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const;
      virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
      virtual Qt::ItemFlags flags(const QModelIndex &index) const;
      virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
      };

      ProxyModelForTablePers::ProxyModelForTablePers (QObject* parent)
      : QIdentityProxyModel (parent) {
      }

      int ProxyModelForTablePers::rowCount(const QModelIndex &parent) const {

      return (this->sourceModel()->rowCount()+1);//for adding a fake line
      

      }

      QVariant ProxyModelForTablePers::data(const QModelIndex &proxyIndex, int role) const {

      if (!proxyIndex.isValid())
          return QVariant ();
      
      if (proxyIndex.row() == 0) {
          return QVariant ("NEW");
      } else
          return QIdentityProxyModel::data(proxyIndex, role);
      

      }

      bool ProxyModelForTablePers::setData(const QModelIndex &index, const QVariant &value, int role) {

      if (index.row() == 0) {
          return true;//not yet imlemented will do the insert
      }
      else
          return QIdentityProxyModel::setData (index, value, role);
      

      }

      Qt::ItemFlags ProxyModelForTablePers::flags(const QModelIndex &index) const {

      Qt::ItemFlags flags = QIdentityProxyModel::flags(index);
      flags |= Qt::ItemIsEditable;
      return flags;
      

      }

      QModelIndex ProxyModelForTablePers::index(int row, int column, const QModelIndex &parent) const {

      if (row == 0) {
          return QModelIndex(parent);
      } else
          return this->sourceModel()->index(row-1, column, parent);
      

      }

      and the code called for the QTableview :

      _SourceModel = new QSqlTableModel (this);
      FillSourceModelViewPers();
      
      ProxyModelForTablePers * lProxy = new ProxyModelForTablePers (this);
      lProxy->setSourceModel(_SourceModel);
      
      this->setModel(lProxy); ("this" is a subclass of QTableView)
      

      @
      [/quote]

      [quote author="bizut" date="1390287425"]Hi all,

      I'd like to use QIdentityProxyModel to add a special line in my tableview in order to avoid adding a button for inserting new data (i use the proxy for not adding fake data in my database for graphic purpose...).
      I have as a sourcemodel, a QSqlTableModel.
      With the following code, i have a line yes, but the text is blank. It seems that the data() function is not called for index.row=0! (that is where i want the special line). The data corresponding to the sourcemodel is well displayed.
      Would you have an explanation what is wrong in my code ? Many thanks!

      @class ProxyModelForTablePers : public QIdentityProxyModel {
      public :
      ProxyModelForTablePers(QObject* parent = 0);
      virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
      virtual QVariant data(const QModelIndex &proxyIndex, int role = Qt::DisplayRole) const;
      virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
      virtual Qt::ItemFlags flags(const QModelIndex &index) const;
      virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
      };

      ProxyModelForTablePers::ProxyModelForTablePers (QObject* parent)
      : QIdentityProxyModel (parent) {
      }

      int ProxyModelForTablePers::rowCount(const QModelIndex &parent) const {

      return (this->sourceModel()->rowCount()+1);//for adding a fake line
      

      }

      QVariant ProxyModelForTablePers::data(const QModelIndex &proxyIndex, int role) const {

      if (!proxyIndex.isValid())
          return QVariant ();
      
      if (proxyIndex.row() == 0) {
          return QVariant ("NEW");
      } else
          return QIdentityProxyModel::data(proxyIndex, role);
      

      }

      bool ProxyModelForTablePers::setData(const QModelIndex &index, const QVariant &value, int role) {

      if (index.row() == 0) {
          return true;//not yet imlemented will do the insert
      }
      else
          return QIdentityProxyModel::setData (index, value, role);
      

      }

      Qt::ItemFlags ProxyModelForTablePers::flags(const QModelIndex &index) const {

      Qt::ItemFlags flags = QIdentityProxyModel::flags(index);
      flags |= Qt::ItemIsEditable;
      return flags;
      

      }

      QModelIndex ProxyModelForTablePers::index(int row, int column, const QModelIndex &parent) const {

      if (row == 0) {
          return QModelIndex(parent);
      } else
          return this->sourceModel()->index(row-1, column, parent);
      

      }

      and the code called for the QTableview :

      _SourceModel = new QSqlTableModel (this);
      FillSourceModelViewPers();
      
      ProxyModelForTablePers * lProxy = new ProxyModelForTablePers (this);
      lProxy->setSourceModel(_SourceModel);
      
      this->setModel(lProxy); ("this" is a subclass of QTableView)
      

      @
      [/quote]

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        IIRC, the QIdentityProxyModel is not suited to do that. It can be used to modify the data but not to modify the model structure. You should rather start with a QSortFilterProxyModel

        Hope it helps

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • B Offline
          B Offline
          bizut
          wrote on last edited by
          #4

          Hi,
          Thanks for your answer. It doesn't work neither with QSortFilterProxyModel.
          I'm wondering if my index method reimplementaion is correct.
          I can see that data form the source model but not my fake line...

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            IIRC you would have to also modify mapToSource

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • B Offline
              B Offline
              bizut
              wrote on last edited by
              #6

              Hi,

              Ok Thank you. Below is the code.
              It works. I mean i have the "new line" displayed as the first line and the sql data displayed the other lines.
              But i still have 2 problems :

              1. The first is that when i move the mouse over the first line, the program crashes.
              2. Instead of having the text "NEW" in the cell where it should be displayed, i have a small rectangular and the text "N...".

              Would you have some suggestions to make it work ? Thank you.
              By the way, would you have some working example ? It would be great.
              Many thanks!

              @
              QModelIndex ProxyModelForTablePers::index(int row, int column, const QModelIndex &parent) const {

              if (row == 0) {
                  return this->createIndex(row, column);
              } else
                  return this->sourceModel()->index(row-1, column, parent);
              

              }

              QModelIndex ProxyModelForTablePers::mapFromSource(const QModelIndex & source) const
              {
              if (!sourceModel())
              return QModelIndex();

              if (!source.parent().isValid())
                  return QModelIndex();
              
              return index(source.row()+1, source.column());
              

              }

              QModelIndex ProxyModelForTablePers::mapToSource(const QModelIndex & proxy) const
              {

              if (!sourceModel())
                  return QModelIndex();
              
              if (proxy.row()==0)
                  return QModelIndex();
              
              return this->sourceModel()->index(proxy.row()-1, proxy.column());
              

              }
              @

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Did you implement the data function ? If so, how does it look like ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  bizut
                  wrote on last edited by
                  #8

                  Hi,

                  Below is the my code :

                  @
                  ProxyModelForTablePers::ProxyModelForTablePers (QObject* parent)
                  : QSortFilterProxyModel (parent) {

                  }

                  int ProxyModelForTablePers::rowCount(const QModelIndex &parent) const {
                  return (this->sourceModel()->rowCount()+1);
                  }

                  QVariant ProxyModelForTablePers::data(const QModelIndex &proxyIndex, int role) const {

                  if (!proxyIndex.isValid())
                      return QVariant ();
                  
                  if (proxyIndex.row() == 0) {
                  
                      if (proxyIndex.column()==1)
                          return QVariant ("new");
                      else
                          return QVariant("test");
                  } else
                      return QSortFilterProxyModel::data(proxyIndex, role);
                      //return this->sourceModel()->data(this->mapToSource(proxyIndex), role);
                  

                  }

                  bool ProxyModelForTablePers::setData(const QModelIndex &index, const QVariant &value, int role) {

                  if (index.row() == 0) {
                      return false;
                  }
                  else
                      return this->sourceModel()->setData (index, value, role);
                  

                  }

                  Qt::ItemFlags ProxyModelForTablePers::flags(const QModelIndex &index) const {

                  Qt::ItemFlags flags = QSortFilterProxyModel::flags(index);
                  flags |= Qt::ItemIsEditable;
                  return flags;
                  

                  }

                  QModelIndex ProxyModelForTablePers::index(int row, int column, const QModelIndex &parent) const {

                  if (row == 0) {
                      return this->createIndex(row, column);
                  } else
                      return this->sourceModel()->index(row-1, column, parent);
                  

                  }

                  QModelIndex ProxyModelForTablePers::mapFromSource(const QModelIndex & source) const
                  {
                  if (!sourceModel())
                  return QModelIndex();

                  if (!source.parent().isValid())
                      return QModelIndex();
                  
                  return index(source.row()+1, source.column());
                  

                  }

                  QModelIndex ProxyModelForTablePers::mapToSource(const QModelIndex & proxy) const
                  {

                  if (!sourceModel())
                      return QModelIndex();
                  
                  if (proxy.row()==0)
                      return QModelIndex();
                  
                  return this->sourceModel()->index(proxy.row()-1, proxy.column());
                  

                  }

                  TableViewPers::TableViewPers (QWidget *parent)
                  : QTableView (parent)
                  {

                  this->setEditTriggers(QAbstractItemView::AllEditTriggers);
                  this->setSortingEnabled(true);
                  this->setSelectionBehavior(QAbstractItemView::SelectRows);
                  this->setSelectionMode(QAbstractItemView::ContiguousSelection);
                  
                  _SourceModel = new QSqlTableModel (this, DataBaseManager::getManager()->getDataBase());
                  

                  FillSourceModelViewPers();

                  ProxyModelForTablePers * lProxy = new ProxyModelForTablePers (this);
                  lProxy->setSourceModel(_SourceModel);
                  
                  this->setModel(lProxy);
                  
                  this->setColumnHidden(0, true);
                  this->resizeColumnsToContents();
                  

                  }

                  @

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    You don't check what role you are given so basically you are giving "test" and "new" for every role whether it asks for DisplayRole or DecorationRole etc...

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      bizut
                      wrote on last edited by
                      #10

                      Hi, thanks for your help !
                      You are perfectly right! It is well displayed now !

                      But i still have the crash problem when the mouse is over the first line. ..Like a onmouseOver event ? Have you got any clue about it ?

                      @
                      QVariant ProxyModelForTablePers::data(const QModelIndex &proxyIndex, int role) const {

                      qDebug()<<proxyIndex.row()<<" "<<proxyIndex.column()<<" "<<rowCount();
                      
                      if (role != Qt::DisplayRole)
                              return QVariant();
                      
                      if (!proxyIndex.isValid())
                          return QVariant ();
                      
                      if (proxyIndex.row() == 0) {
                                  if (proxyIndex.column()==1)
                                      return QVariant ("new");
                                  else
                                      return QVariant("test");
                      
                      } else
                          //return QSortFilterProxyModel::data(proxyIndex, role);
                          return this->sourceModel()->data(this->mapToSource(proxyIndex), role);
                      

                      }
                      @

                      1 Reply Last reply
                      0
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        You should run your program using the debugger, from your proxy code here the only thing that could happen is that you don't have a source model which shouldn't happen since you are setting it in the constructor of TableViewPers

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0
                        • B Offline
                          B Offline
                          bizut
                          wrote on last edited by
                          #12

                          Hi,

                          I don't understand. Maybe that is a Qt bug ?
                          In debug mode, this are the last calls before crash :
                          QSortFilterProxyModel::parent
                          QTableView::visualRect
                          QAbstractItenView::viewportEvent

                          I removed the wrong line from mapFromSource
                          if (!source.parent().isValid())
                          return QModelIndex();

                          But i still have the problem. Any idea ? Thanks

                          1 Reply Last reply
                          0
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            First thing to do is correct the data function to return proper values (or default) for each role

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • B Offline
                              B Offline
                              bizut
                              wrote on last edited by
                              #14

                              Hi,

                              It was simply to implement the parent method...
                              Thanks

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                Of course ! I forgot about that one… Sorry

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                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