天天看點

Qt學習之路(43): QDirModel

今天我們來看一個很有用的model:QDirModel。這個model允許我們在view中顯示作業系統的目錄結構。這次讓我們先來看看運作結果:

這個界面很熟悉吧?不過這可不是由QFileDialog打開的哦,這是我們自己實作的。而提供這種實作支援的,就是QDirModel和QTreeView。我們來看一下代碼。

mytreeview.h

#ifndef MYLISTVIEW_H 

#define MYLISTVIEW_H 

#include <QtGui> 

class MyTreeView : public QWidget 

        Q_OBJECT 

public: 

        MyTreeView(); 

private: 

        QDirModel *model; 

        QTreeView *treeView; 

private slots: 

        void mkdir(); 

        void rm(); 

}; 

#endif // MYLISTVIEW_H

mytreeview.cpp

#include "mylistview.h" 

MyTreeView::MyTreeView() 

        model = new QDirModel; 

        model->setReadOnly(false); 

        model->setSorting(QDir::DirsFirst | QDir::IgnoreCase | QDir::Name); 

        treeView = new QTreeView; 

        treeView->setModel(model); 

        treeView->header()->setStretchLastSection(true); 

        treeView->header()->setSortIndicator(0, Qt::AscendingOrder); 

        treeView->header()->setSortIndicatorShown(true); 

        treeView->header()->setClickable(true); 

        QModelIndex index = model->index(QDir::currentPath()); 

        treeView->expand(index); 

        treeView->scrollTo(index); 

        treeView->resizeColumnToContents(0); 

        QHBoxLayout *btnLayout = new QHBoxLayout; 

        QPushButton *createBtn = new QPushButton(tr("Create Directory...")); 

        QPushButton *delBtn = new QPushButton(tr("Remove")); 

        btnLayout->addWidget(createBtn); 

        btnLayout->addWidget(delBtn); 

        QVBoxLayout *mainLayout = new QVBoxLayout(this); 

        mainLayout->addWidget(treeView); 

        mainLayout->addLayout(btnLayout); 

        this->setLayout(mainLayout); 

        connect(createBtn, SIGNAL(clicked()), this, SLOT(mkdir())); 

        connect(delBtn, SIGNAL(clicked()), this, SLOT(rm())); 

void MyTreeView::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")); 

                } 

void MyTreeView::rm() 

        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))); 

構造函數中,首先我們建立了QDirModel的一個對象,并且設定ReadOnly為false,也就是說我們可以對其進行修改。而下一個setSorting()函數是對其進行排序,排序的依據也很清楚:檔案夾優先(QDir::DirsFirst),忽略大小寫(QDir::IgnoreCase),而且是根據名字排序(QDir::Name)。更多的規則組合可以參見 API 文檔了。

然後我們建立一個QTreeView執行個體,并且把model設定為剛剛的QDirModel執行個體。然後我們開始設定QTreeView的相關屬性。首先把stretchLastSection設定為true。如果把這個屬性設定為true,就是說,當QTreeView的寬度大于所有列寬之和時,最後一列的寬度自動擴充以充滿最後的邊界;否則就讓最後一列的寬度保持原始大小。第二個setSortIndicator()函數是設定哪一列進行排序。由于我們前面設定了model是按照名字排序,是以我們這個傳遞的第一個參數是0,也就是第1列。setSortIndicatorShown()函數設定顯示列頭上面的排序小箭頭。setClickable(true)則允許滑鼠點選列頭。這樣,我們的QTreeView就設定完畢了。最後,我們通過QDir::currentPath()擷取目前exe檔案運作時路徑,并把這個路徑當成程式啟動時顯示的路徑。expand()函數即展開這一路徑;scrollTo()函數是把視圖的視口滾動到這個路徑的位置;resizeColumnToContents()是要求把列頭适應内容的寬度,也就是不産生...符号。這樣,我們就通過一系列的參數設定好了QTreeView,讓它能夠為我們展示目錄結構。

至于後面的兩個slot,其實并不能了解。第一個mkdir()函數就是建立一個檔案夾。

}

正如它的代碼所示,首先擷取選擇的目錄。後面這個isValid()的判斷很重要,因為預設情況下是沒有目錄被選擇的,此時這個路徑是非法的,為了避免程式出現異常,必須要有這一步判斷。然後會彈出對話框詢問新的檔案夾名字,如果建立失敗會有提示,否則就是建立成功。這時候你就可以到硬碟上的實際位置看看啦!

删除目錄的代碼也很類似:

同樣需要實作檢測路徑是否合法。另外需要注意的是,目錄和檔案的删除不是一個函數,需要調用isDir()函數檢測。這一步在代碼中有很清楚的描述,這裡就不再贅述了。

注意,QDirModel 在最新版 Qt 中已經不建議使用了。文檔中說使用 QFileSystemModel 代替。由于這兩者的函數幾乎一樣,是以就沒有對代碼進行修改。與QDirModel不同的是,QFileSystemModel會啟動自己的線程進行檔案夾的掃描,是以不會發生因掃描檔案夾而導緻的主線程阻塞的現象。另外,無論 QDirModel還是QFileSystemModel都會對model結果進行緩存,如果你要立即重新整理結果,前者提供了refresh()函數,而後者會通知QFileSystemWatcher類。

本文轉自 FinderCheng 51CTO部落格,原文連結:

http://blog.51cto.com/devbean/265658

繼續閱讀