emit dataChanged refreshes QTableView only once.



  • Hi!

    I'm working on my code actually and I spotted a problem. I have an app that filters files. Every time I add new filter to QTreeView I want to refresh view and add it to Table. So far I created code like this

    //constructor
    
    FilterModel::FilterModel(QObject* parent, const std::shared_ptr<FilterManager>& filterManager)
        : QAbstractTableModel(parent), mFilterManager(filterManager)
    {
        mFilterManager->addListener([this](unsigned int id){
            QModelIndex idx1 = index(mFilterManager->getIndexById(id), NAME_COLUMN);
            QModelIndex idx2 = index(mFilterManager->getIndexById(id), DESCRIPTION_COLUMN);
            emit dataChanged(idx1, idx2, QVector<int>{Qt::DisplayRole});
        }
        );
    }
    
    //Add Listener method
    
    void FilterManager::addListener(std::function<void(unsigned int)> f)
    {
        listeners.append(f);
    }
    
    
    //notify method
    
    void FilterManager::notifyListeners(unsigned int id)
    {
        for (auto&& listener : listeners)
        {
            listener(id);
        }
    }
    

    notifyListeners is triggered every time data changes (eg. filter is added or activity is changed). View refreshes only when I resize window, and do it once in one execution of program.

    I'm using 5.2.1, on Ubuntu.

    Thanks.



  • can you add:

    • connect(this,&FilterModel::dataChanged,[](){qDebug("changed");}); to FilterModel::FilterModel to make sure the signal is emitted
    • Q_ASSERT(idx1.isValid()); Q_ASSERT(idx2 .isValid()); to the lambda inside addListener to make sure you are passing valid indexes to the view

  • Moderators

    So each time you update something, you are calling your listener functions, right?

    Are you sure you are passing valid ids to them? Are you sure the constructed idx1 and idx2 are valid and correct?

    Are you sure dataChanged() is really being emitted? Because you are trying to emit it from a different object (FilterManager instead of FilterModel)?



  • @sweetMango
    I'm not sure what you're saying you do/do not want, or what you are/are not seeing, but I think the view only refreshes when it next hits the event loop and gets time to repaint, no matter how many times it might have received & acted on multiple dataChanged signals. If you want it to update immediately on each one, I think you need to call http://doc.qt.io/qt-5/qwidget.html#repaint. But maybe that's not what you mean....

    EDIT Looks like @VRonin understands what you're saying better than I do, sorry!



  • @VRonin
    I've applied your suggestions, and every time I add filter, console shows "changed", so signal is emitted, but view refreshes only once in lifetime of program.

    @sierdzio
    Yes, every time I change something, I'm calling notifyListeners. I'm pretty sure, that ids are correct. The goal is to refresh only one row in view, with specific filter. So before refresh it don't exist in View, but after refresh I want it to pop up in
    QTableView.

    @JonB
    Still thanks for your reply!



  • @sweetMango said in emit dataChanged refreshes QTableView only once.:

    So before refresh it don't exist in View, but after refresh I want it to pop up in

    Ok, this is the key of the problem.

    dataChanged only refreshes the contents of existing indexes. You need to use beginInsertRows/endInsertRows to notify the view of new rows spawning

    Edit:
    sorry for the double ninja @sierdzio


  • Moderators

    @sweetMango said in emit dataChanged refreshes QTableView only once.:

    don't exist in View, but after refresh I want it to pop up in
    QTableView.

    Then dataChanged is wrong. You need to use beginInsertRows() and endInsertRows() instead.



  • @sweetMango
    As @sierdzio has just beaten me to posting: when changing the model:

    • If data in an existing row has changed, you need to emit dataChanged.
    • But if a new row has been inserted or an existing row deleted you need to call begin/endInsert/DeleteRows().

    The view needs to know differently from dataChanged when the number of rows changes.



  • @VRonin
    @sierdzio
    @JonB

    Nice! Thanks a lot!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.