【Qt笔记】QFileSystemModel

上一章咱们详细了解了QStringListModel。本章咱们将再来介绍另一个内置模型:QFileSystemModel。看起来,QFileSystemModelQStringListModel要复杂得多;事实也是如此。可是,虽然功能强大,QFileSystemModel的使用仍是简单的。缓存

让咱们从 Qt 内置的模型提及。实际上,Qt 内置了两种模型:QStandardItemModelQFileSystemModelQStandardItemModel是一种多用途的模型,可以让列表、表格、树等视图显示不一样的数据结构。这种模型会将数据保存起来。试想一下,列表和表格所要求的数据结构确定是不同的:前者是一维的,后者是二维的。所以,模型须要保存有实际数据,当视图是列表时,以一维的形式提供数据;当视图是表格时,以二维的形式提供数据。QFileSystemModel则是另一种方式。它的做用是维护一个目录的信息。所以,它不须要保存数据自己,而是保存这些在本地文件系统中的实际数据的一个索引。咱们能够利用QFileSystemModel显示文件系统的信息、甚至经过模型来修改文件系统。数据结构

 

QTreeView是最适合应用QFileSystemModel的视图。下面咱们看一段代码:函数

FileSystemWidget::FileSystemWidget(QWidget *parent) :
    QWidget(parent)
{
    model = new QFileSystemModel;
    model->setRootPath(QDir::currentPath());

    treeView = new QTreeView(this);
    treeView->setModel(model);
    treeView->setRootIndex(model->index(QDir::currentPath()));

    QPushButton *mkdirButton = new QPushButton(tr("Make Directory..."), this);
    QPushButton *rmButton = new QPushButton(tr("Remove"), this);
    QHBoxLayout *buttonLayout = new QHBoxLayout;
    buttonLayout->addWidget(mkdirButton);
    buttonLayout->addWidget(rmButton);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(treeView);
    layout->addLayout(buttonLayout);

    setLayout(layout);
    setWindowTitle("File System Model");

    connect(mkdirButton, SIGNAL(clicked()),
            this, SLOT(mkdir()));
    connect(rmButton, SIGNAL(clicked()),
            this, SLOT(rm()));
}

构造函数很简单,咱们首先建立了QFileSystemModel实例,而后将其做为一个QTreeView的模型。注意咱们将QFileSystemModel的根目录路径设置为当前目录。剩下来的都很简单,咱们添加了按钮之类,这些都再也不赘述。对于 treeView 视图,咱们使用了setRootIndex()对模型进行过滤。咱们能够尝试一下,去掉这一句的话,咱们的程序会显示整个文件系统的目录;而这一句的做用是,从模型中找到 QDir::currentPath()所对应的索引,而后显示这一位置。也就是说,这一语句的做用实际是设置显示哪一个目录。咱们会在后面的章节中详细讨论index()函数。性能

如今,咱们能够运行如下程序看看界面:this

虽然咱们基本一行代码都没写(有关文件系统的代码都没有写),可是从运行截图能够看出,QFileSystemModel彻底将所能想到的东西——名称、大小、类型、修改时间等所有显示出来,可见其强大之处。线程

下面是mkdir()槽函数:code

void FileSystemWidget::mkdir()
{
    QModelIndex index = treeView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    QString dirName = QInputDialog::getText(this,
                                            tr("Create Directory"),
                                            tr("Directory name"));
    if (!dirName.isEmpty()) {
        if (!model->mkdir(index, dirName).isValid()) {
            QMessageBox::information(this,
                                     tr("Create Directory"),
                                     tr("Failed to create the directory"));
        }
    }
}

正如代码所示,首先咱们获取选择的目录。后面这个isValid()判断很重要,由于默认状况下是没有目录被选择的,此时路径是非法的,为了不程序出现异常,必需要有这一步判断。而后弹出对话框询问新的文件夹名字,若是建立失败会有提示,不然就是建立成功。这时候你会发现,硬盘的实际位置的确建立了新的文件夹。orm

下面则是rm()槽函数:对象

void FileSystemWidget::rm()
{
    QModelIndex index = treeView->currentIndex();
    if (!index.isValid()) {
        return;
    }
    bool ok;
    if (model->fileInfo(index).isDir()) {
        ok = model->rmdir(index);
    } else {
        ok = model->remove(index);
    }
    if (!ok) {
        QMessageBox::information(this,
                         tr("Remove"),
                         tr("Failed to remove %1").arg(model->fileName(index)));
    }
}

这里一样须要先检测路径是否合法。另外须要注意的是,目录和文件的删除不是一个函数,须要调用isDir()函数检测。这一步在代码中有很清楚的描述,这里就再也不赘述了。排序

实际上,咱们这里不须要十分担忧QFileSystemModel的性能问题,由于它会启动本身的线程进行文件夹扫描,不会发生因扫描文件夹而致使的主线程阻塞的现象。另外须要注意的是,QFileSystemModel会对模型的结果进行缓存,若是你要当即刷新结果,须要通知QFileSystemWatcher类。

若是仔细查看就会发现,咱们的视图不能排序不能点击列头。为此,咱们可使用下面代码:

treeView->header()->setStretchLastSection(true);
treeView->header()->setSortIndicator(0, Qt::AscendingOrder);
treeView->header()->setSortIndicatorShown(true);
treeView->setSortingEnabled(true);
#if QT_VERSION >= 0x050000
    treeView->header()->setSectionsClickable(true);
#else
    treeView->header()->setClickable(true);
#endif

这是 Qt 中视图类经常使用的一种技术:若是咱们要修改有关列头、行头之类的位置,咱们须要从视图类获取到列头对象,而后对其进行设置。正如代码中所显示的那样。注意上面代码片断的最后一部分,咱们使用一个条件判断来肯定 Qt4 与 Qt5 的不一样。

相关文章
相关标签/搜索