1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
#pragma once
#include <QObject>
#include <qqmlintegration.h>
#include <QAbstractListModel>
#include <QFileSystemWatcher>
#include <QFileInfo>
#include <QDir>
#include <QImageReader>
class FileSystemEntry : public QObject {
Q_OBJECT
QML_ELEMENT;
QML_UNCREATABLE("FileSystemEntry instances can only be retrieved from a FileSystemModel");
Q_PROPERTY(QString path READ path CONSTANT);
Q_PROPERTY(QString relativePath READ relativePath CONSTANT);
Q_PROPERTY(QString name READ name CONSTANT);
Q_PROPERTY(QString parentDir READ parentDir CONSTANT);
Q_PROPERTY(qint64 size READ size CONSTANT);
Q_PROPERTY(bool isDir READ isDir CONSTANT);
Q_PROPERTY(bool isImage READ isImage CONSTANT);
public:
explicit FileSystemEntry(const QString& path, const QString& relativePath, QObject* parent = nullptr)
: QObject(parent), m_fileInfo(QFileInfo(path)), m_path(path), m_relativePath(relativePath) {}
QString path() const { return m_path; };
QString relativePath() const { return m_relativePath; };
QString name() const { return m_fileInfo.fileName(); };
QString parentDir() const { return m_fileInfo.absolutePath(); };
qint64 size() const { return m_fileInfo.size(); };
bool isDir() const { return m_fileInfo.isDir(); };
bool isImage() {
if (!m_isImageInitialised) {
QImageReader reader(m_path);
m_isImage = reader.canRead();
m_isImageInitialised = true;
}
return m_isImage;
}
private:
const QFileInfo m_fileInfo;
const QString m_path;
const QString m_relativePath;
bool m_isImage;
bool m_isImageInitialised;
};
class FileSystemModel : public QAbstractListModel {
Q_OBJECT;
QML_ELEMENT;
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged);
Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged);
Q_PROPERTY(Filter filter READ filter WRITE setFilter NOTIFY filterChanged);
Q_PROPERTY(QList<FileSystemEntry*> entries READ entries NOTIFY entriesChanged);
public:
enum Roles {
FilePathRole = Qt::UserRole + 1,
RelativeFilePathRole,
FileNameRole,
ParentDirRole,
FileSizeRole,
FileIsDirRole,
FileIsImageRole
};
enum Filter {
NoFilter,
Images,
Files
};
Q_ENUM(Filter)
explicit FileSystemModel(QObject* parent = nullptr)
: QAbstractListModel(parent), m_recursive(true), m_filter(NoFilter) {
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::watchDirIfRecursive);
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &FileSystemModel::updateEntries);
}
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
QString path() const;
void setPath(const QString& path);
bool recursive() const;
void setRecursive(bool recursive);
Filter filter() const;
void setFilter(Filter filter);
QList<FileSystemEntry*> entries() const;
signals:
void pathChanged();
void recursiveChanged();
void filterChanged();
void entriesChanged();
private:
QDir m_dir;
QFileSystemWatcher m_watcher;
QList<FileSystemEntry*> m_entries;
QString m_path;
bool m_recursive;
Filter m_filter;
void watchDirIfRecursive(const QString& path);
void update();
void updateWatcher();
void updateEntries();
};
|