The QFileSystemModel class provides a fully featured data model for the local file system provides access to the local file system, providing functions for renaming and removing files and directories, and for creating new directories.

A simple usage of this class is given below[ref: http://doc.qt.io/qt-5/qfilesystemmodel.html#details].

QFileSystemModel *model = new QFileSystemModel;
model->setRootPath(QDir::currentPath());
QTreeView *tree = new QTreeView(splitter);
tree->setModel(model);
tree->setRootIndex(model->index(QDir::currentPath()));

But in the tree view we could see only the contents of the given directory and not the given directory as a parent. So I have decided to write my own custom model which will be populated and show the parent directory and all of its children and its children and so on..

I have derived new class SandBoxItemModel from QStandardItemModel which takes the list of folder path to be shown in the view. Implementation details are given below.

Unlike actual QFileSystemModel here we don not have direct access to the underlying filesystem. It may also required for us to access the actual path of the directory or file when user clicks on it. To achieve this here I have used method “QStandardItem::setAccessibleDescription(const QString)” to set the actual path of the file/directory. And the same will be accessed and displayed on the status bar.

sandboxitemmodel.h

#ifndef SANDBOXITEMMODEL_H
#define SANDBOXITEMMODEL_H
#include <QStandardItemModel>
#include <QStandardItem>
class SandBoxItemModel : public QStandardItemModel
{
public:
    SandBoxItemModel(QObject* parent = 0);
    ~SandBoxItemModel();
    void setSandBoxDetails(QString names);
    void populateSandBoxes(const QStringList &names);
    void createDirectoryItem(QString dirName, QStandardItem *parentItem = NULL);

private:
    QStandardItem *rootItem;
    QIcon dirIcon;
    QIcon fileIcon;
};
#endif // SANDBOXITEMMODEL_H

sandboxitemmodel.cpp

#include "sandboxitemmodel.h"
#include <QApplication>
#include <QStyle>
#include <QDir>
#include <QDebug>
#include <QDirIterator>
SandBoxItemModel::SandBoxItemModel(QObject *parent)
    :QStandardItemModel(parent)
{
    rootItem = this->invisibleRootItem();
    dirIcon = QApplication::style()->standardIcon(QStyle::SP_DirIcon);      //icon for directories
    fileIcon = QApplication::style()->standardIcon(QStyle::SP_FileIcon);    //icon for files
}
SandBoxItemModel::~SandBoxItemModel()
{
}
/*
 Sandbox locations are parsed from the file which are separated by new lines.
*/
void SandBoxItemModel::setSandBoxDetails(QString names)
{
    populateSandBoxes(names.split("\n"));
}

/*
 method to populate the contents of the sandboxes parsed from the file.
*/

void SandBoxItemModel::populateSandBoxes(const QStringList &names)
{
    QString name;
    QStandardItem* parent;
    foreach (name, names) {
        if(!name.isEmpty())
        {
            name.remove("\r");
            parent = new QStandardItem(dirIcon ,name);  //create the parent directory item
            parent->setAccessibleDescription(name);     //set actual path to item
            rootItem->appendRow(parent);                //add the parent item to root item
            createDirectoryItem(name, parent);          //Iterate and populate the contents
        }
    }
}
/*
  Method to populate the contents of the given directory in recursive manner.
  Each found child will be appended to its parent item.
  Files & folders will be using its own standard icons  from current style.
  child->setAccessibleDescription() is used to set the actual path of the item
  which will be useful.
*/
void SandBoxItemModel::createDirectoryItem(QString dirName, QStandardItem *parentItem)
{
    QDir dir(dirName);
    QFileInfoList subFolders;
    QFileInfo folderName;
    QStandardItem* child;
    subFolders = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);    //get all the sub folders
    foreach (folderName, subFolders)
    {
        if(folderName.isFile())
        {
            child = new QStandardItem(fileIcon, folderName.fileName());                 //Append a file
            child->setAccessibleDescription(folderName.filePath());                     //set actual path to item
        }
        else
        {
            child = new QStandardItem(dirIcon, folderName.fileName());                  //Append a folder
            child->setAccessibleDescription(folderName.filePath());                     //set actual path to item
       }
        parentItem->appendRow(child);
        createDirectoryItem(folderName.filePath(), child);                              //Recurse its subdirectories
    }
}

Now we will create a main window class which has  a TreeView widget to show our model and data.

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTreeView>
#include <QStatusBar>
#include "sandboxitemmodel.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void initUI();
private:
    QTreeView* treeView;
    SandBoxItemModel* sandBoxModel;
    QStatusBar* statusBar;
private slots:
    void onSelected(QModelIndex index);
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QHeaderView>
#include <QFile>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    resize(800, 600);
    initUI();
}
MainWindow::~MainWindow()
{
}
void MainWindow::initUI()
{
    statusBar = new QStatusBar(this);
    this->setStatusBar(statusBar);
    sandBoxModel = new SandBoxItemModel();
    QFile file(":/resources/sandbox.txt");              //sandbox locations are read from the text file
    file.open(QIODevice::ReadOnly);
    sandBoxModel->setSandBoxDetails(file.readAll());
    treeView = new QTreeView();
    treeView->setModel(sandBoxModel);
    treeView->header()->hide();
    connect(treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onSelected(QModelIndex)));
    this->setCentralWidget(treeView);
}
/*
 This slot will get the accessible dewcription from the current selected item and show it in the status bar.
*/
void MainWindow::onSelected(QModelIndex index)
{
    QStandardItem *item = sandBoxModel->itemFromIndex(index);
    QString data = item->accessibleDescription();
    statusBar->showMessage(data);
}

As you can see in the code above in MainWidnow  class we have a QTreeView to show our folder structure and a QStatusBar to show the current selected item in the tree view when user clicks on it.

here goes the main.cpp

#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

Below is my sample “sandbox.txt” file.

D:\MySandBox
D:\MySandBox2

And here is the program running.

customtreemodel

Source code:

Git:/CustomFileSystemModel

Tagged

One thought on “Custom FileSystemModel display

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s