Results 1 to 6 of 6

Thread: QFileSystemModel /QTreeView, check and expend all items under a user checked item

Threaded View

Previous Post Previous Post   Next Post Next Post
  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 QFileSystemModel /QTreeView, check and expend all items under a user checked item

    I’m having an issue for a while with a QFileSystemModel /QTreeView implementation. What I’m trying to achieve form the application user prospective. I have a QTreeView displaying the file system it only shows the directory name and file names. Each item in the view is checkable. That part is easy to design but what comes next is much harder. I’d like the application automatically expend and check all the items in all sub-directories if the user checks a directory. And I’d like it to automatically uncheck all the items in all sub-directories if the user unchecks a directory too.

    I have been trying to implement the second part for a while. I searched the forum and the internet for hints and I found that other people had the same problem and could not find solid answers.Some people tried to iterate recursively through the indexes in the model starting from the parent index associated with the checked directory in the view. (If the children in level#2 are parents then we iterate through them, and so on in all the sub level, until there is no more parents to iterate through.) And most people have issues with:
    Int rowCount(const QModelIndex & parent = QModelIndex()) const
    In my case, it returns inconsistent results (often 1 or 0) even if there are many more child elements under the parent element.

    Here is one of the unsuccessful attempts I made to check all the elements under the user selected directory in my QFileSystemModel subclass:
    Qt Code:
    1. bool FileSysSelectModel::setData(const QModelIndex &index, const QVariant &value, int role)
    2. {
    3. if (role == Qt::CheckStateRole)
    4. {
    5.  
    6. //if the current item is in the checklist then remove it.
    7. //if the current item is not in the checklist then add it.
    8. if(value == Qt::Checked) m_checkTable.insert(index); else m_checkTable.remove(index);
    9. emit dataChanged(index, index);
    10.  
    11. QModelIndex *currentIndex;
    12. QModelIndex *currentChildIndex;
    13. std::vector<QModelIndex*> parentTable(1,&const_cast<QModelIndex&>(index));
    14.  
    15. //Check all the sub-items.
    16. while (!parentTable.empty())
    17. {
    18. currentIndex = parentTable[parentTable.size()-1];
    19. parentTable.pop_back();
    20. if(value == Qt::Checked) m_checkTable.insert(*currentIndex); else m_checkTable.remove(*currentIndex);
    21. emit dataChanged(*currentIndex, *currentIndex);
    22. if (hasChildren(*currentIndex))
    23. {
    24.  
    25. for (int i(0); i < rowCount(*currentIndex); i++)
    26. {
    27. currentChildIndex = &FileSysSelectModel::index(i,0,*currentIndex);
    28. parentTable.push_back(currentChildIndex);
    29. }
    30. }
    31. }
    32. return true;
    33. }
    34. // regular QFileSystemModel case.
    35. return QFileSystemModel::setData(index, value, role)
    To copy to clipboard, switch view to plain text mode 
    Question1: Does the data in the tree model depend on the exposed items in the tree view?
    For example, does the data corresponding to a collapsed branch exist in the model? I believe it does not and I think that the model retrieves the data corresponding to a directory only when the user asks for expending that same directory in the tree view. I’d like to confirm that because the QFileSystemModel doc says very little about it and it not clear to me at all.

    Question2: If my assumption in question 1 is correct, how do we access the data of the collapsed branches in order to iterate through them?

    A few people mentioned the use of the two following methodes to resolve the issue in one or two threads I’ve seen:
    • Virtual Bool canFetchMore(const QModelIndex & parent) const
    • Virtual void fetchMore(const QModelIndex & parent)

    Here again, the documentation does not say much about it.

    Question 3: From my understanding fetchMore populates the data under the parent QModelIndex and adds it to the model. Is that correct?
    Here is another attempt. I tried to rework the same piece of code but it does not do better:
    Qt Code:
    1. //Check all the sub-items.
    2. while (!parentTable.empty())
    3. {
    4. currentIndex = parentTable[parentTable.size()-1];
    5. parentTable.pop_back();
    6. if(value == Qt::Checked) m_checkTable.insert(*currentIndex); else m_checkTable.remove(*currentIndex);
    7. emit dataChanged(*currentIndex, *currentIndex);
    8. if (hasChildren(*currentIndex))
    9. {
    10. while (canFetchMore(*currentIndex))
    11. {
    12. fetchMore(*currentIndex);
    13. }
    14.  
    15. for (int i(0); i < rowCount(*currentIndex); i++)
    16. {
    17. currentChildIndex = &FileSysSelectModel::index(i,0,*currentIndex);
    18. parentTable.push_back(currentChildIndex);
    19. }
    20. }
    21. }
    To copy to clipboard, switch view to plain text mode 
    Some fetchMore users say that the reason why that kind of implementation does not work is because the FileSystemModel updated its data with an independent thread, so when the main thread executes rowCount, fetchMore has not finished updating the data.
    I tried to use the directoryLoaded(const QString & path) signal by implementing the SLOT below in my FileSystemModel sub class to make sure fetchMore more had finish executing when calling rowCount.
    Qt Code:
    1. void FileSysSelectModel::dataReady(const QString &currentPath)
    2. {
    3. m_currentPath = currentPath;
    4. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. //Check all the sub-items.
    2. while (!parentTable.empty())
    3. {
    4. currentIndex = parentTable[parentTable.size()-1];
    5. parentTable.pop_back();
    6. if(value == Qt::Checked) m_checkTable.insert(*currentIndex); else m_checkTable.remove(*currentIndex);
    7. emit dataChanged(*currentIndex, *currentIndex);
    8. if (hasChildren(*currentIndex))
    9. {
    10. QString test1 = filePath(*currentIndex); //debug
    11. while ((canFetchMore(*currentIndex)) || (m_currentPath != filePath(*currentIndex)))
    12. {
    13. fetchMore(*currentIndex);
    14. }
    15.  
    16. for (int i(0); i < rowCount(*currentIndex); i++)
    17. {
    18. currentChildIndex = &FileSysSelectModel::index(i,0,*currentIndex);
    19. parentTable.push_back(currentChildIndex);
    20. }
    21. }
    22. }
    23. return true;
    To copy to clipboard, switch view to plain text mode 
    That does not work either.
    Any idea?

    Thanks

  2. The following user says thank you to Guett_31 for this useful post:


Similar Threads

  1. Replies: 2
    Last Post: 17th May 2011, 13:47
  2. QTreeView different item delegate for child items possible?
    By Royceybaby in forum Qt Programming
    Replies: 4
    Last Post: 7th January 2010, 21:14
  3. Replies: 2
    Last Post: 13th September 2008, 13:55
  4. Checked item in QTreeWidget?
    By vishal.chauhan in forum Qt Programming
    Replies: 18
    Last Post: 3rd January 2008, 20:18
  5. Iterate and get Checked QTable items??
    By darpan in forum Newbie
    Replies: 2
    Last Post: 10th May 2006, 18:27

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.