Results 1 to 15 of 15

Thread: QFileSystemModel with checkboxes...

  1. #1
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default QFileSystemModel with checkboxes...

    Is there a way to make a QFileSystemModel add a checkbox to each of its rows? I know I can create a QStandardItemModel and add a QStandardItem with a checkbox added to it, but I need the functionality the QFileSystemModel gives me.

  2. #2
    Join Date
    Nov 2009
    Posts
    129
    Thanks
    4
    Thanked 29 Times in 29 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Subclass QFileSystemModel and provide custom implementations of the data, flags and setData functions:
    Qt Code:
    1. QVariant CustomModel::data(const QModelIndex& index, int role) const {
    2. if (role == Qt::CheckStateRole) {
    3. /* determine whether the box should be checked or unchecked */
    4. return shouldBeChecked ? Qt::Checked : Qt::Unchecked;
    5. }
    6. return QFileSystemModel::data(index, role);
    7. }
    8.  
    9. Qt::ItemFlags CustomModel::flags(const QModelIndex& index) const {
    10. return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable;
    11. }
    12.  
    13. bool CustomModel::setData(const QModelIndex& index, const QVariant& value, int role) {
    14. if (role == Qt::CheckStateRole) {
    15. /* set indicator in your backing store according to whether value == Qt::Checked */
    16. emit dataChanged(index, index);
    17. return true;
    18. }
    19. return QFileSystemModel::setData(index, value, role);
    20. }
    To copy to clipboard, switch view to plain text mode 
    You will have to invent a way of keeping track of which items are checked and unchecked, so that you can access that information in data and update it in setData.

  3. #3
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    If this implementation of the flags() function returns "Qt::ItemIsUserCheckable", then each rows checkbox should be checkable, right?
    That doesn't happen. It would be nicer to be able to check-uncheck without having to grab the mouse-click then call on setData().
    Last edited by been_1990; 15th January 2010 at 19:06.

  4. #4
    Join Date
    Nov 2009
    Posts
    129
    Thanks
    4
    Thanked 29 Times in 29 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Quote Originally Posted by been_1990 View Post
    If this implementation of the flags() function returns "Qt::ItemIsUserCheckable", then each rows checkbox should be checkable, right?
    That doesn't happen.
    Yes, but there’s an easy mistake to make, so I’ll take a guess that it’s relevant and describe it.

    When the value returned by flags includes Qt::ItemIsUserCheckable, clicking on the checkbox causes setData to be called specifying the appropriate item index, Qt::CheckStateRole and either Qt::Checked or Qt::Unchecked according to the state to which the checkbox should change... but it doesn’t change the state for you.

    You have to emit the dataChanged signal and return true, but you must also do whatever is required in your implementation to be sure that when data is called for that item index with Qt::CheckStateRole it returns the new check state.

    If you don’t do those things, when you click on the checkboxes, they won’t change state. None of the Qt classes involved here will maintain the state of the checkboxes for you, not even as far as changing their appearance when you click them. The state is will always show as whatever your data function returns.

  5. #5
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Let's see if I got it right:
    When I click on a checkbox, setData() is called.
    It then emits dataChanged(), that probably calls the flag() function. Which then updates all indexes.

    But then:
    How can I check whether the checkbox state is checked/unchecked?
    And how can I change only the state of the checkbox that was clicked on?(When I click on 1, all other rows get checked also)

    It seems that setData()'s int role is always the same, 10(or Qt::CheckStateRole) whenever I click the checkbox.

  6. #6
    Join Date
    Nov 2009
    Posts
    129
    Thanks
    4
    Thanked 29 Times in 29 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Quote Originally Posted by been_1990 View Post
    Let's see if I got it right:
    When I click on a checkbox, setData() is called.
    It then emits dataChanged(), that probably calls the flag() function.
    I haven’t checked the Qt source code, but I think that’s wrong. I think:
    • When displaying an item, Qt calls the data function with Qt::CheckStateRole to determine whether to show a box with a check mark, a box without a check mark, or no checkbox at all.
    • When you click on a checkbox, Qt calls the flag function to find out whether it should pay any attention.
    • If the flag function returns a value including Qt::ItemIsUserCheckable, Qt calls the setData function with a value that is the opposite of the one currently displayed by the checkbox.
    • The setData function now must emit dataChanged and return true; it must also do “something” that will tell the data function to return the opposite value from the one it returned before for this index.


    Quote Originally Posted by been_1990 View Post
    And how can I change only the state of the checkbox that was clicked on?(When I click on 1, all other rows get checked also)
    Qt doesn’t do that for you; you have to keep track. I’d suggest getting a QPersistentModelIndex in the setData function and storing those in a QSet<QPersistentModelIndex> that lists the ones that are checked. The data function could then use this to determine the proper check state to return.

    Quote Originally Posted by been_1990 View Post
    Let's see if I got it right:
    It seems that setData()'s int role is always the same, 10(or Qt::CheckStateRole) whenever I click the checkbox.
    That’s expected. The value should change between checked and unchecked... if you’ve implemented data correctly.

  7. #7
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    If the flag function returns a value including Qt::ItemIsUserCheckable, Qt calls the setData function with a value that is the opposite of the one currently displayed by the checkbox.
    So if it's checked it will call setData with the Qt::Unchecked value?
    Qt Code:
    1. setData(const QModelIndex& index, const QVariant& value, int role)
    To copy to clipboard, switch view to plain text mode 
    Trough which : "QVariant& value" or "int role" ?

    The setData function now must emit dataChanged and return true; it must also do “something” that will tell the data function to return the opposite value from the one it returned before for this index.
    So:
    Qt Code:
    1. setData(const QModelIndex& index, const QVariant& value, int role) {
    2. if (role == Qt::CheckStateRole) {
    3. ///////*
    4. If the checkbox is checked, tell data() to uncheck it;
    5. If unchecked, tell data() to check it;
    6. *////////
    7. emit dataChanged(index, index);
    8. return true;
    9. }
    10. return QFileSystemModel::setData(index, value, role);
    11. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. The value should change between checked and unchecked... if you’ve implemented data correctly.
    To copy to clipboard, switch view to plain text mode 
    You mean QVariant& value?

  8. #8
    Join Date
    Nov 2009
    Posts
    129
    Thanks
    4
    Thanked 29 Times in 29 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Quote Originally Posted by been_1990 View Post
    So if it's checked it will call setData with the Qt::Unchecked value?
    [...]
    Trough which : "QVariant& value" or "int role" ?
    The value. We’re discussing only the case where role == Qt::CheckStateRole; otherwise, the call applies to something else, not the checkbox.

    Quote Originally Posted by been_1990 View Post
    The value should change between checked and unchecked... if you’ve implemented data correctly.
    You mean QVariant& value?
    Right. The aggravating part of this is that nothing in any of the Qt classes will maintain the state of each item’s checkbox for you. You have to invent a way of keeping track of that, feeding the correct value to the data function, and updating it in the setData function. If you don’t return the correct state from data when it’s called on Qt::CheckStateRole, nothing else will work right.

  9. #9
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    I already can change the checkbox state from checked to unchecked. But that still checks all of them(like you said it would..)
    Do you think the code of QStandardItemModel would have the implementation to check/uncheck items independently? I'm gonna look at it, but I might get lost with all the code. (if there really is a check/uncheck mechanism that I could copy)

  10. #10
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Ok, here is the code. It aparently does what you suggested:

    Qt Code:
    1. void QStandardItem::setData(const QVariant &value, int role)
    2. {
    3. role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
    4. QVector<QWidgetItemData>::iterator it;
    5. for (it = d->values.begin(); it != d->values.end(); ++it) {
    6. if ((*it).role == role) {
    7. if (value.isValid()) {
    8. if ((*it).value.type() == value.type() && (*it).value == value)
    9. return;
    10. (*it).value = value;
    11. } else {
    12. d->values.erase(it);
    13. }
    14. if (d->model)
    15. d->model->d_func()->itemChanged(this);
    16. return;
    17. }
    18. }
    19. d->values.append(QWidgetItemData(role, value));
    20. if (d->model)
    21. d->model->d_func()->itemChanged(this);
    22. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. QVariant QStandardItem::data(int role) const
    2. {
    3. Q_D(const QStandardItem);
    4. role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
    5. QVector<QWidgetItemData>::const_iterator it;
    6. for (it = d->values.begin(); it != d->values.end(); ++it) {
    7. if ((*it).role == role)
    8. return (*it).value;
    9. }
    10. return QVariant();
    11. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. Qt::ItemFlags QStandardItem::flags() const
    2. {
    3. QVariant v = data(Qt::UserRole - 1);
    4. if (!v.isValid())
    5. return (Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable
    6. |Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled);
    7. return Qt::ItemFlags(v.toInt());
    8. }
    To copy to clipboard, switch view to plain text mode 

  11. #11
    Join Date
    Nov 2009
    Posts
    129
    Thanks
    4
    Thanked 29 Times in 29 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Quote Originally Posted by been_1990 View Post
    I already can change the checkbox state from checked to unchecked. But that still checks all of them(like you said it would..)
    Do you think the code of QStandardItemModel would have the implementation to check/uncheck items independently?
    I don’t think the code it has would be very useful, since it relies on instances of QStandardItem to keep the data, and you don’t have a model built on QStandardItems, you have a QFileSystemModel, the backing store of which is not accessible to programs that use the model.

    Try something like this (off the top of my head, so errors/typos are not unlikely):
    Qt Code:
    1. class CustomModel : public QFileSystemModel {
    2. //...
    3. QSet<QPersistentModelIndex> checklist;
    4. //...
    5. };
    6.  
    7. QVariant CustomModel::data(const QModelIndex& index, int role) const {
    8. if (role == Qt::CheckStateRole) return checklist.contains(index) ? Qt::Checked : Qt::Unchecked;
    9. return QFileSystemModel::data(index, role);
    10. }
    11.  
    12. Qt::ItemFlags CustomModel::flags(const QModelIndex& index) const {
    13. return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable;
    14. }
    15.  
    16. bool CustomModel::setData(const QModelIndex& index, const QVariant& value, int role) {
    17. if (role == Qt::CheckStateRole) {
    18. if (value == Qt::Checked) checklist.insert(index);
    19. else checklist.remove(index);
    20. emit dataChanged(index, index);
    21. return true;
    22. }
    23. return QFileSystemModel::setData(index, value, role);
    24. }
    To copy to clipboard, switch view to plain text mode 

    Note that the QSet keeps QPersistentModelIndexes, not ordinary QModelIndexes.

  12. #12
    Join Date
    Oct 2008
    Posts
    306
    Thanks
    6
    Thanked 9 Times in 8 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QFileSystemModel with checkboxes...

    Seems pretty simple. I dont know why I thought it would be complicated. Should be kicking myself now...

  13. #13
    Join Date
    Feb 2011
    Location
    The Netherlands
    Posts
    5
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QFileSystemModel with checkboxes...

    This works like a charm, only down-side is that it gives me a checkbox per field.

    I'd love to have a checkbox per row. I tried with index.column() == 0 but that only makes the first column checkbox checkable.
    The other boxes are still shown.

    What am I doing wrong?

  14. #14
    Join Date
    Dec 2009
    Posts
    128
    Thanks
    7
    Thanked 14 Times in 14 Posts
    Platforms
    Unix/X11 Windows

    Default Re: QFileSystemModel with checkboxes...

    take a look at the CustomModel::flags() method, and add your column test here ?

  15. #15
    Join Date
    Feb 2011
    Location
    The Netherlands
    Posts
    5
    Qt products
    Qt3 Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QFileSystemModel with checkboxes...

    That's what I did . . they are now non-checkable but still visible.


    Added after 12 minutes:


    Added column check to data method.

    Now works like a charm!
    Last edited by the_jinx; 11th March 2011 at 16:01.

Similar Threads

  1. Help with QFileSystemModel
    By TheShow in forum Qt Programming
    Replies: 4
    Last Post: 5th January 2010, 21:11
  2. Notifying QFileSystemModel about changes
    By squidge in forum Qt Programming
    Replies: 3
    Last Post: 24th November 2009, 00:24
  3. Known problem with filters and QFileSystemModel?
    By Kumosan in forum Qt Programming
    Replies: 3
    Last Post: 27th August 2009, 09:14
  4. QDirModel or QFileSystemModel?
    By ricardo in forum Qt Programming
    Replies: 1
    Last Post: 21st June 2009, 18:10
  5. QFileSystemModel has no sorting
    By mpi in forum Qt Programming
    Replies: 3
    Last Post: 28th May 2009, 09:14

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.