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. Do I need to emit dataChanged when correcting a proxy model's state after the source model emits rowsInserted?

Do I need to emit dataChanged when correcting a proxy model's state after the source model emits rowsInserted?

Scheduled Pinned Locked Moved Unsolved General and Desktop
1 Posts 1 Posters 174 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.
  • J Offline
    J Offline
    Jack Hill
    wrote on last edited by Jack Hill
    #1

    Suppose we have a list model that stores characters,

    class CharacterModel : QAbstractListModel {
        Q_OBJECT
    
    public:
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
        {
            return m_characters.at(index.row());
        }
    
        int rowCount(const QModelIndex &parent = QModelIndex()) const override
        {
            return m_characters.count();
        }
    
    private:
        QList<QChar> m_characters = {'a', 'b', 'd'};
    

    And a proxy model that maps the index of each character to a random location

    class RandomProxyModel : QAbstractProxyModel {
        Q_OBJECT
    
    public:
        QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
        {
            return index(mapping.indexOf(sourceIndex.row()), sourceIndex.column());
        }
    
        QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
        {
            return sourceModel()->index(mapping.at(proxyIndex.row()), proxyIndex.column());
        }
    
        void setSourceModel(QAbstractItemModel *sourceModel) override
        {
            beginResetModel()
            connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &RandomProxyModel::sourceRowsInserted);
            QAbstractProxyModel::setSourceModel(sourceModel);
            endResetModel()
        }
    
    private:
        void sourceRowsInserted(const QModelIndex &parent, int first, int last)
        {
            // Proxy model state is now invalid, so first we should fix the mapping
            int rowsAdded = 1 + last - first;
            for (int proxyRow = 0; proxyRow < m_mapping.count(); ++proxyRow) {
                if (m_mapping.at(proxyRow) >= first) {
                    m_mapping[proxyRow] += rowsAdded;
                    Q_EMIT dataChanged(index(proxyRow, 0), index(proxyRow, 0));
                }
            }
    
            // code for adding the new rows
        }
    
        QList<int> m_mapping = {2, 0, 1};
    }
    

    Basically I'm wondering if the calls to dataChanged are necessary here. I'm fairly sure that they are not required, but I would like some confirmation from people who know what they're doing.

    I'm thinking that (assuming the models & views are in the same thread) the connection from rowsInserted to sourceRowsInserted should be synchronous, so there is no chance for the view to query the proxy model in its invalid state.

    Btw this code is untested and is just to illustrate the question. Please do not get fussed about me not checking for invalid QModelIndex's, typos, not batching the calls to dataChanged, etc.

    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