Changeset View
Changeset View
Standalone View
Standalone View
src/contentlist/ContentList.cpp
Show All 23 Lines | |||||
24 | 24 | | |||
25 | #ifdef BALOO_FOUND | 25 | #ifdef BALOO_FOUND | ||
26 | #include "BalooContentLister.h" | 26 | #include "BalooContentLister.h" | ||
27 | #endif | 27 | #endif | ||
28 | 28 | | |||
29 | #include <QDebug> | 29 | #include <QDebug> | ||
30 | #include <QMimeDatabase> | 30 | #include <QMimeDatabase> | ||
31 | #include <QTimer> | 31 | #include <QTimer> | ||
32 | #include <QUrl> | ||||
32 | 33 | | |||
33 | struct ContentEntry { | 34 | struct ContentEntry { | ||
34 | QString filename; | 35 | QString filename; | ||
35 | QVariantHash metadata; | 36 | QUrl filePath; | ||
37 | QVariantMap metadata; | ||||
36 | }; | 38 | }; | ||
37 | 39 | | |||
38 | class ContentList::Private { | 40 | class ContentList::Private { | ||
39 | public: | 41 | public: | ||
42 | typedef QQmlListProperty<ContentQuery> QueryListProperty; | ||||
43 | | ||||
40 | Private() | 44 | Private() | ||
41 | : actualContentList(nullptr) | 45 | : actualContentList(nullptr) | ||
42 | {} | 46 | {} | ||
43 | QList<ContentEntry*> entries; | 47 | QList<ContentEntry*> entries; | ||
44 | ContentListerBase* actualContentList; | 48 | ContentListerBase* actualContentList; | ||
49 | | ||||
50 | QList<ContentQuery*> queries; | ||||
51 | QueryListProperty listProperty; | ||||
52 | | ||||
53 | QSet<QString> knownFiles; | ||||
54 | | ||||
55 | bool autoSearch = false; | ||||
56 | bool cacheResults = false; | ||||
57 | bool completed = false; | ||||
58 | | ||||
59 | static void appendToList(QueryListProperty* property, ContentQuery* value); | ||||
60 | static ContentQuery* listValueAt(QueryListProperty* property, int index); | ||||
61 | static void clearList(QueryListProperty* property); | ||||
62 | static int countList(QueryListProperty* property); | ||||
63 | | ||||
64 | static QStringList cachedFiles; | ||||
45 | }; | 65 | }; | ||
46 | 66 | | |||
67 | QStringList ContentList::Private::cachedFiles; | ||||
68 | | ||||
47 | ContentList::ContentList(QObject* parent) | 69 | ContentList::ContentList(QObject* parent) | ||
48 | : QAbstractListModel(parent) | 70 | : QAbstractListModel(parent) | ||
49 | , d(new Private) | 71 | , d(new Private) | ||
50 | { | 72 | { | ||
51 | #ifdef BALOO_FOUND | 73 | #ifdef BALOO_FOUND | ||
52 | BalooContentLister* baloo = new BalooContentLister(this); | 74 | BalooContentLister* baloo = new BalooContentLister(this); | ||
53 | if(baloo->balooEnabled()) | 75 | if(baloo->balooEnabled()) | ||
54 | { | 76 | { | ||
55 | d->actualContentList = baloo; | 77 | d->actualContentList = baloo; | ||
56 | qDebug() << "Baloo support enabled"; | | |||
57 | } | 78 | } | ||
58 | else | 79 | else | ||
59 | { | 80 | { | ||
60 | baloo->deleteLater(); | 81 | baloo->deleteLater(); | ||
61 | d->actualContentList = new FilesystemContentLister(this); | 82 | d->actualContentList = new FilesystemContentLister(this); | ||
62 | qDebug() << "Baloo is disabled for the system, use the filesystem scraper"; | | |||
63 | } | 83 | } | ||
64 | #else | 84 | #else | ||
65 | d->actualContentList = new FilesystemContentLister(this); | 85 | d->actualContentList = new FilesystemContentLister(this); | ||
66 | #endif | 86 | #endif | ||
67 | connect(d->actualContentList, SIGNAL(fileFound(QString,QVariantHash)), this, SLOT(fileFound(QString,QVariantHash))); | 87 | connect(d->actualContentList, &ContentListerBase::fileFound, this, &ContentList::fileFound); | ||
68 | connect(d->actualContentList, SIGNAL(searchCompleted()), this, SIGNAL(searchCompleted())); | 88 | connect(d->actualContentList, &ContentListerBase::searchCompleted, this, &ContentList::searchCompleted); | ||
89 | | ||||
90 | d->listProperty = QQmlListProperty<ContentQuery>{this, &d->queries, | ||||
91 | &ContentList::Private::appendToList, | ||||
92 | &ContentList::Private::countList, | ||||
93 | &ContentList::Private::listValueAt, | ||||
94 | &ContentList::Private::clearList | ||||
95 | }; | ||||
69 | } | 96 | } | ||
70 | 97 | | |||
71 | ContentList::~ContentList() | 98 | ContentList::~ContentList() | ||
72 | { | 99 | { | ||
73 | delete d; | 100 | delete d; | ||
74 | } | 101 | } | ||
75 | 102 | | |||
76 | QString ContentList::getMimetype(QString filePath) | 103 | QQmlListProperty<ContentQuery> ContentList::queries() | ||
77 | { | 104 | { | ||
78 | QMimeDatabase db; | 105 | return d->listProperty; | ||
79 | QMimeType mime = db.mimeTypeForFile(filePath); | | |||
80 | return mime.name(); | | |||
81 | } | 106 | } | ||
82 | 107 | | |||
83 | void ContentList::addLocation(QString path) | 108 | bool ContentList::autoSearch() const | ||
84 | { | 109 | { | ||
85 | d->actualContentList->addLocation(path); | 110 | return d->autoSearch; | ||
86 | } | 111 | } | ||
87 | 112 | | |||
88 | void ContentList::addMimetype(QString mimetype) | 113 | bool ContentList::cacheResults() const | ||
89 | { | 114 | { | ||
90 | d->actualContentList->addMimetype(mimetype); | 115 | return d->cacheResults; | ||
91 | } | 116 | } | ||
92 | 117 | | |||
93 | void ContentList::setSearchString(const QString& searchString) | 118 | QString ContentList::getMimetype(QString filePath) | ||
94 | { | 119 | { | ||
95 | d->actualContentList->setSearchString(searchString); | 120 | QMimeDatabase db; | ||
121 | QMimeType mime = db.mimeTypeForFile(filePath); | ||||
122 | return mime.name(); | ||||
96 | } | 123 | } | ||
97 | 124 | | |||
98 | void ContentList::startSearch() | 125 | void ContentList::startSearch() | ||
99 | { | 126 | { | ||
100 | QTimer::singleShot(1, d->actualContentList, SLOT(startSearch())); | 127 | QTimer::singleShot(1, [this]() { | ||
128 | d->actualContentList->startSearch(d->queries); | ||||
129 | }); | ||||
101 | } | 130 | } | ||
102 | 131 | | |||
103 | void ContentList::setKnownFiles(QStringList knownFiles) | 132 | void ContentList::fileFound(const QString& filePath, const QVariantMap& metaData) | ||
104 | { | 133 | { | ||
105 | d->actualContentList->setKnownFiles(knownFiles); | 134 | if(d->knownFiles.contains(filePath)) | ||
106 | } | 135 | return; | ||
136 | | ||||
137 | auto fileUrl = QUrl::fromLocalFile(filePath); | ||||
107 | 138 | | |||
108 | void ContentList::fileFound(const QString& filePath, const QVariantHash& metadata) | | |||
109 | { | | |||
110 | ContentEntry* entry = new ContentEntry(); | 139 | ContentEntry* entry = new ContentEntry(); | ||
111 | entry->filename = filePath; | 140 | entry->filename = fileUrl.fileName(); | ||
112 | entry->metadata = metadata; | 141 | entry->filePath = fileUrl; | ||
142 | entry->metadata = metaData; | ||||
leinir: This breaks the consumption end for Peruse, so even if files are found for me (with baloo… | |||||
Woops, you are right. Fixed the use in BookListModel. Are there any other places where ContentList is used directly? As far as I could tell, everything else uses BookListModel. ahiemstra: Woops, you are right. Fixed the use in BookListModel. Are there any other places where… | |||||
Thank you! Nope, i deliberately kept it centralised, so there's only the only place that connects to the ContentList :) leinir: Thank you! Nope, i deliberately kept it centralised, so there's only the only place that… | |||||
113 | 143 | | |||
114 | int newRow = d->entries.count(); | 144 | int newRow = d->entries.count(); | ||
115 | beginInsertRows(QModelIndex(), newRow, newRow); | 145 | beginInsertRows(QModelIndex(), newRow, newRow); | ||
116 | d->entries.append(entry); | 146 | d->entries.append(entry); | ||
117 | endInsertRows(); | 147 | endInsertRows(); | ||
148 | | ||||
149 | if(d->cacheResults) | ||||
150 | Private::cachedFiles.append(filePath); | ||||
151 | } | ||||
152 | | ||||
153 | void ContentList::setAutoSearch(bool autoSearch) | ||||
154 | { | ||||
155 | if(autoSearch == d->autoSearch) | ||||
156 | return; | ||||
157 | | ||||
158 | d->autoSearch = autoSearch; | ||||
159 | emit autoSearchChanged(); | ||||
160 | } | ||||
161 | | ||||
162 | void ContentList::setCacheResults(bool cacheResults) | ||||
163 | { | ||||
164 | if(cacheResults == d->cacheResults) | ||||
165 | return; | ||||
166 | | ||||
167 | d->cacheResults = cacheResults; | ||||
168 | | ||||
169 | if(d->cacheResults && d->completed && !Private::cachedFiles.isEmpty()) | ||||
170 | { | ||||
171 | setKnownFiles(Private::cachedFiles); | ||||
172 | } | ||||
173 | | ||||
174 | emit cacheResultsChanged(); | ||||
175 | } | ||||
176 | | ||||
177 | void ContentList::setKnownFiles(const QStringList& results) | ||||
178 | { | ||||
179 | beginResetModel(); | ||||
180 | d->entries.clear(); | ||||
181 | d->knownFiles.clear(); | ||||
182 | for(const auto& result : results) | ||||
183 | { | ||||
184 | auto entry = new ContentEntry{}; | ||||
185 | auto url = QUrl::fromLocalFile(result); | ||||
186 | | ||||
187 | entry->filename = url.fileName(); | ||||
188 | entry->filePath = url; | ||||
189 | entry->metadata = ContentListerBase::metaDataForFile(result); | ||||
190 | | ||||
191 | d->entries.append(entry); | ||||
192 | d->knownFiles.insert(result); | ||||
193 | } | ||||
194 | endResetModel(); | ||||
118 | } | 195 | } | ||
119 | 196 | | |||
120 | QHash<int, QByteArray> ContentList::roleNames() const | 197 | QHash<int, QByteArray> ContentList::roleNames() const | ||
121 | { | 198 | { | ||
122 | QHash<int, QByteArray> roles; | 199 | QHash<int, QByteArray> roles; | ||
123 | roles[FilenameRole] = "filename"; | 200 | roles[FilenameRole] = "filename"; | ||
201 | roles[FilePathRole] = "filePath"; | ||||
124 | roles[MetadataRole] = "metadata"; | 202 | roles[MetadataRole] = "metadata"; | ||
125 | return roles; | 203 | return roles; | ||
126 | } | 204 | } | ||
127 | 205 | | |||
128 | QVariant ContentList::data(const QModelIndex& index, int role) const | 206 | QVariant ContentList::data(const QModelIndex& index, int role) const | ||
129 | { | 207 | { | ||
130 | QVariant result; | 208 | QVariant result; | ||
131 | if(index.isValid() && index.row() > -1 && index.row() < d->entries.count()) | 209 | if(index.isValid() && index.row() > -1 && index.row() < d->entries.count()) | ||
132 | { | 210 | { | ||
133 | const ContentEntry* entry = d->entries[index.row()]; | 211 | const ContentEntry* entry = d->entries[index.row()]; | ||
134 | switch(role) | 212 | switch(role) | ||
135 | { | 213 | { | ||
136 | case FilenameRole: | 214 | case FilenameRole: | ||
137 | result.setValue(entry->filename); | 215 | result.setValue(entry->filename); | ||
This was deliberate, please put back the original logic. Not too keen on returning in the middle of functions unless it's unavoidable within reason. leinir: This was deliberate, please put back the original logic. Not too keen on returning in the… | |||||
Ah, I generally prefer early return instead. But fair enough, changed it back. ahiemstra: Ah, I generally prefer early return instead. But fair enough, changed it back. | |||||
138 | break; | 216 | break; | ||
217 | case FilePathRole: | ||||
218 | result.setValue(entry->filePath); | ||||
219 | break; | ||||
139 | case MetadataRole: | 220 | case MetadataRole: | ||
140 | result.setValue(entry->metadata); | 221 | result.setValue(entry->metadata); | ||
141 | break; | 222 | break; | ||
142 | default: | 223 | default: | ||
143 | result.setValue(QString("Unknown role")); | | |||
144 | break; | 224 | break; | ||
145 | } | 225 | } | ||
146 | } | 226 | } | ||
147 | return result; | 227 | return result; | ||
148 | } | 228 | } | ||
149 | 229 | | |||
150 | int ContentList::rowCount(const QModelIndex& parent) const | 230 | int ContentList::rowCount(const QModelIndex& parent) const | ||
151 | { | 231 | { | ||
152 | if(parent.isValid()) | 232 | if(parent.isValid()) | ||
153 | return 0; | 233 | return 0; | ||
154 | return d->entries.count(); | 234 | return d->entries.count(); | ||
155 | } | 235 | } | ||
236 | | ||||
237 | void ContentList::classBegin() | ||||
238 | { | ||||
239 | } | ||||
240 | | ||||
241 | void ContentList::componentComplete() | ||||
242 | { | ||||
243 | d->completed = true; | ||||
244 | | ||||
245 | if(d->cacheResults && !Private::cachedFiles.isEmpty()) | ||||
246 | setKnownFiles(Private::cachedFiles); | ||||
247 | | ||||
248 | if(d->autoSearch) | ||||
leinir: surely this would be be if(d->autosearch) { automatically start search } ;) | |||||
Hah, good point. I think I originally had some more code following this if, but now it no longer makes sense indeed. :) ahiemstra: Hah, good point. I think I originally had some more code following this if, but now it no… | |||||
249 | d->actualContentList->startSearch(d->queries); | ||||
250 | } | ||||
251 | | ||||
252 | bool ContentList::isComplete() const | ||||
253 | { | ||||
254 | return d->completed; | ||||
255 | } | ||||
256 | | ||||
257 | void ContentList::Private::appendToList(Private::QueryListProperty* property, ContentQuery* value) | ||||
258 | { | ||||
259 | auto list = static_cast<QList<ContentQuery*>*>(property->data); | ||||
260 | auto model = static_cast<ContentList*>(property->object); | ||||
261 | list->append(value); | ||||
262 | if(model->autoSearch() && model->isComplete()) | ||||
263 | model->startSearch(); | ||||
264 | } | ||||
265 | | ||||
266 | ContentQuery* ContentList::Private::listValueAt(Private::QueryListProperty* property, int index) | ||||
267 | { | ||||
268 | return static_cast<QList<ContentQuery*>*>(property->data)->at(index); | ||||
269 | } | ||||
270 | | ||||
271 | int ContentList::Private::countList(Private::QueryListProperty* property) | ||||
272 | { | ||||
273 | return static_cast<QList<ContentQuery*>*>(property->data)->size(); | ||||
274 | } | ||||
275 | | ||||
276 | void ContentList::Private::clearList(Private::QueryListProperty* property) | ||||
277 | { | ||||
278 | auto list = static_cast<QList<ContentQuery*>*>(property->data); | ||||
279 | auto model = static_cast<ContentList*>(property->object); | ||||
280 | model->beginResetModel(); | ||||
281 | list->clear(); | ||||
282 | model->endResetModel(); | ||||
283 | } |
This breaks the consumption end for Peruse, so even if files are found for me (with baloo turned off), it fails to add the files properly, as it doesn't read filePath. It likely is a bug in the original use anyway, but this still breaks it, so it needs changing there as well :)