QT5學習 QFileSystemModel

huffscan發表於2017-09-27

QFileSystemModel。看起來,QFileSystemModelQStringListModel要複雜得多;事實也是如此。但是,雖然功能強大,QFileSystemModel的使用還是簡單的。

讓我們從 Qt 內建的模型說起。實際上,Qt 內建了兩種模型:QStandardItemModelQFileSystemModelQStandardItemModel是一種多用途的模型,能夠讓列表、表格、樹等檢視顯示不同的資料結構。這種模型會將資料儲存起來。試想一下,列表和表格所要求的資料結構肯定是不一樣的:前者是一維的,後者是二維的。因此,模型需要儲存有實際資料,當檢視是列表時,以一維的形式提供資料;當檢視是表格時,以二維的形式提供資料。QFileSystemModel則是另外一種方式。它的作用是維護一個目錄的資訊。因此,它不需要儲存資料本身,而是儲存這些在本地檔案系統中的實際資料的一個索引。我們可以利用QFileSystemModel顯示檔案系統的資訊、甚至通過模型來修改檔案系統。 

.h 檔案 

#pragma once

#ifndef DIRECTPATH_H
#define DIRECTPATH_H
#include <QDialog>
#include <QFileSystemModel>
#include <QTreeView> 

#define prallelCat 
class DirctPathViewer : public QDialog
{
Q_OBJECT

public:
DirctPathViewer(QWidget  *parent = 0 );    // 帶有預設值引數的建構函式 
  ~DirctPathViewer();
private slots:     // 槽函式
void remove();
void createDirctPath();  
void mkdir();
void rm();
private:
QFileSystemModel *model;
QTreeView *treeView;
};
#endif  

.cpp檔案 

#include "DirctPathViewer.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QInputDialog>
#include <QMessageBox>


DirctPathViewer::DirctPathViewer(QWidget  *parent)
: QDialog(parent)

#ifdef treeViewer
model = new QFileSystemModel;
model->setReadOnly(false);            //設定可以修改
model->setRootPath(QDir::currentPath());

treeView = new QTreeView;
treeView->setModel(model);

treeView->header()->setStretchLastSection(true);
treeView->header()->setSortIndicator(0, Qt::AscendingOrder);
treeView->header()->setSortIndicatorShown(true);
//treeView->header()->s(true);

QModelIndex index = model->index(QDir::currentPath());
treeView->expand(index);      //當前項展開
treeView->scrollTo(index);    //定位到當前項
treeView->resizeColumnToContents(0);

QPushButton *createButton = new QPushButton("Create Directory", this);
QPushButton *removeButton = new QPushButton("Remove", this);

QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addWidget(createButton);
hlayout->addWidget(removeButton);

QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addWidget(treeView);
vlayout->addLayout(hlayout);

setLayout(vlayout);
connect(createButton, SIGNAL(clicked()), this, SLOT(createDirectory()));
connect(removeButton, SIGNAL(clicked()), this, SLOT(remove()));
#endif 
#ifdef prallelCat 
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()));
#endif 

}


DirctPathViewer::~DirctPathViewer()
{

}


void DirctPathViewer::createDirctPath()
{
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 DirctPathViewer::remove()
{
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)));
}



void DirctPathViewer::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 DirctPathViewer::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)));
}
}

建構函式很簡單,我們首先建立了QFileSystemModel例項,然後將其作為一個QTreeView的模型。注意我們將QFileSystemModel的根目錄路徑設定為當前目錄。剩下來的都很簡單,我們新增了按鈕之類,這些都不再贅述。對於 treeView 檢視,我們使用了setRootIndex()對模型進行過濾。我們可以嘗試一下,去掉這一句的話,我們的程式會顯示整個檔案系統的目錄;而這一句的作用是,從模型中找到 QDir::currentPath()所對應的索引,然後顯示這一位置。也就是說,這一語句的作用實際是設定顯示哪個目錄。我們會在後面的章節中詳細討論index()函式。

建立資料夾:

首先我們獲取選擇的目錄。後面這個isValid()判斷很重要,因為預設情況下是沒有目錄被選擇的,此時路徑是非法的,為了避免程式出現異常,必須要有這一步判斷。然後彈出對話方塊詢問新的資料夾名字,如果建立失敗會有提示,否則就是建立成功。這時候你會發現,硬碟的實際位置的確建立了新的資料夾。 

移除資料夾:

這裡同樣需要先檢測路徑是否合法。另外需要注意的是,目錄和檔案的刪除不是一個函式,需要呼叫isDir()函式檢測。這一步在程式碼中有很清楚的描述,這裡就不再贅述了。

實際上,我們這裡不需要十分擔心QFileSystemModel的效能問題,因為它會啟動自己的執行緒進行資料夾掃描,不會發生因掃描資料夾而導致的主執行緒阻塞的現象。另外需要注意的是,QFileSystemModel會對模型的結果進行快取,如果你要立即重新整理結果,需要通知QFileSystemWatcher類。





相關文章