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
124
|
#pragma once
#include <QAbstractListModel>
#include <QDir>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QFuture>
#include <QImageReader>
#include <QObject>
#include <qqmlintegration.h>
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 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::updateEntriesForDir);
}
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();
void added(const FileSystemEntry* entry);
void removed(const QString& path);
private:
QDir m_dir;
QFileSystemWatcher m_watcher;
QList<FileSystemEntry*> m_entries;
QHash<QString, QFuture<QPair<QSet<QString>, QSet<QString>>>> m_futures;
QString m_path;
bool m_recursive;
Filter m_filter;
void watchDirIfRecursive(const QString& path);
void update();
void updateWatcher();
void updateEntries();
void updateEntriesForDir(const QString& dir);
};
|