Merge lp:~schwann/gallery-app/gallery-previewmanager-refactor into lp:gallery-app
- gallery-previewmanager-refactor
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Günter Schwann |
Approved revision: | 685 |
Merged at revision: | 686 |
Proposed branch: | lp:~schwann/gallery-app/gallery-previewmanager-refactor |
Merge into: | lp:gallery-app |
Diff against target: |
1186 lines (+433/-203) 21 files modified
src/database/database.cpp (+2/-2) src/gallery-manager.cpp (+39/-4) src/gallery-manager.h (+2/-0) src/media/media-monitor.cpp (+2/-2) src/media/media-source.cpp (+6/-6) src/media/media-source.h (+2/-2) src/media/preview-manager.cpp (+127/-81) src/media/preview-manager.h (+34/-17) src/qml/gallery-standard-image-provider.cpp (+35/-30) src/qml/gallery-standard-image-provider.h (+3/-3) src/qml/gallery-thumbnail-image-provider.cpp (+2/-3) src/util/resource.cpp (+19/-0) src/util/resource.h (+4/-0) tests/unittests/gallerystandardimageprovider/CMakeLists.txt (+6/-1) tests/unittests/gallerystandardimageprovider/media/media-collection.h (+28/-0) tests/unittests/gallerystandardimageprovider/preview-manager.cpp (+27/-23) tests/unittests/gallerystandardimageprovider/tst_gallerystandardimageprovidertest.cpp (+22/-10) tests/unittests/gallerythumbnailimageprovider/CMakeLists.txt (+5/-0) tests/unittests/gallerythumbnailimageprovider/media/media-collection.h (+28/-0) tests/unittests/gallerythumbnailimageprovider/preview-manager.cpp (+24/-18) tests/unittests/resource/tst_resource.cpp (+16/-1) |
To merge this branch: | bzr merge lp:~schwann/gallery-app/gallery-previewmanager-refactor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Olivier Tilloy | Approve | ||
Review via email: mp+167234@code.launchpad.net |
Commit message
Refactor PreviewManager to save thumbnails in $HOME/.
Description of the change
Refactor PreviewManager.
Fixes bug LP 1089655
Saves the thumbnails in $HOME/.
Thumbnail creation is now closer to the freedesktop standard
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:684
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Olivier Tilloy (osomon) wrote : | # |
411 + * \brief PreviewManager:
You mean "in a safe way", right?
Olivier Tilloy (osomon) wrote : | # |
474 + QString previewDir = m_thumbnailDir + levelName + "/";
In some places you’re using "/", and in other places QDir::separator(). It would be good to make this consistent (I’d go for the latter, for portability).
Olivier Tilloy (osomon) wrote : | # |
Apart from the two comments above, the changeset looks good to me.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:685
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
UNSTABLE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:685
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:685
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:685
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:685
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'src/database/database.cpp' |
2 | --- src/database/database.cpp 2013-06-03 15:18:06 +0000 |
3 | +++ src/database/database.cpp 2013-06-05 09:11:06 +0000 |
4 | @@ -44,7 +44,7 @@ |
5 | QDir dir; |
6 | bool createOk = dir.mkpath(m_databaseDirectory); |
7 | if (!createOk) |
8 | - qWarning() << "Unanble to create DB directory" << m_databaseDirectory; |
9 | + qWarning() << "Unable to create DB directory" << m_databaseDirectory; |
10 | } |
11 | |
12 | album_table_ = new AlbumTable(this, this); |
13 | @@ -156,7 +156,7 @@ |
14 | for (;; version++) { |
15 | // Check for the existence of an updated db file. |
16 | // Filename format is n.sql, where n is the schema version number. |
17 | - QFile file(get_sql_dir() + "/" + QString::number(version) + ".sql"); |
18 | + QFile file(get_sql_dir() + QDir::separator() + QString::number(version) + ".sql"); |
19 | if (!file.exists()) |
20 | return; |
21 | |
22 | |
23 | === modified file 'src/gallery-manager.cpp' |
24 | --- src/gallery-manager.cpp 2013-06-03 15:18:06 +0000 |
25 | +++ src/gallery-manager.cpp 2013-06-05 09:11:06 +0000 |
26 | @@ -71,6 +71,8 @@ |
27 | |
28 | void GalleryManager::post_init() |
29 | { |
30 | + Q_ASSERT(resource_); |
31 | + |
32 | if (!collections_initialised) |
33 | { |
34 | qDebug() << "Opening" << resource_->picturesDirectory() << "..."; |
35 | @@ -85,13 +87,11 @@ |
36 | media_collection_ = new MediaCollection(mediaDir); |
37 | album_collection_ = new AlbumCollection(); |
38 | event_collection_ = new EventCollection(); |
39 | - preview_manager_ = new PreviewManager(); |
40 | - |
41 | - gallery_standard_image_provider_->setPreviewManager(preview_manager_); |
42 | - gallery_thumbnail_image_provider_->setPreviewManager(preview_manager_); |
43 | |
44 | collections_initialised = true; |
45 | |
46 | + initPreviewManager(); |
47 | + |
48 | qDebug() << "Opened" << resource_->picturesDirectory(); |
49 | } |
50 | } |
51 | @@ -125,3 +125,38 @@ |
52 | delete preview_manager_; |
53 | preview_manager_ = NULL; |
54 | } |
55 | + |
56 | +/*! |
57 | + * \brief GalleryManager::initPreviewManager creates the PreviewManager, |
58 | + * assigns it to all needed objects and creates all signal slot connection. |
59 | + */ |
60 | +void GalleryManager::initPreviewManager() |
61 | +{ |
62 | + Q_ASSERT(resource_); |
63 | + Q_ASSERT(media_collection_); |
64 | + Q_ASSERT(gallery_standard_image_provider_); |
65 | + Q_ASSERT(gallery_thumbnail_image_provider_); |
66 | + |
67 | + if (preview_manager_) |
68 | + return; |
69 | + |
70 | + preview_manager_ = new PreviewManager(resource_->thumbnailDirectory(), |
71 | + media_collection_); |
72 | + |
73 | + gallery_standard_image_provider_->setPreviewManager(preview_manager_); |
74 | + gallery_thumbnail_image_provider_->setPreviewManager(preview_manager_); |
75 | + |
76 | + // Monitor MediaCollection for all new MediaSources |
77 | + QObject::connect(media_collection_, |
78 | + SIGNAL(contents_altered(const QSet<DataObject*>*,const QSet<DataObject*>*)), |
79 | + preview_manager_, |
80 | + SLOT(on_media_added_removed(const QSet<DataObject*>*,const QSet<DataObject*>*))); |
81 | + |
82 | + QObject::connect(media_collection_, |
83 | + SIGNAL(destroying(const QSet<DataObject*>*)), |
84 | + preview_manager_, |
85 | + SLOT(on_media_destroying(const QSet<DataObject*>*))); |
86 | + |
87 | + // Verify previews for all existing added MediaSources |
88 | + preview_manager_->onMediaAddedRemoved(&media_collection_->GetAsSet(), NULL); |
89 | +} |
90 | |
91 | === modified file 'src/gallery-manager.h' |
92 | --- src/gallery-manager.h 2013-06-03 15:18:06 +0000 |
93 | +++ src/gallery-manager.h 2013-06-05 09:11:06 +0000 |
94 | @@ -69,6 +69,8 @@ |
95 | GalleryManager(const GalleryManager&); |
96 | void operator=(const GalleryManager&); |
97 | |
98 | + void initPreviewManager(); |
99 | + |
100 | static GalleryManager* gallery_mgr_; |
101 | |
102 | bool collections_initialised; |
103 | |
104 | === modified file 'src/media/media-monitor.cpp' |
105 | --- src/media/media-monitor.cpp 2013-02-25 10:16:29 +0000 |
106 | +++ src/media/media-monitor.cpp 2013-06-05 09:11:06 +0000 |
107 | @@ -65,8 +65,8 @@ |
108 | |
109 | QStringList difference = subtract_manifest(new_manifest, manifest_); |
110 | for (int i = 0; i < difference.size(); i++) |
111 | - notify_media_item_added(target_directory_.absolutePath() + "/" + |
112 | - difference.at(i)); |
113 | + notify_media_item_added(target_directory_.absolutePath() + |
114 | + QDir::separator() + difference.at(i)); |
115 | |
116 | manifest_ = new_manifest; |
117 | } |
118 | |
119 | === modified file 'src/media/media-source.cpp' |
120 | --- src/media/media-source.cpp 2013-05-28 13:50:03 +0000 |
121 | +++ src/media/media-source.cpp 2013-06-05 09:11:06 +0000 |
122 | @@ -85,9 +85,9 @@ |
123 | * \brief MediaSource::preview_file |
124 | * \return |
125 | */ |
126 | -QFileInfo MediaSource::preview_file() const |
127 | +QString MediaSource::preview_file() const |
128 | { |
129 | - return GalleryManager::instance()->preview_manager()->PreviewFileFor(file_); |
130 | + return GalleryManager::instance()->preview_manager()->previewFileName(file_); |
131 | } |
132 | |
133 | /*! |
134 | @@ -96,7 +96,7 @@ |
135 | */ |
136 | QUrl MediaSource::preview_path() const |
137 | { |
138 | - return QUrl::fromLocalFile(preview_file().absoluteFilePath()); |
139 | + return QUrl::fromLocalFile(preview_file()); |
140 | } |
141 | |
142 | /*! |
143 | @@ -112,9 +112,9 @@ |
144 | * \brief MediaSource::thumbnail_file |
145 | * \return |
146 | */ |
147 | -QFileInfo MediaSource::thumbnail_file() const |
148 | +QString MediaSource::thumbnail_file() const |
149 | { |
150 | - return GalleryManager::instance()->preview_manager()->ThumbnailFileFor(file_); |
151 | + return GalleryManager::instance()->preview_manager()->thumbnailFileName(file_); |
152 | } |
153 | |
154 | /*! |
155 | @@ -123,7 +123,7 @@ |
156 | */ |
157 | QUrl MediaSource::thumbnail_path() const |
158 | { |
159 | - return QUrl::fromLocalFile(thumbnail_file().absoluteFilePath()); |
160 | + return QUrl::fromLocalFile(thumbnail_file()); |
161 | } |
162 | |
163 | /*! |
164 | |
165 | === modified file 'src/media/media-source.h' |
166 | --- src/media/media-source.h 2013-03-29 11:21:18 +0000 |
167 | +++ src/media/media-source.h 2013-06-05 09:11:06 +0000 |
168 | @@ -82,11 +82,11 @@ |
169 | QUrl path() const; |
170 | virtual QUrl gallery_path() const; |
171 | |
172 | - QFileInfo preview_file() const; |
173 | + QString preview_file() const; |
174 | QUrl preview_path() const; |
175 | virtual QUrl gallery_preview_path() const; |
176 | |
177 | - QFileInfo thumbnail_file() const; |
178 | + QString thumbnail_file() const; |
179 | QUrl thumbnail_path() const; |
180 | virtual QUrl gallery_thumbnail_path() const; |
181 | |
182 | |
183 | === modified file 'src/media/preview-manager.cpp' |
184 | --- src/media/preview-manager.cpp 2013-05-28 13:50:03 +0000 |
185 | +++ src/media/preview-manager.cpp 2013-06-05 09:11:06 +0000 |
186 | @@ -17,51 +17,51 @@ |
187 | * Jim Nelson <jim@yorba.org> |
188 | */ |
189 | |
190 | +#include <QCryptographicHash> |
191 | #include <QDir> |
192 | #include <QMutexLocker> |
193 | |
194 | #include "preview-manager.h" |
195 | #include "media-collection.h" |
196 | #include "photo/photo.h" |
197 | -#include "gallery-manager.h" |
198 | |
199 | -const int PreviewManager::PREVIEW_WIDTH_MAX = 360; |
200 | -const int PreviewManager::PREVIEW_HEIGHT_MAX = 360; |
201 | // FIXME adapt to different sizes. This is fixed size for the demo device |
202 | -const int PreviewManager::THUMBNAIL_SIZE = 216; |
203 | +const int PreviewManager::PREVIEW_SIZE = 360; // in pixel |
204 | +const int PreviewManager::THUMBNAIL_SIZE = 216; // in pixel |
205 | const int PreviewManager::PREVIEW_QUALITY = 70; |
206 | const char* PreviewManager::PREVIEW_FILE_FORMAT = "JPEG"; |
207 | -const char* PreviewManager::PREVIEW_FILE_EXT = "JPG"; |
208 | -const QString PreviewManager::PREVIEW_DIR = ".thumbs"; |
209 | +const char* PreviewManager::PREVIEW_FILE_EXT = ".jpg"; |
210 | +const QString PreviewManager::PREVIEW_DIR = "preview"; |
211 | +const QString PreviewManager::THUMBNAIL_DIR = "square"; |
212 | |
213 | -QMutex PreviewManager::createMutex_; |
214 | +QMutex PreviewManager::m_createMutex; |
215 | |
216 | /*! |
217 | * \brief PreviewManager::PreviewManager |
218 | */ |
219 | -PreviewManager::PreviewManager() |
220 | +PreviewManager::PreviewManager(const QString &thumbnailDirectory, |
221 | + MediaCollection *mediaCollection, QObject *parent) |
222 | + : QObject(parent), |
223 | + m_thumbnailDir(thumbnailDirectory), |
224 | + m_mediaCollection(mediaCollection) |
225 | { |
226 | - // Monitor MediaCollection for all new MediaSources |
227 | - QObject::connect(GalleryManager::instance()->media_collection(), |
228 | - SIGNAL(contents_altered(const QSet<DataObject*>*,const QSet<DataObject*>*)), |
229 | - this, |
230 | - SLOT(on_media_added_removed(const QSet<DataObject*>*,const QSet<DataObject*>*))); |
231 | - |
232 | - QObject::connect(GalleryManager::instance()->media_collection(), |
233 | - SIGNAL(destroying(const QSet<DataObject*>*)), |
234 | - this, |
235 | - SLOT(on_media_destroying(const QSet<DataObject*>*))); |
236 | - |
237 | - // Verify previews for all existing added MediaSources |
238 | - on_media_added_removed(&GalleryManager::instance()->media_collection()->GetAsSet(), NULL); |
239 | + Q_ASSERT(m_mediaCollection); |
240 | + |
241 | + if (m_thumbnailDir.right(1) != QDir::separator()) |
242 | + m_thumbnailDir += QDir::separator(); |
243 | + |
244 | + // create the thumbnail directory if not already present |
245 | + QDir dir; |
246 | + dir.mkpath(m_thumbnailDir + PREVIEW_DIR); |
247 | + dir.mkpath(m_thumbnailDir + THUMBNAIL_DIR); |
248 | } |
249 | |
250 | /*! |
251 | - * \brief PreviewManager::on_media_added_removed |
252 | + * \brief PreviewManager::onMediaAddedRemoved |
253 | * \param added |
254 | * \param removed |
255 | */ |
256 | -void PreviewManager::on_media_added_removed(const QSet<DataObject*>* added, |
257 | +void PreviewManager::onMediaAddedRemoved(const QSet<DataObject*>* added, |
258 | const QSet<DataObject*>* removed) |
259 | { |
260 | if (added != NULL) { |
261 | @@ -70,7 +70,7 @@ |
262 | MediaSource* source = qobject_cast<MediaSource*>(object); |
263 | |
264 | QObject::connect(source, SIGNAL(data_altered()), |
265 | - this, SLOT(on_media_data_altered()), Qt::UniqueConnection); |
266 | + this, SLOT(updatePreview()), Qt::UniqueConnection); |
267 | } |
268 | } |
269 | |
270 | @@ -79,76 +79,73 @@ |
271 | foreach (object, *removed) { |
272 | MediaSource* source = qobject_cast<MediaSource*>(object); |
273 | QObject::disconnect(source, SIGNAL(data_altered()), |
274 | - this, SLOT(on_media_data_altered())); |
275 | + this, SLOT(updatePreview())); |
276 | } |
277 | } |
278 | } |
279 | |
280 | /*! |
281 | - * \brief PreviewManager::on_media_destroying |
282 | + * \brief PreviewManager::onMediaDestroying |
283 | * \param destroying |
284 | */ |
285 | -void PreviewManager::on_media_destroying(const QSet<DataObject*>* destroying) |
286 | +void PreviewManager::onMediaDestroying(const QSet<DataObject*>* destroying) |
287 | { |
288 | if (destroying != NULL) { |
289 | DataObject* object; |
290 | foreach (object, *destroying) |
291 | - DestroyPreview(qobject_cast<MediaSource*>(object)); |
292 | + destroyPreviews(qobject_cast<MediaSource*>(object)); |
293 | } |
294 | } |
295 | |
296 | /*! |
297 | - * \brief PreviewManager::on_media_data_altered |
298 | + * \brief PreviewManager::updatePreview |
299 | */ |
300 | -void PreviewManager::on_media_data_altered() |
301 | +void PreviewManager::updatePreview() |
302 | { |
303 | QObject* object = QObject::sender(); |
304 | MediaSource* source = qobject_cast<MediaSource*>(object); |
305 | |
306 | - ensure_preview_for_media(source->file(), true); |
307 | -} |
308 | - |
309 | -/*! |
310 | - * \brief PreviewManager::PreviewFileFor |
311 | - * \param file |
312 | - * \return |
313 | - */ |
314 | -QFileInfo PreviewManager::PreviewFileFor(const QFileInfo& file) |
315 | -{ |
316 | - return QFileInfo(file.dir(), PREVIEW_DIR + "/" + file.completeBaseName() + "_th." + PREVIEW_FILE_EXT); |
317 | -} |
318 | - |
319 | -/*! |
320 | - * \brief PreviewManager::ThumbnailFileFor |
321 | - * \param file |
322 | - * \return |
323 | - */ |
324 | -QFileInfo PreviewManager::ThumbnailFileFor(const QFileInfo& file) |
325 | -{ |
326 | - return QFileInfo(file.dir(), PREVIEW_DIR + "/" + file.completeBaseName() + "_th_s." + PREVIEW_FILE_EXT); |
327 | -} |
328 | - |
329 | -/*! |
330 | - * \brief PreviewManager::ensure_preview_for_media |
331 | + ensurePreview(source->file(), true); |
332 | +} |
333 | + |
334 | +/*! |
335 | + * \brief PreviewManager::previewFileName |
336 | + * \param file |
337 | + * \return |
338 | + */ |
339 | +QString PreviewManager::previewFileName(const QFileInfo& file) const |
340 | +{ |
341 | + return thumbnailFileName(file.canonicalFilePath(), PREVIEW_DIR); |
342 | +} |
343 | + |
344 | +/*! |
345 | + * \brief PreviewManager::thumbnailFileName |
346 | + * \param file |
347 | + * \return |
348 | + */ |
349 | +QString PreviewManager::thumbnailFileName(const QFileInfo& file) const |
350 | +{ |
351 | + return thumbnailFileName(file.canonicalFilePath(), THUMBNAIL_DIR); |
352 | +} |
353 | + |
354 | +/*! |
355 | + * \brief PreviewManager::ensurePreview |
356 | * \param file |
357 | * \param regen |
358 | * \return |
359 | */ |
360 | -bool PreviewManager::ensure_preview_for_media(QFileInfo file, bool regen) |
361 | +bool PreviewManager::ensurePreview(QFileInfo file, bool regen) |
362 | { |
363 | - QMutexLocker locker(&createMutex_); |
364 | - |
365 | - // create the thumbnail directory if not already present |
366 | - file.dir().mkdir(PREVIEW_DIR); |
367 | + QMutexLocker locker(&m_createMutex); |
368 | |
369 | // If preview file exists, considered valid (unless we're regenerating it). |
370 | - QFileInfo preview = PreviewFileFor(file); |
371 | - QFileInfo thumbnail = ThumbnailFileFor(file); |
372 | + QString preview = previewFileName(file); |
373 | + QString thumbnail = thumbnailFileName(file); |
374 | |
375 | QImage thumbMaster; |
376 | - if (!preview.exists() || regen) { |
377 | - Photo* photo = GalleryManager::instance()->media_collection()->photoFromFileinfo(file); |
378 | - QSize previewSize(PREVIEW_WIDTH_MAX, PREVIEW_WIDTH_MAX); |
379 | + if (updateNeeded(file, QFileInfo(preview)) || regen) { |
380 | + Photo* photo = m_mediaCollection->photoFromFileinfo(file); |
381 | + QSize previewSize(PREVIEW_SIZE, PREVIEW_SIZE); |
382 | QImage fullsized(photo->Image(true, previewSize)); |
383 | if (fullsized.isNull()) { |
384 | qDebug() << "Unable to generate fullsized image for " << file.filePath() << "not generating preview"; |
385 | @@ -159,34 +156,34 @@ |
386 | // these values are replicated in the QML so that the preview will fill each |
387 | // grid cell, cropping down to the center of the image if necessary |
388 | QImage scaled = (fullsized.height() > fullsized.width()) |
389 | - ? fullsized.scaledToWidth(PREVIEW_WIDTH_MAX, Qt::SmoothTransformation) |
390 | - : fullsized.scaledToHeight(PREVIEW_HEIGHT_MAX, Qt::SmoothTransformation); |
391 | + ? fullsized.scaledToWidth(PREVIEW_SIZE, Qt::SmoothTransformation) |
392 | + : fullsized.scaledToHeight(PREVIEW_SIZE, Qt::SmoothTransformation); |
393 | |
394 | if (scaled.isNull()) { |
395 | qDebug() << "Unable to scale " << file.filePath() << "for preview"; |
396 | return false; |
397 | } |
398 | |
399 | - if (!scaled.save(preview.filePath(), PREVIEW_FILE_FORMAT, PREVIEW_QUALITY)) { |
400 | - qDebug("Unable to save preview %s", qPrintable(preview.filePath())); |
401 | + if (!saveThumbnail(scaled, preview)) { |
402 | + qDebug("Unable to save preview %s", qPrintable(preview)); |
403 | return false; |
404 | } |
405 | thumbMaster = scaled; |
406 | } |
407 | |
408 | - if (!thumbnail.exists() || regen) { |
409 | + if (updateNeeded(file, QFileInfo(thumbnail)) || regen) { |
410 | if (thumbMaster.isNull()) { |
411 | - thumbMaster.load(preview.filePath()); |
412 | + thumbMaster.load(preview); |
413 | if (thumbMaster.isNull()) { |
414 | qDebug("Unable load preview image for %s, not generating thumbnail", |
415 | - qPrintable(preview.filePath())); |
416 | + qPrintable(preview)); |
417 | return false; |
418 | } |
419 | } |
420 | |
421 | - QImage square = generate_Thumbnail(thumbMaster); |
422 | - if (!square.save(thumbnail.filePath(), PREVIEW_FILE_FORMAT, PREVIEW_QUALITY)) { |
423 | - qDebug("Unable to save preview %s", qPrintable(thumbnail.filePath())); |
424 | + QImage square = generateThumbnail(thumbMaster); |
425 | + if (!saveThumbnail(square, thumbnail)) { |
426 | + qDebug("Unable to save preview %s", qPrintable(thumbnail)); |
427 | return false; |
428 | } |
429 | } |
430 | @@ -195,25 +192,44 @@ |
431 | } |
432 | |
433 | /*! |
434 | - * \brief PreviewManager::DestroyPreview |
435 | + * \brief PreviewManager::saveThumbnail saves the thumbnail in a safe way |
436 | + * The image is written to a temporary file, and then moved (the move is atomic) |
437 | + * \param image thumbnail to save |
438 | + * \param fileName filename of the thumbnail |
439 | + * \return true, if saving the file was successful |
440 | + */ |
441 | +bool PreviewManager::saveThumbnail(const QImage &image, const QString &fileName) const |
442 | +{ |
443 | + QString temporaryName(fileName+".tmp"); |
444 | + bool ok; |
445 | + ok = image.save(temporaryName, PREVIEW_FILE_FORMAT, PREVIEW_QUALITY); |
446 | + if (!ok) |
447 | + return false; |
448 | + |
449 | + QFile thumbnail(temporaryName); |
450 | + return thumbnail.rename(fileName); |
451 | +} |
452 | + |
453 | +/*! |
454 | + * \brief PreviewManager::destroyPreviews |
455 | * \param media |
456 | */ |
457 | -void PreviewManager::DestroyPreview(MediaSource* media) |
458 | +void PreviewManager::destroyPreviews(MediaSource* media) |
459 | { |
460 | - QString filename = PreviewFileFor(media->file()).filePath(); |
461 | + QString filename = previewFileName(media->file()); |
462 | if (!QFile::remove(filename)) |
463 | qDebug("Unable to remove preview %s", qPrintable(filename)); |
464 | - filename = ThumbnailFileFor(media->file()).filePath(); |
465 | + filename = thumbnailFileName(media->file()); |
466 | if (!QFile::remove(filename)) |
467 | qDebug("Unable to remove thumbnail %s", qPrintable(filename)); |
468 | } |
469 | |
470 | /*! |
471 | - * \brief PreviewManager::generate_Thumbnail |
472 | + * \brief PreviewManager::generateThumbnail |
473 | * \param master |
474 | * \return |
475 | */ |
476 | -QImage PreviewManager::generate_Thumbnail(const QImage &master) const |
477 | +QImage PreviewManager::generateThumbnail(const QImage &master) const |
478 | { |
479 | int xOffset = 0; |
480 | int yOffset = 0; |
481 | @@ -230,3 +246,33 @@ |
482 | QImage thumbnail = square.scaled(THUMBNAIL_SIZE, THUMBNAIL_SIZE); |
483 | return thumbnail; |
484 | } |
485 | + |
486 | +/*! |
487 | + * \brief PreviewManager::thumbnailFileName generates the file name for a given |
488 | + * file and it's level (size/type) |
489 | + * \param fileName full filename URI (file:///directory/file.name.png) |
490 | + * \param levelName correclates to the sub directory inside of the thumbnail directory |
491 | + * \return full filePath of the thumbnail |
492 | + */ |
493 | +QString PreviewManager::thumbnailFileName(const QString &fileName, |
494 | + const QString &levelName) const |
495 | +{ |
496 | + QCryptographicHash md5(QCryptographicHash::Md5); |
497 | + md5.addData(QUrl::fromLocalFile(fileName).toEncoded()); |
498 | + QString previewDir = m_thumbnailDir + levelName + QDir::separator(); |
499 | + return QString(previewDir + md5.result().toHex() + PREVIEW_FILE_EXT); |
500 | +} |
501 | + |
502 | +/*! |
503 | + * \brief PreviewManager::updateNeeded checks if the thumbnail needs to be (re-)created |
504 | + * \param mediaFile the original photo/video |
505 | + * \param previewFile the preview file |
506 | + * \return true if the thumbnail needs to be created |
507 | + */ |
508 | +bool PreviewManager::updateNeeded(const QFileInfo &mediaFile, const QFileInfo &previewFile) const |
509 | +{ |
510 | + if (!previewFile.exists()) |
511 | + return true; |
512 | + |
513 | + return mediaFile.lastModified() > previewFile.lastModified(); |
514 | +} |
515 | |
516 | === modified file 'src/media/preview-manager.h' |
517 | --- src/media/preview-manager.h 2013-05-28 13:50:03 +0000 |
518 | +++ src/media/preview-manager.h 2013-06-05 09:11:06 +0000 |
519 | @@ -28,43 +28,60 @@ |
520 | |
521 | class QImage; |
522 | class DataObject; |
523 | +class MediaCollection; |
524 | class MediaSource; |
525 | |
526 | /*! |
527 | - * \brief The PreviewManager class |
528 | + * \brief The PreviewManager class creates and removes thumbnails |
529 | + * |
530 | + * The thumbnail storage and creation is inspired by |
531 | + * http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html |
532 | + * But it uses jpeg (for performance), |
533 | + * uses different sizes, |
534 | + * not the standard sub directoy name (because of the sizes), |
535 | + * does not save any meta information in the thumbnails, |
536 | + * does not use the fail directory |
537 | */ |
538 | class PreviewManager : public QObject |
539 | { |
540 | Q_OBJECT |
541 | |
542 | public: |
543 | - static const int PREVIEW_WIDTH_MAX; |
544 | - static const int PREVIEW_HEIGHT_MAX; |
545 | + static const int PREVIEW_SIZE; |
546 | static const int THUMBNAIL_SIZE; |
547 | static const int PREVIEW_QUALITY; |
548 | static const char* PREVIEW_FILE_FORMAT; |
549 | static const char* PREVIEW_FILE_EXT; |
550 | |
551 | static const QString PREVIEW_DIR; |
552 | - |
553 | - PreviewManager(); |
554 | - |
555 | - static QFileInfo PreviewFileFor(const QFileInfo& file); |
556 | - static QFileInfo ThumbnailFileFor(const QFileInfo& file); |
557 | - |
558 | - bool ensure_preview_for_media(QFileInfo file, bool regen = false); |
559 | + static const QString THUMBNAIL_DIR; |
560 | + |
561 | + PreviewManager(const QString& thumbnailDirectory, MediaCollection *mediaCollection, |
562 | + QObject* parent = 0); |
563 | + |
564 | + QString previewFileName(const QFileInfo& file) const; |
565 | + QString thumbnailFileName(const QFileInfo& file) const; |
566 | + |
567 | + bool ensurePreview(QFileInfo file, bool regen = false); |
568 | + |
569 | +public slots: |
570 | + void onMediaAddedRemoved(const QSet<DataObject*>* added, |
571 | + const QSet<DataObject*>* removed); |
572 | + void onMediaDestroying(const QSet<DataObject*>* destroying); |
573 | |
574 | private slots: |
575 | - void on_media_added_removed(const QSet<DataObject*>* added, |
576 | - const QSet<DataObject*>* removed); |
577 | - void on_media_destroying(const QSet<DataObject*>* destroying); |
578 | - void on_media_data_altered(); |
579 | + void updatePreview(); |
580 | |
581 | private: |
582 | - void DestroyPreview(MediaSource* media); |
583 | - QImage generate_Thumbnail(const QImage& master) const; |
584 | + bool saveThumbnail(const QImage& image, const QString& fileName) const; |
585 | + void destroyPreviews(MediaSource* media); |
586 | + QImage generateThumbnail(const QImage& master) const; |
587 | + QString thumbnailFileName(const QString& fileName, const QString& levelName) const; |
588 | + bool updateNeeded(const QFileInfo& mediaFile, const QFileInfo& previewFile) const; |
589 | |
590 | - static QMutex createMutex_; |
591 | + static QMutex m_createMutex; |
592 | + QString m_thumbnailDir; |
593 | + MediaCollection *m_mediaCollection; |
594 | }; |
595 | |
596 | #endif // GALLERY_PREVIEW_MANAGER_H_ |
597 | |
598 | === modified file 'src/qml/gallery-standard-image-provider.cpp' |
599 | --- src/qml/gallery-standard-image-provider.cpp 2013-05-28 13:50:03 +0000 |
600 | +++ src/qml/gallery-standard-image-provider.cpp 2013-06-05 09:11:06 +0000 |
601 | @@ -39,7 +39,7 @@ |
602 | |
603 | // fully load previews into memory when requested |
604 | const int SCALED_LOAD_FLOOR_DIM_PIXELS = |
605 | - qMax(PreviewManager::PREVIEW_WIDTH_MAX, PreviewManager::PREVIEW_HEIGHT_MAX); |
606 | + qMax(PreviewManager::PREVIEW_SIZE, PreviewManager::PREVIEW_SIZE); |
607 | |
608 | /*! |
609 | * \brief GalleryStandardImageProvider::GalleryStandardImageProvider |
610 | @@ -100,7 +100,7 @@ |
611 | |
612 | QUrl url(id); |
613 | QFileInfo photoFile(url.path()); |
614 | - m_previewManager->ensure_preview_for_media(photoFile); |
615 | + m_previewManager->ensurePreview(photoFile); |
616 | |
617 | CachedImage* cachedImage = claim_cached_image_entry(id, loggingStr); |
618 | Q_ASSERT(cachedImage != NULL); |
619 | @@ -178,7 +178,7 @@ |
620 | // remove CachedImage before prepending to FIFO |
621 | fifo_.removeOne(id); |
622 | } else { |
623 | - cachedImage = new CachedImage(id); |
624 | + cachedImage = new CachedImage(id, idToFile(id)); |
625 | cache_.insert(id, cachedImage); |
626 | LOG_IMAGE_STATUS("new-cache-entry "); |
627 | } |
628 | @@ -392,11 +392,40 @@ |
629 | } |
630 | |
631 | /*! |
632 | + * \brief GalleryStandardImageProvider::idToFile |
633 | + * \param id |
634 | + * \return |
635 | + */ |
636 | +QString GalleryStandardImageProvider::idToFile(const QString& id) const |
637 | +{ |
638 | + if (!m_previewManager) { |
639 | + qWarning() << Q_FUNC_INFO << "no PreviewManager set"; |
640 | + return QString(); |
641 | + } |
642 | + |
643 | + QUrl url = QUrl(id); |
644 | + QString fileName = url.path(); |
645 | + |
646 | + //Get our item value from our query by it's key. |
647 | + QUrlQuery url_query(url); |
648 | + url_query.hasQueryItem(GalleryStandardImageProvider::SIZE_KEY); |
649 | + QString value = url_query.queryItemValue(GalleryStandardImageProvider::SIZE_KEY); |
650 | + |
651 | + if (value == "1") { |
652 | + fileName = m_previewManager->previewFileName(fileName); |
653 | + } |
654 | + |
655 | + return fileName; |
656 | +} |
657 | + |
658 | +/*! |
659 | * \brief GalleryStandardImageProvider::CachedImage::CachedImage |
660 | - * \param id |
661 | + * \param id the full URI of the image |
662 | + * \param fileName the filename for the URI (can be the file itself or the preview) |
663 | */ |
664 | -GalleryStandardImageProvider::CachedImage::CachedImage(const QString& id) |
665 | - : id_(id), uri_(id), file_(idToFile(id)), hasOrientation_(false), |
666 | +GalleryStandardImageProvider::CachedImage::CachedImage(const QString& id, |
667 | + const QString& filename) |
668 | + : id_(id), uri_(id), file_(filename), hasOrientation_(false), |
669 | orientation_(TOP_LEFT_ORIGIN), inUseCount_(0), byteCount_(0) |
670 | { |
671 | QUrlQuery query(uri_); |
672 | @@ -414,30 +443,6 @@ |
673 | } |
674 | |
675 | /*! |
676 | - * \brief GalleryStandardImageProvider::CachedImage::idToFile |
677 | - * \param id |
678 | - * \return |
679 | - */ |
680 | -QString GalleryStandardImageProvider::CachedImage::idToFile(const QString& id) |
681 | -{ |
682 | - QUrl url = QUrl(id); |
683 | - QString fileName = url.path(); |
684 | - |
685 | - //Get our item value from our query by it's key. |
686 | - QUrlQuery url_query(url); |
687 | - url_query.hasQueryItem(GalleryStandardImageProvider::SIZE_KEY); |
688 | - QString value = url_query.queryItemValue(GalleryStandardImageProvider::SIZE_KEY); |
689 | - |
690 | - if (value == "1") |
691 | - { |
692 | - QFileInfo thumbnailFile = PreviewManager::PreviewFileFor(fileName); |
693 | - fileName = thumbnailFile.absoluteFilePath(); |
694 | - } |
695 | - |
696 | - return fileName; |
697 | -} |
698 | - |
699 | -/*! |
700 | * \brief GalleryStandardImageProvider::CachedImage::storeImage |
701 | * Importand: the following should only be called when imageMutex_ is locked |
702 | * \param image |
703 | |
704 | === modified file 'src/qml/gallery-standard-image-provider.h' |
705 | --- src/qml/gallery-standard-image-provider.h 2013-05-28 13:50:03 +0000 |
706 | +++ src/qml/gallery-standard-image-provider.h 2013-06-05 09:11:06 +0000 |
707 | @@ -95,9 +95,7 @@ |
708 | int inUseCount_; |
709 | uint byteCount_; |
710 | |
711 | - CachedImage(const QString& id); |
712 | - |
713 | - static QString idToFile(const QString& id); |
714 | + CachedImage(const QString& id, const QString& filename); |
715 | |
716 | void storeImage(const QImage& image, const QSize& fullSize, Orientation orientation); |
717 | bool isFullSized() const; |
718 | @@ -123,6 +121,8 @@ |
719 | void release_cached_image_entry(CachedImage* cachedImage, uint bytesLoaded, |
720 | long* currentCachedBytes, int* currentCacheEntries); |
721 | |
722 | + QString idToFile(const QString& id) const; |
723 | + |
724 | //Allow our test access to private variables. |
725 | friend class tst_GalleryStandardImageProvider; |
726 | }; |
727 | |
728 | === modified file 'src/qml/gallery-thumbnail-image-provider.cpp' |
729 | --- src/qml/gallery-thumbnail-image-provider.cpp 2013-05-28 13:50:03 +0000 |
730 | +++ src/qml/gallery-thumbnail-image-provider.cpp 2013-06-05 09:11:06 +0000 |
731 | @@ -69,10 +69,9 @@ |
732 | |
733 | QUrl url(id); |
734 | QFileInfo photoFile(url.path()); |
735 | - m_previewManager->ensure_preview_for_media(photoFile); |
736 | + m_previewManager->ensurePreview(photoFile); |
737 | |
738 | - QFileInfo thumbnailFile = m_previewManager->ThumbnailFileFor(photoFile); |
739 | - QString fileName = thumbnailFile.absoluteFilePath(); |
740 | + QString fileName = m_previewManager->thumbnailFileName(photoFile); |
741 | |
742 | QImage thumbnail; |
743 | thumbnail.load(fileName); |
744 | |
745 | === modified file 'src/util/resource.cpp' |
746 | --- src/util/resource.cpp 2013-06-03 15:18:06 +0000 |
747 | +++ src/util/resource.cpp 2013-06-05 09:11:06 +0000 |
748 | @@ -25,6 +25,7 @@ |
749 | #include <QStandardPaths> |
750 | |
751 | const QLatin1String Resource::DATABASE_DIR = QLatin1String("database"); |
752 | +const QLatin1String Resource::THUMBNAIL_DIR = QLatin1String("thumbnails"); |
753 | |
754 | /*! |
755 | * \brief Resource::Resource |
756 | @@ -35,6 +36,7 @@ |
757 | Resource::Resource(const QString &pictureDir, QQuickView *view) |
758 | : m_pictureDirectory(pictureDir), |
759 | m_databaseDirectory(""), |
760 | + m_thumbnailDirectory(""), |
761 | m_view(view), |
762 | m_maxTextureSize(0) |
763 | { |
764 | @@ -83,6 +85,23 @@ |
765 | } |
766 | |
767 | /*! |
768 | + * \brief Resource::thumbnailDirectory returns the base directory of the thumbnails |
769 | + * \return |
770 | + */ |
771 | +const QString &Resource::thumbnailDirectory() const |
772 | +{ |
773 | + if (m_thumbnailDirectory.isEmpty()) { |
774 | + if (m_pictureDirectory == QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)) { |
775 | + m_thumbnailDirectory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + |
776 | + QDir::separator() + THUMBNAIL_DIR; |
777 | + } else { |
778 | + m_thumbnailDirectory = m_pictureDirectory + QDir::separator() + "." + THUMBNAIL_DIR; |
779 | + } |
780 | + } |
781 | + return m_thumbnailDirectory; |
782 | +} |
783 | + |
784 | +/*! |
785 | * \brief maxTextureSize |
786 | * \return max texture size provided by OpenGL |
787 | */ |
788 | |
789 | === modified file 'src/util/resource.h' |
790 | --- src/util/resource.h 2013-06-03 15:18:06 +0000 |
791 | +++ src/util/resource.h 2013-06-05 09:11:06 +0000 |
792 | @@ -37,6 +37,7 @@ |
793 | |
794 | const QString &picturesDirectory() const; |
795 | const QString &databaseDirectory() const; |
796 | + const QString &thumbnailDirectory() const; |
797 | |
798 | int maxTextureSize() const; |
799 | void setView(QQuickView* view); |
800 | @@ -44,11 +45,14 @@ |
801 | private: |
802 | QString m_pictureDirectory; |
803 | mutable QString m_databaseDirectory; |
804 | + mutable QString m_thumbnailDirectory; |
805 | QQuickView* m_view; |
806 | mutable int m_maxTextureSize; |
807 | |
808 | // Path to database, relative to application data path. |
809 | static const QLatin1String DATABASE_DIR; |
810 | + // Path to database, relative to application cache path. |
811 | + static const QLatin1String THUMBNAIL_DIR; |
812 | |
813 | friend class tst_Resource; |
814 | }; |
815 | |
816 | === added directory 'tests/autopilot/gallery_app/data/.thumbnails' |
817 | === added directory 'tests/autopilot/gallery_app/data/.thumbnails/preview' |
818 | === added file 'tests/autopilot/gallery_app/data/.thumbnails/preview/b117f754f46e254a434a73c9f4501853.jpg' |
819 | Binary files tests/autopilot/gallery_app/data/.thumbnails/preview/b117f754f46e254a434a73c9f4501853.jpg 1970-01-01 00:00:00 +0000 and tests/autopilot/gallery_app/data/.thumbnails/preview/b117f754f46e254a434a73c9f4501853.jpg 2013-06-05 09:11:06 +0000 differ |
820 | === added file 'tests/autopilot/gallery_app/data/.thumbnails/preview/e3034181bd65a2f1b1e8fa3ec1961bed.jpg' |
821 | Binary files tests/autopilot/gallery_app/data/.thumbnails/preview/e3034181bd65a2f1b1e8fa3ec1961bed.jpg 1970-01-01 00:00:00 +0000 and tests/autopilot/gallery_app/data/.thumbnails/preview/e3034181bd65a2f1b1e8fa3ec1961bed.jpg 2013-06-05 09:11:06 +0000 differ |
822 | === added directory 'tests/autopilot/gallery_app/data/.thumbnails/square' |
823 | === added file 'tests/autopilot/gallery_app/data/.thumbnails/square/b117f754f46e254a434a73c9f4501853.jpg' |
824 | Binary files tests/autopilot/gallery_app/data/.thumbnails/square/b117f754f46e254a434a73c9f4501853.jpg 1970-01-01 00:00:00 +0000 and tests/autopilot/gallery_app/data/.thumbnails/square/b117f754f46e254a434a73c9f4501853.jpg 2013-06-05 09:11:06 +0000 differ |
825 | === added file 'tests/autopilot/gallery_app/data/.thumbnails/square/e3034181bd65a2f1b1e8fa3ec1961bed.jpg' |
826 | Binary files tests/autopilot/gallery_app/data/.thumbnails/square/e3034181bd65a2f1b1e8fa3ec1961bed.jpg 1970-01-01 00:00:00 +0000 and tests/autopilot/gallery_app/data/.thumbnails/square/e3034181bd65a2f1b1e8fa3ec1961bed.jpg 2013-06-05 09:11:06 +0000 differ |
827 | === removed directory 'tests/autopilot/gallery_app/data/.thumbs' |
828 | === removed file 'tests/autopilot/gallery_app/data/.thumbs/sample01_th.JPG' |
829 | Binary files tests/autopilot/gallery_app/data/.thumbs/sample01_th.JPG 2013-03-28 10:35:15 +0000 and tests/autopilot/gallery_app/data/.thumbs/sample01_th.JPG 1970-01-01 00:00:00 +0000 differ |
830 | === removed file 'tests/autopilot/gallery_app/data/.thumbs/sample01_th_s.JPG' |
831 | Binary files tests/autopilot/gallery_app/data/.thumbs/sample01_th_s.JPG 2013-03-28 10:35:15 +0000 and tests/autopilot/gallery_app/data/.thumbs/sample01_th_s.JPG 1970-01-01 00:00:00 +0000 differ |
832 | === removed file 'tests/autopilot/gallery_app/data/.thumbs/sample02_th.JPG' |
833 | Binary files tests/autopilot/gallery_app/data/.thumbs/sample02_th.JPG 2013-03-28 10:35:15 +0000 and tests/autopilot/gallery_app/data/.thumbs/sample02_th.JPG 1970-01-01 00:00:00 +0000 differ |
834 | === removed file 'tests/autopilot/gallery_app/data/.thumbs/sample02_th_s.JPG' |
835 | Binary files tests/autopilot/gallery_app/data/.thumbs/sample02_th_s.JPG 2013-03-28 10:35:15 +0000 and tests/autopilot/gallery_app/data/.thumbs/sample02_th_s.JPG 1970-01-01 00:00:00 +0000 differ |
836 | === modified file 'tests/unittests/gallerystandardimageprovider/CMakeLists.txt' |
837 | --- tests/unittests/gallerystandardimageprovider/CMakeLists.txt 2013-05-28 13:50:03 +0000 |
838 | +++ tests/unittests/gallerystandardimageprovider/CMakeLists.txt 2013-06-05 09:11:06 +0000 |
839 | @@ -10,11 +10,16 @@ |
840 | ${GSTLIB_INCLUDE_DIRS} |
841 | ) |
842 | |
843 | +QT_WRAP_CPP(gallerystandardimageprovider GALLERYSTANDARDIMAGEPROVIDIER_MOCS |
844 | + ${gallery_src_SOURCE_DIR}/media/preview-manager.h |
845 | + ) |
846 | + |
847 | add_executable(gallerystandardimageprovider |
848 | tst_gallerystandardimageprovidertest.cpp |
849 | preview-manager.cpp |
850 | photometa-data.cpp |
851 | ${gallery_src_SOURCE_DIR}/qml/gallery-standard-image-provider.cpp |
852 | + ${GALLERYSTANDARDIMAGEPROVIDIER_MOCS} |
853 | ) |
854 | |
855 | qt5_use_modules(gallerystandardimageprovider Quick Test) |
856 | @@ -25,6 +30,6 @@ |
857 | TIMEOUT ${CTEST_TESTING_TIMEOUT} |
858 | ENVIRONMENT "QT_QPA_PLATFORM=minimal" |
859 | ) |
860 | -target_link_libraries(gallerystandardimageprovider |
861 | +target_link_libraries(gallerystandardimageprovider |
862 | ${GSTLIB_LDFLAGS} |
863 | ) |
864 | |
865 | === added directory 'tests/unittests/gallerystandardimageprovider/media' |
866 | === added file 'tests/unittests/gallerystandardimageprovider/media/media-collection.h' |
867 | --- tests/unittests/gallerystandardimageprovider/media/media-collection.h 1970-01-01 00:00:00 +0000 |
868 | +++ tests/unittests/gallerystandardimageprovider/media/media-collection.h 2013-06-05 09:11:06 +0000 |
869 | @@ -0,0 +1,28 @@ |
870 | +/* |
871 | + * Copyright (C) 2013 Canonical Ltd |
872 | + * |
873 | + * This program is free software: you can redistribute it and/or modify |
874 | + * it under the terms of the GNU General Public License version 3 as |
875 | + * published by the Free Software Foundation. |
876 | + * |
877 | + * This program is distributed in the hope that it will be useful, |
878 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
879 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
880 | + * GNU General Public License for more details. |
881 | + * |
882 | + * You should have received a copy of the GNU General Public License |
883 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
884 | + */ |
885 | + |
886 | +#ifndef GALLERY_MEDIA_COLLECTION_H_ |
887 | +#define GALLERY_MEDIA_COLLECTION_H_ |
888 | + |
889 | +#include <QDir> |
890 | + |
891 | +class MediaCollection |
892 | +{ |
893 | +public: |
894 | + MediaCollection(const QDir& directory) {Q_UNUSED(directory);} |
895 | +}; |
896 | + |
897 | +#endif |
898 | |
899 | === modified file 'tests/unittests/gallerystandardimageprovider/preview-manager.cpp' |
900 | --- tests/unittests/gallerystandardimageprovider/preview-manager.cpp 2013-05-28 13:50:03 +0000 |
901 | +++ tests/unittests/gallerystandardimageprovider/preview-manager.cpp 2013-06-05 09:11:06 +0000 |
902 | @@ -21,14 +21,20 @@ |
903 | #include <QDir> |
904 | |
905 | #include "media/preview-manager.h" |
906 | - |
907 | -const int PreviewManager::PREVIEW_WIDTH_MAX = 360; |
908 | -const int PreviewManager::PREVIEW_HEIGHT_MAX = 360; |
909 | - |
910 | +#include "media/media-collection.h" |
911 | + |
912 | +const int PreviewManager::PREVIEW_SIZE = 360; |
913 | const QString PreviewManager::PREVIEW_DIR = ".thumbs"; |
914 | const char* PreviewManager::PREVIEW_FILE_EXT = "JPG"; |
915 | |
916 | -bool PreviewManager::ensure_preview_for_media(QFileInfo file, bool regen) |
917 | +PreviewManager::PreviewManager(const QString &thumbnailDirectory, |
918 | + MediaCollection *mediaCollection, QObject *parent) |
919 | +{ |
920 | + Q_UNUSED(thumbnailDirectory); |
921 | + Q_UNUSED(mediaCollection) |
922 | +} |
923 | + |
924 | +bool PreviewManager::ensurePreview(QFileInfo file, bool regen) |
925 | { |
926 | file = QFileInfo(); |
927 | regen = false; |
928 | @@ -36,22 +42,20 @@ |
929 | return regen; |
930 | } |
931 | |
932 | -void PreviewManager::on_media_added_removed(const QSet<DataObject *> *, const QSet<DataObject *> *) |
933 | -{ |
934 | - |
935 | -} |
936 | - |
937 | -void PreviewManager::on_media_destroying(const QSet<DataObject *> *) |
938 | -{ |
939 | - |
940 | -} |
941 | - |
942 | -void PreviewManager::on_media_data_altered() |
943 | -{ |
944 | - |
945 | -} |
946 | - |
947 | -QFileInfo PreviewManager::PreviewFileFor(const QFileInfo &file) |
948 | -{ |
949 | - return QFileInfo(file.dir(), PREVIEW_DIR + "/" + file.completeBaseName() + "_th." + PREVIEW_FILE_EXT); |
950 | +void PreviewManager::onMediaAddedRemoved(const QSet<DataObject *> *, const QSet<DataObject *> *) |
951 | +{ |
952 | +} |
953 | + |
954 | +void PreviewManager::onMediaDestroying(const QSet<DataObject *> *) |
955 | +{ |
956 | +} |
957 | + |
958 | +void PreviewManager::updatePreview() |
959 | +{ |
960 | +} |
961 | + |
962 | +QString PreviewManager::previewFileName(const QFileInfo &file) const |
963 | +{ |
964 | + return QString(file.absolutePath() + QDir::separator() + PREVIEW_DIR + |
965 | + QDir::separator() + file.completeBaseName() + "_th." + PREVIEW_FILE_EXT); |
966 | } |
967 | |
968 | === modified file 'tests/unittests/gallerystandardimageprovider/tst_gallerystandardimageprovidertest.cpp' |
969 | --- tests/unittests/gallerystandardimageprovider/tst_gallerystandardimageprovidertest.cpp 2013-05-28 13:50:03 +0000 |
970 | +++ tests/unittests/gallerystandardimageprovider/tst_gallerystandardimageprovidertest.cpp 2013-06-05 09:11:06 +0000 |
971 | @@ -19,11 +19,14 @@ |
972 | */ |
973 | |
974 | #include <QtTest/QtTest> |
975 | +#include <QDir> |
976 | #include <QFileInfo> |
977 | #include <QUrl> |
978 | |
979 | #include "qml/gallery-standard-image-provider.h" |
980 | #include "media/preview-manager.h" |
981 | +#include "media/media-collection.h" |
982 | +#include "gallery-manager.h" |
983 | |
984 | class tst_GalleryStandardImageProvider : public QObject |
985 | { |
986 | @@ -33,8 +36,8 @@ |
987 | |
988 | private slots: |
989 | void ToURL(); |
990 | - void Fullsize(); |
991 | - void Thumbnail(); |
992 | + void idToFile_data(); |
993 | + void idToFile(); |
994 | |
995 | private: |
996 | GalleryStandardImageProvider gallery_standard_image_provider; |
997 | @@ -54,18 +57,27 @@ |
998 | QCOMPARE(url, expect); |
999 | } |
1000 | |
1001 | -void tst_GalleryStandardImageProvider::Fullsize() |
1002 | +void tst_GalleryStandardImageProvider::idToFile_data() |
1003 | { |
1004 | - QString id = "/home/user/Pictures/logo.jpg?size_level=0&orientation=1"; |
1005 | - QString fileName = "/home/user/Pictures/logo.jpg"; |
1006 | - QCOMPARE(GalleryStandardImageProvider::CachedImage::idToFile(id), fileName); |
1007 | + QTest::addColumn<QString>("id"); |
1008 | + QTest::addColumn<QString>("fileName"); |
1009 | + |
1010 | + QTest::newRow("FullSize") << "/home/user/Pictures/logo.jpg?size_level=0&orientation=1" << |
1011 | + "/home/user/Pictures/logo.jpg"; |
1012 | + QTest::newRow("Thumbnail") << "/home/user/Pictures/logo.jpg?size_level=1&orientation=1" << |
1013 | + "/home/user/Pictures/.thumbs/logo_th.JPG"; |
1014 | } |
1015 | |
1016 | -void tst_GalleryStandardImageProvider::Thumbnail() |
1017 | +void tst_GalleryStandardImageProvider::idToFile() |
1018 | { |
1019 | - QString id = "/home/user/Pictures/logo.jpg?size_level=1&orientation=1"; |
1020 | - QString fileName = "/home/user/Pictures/.thumbs/logo_th.JPG"; |
1021 | - QCOMPARE(GalleryStandardImageProvider::CachedImage::idToFile(id), fileName); |
1022 | + QFETCH(QString, id); |
1023 | + QFETCH(QString, fileName); |
1024 | + |
1025 | + MediaCollection mediaCollection(QDir("/home/user/Pictures")); |
1026 | + PreviewManager previewManager("/home/user/thumbnails", &mediaCollection); |
1027 | + GalleryStandardImageProvider provider; |
1028 | + provider.setPreviewManager(&previewManager); |
1029 | + QCOMPARE(provider.idToFile(id), fileName); |
1030 | } |
1031 | |
1032 | QTEST_MAIN(tst_GalleryStandardImageProvider); |
1033 | |
1034 | === modified file 'tests/unittests/gallerythumbnailimageprovider/CMakeLists.txt' |
1035 | --- tests/unittests/gallerythumbnailimageprovider/CMakeLists.txt 2013-05-28 13:50:03 +0000 |
1036 | +++ tests/unittests/gallerythumbnailimageprovider/CMakeLists.txt 2013-06-05 09:11:06 +0000 |
1037 | @@ -10,10 +10,15 @@ |
1038 | ${GSTLIB_INCLUDE_DIRS} |
1039 | ) |
1040 | |
1041 | +QT_WRAP_CPP(gallerythumbnailimageprovider GALLERYTHUMBNAILIMAGEPROVIDIER_MOCS |
1042 | + ${gallery_src_SOURCE_DIR}/media/preview-manager.h |
1043 | + ) |
1044 | + |
1045 | add_executable(gallerythumbnailimageprovider |
1046 | tst_gallerythumbnailimageprovider.cpp |
1047 | preview-manager.cpp |
1048 | ${gallery_src_SOURCE_DIR}/qml/gallery-thumbnail-image-provider.cpp |
1049 | + ${GALLERYTHUMBNAILIMAGEPROVIDIER_MOCS} |
1050 | ) |
1051 | |
1052 | qt5_use_modules(gallerythumbnailimageprovider Quick Test) |
1053 | |
1054 | === added directory 'tests/unittests/gallerythumbnailimageprovider/media' |
1055 | === added file 'tests/unittests/gallerythumbnailimageprovider/media/media-collection.h' |
1056 | --- tests/unittests/gallerythumbnailimageprovider/media/media-collection.h 1970-01-01 00:00:00 +0000 |
1057 | +++ tests/unittests/gallerythumbnailimageprovider/media/media-collection.h 2013-06-05 09:11:06 +0000 |
1058 | @@ -0,0 +1,28 @@ |
1059 | +/* |
1060 | + * Copyright (C) 2013 Canonical Ltd |
1061 | + * |
1062 | + * This program is free software: you can redistribute it and/or modify |
1063 | + * it under the terms of the GNU General Public License version 3 as |
1064 | + * published by the Free Software Foundation. |
1065 | + * |
1066 | + * This program is distributed in the hope that it will be useful, |
1067 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1068 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1069 | + * GNU General Public License for more details. |
1070 | + * |
1071 | + * You should have received a copy of the GNU General Public License |
1072 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1073 | + */ |
1074 | + |
1075 | +#ifndef GALLERY_MEDIA_COLLECTION_H_ |
1076 | +#define GALLERY_MEDIA_COLLECTION_H_ |
1077 | + |
1078 | +#include <QDir> |
1079 | + |
1080 | +class MediaCollection |
1081 | +{ |
1082 | +public: |
1083 | + MediaCollection(const QDir& directory) {Q_UNUSED(directory);} |
1084 | +}; |
1085 | + |
1086 | +#endif |
1087 | |
1088 | === modified file 'tests/unittests/gallerythumbnailimageprovider/preview-manager.cpp' |
1089 | --- tests/unittests/gallerythumbnailimageprovider/preview-manager.cpp 2013-05-28 13:50:03 +0000 |
1090 | +++ tests/unittests/gallerythumbnailimageprovider/preview-manager.cpp 2013-06-05 09:11:06 +0000 |
1091 | @@ -25,7 +25,14 @@ |
1092 | const QString PreviewManager::PREVIEW_DIR = ".thumbs"; |
1093 | const char* PreviewManager::PREVIEW_FILE_EXT = "JPG"; |
1094 | |
1095 | -bool PreviewManager::ensure_preview_for_media(QFileInfo file, bool regen) |
1096 | +PreviewManager::PreviewManager(const QString &thumbnailDirectory, |
1097 | + MediaCollection *mediaCollection, QObject *parent) |
1098 | +{ |
1099 | + Q_UNUSED(thumbnailDirectory); |
1100 | + Q_UNUSED(mediaCollection) |
1101 | +} |
1102 | + |
1103 | +bool PreviewManager::ensurePreview(QFileInfo file, bool regen) |
1104 | { |
1105 | file = QFileInfo(); |
1106 | regen = false; |
1107 | @@ -33,21 +40,20 @@ |
1108 | return regen; |
1109 | } |
1110 | |
1111 | -void PreviewManager::on_media_added_removed(const QSet<DataObject *> *, const QSet<DataObject *> *) |
1112 | -{ |
1113 | - |
1114 | -} |
1115 | - |
1116 | -void PreviewManager::on_media_destroying(const QSet<DataObject *> *) |
1117 | -{ |
1118 | - |
1119 | -} |
1120 | - |
1121 | -void PreviewManager::on_media_data_altered() |
1122 | -{ |
1123 | - |
1124 | -} |
1125 | - |
1126 | -QFileInfo PreviewManager::ThumbnailFileFor(const QFileInfo& file) { |
1127 | - return QFileInfo(file.dir(), PREVIEW_DIR + "/" + file.completeBaseName() + "_th_s." + PREVIEW_FILE_EXT); |
1128 | +void PreviewManager::onMediaAddedRemoved(const QSet<DataObject *> *, const QSet<DataObject *> *) |
1129 | +{ |
1130 | +} |
1131 | + |
1132 | +void PreviewManager::onMediaDestroying(const QSet<DataObject *> *) |
1133 | +{ |
1134 | +} |
1135 | + |
1136 | +void PreviewManager::updatePreview() |
1137 | +{ |
1138 | +} |
1139 | + |
1140 | +QString PreviewManager::thumbnailFileName(const QFileInfo& file) const |
1141 | +{ |
1142 | + return QString(file.absolutePath() + PREVIEW_DIR + QDir::separator() + |
1143 | + file.completeBaseName() + "_th_s." + PREVIEW_FILE_EXT); |
1144 | } |
1145 | |
1146 | === modified file 'tests/unittests/resource/tst_resource.cpp' |
1147 | --- tests/unittests/resource/tst_resource.cpp 2013-06-03 13:08:17 +0000 |
1148 | +++ tests/unittests/resource/tst_resource.cpp 2013-06-05 09:11:06 +0000 |
1149 | @@ -30,6 +30,7 @@ |
1150 | private slots: |
1151 | void picturesDirectory(); |
1152 | void databaseDirectory(); |
1153 | + void thumbnailDirectory(); |
1154 | void maxTextureSize(); |
1155 | }; |
1156 | |
1157 | @@ -46,7 +47,8 @@ |
1158 | void tst_Resource::databaseDirectory() |
1159 | { |
1160 | Resource resource("", 0); |
1161 | - QString dbDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + Resource::DATABASE_DIR; |
1162 | + QString dbDir = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + |
1163 | + QDir::separator() + Resource::DATABASE_DIR; |
1164 | QCOMPARE(resource.databaseDirectory(), dbDir); |
1165 | |
1166 | QString picDir("/some/where/else"); |
1167 | @@ -55,6 +57,19 @@ |
1168 | QCOMPARE(resource2.databaseDirectory(), dbDir); |
1169 | } |
1170 | |
1171 | +void tst_Resource::thumbnailDirectory() |
1172 | +{ |
1173 | + Resource resource("", 0); |
1174 | + QString dbDir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + |
1175 | + QDir::separator() + Resource::THUMBNAIL_DIR; |
1176 | + QCOMPARE(resource.thumbnailDirectory(), dbDir); |
1177 | + |
1178 | + QString picDir("/some/where/else"); |
1179 | + Resource resource2(picDir, 0); |
1180 | + dbDir = picDir + "/." + Resource::THUMBNAIL_DIR; |
1181 | + QCOMPARE(resource2.thumbnailDirectory(), dbDir); |
1182 | +} |
1183 | + |
1184 | void tst_Resource::maxTextureSize() |
1185 | { |
1186 | Resource resource("", 0); |
PASSED: Continuous integration, rev:683 jenkins. qa.ubuntu. com/job/ gallery- app-ci/ 192/ jenkins. qa.ubuntu. com/job/ gallery- app-saucy- amd64-ci/ 2 jenkins. qa.ubuntu. com/job/ gallery- app-saucy- armhf-ci/ 2 jenkins. qa.ubuntu. com/job/ gallery- app-saucy- armhf-ci/ 2/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ gallery- app-saucy- i386-ci/ 2 jenkins. qa.ubuntu. com/job/ generic- mediumtests- runner/ 1844
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ gallery- app-ci/ 192/rebuild
http://