How to add a custom role to QFileSystemModel

2019-02-26 09:44发布

I would like to add a custom role to a QFileSystemModel (probably to a derived model). I want to use this role to save the check state of a CheckBox which is displayed next to the filename in a custom delegate. How can this be done?

1条回答
Luminary・发光体
2楼-- · 2019-02-26 10:43

I have used using the example Qt Quick Controls - File System Browser Example removing the part of the selection.

The steps were the following:

  • Add a new role in roleNames:

    QHash<int,QByteArray> roleNames() const Q_DECL_OVERRIDE
    {
        QHash<int, QByteArray> result = QFileSystemModel::roleNames();
        result.insert(SizeRole, QByteArrayLiteral("size"));
        result.insert(DisplayableFilePermissionsRole, QByteArrayLiteral("displayableFilePermissions"));
        result.insert(LastModifiedRole, QByteArrayLiteral("lastModified"));
        result.insert(Qt::CheckStateRole, QByteArrayLiteral("checkRole"));
        return result;
    }
    
  • Create a container that stores the information of the selection, in this case I will use QMap:

    QMap<QPersistentModelIndex, Qt::CheckState> m_checks;
    
  • Overwrite the data() method that returns the state if it is stored in the container, if it is not returned Qt::UnChecked as the default value:

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE
    {
        if (index.isValid() && role >= SizeRole) {
            ...
        }
        else if (role == Qt::CheckStateRole) {
            QPersistentModelIndex pix(index);
            if(m_checks.contains(pix)){
                return m_checks[pix];
            }
            return Qt::Unchecked;
        }
        return QFileSystemModel::data(index, role);
    }
    
  • Overwrite the setData() method, which you must modify if necessary and create the data.

    bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole){
        if(role == Qt::CheckStateRole && index.isValid()){
    
            Qt::CheckState current = value.value<Qt::CheckState>();
            if(m_checks.contains(index)){
                Qt::CheckState last = m_checks[index];
                if(last == current)
                    return false;
                m_checks[index] = current;
            }
            else{
                m_checks.insert(index, current);
            }
            emit dataChanged(index, index, {role});
            return true;
        }
        return QFileSystemModel::setData(index, value, role);
    }
    
  • I have added a new column where I have established the delegate to the CheckBox and I used the onCheckedChanged slot to set the value using the setData() method, the QModelIndex is passed, the data and the role, in this case, pass 10 because it is the value number of Qt::CheckStateRole.

    TreeView {
        id: view
        model: fileSystemModel
        ...
    
        TableViewColumn {
            role: "checkRole"
            delegate: Component {
                CheckBox {
                    id: mycbx
                    checked: styleData.value
                    onCheckedChanged: view.model.setData(styleData.index, checked, 10)
                }
            }
        }
    ...
    

The complete example can be found in the following link.

查看更多
登录 后发表回答