Results 1 to 7 of 7

Thread: Model/View synchronization issue. Need a QThread?

  1. #1
    Join Date
    Feb 2013
    Location
    San Diego
    Posts
    37
    Thanks
    14
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Model/View synchronization issue. Need a QThread?

    Hello,

    I have a QFileSystemModel sub-class “FileSysSelectModel” connected to a QTreeView
    The QTreeView shows only the file name information and each item is checkable.

    Here is how the QFileSystemModel sub_class is implemented.
    Qt Code:
    1. #ifndef FILESYSSELECTMODEL_H
    2. #define FILESYSSELECTMODEL_H
    3.  
    4. #include<QFileSystemModel>
    5. #include <QSet>
    6. #include <QPersistentModelIndex>
    7. #include <QVariant>
    8.  
    9. class FileSysSelectModel: public QFileSystemModel
    10. {
    11. Q_OBJECT
    12.  
    13. private:
    14. QSet<QPersistentModelIndex> m_checkTable;
    15. QVariant m_noData;
    16.  
    17. public:
    18. int FileSysSelectModel::columnCount(const QModelIndex &parent) const;
    19. QVariant FileSysSelectModel::data(const QModelIndex &index, int role) const;
    20. virtual Qt::ItemFlags FileSysSelectModel::flags(const QModelIndex &index) const;
    21. virtual bool FileSysSelectModel::setData(const QModelIndex &index, const QVariant &value, int role);
    22.  
    23. signals:
    24. void expandParentItem(const QModelIndex &index);
    25. };
    26.  
    27. #endif // FILESYSSELECTMODEL_H
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. #include "FileSysSelectModel.h"
    2.  
    3. //Returns columnCount=1 if columnCount >= 1, so only the name item displays.
    4. int FileSysSelectModel::columnCount(const QModelIndex &parent) const
    5. {
    6. int columns = QFileSystemModel::columnCount(parent);
    7. return (columns >= 1)? 1 : columns;
    8. }
    9.  
    10.  
    11. //Returns the regular QFileSystemModel data or the CheckState status if required.
    12. //All decoration has been removed from QFileSystemModel data.
    13. QVariant FileSysSelectModel::data(const QModelIndex &index, int role) const
    14. {
    15. if (role == Qt::CheckStateRole) return m_checkTable.contains(index)? Qt::Checked : Qt::Unchecked;
    16. if (role == Qt::DecorationRole) return m_noData;
    17. // regular QFileSystemModel case.
    18. return QFileSystemModel::data(index, role);
    19. }
    20.  
    21.  
    22. //Sets all elements as user checkable.
    23. Qt::ItemFlags FileSysSelectModel::flags(const QModelIndex &index) const
    24. {
    25. return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable;
    26. }
    27.  
    28.  
    29. //Sets the regular QFileSystemModel data or the CheckState status.
    30. bool FileSysSelectModel::setData(const QModelIndex &index, const QVariant &value, int role)
    31. {
    32. if (role == Qt::CheckStateRole)
    33. {
    34. QModelIndex *currentFirstChildItem;
    35. QModelIndex *currentItem;
    36. QModelIndex *currentChildItem;
    37. std::vector<QModelIndex*> parentTable(1,&const_cast<QModelIndex&>(index));
    38.  
    39. //if the current item is in the checklist then remove it.
    40. //if the current item is not in the checklist then add it.
    41. if(value == Qt::Checked) m_checkTable.insert(index); else m_checkTable.remove(index);
    42. emit dataChanged(index, index);
    43.  
    44. //Expand all the sub-items.
    45. while (!parentTable.empty())
    46. {
    47. currentItem = parentTable[parentTable.size()-1];
    48. parentTable.pop_back();
    49. currentFirstChildItem = &currentItem->child(0,0);
    50.  
    51. if (currentFirstChildItem->isValid())
    52. {
    53. emit expandParentItem(*currentItem);
    54. int i = 0;
    55. while(1)
    56. {
    57. currentChildItem = &currentItem->child(i,0);
    58. if (!currentChildItem->isValid()) break;
    59. parentTable.push_back(currentChildItem);
    60. ++i;
    61. }
    62. }
    63. }
    64. return true;
    65. }
    66. // regular QFileSystemModel case.
    67. return QFileSystemModel::setData(index, value, role);
    68. }
    To copy to clipboard, switch view to plain text mode 
    Here is my problem.
    When I check an item, I would like the QTreeView to automatically expand all the checked item’s children (in all sub levels).
    I tried to implement a mechanism in FileSysSelectModel::setData. It uses a While loop and a vector < QModelIndex* > to process and expand each item in the sub-tree under the check item.
    I initialize the vector with the checked item. The While loop runs until the vector is empty. And here is what is going on inside the loop. The currently processed item is removed from the vector. If it has children, it expands it, it explores its children and it saves all ones that have children in the vector (for them to be processed on a next round).

    It does not run as expected… When I check an item it only expands the first level under the checked item.
    When running it with the debugger, I figured out that the all the signals that were emitted in the while loop were processed by the QTreeView slot only after the while loop terminated… That is probably where the issue is.

    I need the QTreeView to check for signals for each iteration in the While loop, right?
    Is a QThread the only solution for that issue?
    If yes, Do I need to implement the entire QFileSystemModel instance in a sub-QThread? Or only a portion of it?

    Thanks!

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Model/View synchronization issue. Need a QThread?

    Quote Originally Posted by Guett_31 View Post
    When I check an item, I would like the QTreeView to automatically expand all the checked item’s children (in all sub levels).
    I tried to implement a mechanism in FileSysSelectModel::setData.
    If you want the view to do something, why are you trying to implement that in the model and not in the view?

    Connect to the dataChanged() signal of the model, detect a situation when an item was checked and iterate through its children expanding them the way you want.

    Is a QThread the only solution for that issue?
    You can't use threads here.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Feb 2013
    Location
    San Diego
    Posts
    37
    Thanks
    14
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Model/View synchronization issue. Need a QThread?

    I'm probably having a logic issue here... I don't understand why you want to use the dataChanged() signal to tell the view to expand items.

    The data does not change, except for the checked item. For that, I do use dataChanged() to tell the view that this only one item has changed. And that is before entering the While loop. Once in the While loop, the data part remains the same. The only thing that changes is how we look at the data through the view by expanding or to collapsing items.
    That is why I use my own signal here "expandParentItem" to the the view to expand the items.
    All I do in the loop is exploring the data to determine its structure and I just want to tell the view to expand any item that has children...

    Here is how the signal is connected in my Main Window:
    Qt Code:
    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3.  
    4. MainWindow::MainWindow(QWidget *parent) :
    5. QMainWindow(parent),
    6. ui(new Ui::MainWindow)
    7. {
    8. ui->setupUi(this);
    9.  
    10. m_fileSystemModel = new FileSysSelectModel;
    11. m_fileSystemModel->setRootPath(QDir::currentPath());
    12. ui->scriptFileView->setModel(m_fileSystemModel);
    13.  
    14. QObject::connect(m_fileSystemModel,SIGNAL(expandParentItem(QModelIndex)),ui->scriptFileView,SLOT(expand(QModelIndex)));
    15. }
    16.  
    17. MainWindow::~MainWindow()
    18. {
    19. delete ui;
    20. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Model/View synchronization issue. Need a QThread?

    Precisely, the data does not change (apart from the Qt::CheckState obviously). The model is all about the data. The while loop you refer to is in the model which is not required to change, i.e. the wrong place.

    Expanding or collapsing a branch is about changing how data is presented. The view is all about how that data is presented. You want the view to expand the branch underneath an item when it is checked. The model's QAbtractItemModel::dataChanged() signal allows the view to know that a particular model item changed, and the view can choose to react to that by QTreeView::expand()ing the affected branch (if there is one) etc. Your view can then expand no matter how the check state in the model is changed; whether by your user interacting with this view, another view on the same model, or if the check state changes programatically.

    You don't explain why you want this behaviour tied to check state. The default expansion controls already give the user a way to expand a branch. If you want expanding to cascade you might be able to get the result you seek by using the view's own expanded() signal to trigger a routine to expand subordinate branches. This logic could be entirely with the view.
    "We can't solve problems by using the same kind of thinking we used when we created them." -- Einstein
    If you are posting code then please use [code] [/code] tags around it - makes addressing the problem easier.

  5. The following user says thank you to ChrisW67 for this useful post:

    Guett_31 (2nd March 2013)

  6. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Model/View synchronization issue. Need a QThread?

    One additional thing to question which you should answer to understand that your approach is not correct -- what happens if your model is connected to two or more views? Why would all views on the model have to expand their items?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. The following user says thank you to wysota for this useful post:

    Guett_31 (2nd March 2013)

  8. #6
    Join Date
    Feb 2013
    Location
    San Diego
    Posts
    37
    Thanks
    14
    Thanked 7 Times in 7 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Model/View synchronization issue. Need a QThread?

    Thank you guys for your helpful answers. I understand my mistake now. The mechanism with the While loop needs to be located within the QTreeView instance, and it needs to be triggered by a signal on the model side that is emitted when the Qt::CheckState is modified.

    The problem I'm facing now is that the QTreeView instance lives in a Form that I have created with Qt Designer. From what I know about Qt Designer (which is not much...), it only allows the use of regular Qt classes. Is there a way I can create a sub QTreeView class with the mechanism I mentioned above and use it in the Form?

  9. #7
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Model/View synchronization issue. Need a QThread?

    Look for Promote To on the tree widget context menu in Designer and in the Designer manual

Similar Threads

  1. Replies: 4
    Last Post: 18th April 2012, 19:11
  2. Replies: 0
    Last Post: 21st April 2010, 13:23
  3. Replies: 1
    Last Post: 1st February 2010, 19:42
  4. QSql Model-View: How to keep view in sync with model
    By schall_l in forum Qt Programming
    Replies: 1
    Last Post: 23rd December 2008, 00:31
  5. Table model / view editing issue
    By Caius Aérobus in forum Qt Programming
    Replies: 9
    Last Post: 7th April 2006, 12:03

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.