Results 1 to 6 of 6

Thread: Emit endResetModel using a QTimer

  1. #1
    Join Date
    Feb 2010
    Location
    Sydney, Australia
    Posts
    111
    Thanks
    18
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Emit endResetModel using a QTimer

    Existing setup:

    I have a custom QAbstractListModel with an attached QTableView. The model receives data from two sources - one source's data goes into a vector and the other source's data goes into a map. The model then provides data for column 1 from the vector and the data for column 2 from the map.

    Each time data arrives from source 2 it gets inserted into the map and the beginResetModel/endResetModel signals are emitted.

    The problem:

    A flood of data from source 2 arrives. Each bit of data that arrives results in beginResetModel/endResetModel being emitted, which results in the QTableView doing a lot of work and the GUI locks up for a while while the data is being processed.

    It's not feasible to emit dataChanged instead of beginResetModel/endResetModel because that would require a linear search through the vector to determine which the QModelIndex of the cell to be changed.

    My current solution:

    Each time some data arrives from source 2, I emit beginResetModel. Then I start/restart a timer that runs for 500ms. When the timer completes the endResetModel signal is emitted. In this way if a flood of data arrives from source 2, endResetModel is only called once after all the data has been loaded into the model (assuming that the time gap between data arriving is less than 500ms of course).

    Possible problem with my solution:

    I emit beginResetModel every time I receive data from source 2, but I don't emit endResetModel every time. Does there always need to be an endResetModel for every beginResetModel?

    Has anyone got any ideas on how to improve this?

  2. #2
    Join Date
    Jan 2006
    Location
    Belgium
    Posts
    1,938
    Thanked 268 Times in 268 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Wiki edits
    20

    Default Re: Emit endResetModel using a QTimer

    Call both beginResetModel and endResetModel once.

    Why not use insertRows? Why do you need to reset the model everytime you get new data?

  3. #3
    Join Date
    Feb 2010
    Location
    Sydney, Australia
    Posts
    111
    Thanks
    18
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Emit endResetModel using a QTimer

    Thanks for the response

    When data arrives from source 2 it is not adding a new row, but rather adding information to or updating information on an existing row. Therefore insertRows will not work.

    I reset the whole model each time I get new information from source 2 because it is expensive for me to establish which row of the model would change as a result of the new data. When I say expensive, I mean that I would need to do a search (linear time) through a vector to establish the row and I don't want to have to do this every time. Of course, I don't want to have to begin/endResetModel each time new data from source 2 arrives either as this causes a lot of work for the QTableView.

    So this is what I'm trying:
    • beginResetModel
    • update model data
    • [beginResetModel, update model data] X 100
    • endResetModel


    i.e. beginResetModel could be emitted 100 times without endResetModel being emitted. And then endResetModel would be emitted once.

    This is the relevant code that creates the endResetModel timer and handles data from source 2:

    Qt Code:
    1. MyModel::MyModel()
    2. {
    3. ...
    4. source2Timer = new QTimer(this);
    5. source2Timer->setInterval(500);
    6. source2Timer->setSingleShot(true);
    7. connect(source2Timer, SIGNAL(timeout()), this, SLOT(endResetModel()));
    8. }
    9.  
    10. void MyModel::HandleSource2Data(const DataItem& item)
    11. {
    12. beginResetModel();
    13. source2Cache.Add(item);
    14. source2Timer->start();
    15. }
    To copy to clipboard, switch view to plain text mode 

    Or do I NEED to emit an endResetModel for every beginResetModel signal emitted? Or is what I'm planning OK?
    Last edited by stefanadelbert; 9th June 2010 at 08:06. Reason: Added "source2Timer->setSingleShot(true);" to code

  4. #4
    Join Date
    Jan 2006
    Location
    Belgium
    Posts
    1,938
    Thanked 268 Times in 268 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows
    Wiki edits
    20

    Default Re: Emit endResetModel using a QTimer

    How many rows do you want to update every 500ms ?

  5. #5
    Join Date
    Feb 2010
    Location
    Sydney, Australia
    Posts
    111
    Thanks
    18
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Emit endResetModel using a QTimer

    It's possible that there are 2000 rows in the model (i.e. the vector (source 1) has 2000 elements and the map (source 2) has up to 2000 elements). It is possible that I get ~1000 updates from source 2 in the space of 500ms, i.e. 1000 rows would need to be updated in the model. But it's not necessarily critical that the QTableView updates after every model update. As long as the view updates within 500ms of the last source 2 update, all is well.

    Note: This is not a periodic update every 500ms - it's more of a once off.

    Note: I edited the source code in my previous post to include "source2Timer->setSingleShot(true);"
    Last edited by stefanadelbert; 9th June 2010 at 08:15. Reason: updated contents

  6. #6
    Join Date
    Feb 2010
    Location
    Sydney, Australia
    Posts
    111
    Thanks
    18
    Thanked 5 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Emit endResetModel using a QTimer

    I think I've managed to make this work, but not quite how I originally intended. My code now looks something like this:

    Qt Code:
    1. class MyModel {
    2. MyModel();
    3. ...
    4. slots:
    5. void EndResetModel();
    6. ...
    7. void MyModel::HandleSource2Data(const DataItem& item)
    8. ...
    9. }
    10.  
    11. MyModel::MyModel()
    12. {
    13. ...
    14. source2Timer = new QTimer(this);
    15. source2Timer->setInterval(500);
    16. source2Timer->setSingleShot(true);
    17. connect(source2Timer, SIGNAL(timeout()), this, SLOT(EndResetModel()));
    18. }
    19.  
    20. void MyModel::EndResetModel()
    21. {
    22. endResetModel();
    23. }
    24.  
    25. void MyModel::HandleSource2Data(const DataItem& item)
    26. {
    27. beginResetModel();
    28. source2Cache.Add(item);
    29. source2Timer->start();
    30. }
    To copy to clipboard, switch view to plain text mode 

    endResetModel() is not a slot, its just a protected function. So the timer can't call endResetModel() directly; it needs to call a custom slot that in turn calls endResetModel().

Similar Threads

  1. crash in emit()
    By mhoover in forum Qt Programming
    Replies: 9
    Last Post: 27th August 2009, 08:36
  2. emit Signals
    By Fastman in forum Qt Programming
    Replies: 5
    Last Post: 22nd August 2007, 14:14
  3. emit a signal
    By Morea in forum Qt Programming
    Replies: 2
    Last Post: 27th February 2006, 12:14
  4. Emit
    By ToddAtWSU in forum Newbie
    Replies: 3
    Last Post: 2nd February 2006, 11:59
  5. Replies: 2
    Last Post: 6th January 2006, 22:15

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.