【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 的不一樣。

相關文章
相關標籤/搜索