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.
  • 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