QT从文件和文件夹列表中选择多个项目

时间:2017-03-13 20:28:47

标签: c++ qt qdir

我正在Unix中开发Qt C ++应用程序,而且我一直试图做一些与此图像相似的事情:

enter image description here

如您所见,有一个文件和文件夹列表,用户可以选择多个文件和文件夹(如果选择了一个文件夹,则所有子项也会被选中)。如果显示文件夹/文件图标,我真的不在乎。

我能够创建一个QDir列表,它存储了给定根路径的所有文件和文件夹路径。问题是我不知道用哪些小部件来设计选择面板。

顺便说一句,to_uncompress = JSON.parse(to_uncompress) 的lis是一个向量,但它可以很容易地修改为其他任何东西。

谢谢!

3 个答案:

答案 0 :(得分:2)

您可以尝试为QFileSystemModel创建代理模型,使用Qt :: ItemIsUserCheckable覆盖flags(),覆盖setData()并将模型应用于QTreeView。完整的示例可以在https://github.com/em2er/filesysmodel找到。这段代码只是一个概念,我没有彻底测试过,但你可以从中得到一些想法。在截图中看起来很像: It will look smth like on the screenshot

此外,您可以将其与Merged Proxy Model结合使用,以在一个视图中显示多个起始路径。

答案 1 :(得分:1)

您可能需要考虑QTreeWidget,或者它是一个更高级的版本 - QTreeView和适当的数据模型。

答案 2 :(得分:0)

正如一些用户建议的那样,我最终使用了QFileSystemModel。我将完整描述我是如何实现它的,以防其他人提出这个问题并需要明确的响应。

首先,QFileSystemModel是一个没有复选框的文件树,要添加它们,一个扩展QFileSystemModel的新类,必须覆盖至少3个方法。

class FileSelector : public QFileSystemModel
{
public:
    FileSelector(const char *rootPath, QObject *parent = nullptr);
    ~FileSelector();

    bool setData(const QModelIndex& index, const QVariant& value, int role);
    Qt::ItemFlags flags(const QModelIndex& index) const;
    QVariant data(const QModelIndex& index, int role) const;

private:
    QObject *parent_;
    /* checklist_ stores all the elements which have been marked as checked */
    QSet<QPersistentModelIndex> checklist_;
};

创建模型时,必须设置一个标志,表示它应该有一个可检查框。这就是为什么我们将使用flags函数:

Qt::ItemFlags FileSelector::flags(const QModelIndex& index) const
{
    return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable;
}

当在复选框中单击时,将调用方法setData,其中包含所单击元素的索引(不是复选框本身,而是:

bool FileSelector::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (role == Qt::CheckStateRole && index.column() == 0) {
        QModelIndexList list;
        getAllChildren(index, list); // this function gets all children 
        // given the index and saves them into list (also saves index in the head)
        if(value == Qt::Checked)
        {
            for(int i = 0; i < list.size(); i++)
            {
               checklist_.insert(list[i]);
               // signals that a change has been made
               emit dataChanged(list[i], list[i]);
            }
        }
        else if(value == Qt::Unchecked)
        {
            for(int i = 0; i < list.size(); i++)
            {
                checklist_.remove(list[i]);
                emit dataChanged(list[i], list[i]);
            }
        }
        return true;
    }
    return QFileSystemModel::setData(index, value, role);
}

当发出dataChanged信号或您打开树的新路径时,将调用data函数。在这里,您必须确保仅显示第一列(文件名旁边)的复选框,并检索复选框的状态,以将其标记为选中/取消选中。

QVariant FileSelector::data(const QModelIndex& index, int role) const
{
    if (role == Qt::CheckStateRole && index.column() == 0) {
        if(checklist_.contains(index)) return Qt::Checked;
        else return Qt::Unchecked;
    }
    return QFileSystemModel::data(index, role);
}

我唯一无法完成的就是获得所有孩子,因为必须打开文件夹才能找回孩子。因此,在您打开它之前,关闭的文件夹将不会有任何子项。

希望这可以帮助那些遇到与我一样的问题的人!