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
Qt 6.11 is out! See what's new in the release blog

QSortFilterProxyModel: inconsistent changes reported by source model

Scheduled Pinned Locked Moved General and Desktop
17 Posts 3 Posters 17.2k 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.
  • ? Offline
    ? Offline
    A Former User
    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?

    1 Reply Last reply
    0
    • ? Offline
      ? Offline
      A Former User
      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
      • ? Offline
        ? Offline
        A Former User
        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
        • ? Offline
          ? Offline
          A Former User
          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
          • ? Offline
            ? Offline
            A Former User
            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
            • ? Offline
              ? Offline
              A Former User
              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.

              1 Reply Last reply
              0
              • ? Offline
                ? Offline
                A Former User
                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
                • ? Offline
                  ? Offline
                  A Former User
                  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.

                  1 Reply Last reply
                  0
                  • ? Offline
                    ? Offline
                    A Former User
                    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
                    • ? Offline
                      ? Offline
                      A Former User
                      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.

                      1 Reply Last reply
                      0
                      • ? Offline
                        ? Offline
                        A Former User
                        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
                        • ? Offline
                          ? Offline
                          A Former User
                          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.

                          1 Reply Last reply
                          0
                          • ? Offline
                            ? Offline
                            A Former User
                            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
                            • ? Offline
                              ? Offline
                              A Former User
                              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.

                              1 Reply Last reply
                              0
                              • ? Offline
                                ? Offline
                                A Former User
                                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
                                • ? Offline
                                  ? Offline
                                  A Former User
                                  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