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.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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    Good day!

    There is a table model of the heir QAbstractTableModel. It displays on a QTableView via QSortFilterProxyModel.
    All works fine and is even deleted, but the process in creators (in debug mode) is displayed - QSortFilterProxyModel: inconsistent changes reported by source model.
    And removal about 1000 lines ccontinue for about 1 minute - it is long, i think , I suppose maybe because of this error.

    Prompt where to look?

    1 Reply Last reply
    0
    • ? 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