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. QSortFilterProxyModel: inconsistent changes reported by source model
QtWS25 Last Chance

QSortFilterProxyModel: inconsistent changes reported by source model

Scheduled Pinned Locked Moved General and Desktop
17 Posts 3 Posters 12.6k 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.
  • Z Offline
    Z Offline
    ZapB
    wrote on last edited by
    #2

    You'll need to post some code in order for people to be able to help you with this. Can you make a small compilable example that reproduces the problem please?

    Nokia Certified Qt Specialist
    Interested in hearing about Qt related work

    1 Reply Last reply
    0
    • K Offline
      K Offline
      kunashir
      wrote on last edited by
      #3

      I think the message is a simple problem.

      Excerpt from the code:

      catalogTableModel.h
      @
      class CatalogTableModel : public QAbstractTableModel
      {
      Q_OBJECT
      public:
      explicit CatalogTableModel(TlsPrices *lsItem, QObject *parent);
      ~CatalogTableModel ();

      int                   rowCount         (const QModelIndex &parent = QModelIndex ()) const;
      int                   columnCount   (const QModelIndex &parent = QModelIndex ()) const;
      QVariant         headerData     (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
      Qt::ItemFlags flags                (const QModelIndex &index) const;
      QVariant         data                  (const QModelIndex &index, int role = Qt::DisplayRole) const;
      bool                 hasChildren    (const QModelIndex &parent = QModelIndex ()) const;
      bool                 setData           (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
      bool                 removeRows (int row, int count, const QModelIndex &parent = QModelIndex ());
      bool                removeRowsWithCondition(int column, QString value);
      bool                insertRows     (int row, int count, const QModelIndex &parent = QModelIndex ());
      TlsPrices*      getPointerToData () {   return listItem;}
      void                setHeaderList (QList<QString> ls) { keys = ls;}
      

      private:
      TlsPrices *listItem;
      QList <QString> lsNameAttr;
      QList <QString> keys; //list with names of columns
      };
      @

      1 Reply Last reply
      0
      • K Offline
        K Offline
        kunashir
        wrote on last edited by
        #4

        catalogTableModel.cpp

        @
        #include <QSize>
        #include <QFont>
        #include <QFontMetrics>
        #include "catalogtablemodel.h"

        CatalogTableModel::CatalogTableModel(TlsPrices *lsItem, QObject *parent) :
        QAbstractTableModel(parent)
        {
        listItem = lsItem;
        }

        CatalogTableModel::~CatalogTableModel()
        {

        }

        int CatalogTableModel::rowCount(const QModelIndex &parent) const
        {
        if (parent.isValid())
        return 0;
        return listItem->count() ;
        }

        int CatalogTableModel::columnCount(const QModelIndex &parent) const
        {
        return keys.count();//7;//lsNameAttr.count() ;
        }

        QVariant CatalogTableModel::headerData(int section, Qt::Orientation orientation, int role) const
        {
        if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        {
        return keys.at(section);
        }
        return QAbstractItemModel::headerData(section, orientation, role);
        }

        Qt::ItemFlags CatalogTableModel::flags(const QModelIndex &index) const
        {
        bool isSpec = false;
        if (keys.count() < 6)
        isSpec = true;
        if (index.column() == 6 || (index.column() == 2 && isSpec))
        return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;

        return QAbstractItemModel::flags(index);
        

        }

        QVariant CatalogTableModel::data(const QModelIndex &index, int role) const
        {
        if (!index.isValid() || !listItem->count())
        return QVariant ();
        if (role == Qt::FontRole)
        {
        return QFont ("Helvetica");
        }
        if (role == Qt::SizeHintRole)
        {
        //deside best size
        QFont f ("Helvetica");
        QFontMetrics fm (f);
        if (index.column() == 0 || index.column() == 1
        || index.column() == 3)
        {
        int w = fm.width (listItem->at(index.row())->getData(index.column()).toString());
        int h = fm.height() - 2;
        if ( (w/200) > 1)
        {
        double ost = w/double (200);
        h = h*ost; //(w/200);
        w = 200;
        }
        return QSize (w, h);
        }
        return QSize (50, 25);
        //QFont
        //listItem->at(index.row())->getData(index.column()).toString().;
        }
        // QList <QString> keys = listItem->keys();
        if (role == Qt::DisplayRole || role == Qt::EditRole)
        {
        bool isSpec = false;
        if (keys.count() < 6)
        {
        isSpec = true;
        if (index.column() == 4)
        {
        double summa = listItem->at(index.row())->getData(2, isSpec).toDouble()*listItem->at(index.row())->getData(3, isSpec).toDouble();
        return summa;
        }
        }
        return listItem->at(index.row())->getData(index.column(), isSpec);

        }
        else if ( role == Qt::UserRole)
        {
        
        }
        return QVariant ();
        

        }

        bool CatalogTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
        {
        if (index.column() == 6)
        {
        listItem->at(index.row())->order = value.toInt();

            return true;
         }
        

        // bool isSpec = false;
        if (keys.count() < 6)
        {
        //isSpec = true;
        if (index.column() == 2)
        {
        listItem->at(index.row())->price = value.toDouble();
        reset ();//for updating views
        return true;
        }

        }
         return false;
        

        }

        bool CatalogTableModel::insertRows (int row, int count, const QModelIndex &parent)
        {
        return true;
        }

        bool CatalogTableModel::removeRows (int row, int count, const QModelIndex &parent)
        {
        //TODO:
        Q_UNUSED (parent);
        beginRemoveRows(QModelIndex(), row, row + count - 1);
        //int column = row + count;
        for (int i = 0; i < count; ++i)
        {
        delete listItem->at(row);
        listItem->removeAt(row);
        }
        emit layoutChanged();
        endRemoveRows();
        return true;
        }

        bool CatalogTableModel::hasChildren(const QModelIndex &parent) const
        {
        return !parent.isValid();
        }

        bool CatalogTableModel::removeRowsWithCondition(int column, QString value)
        {
        //int i = 0;
        int sizeOfList = listItem->count()-1;
        //while (i < sizeOfList)
        for (int i = sizeOfList; i >= 0; --i)
        {
        if (listItem->at(i)->getData(column).toString() == value)
        {
        removeRows(i, 1);
        }
        }
        }

        @

        section of mainwindows.cpp

        @
        void MainWindow::setHierarhy()
        {
        if (ui->checkBox->isChecked())
        {
        tableProxyModel->setSourceModel(model.getTableModel());//вот с этой моделью работаю
        ui->treeView->setVisible(false);
        }
        else
        {
        tableProxyModel->setSourceModel(&model);
        ui->treeView->setVisible(true);
        }
        }

        void MainWindow::delRowPrice()
        {
        //model.getTableModel()->removeRows( tableProxyModel->mapToSource(ui->tableView->currentIndex()).row(), 1);
        int row = ui->tableView->currentIndex().row();
        if (ui->tableView->currentIndex().isValid())
        tableProxyModel->removeRows(ui->tableView->currentIndex().row(), 1);
        //tableProxyModel->removeRow(ui->tableView->currentIndex().row());
        ui->tableView->setCurrentIndex(tableProxyModel->index(row, 0));
        }

        @

        1 Reply Last reply
        0
        • K Offline
          K Offline
          kunashir
          wrote on last edited by
          #5

          I find this:

          @int proxy_count = proxy_to_source.size();
          if (proxy_count > source_to_proxy.size()) {
          // mapping is in an inconsistent state -- redo the whole mapping
          qWarning("QSortFilterProxyModel: inconsistent changes reported by source model");
          remove_from_mapping(source_parent);
          Q_Q(QSortFilterProxyModel);
          q->reset();
          return;
          }@
          but i don't know how right set size of proxy model.
          unless of course this is the case.

          1 Reply Last reply
          0
          • K Offline
            K Offline
            kunashir
            wrote on last edited by
            #6

            While using the following decision:
            @
            void MainWindow::cancelLoadPrice ()
            {
            tableProxyModel->setSourceModel( NULL ); //reset proxy model
            for (int i = 0; i < lsProperty.count(); ++i)
            {
            if (lsProperty.at(i)->isMarked)
            {

                    model.delPricePosition(3, lsProperty.at(i)->contra);
                    lsProperty.at(i)->isLoad = false; 
                }
            }
            tableProxyModel->setSourceModel(model.getTableModel()); //again use proxy
            ui->tableView->resizeColumnsToContents();
            ui->tableView->resizeRowsToContents();
            

            @
            Removing move very fast. But I think it is not right resolving
            }

            1 Reply Last reply
            0
            • Z Offline
              Z Offline
              ZapB
              wrote on last edited by
              #7

              Are you correctly calling beginRemoveRows() and endRemoveRows() in your model implementation? These are needed to notify any connected proxies and views that the source model is changing.

              Nokia Certified Qt Specialist
              Interested in hearing about Qt related work

              1 Reply Last reply
              0
              • K Offline
                K Offline
                kunashir
                wrote on last edited by
                #8

                In source model:
                @
                bool CatalogTableModel::removeRows (int row, int count, const QModelIndex &parent)
                {
                //TODO:
                Q_UNUSED (parent);
                beginRemoveRows(QModelIndex(), row, row + count - 1);
                //int column = row + count;
                for (int i = 0; i < count; ++i)
                {
                delete listItem->at(row);
                listItem->removeAt(row);
                }
                emit layoutChanged();
                endRemoveRows();
                return true;
                }
                @
                I don't sure correctly it is or not..

                1 Reply Last reply
                0
                • Z Offline
                  Z Offline
                  ZapB
                  wrote on last edited by
                  #9

                  I don't think that you need to emit the layoutChanged() signal. The {begin|end}RemoveRows() functions do everything that is needed for you. Try removing that emit end see if it works then.

                  I suspect what is happening is that the proxy and views are receiving signals from you and from {begin|end}RemoveRows() in an unexpected order which causes them to misbehave.

                  Nokia Certified Qt Specialist
                  Interested in hearing about Qt related work

                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    kunashir
                    wrote on last edited by
                    #10

                    With out emit the layoutChanged() programm to crash!
                    Maybe link between source model and proxy is not correct?

                    1 Reply Last reply
                    0
                    • Z Offline
                      Z Offline
                      ZapB
                      wrote on last edited by
                      #11

                      Setting a proxy is a one-liner so I doubt it is that. I suspect you have a problem in your model. I suggest that you run your model with the qmodeltest helper which diagnoses common model implementation problems. This "wiki article":http://developer.qt.nokia.com/wiki/Model_Test describes how to use qmodeltest and the source can be downloaded from "gitorious":https://qt.gitorious.org/qt/qt/trees/4.7/tests/auto/modeltest.

                      Nokia Certified Qt Specialist
                      Interested in hearing about Qt related work

                      1 Reply Last reply
                      0
                      • K Offline
                        K Offline
                        kunashir
                        wrote on last edited by
                        #12

                        Let's me stupid question - gitotious of model test have pro-file, but wiki article say about pri-file. How I can get pri file?

                        1 Reply Last reply
                        0
                        • Z Offline
                          Z Offline
                          ZapB
                          wrote on last edited by
                          #13

                          Ah the instructions must be slightly out of date wrt the code. It used to be in it's own repository on Qt-labs. I think you can just copy the modeltest.{h,cpp} files to a little test project and instatiate them as shown in the above wiki article.

                          Nokia Certified Qt Specialist
                          Interested in hearing about Qt related work

                          1 Reply Last reply
                          0
                          • K Offline
                            K Offline
                            kunashir
                            wrote on last edited by
                            #14

                            I use modeltest and have next message:

                            ratbr QModelIndex(-1,-1,0x0,QObject(0x0) ) 73 73
                            rr QModelIndex(-1,-1,0x0,QObject(0x0) ) 73 73

                            and other simular.
                            Is it Ok? I check mapping index from proxy to source - it ok.
                            What else I may do?

                            1 Reply Last reply
                            0
                            • Z Offline
                              Z Offline
                              ZapB
                              wrote on last edited by
                              #15

                              Debug your removeRows() function to make sure it is working properly. Step through it in a debugger to see where it crashes and why.

                              Nokia Certified Qt Specialist
                              Interested in hearing about Qt related work

                              1 Reply Last reply
                              0
                              • K Offline
                                K Offline
                                kunashir
                                wrote on last edited by
                                #16

                                I get error:
                                @
                                void QSortFilterProxyModelPrivate::source_items_removed(
                                const QModelIndex &source_parent, int start, int end, Qt::Orientation orient)
                                {
                                if ((start < 0) || (end < 0))
                                return;
                                IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
                                if (it == source_index_mapping.constEnd()) {
                                // Don't care, since we don't have mapping for this index
                                return;
                                }

                                Mapping *m = it.value();
                                QVector<int> &source_to_proxy = (orient == Qt::Vertical) ? m->proxy_rows : m->proxy_columns;
                                QVector<int> &proxy_to_source = (orient == Qt::Vertical) ? m->source_rows : m->source_columns;
                                
                                if (end >= source_to_proxy.size())
                                    end = source_to_proxy.size() - 1;
                                
                                // Shrink the source-to-proxy mapping to reflect the new item count
                                int delta_item_count = end - start + 1;
                                source_to_proxy.remove(start, delta_item_count); //This crash
                                

                                @

                                1 Reply Last reply
                                0
                                • G Offline
                                  G Offline
                                  gonzomcgraw
                                  wrote on last edited by
                                  #17

                                  As ZapB said
                                  [quote author="ZapB" date="1310123242"]Setting a proxy is a one-liner[/quote]unless you must overwrite a standard function of QSortFilterProxyModel.

                                  Normally removing rows will be done in the sourcemodel. As you do a selection in the view you have to map the indexes getting from the view to the source with
                                  @// single selection
                                  QModelIndex SourceIndex = tableProxyModel->mapToSource(viewIndex);

                                  // multiple selection
                                  QModelIndexList SourceIndexList;
                                  for (int i=0; i<viewIndexList.length(); i++)
                                  {
                                  SourceIndexList.append(tableProxyModel->mapToSource(viewIndexList[i]));
                                  }
                                  @

                                  Also, if you have multiple selection you must sort the indexlist before removing like this:
                                  @void CatalogTableModel::removeSelectedRows(const QModelIndexList &indexlist)
                                  {
                                  QList<int> rows;
                                  foreach(const QModelIndex & index, indexlist)
                                  {
                                  rows.append(index.row());
                                  }

                                  qSort(rows);
                                  
                                  int prev = -1;
                                  for(int i=rows.count()-1; i>=0; i-=1 )
                                  {
                                      int current = rows[i];
                                      if(current != prev)
                                      {
                                          QModelIndex _index = createIndex(current, 0);
                                          removeLabel(_index);
                                          prev = current;
                                      }
                                  }
                                  

                                  }
                                  @

                                  Cheers,
                                  Thomas

                                  Edit: Uuups, little bit late ...

                                  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