summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2010-08-05 14:18:19 +1000
committerAndrew den Exter <andrew.den-exter@nokia.com>2010-08-05 14:18:19 +1000
commite3c2463502b1e4fc06fb4c78d4c9a2368e45ddf1 (patch)
tree0d72ea2762b1d5b543c34c61fdb3b0b8b41d41ff
parent9d48868867a286c6e20bac1682b695c101bb85bb (diff)
Add thumbnails and cover art to the media browser.
-rw-r--r--examples/mediabrowser/albumview.cpp14
-rw-r--r--examples/mediabrowser/coverartmodel.cpp83
-rw-r--r--examples/mediabrowser/coverartmodel.h66
-rw-r--r--examples/mediabrowser/mediabrowser.pro14
-rw-r--r--examples/mediabrowser/photoview.cpp7
-rw-r--r--examples/mediabrowser/thumbnailmodel.cpp147
-rw-r--r--examples/mediabrowser/thumbnailmodel.h75
7 files changed, 398 insertions, 8 deletions
diff --git a/examples/mediabrowser/albumview.cpp b/examples/mediabrowser/albumview.cpp
index 0d5b0bd0c0..c4afad5270 100644
--- a/examples/mediabrowser/albumview.cpp
+++ b/examples/mediabrowser/albumview.cpp
@@ -45,11 +45,20 @@
#include <QtGui>
#include <qdocumentgallery.h>
-#include <qgalleryquerymodel.h>
+
+#if defined(Q_WS_MAEMO_5)
+#include "coverartmodel.h"
+#else
+#include <thumbnailmodel.h>
+#endif
AlbumView::AlbumView(QAbstractGallery *gallery, QWidget *parent, Qt::WindowFlags flags)
: GalleryView(parent, flags)
+#if defined(Q_WS_MAEMO_5)
+ , model(new CoverArtModel(gallery))
+#else
, model(new QGalleryQueryModel(gallery))
+#endif
{
model->setRootType(QDocumentGallery::Album);
@@ -63,7 +72,7 @@ AlbumView::AlbumView(QAbstractGallery *gallery, QWidget *parent, Qt::WindowFlags
<< QDocumentGallery::title);
QListView *view = new QListView;
- view->setIconSize(QSize(124, 124));
+ view->setIconSize(ThumbnailModel::thumbnailSize);
view->setFlow(QListView::LeftToRight);
view->setViewMode(QListView::IconMode);
view->setSpacing(4);
@@ -72,7 +81,6 @@ AlbumView::AlbumView(QAbstractGallery *gallery, QWidget *parent, Qt::WindowFlags
view->setItemDelegate(new AlbumDelegate(this));
connect(view, SIGNAL(activated(QModelIndex)), this, SLOT(activated(QModelIndex)));
-
QBoxLayout *layout = new QVBoxLayout;
layout->setMargin(0);
layout->setSpacing(0);
diff --git a/examples/mediabrowser/coverartmodel.cpp b/examples/mediabrowser/coverartmodel.cpp
new file mode 100644
index 0000000000..b7f116daaf
--- /dev/null
+++ b/examples/mediabrowser/coverartmodel.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "coverartmodel.h"
+
+#include "albumdelegate.h"
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qurl.h>
+
+#define QT_GALLERY_MEDIA_ART_ILLEGAL_CHARACTERS \
+ "\\(.*\\)|\\{.*\\}|\\[.*\\]|<.*>|[\\(\\)_\\{\\}\\[\\]\\!@#$\\^&\\*\\+\\=\\|\\\\/\"'\\?~`]"
+
+CoverArtModel::CoverArtModel(QAbstractGallery *gallery, QObject *parent)
+ : ThumbnailModel(gallery, parent)
+ , illegalCharacters(QLatin1String(QT_GALLERY_MEDIA_ART_ILLEGAL_CHARACTERS))
+ , whitespace(QCryptographicHash::hash(" ", QCryptographicHash::Md5).toHex())
+{
+}
+
+QString CoverArtModel::imagePath(const QModelIndex &index) const
+{
+ QString title = index.data(Qt::DisplayRole).toString();
+ QString artist = index.data(AlbumDelegate::Artist).toString();
+
+ QString fileName = QDir::homePath()
+ + QLatin1String("/.cache/media-art/album-")
+ + hash(artist)
+ + QLatin1Char('-')
+ + hash(title)
+ + QLatin1String(".jpeg");
+
+ return thumbnailPath(QUrl::fromLocalFile(fileName));
+}
+
+QString CoverArtModel::hash(const QString &identifier) const
+{
+ if (identifier.isEmpty()) {
+ return whitespace;
+ } else {
+ return QCryptographicHash::hash(
+ identifier.toLower().remove(illegalCharacters).simplified().toUtf8(),
+ QCryptographicHash::Md5).toHex();
+ }
+}
diff --git a/examples/mediabrowser/coverartmodel.h b/examples/mediabrowser/coverartmodel.h
new file mode 100644
index 0000000000..d2329ec7bb
--- /dev/null
+++ b/examples/mediabrowser/coverartmodel.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COVERARTMODEL_H
+#define COVERARTMODEL_H
+
+#include "thumbnailmodel.h"
+
+#include <QtCore/qregexp.h>
+
+QTM_USE_NAMESPACE
+
+class CoverArtModel : public ThumbnailModel
+{
+ Q_OBJECT
+public:
+ CoverArtModel(QAbstractGallery *gallery, QObject *parent = 0);
+
+protected:
+ QString imagePath(const QModelIndex &index) const;
+
+private:
+ QString hash(const QString &identifier) const;
+
+ QRegExp illegalCharacters;
+ QString whitespace;
+};
+
+#endif
diff --git a/examples/mediabrowser/mediabrowser.pro b/examples/mediabrowser/mediabrowser.pro
index e98181679d..cdfedeb02d 100644
--- a/examples/mediabrowser/mediabrowser.pro
+++ b/examples/mediabrowser/mediabrowser.pro
@@ -17,7 +17,8 @@ HEADERS = \
galleryview.h \
photodelegate.h \
photoview.h \
- songview.h
+ songview.h \
+ thumbnailmodel.h
SOURCES = \
albumdelegate.cpp \
@@ -29,4 +30,13 @@ SOURCES = \
main.cpp \
photodelegate.cpp \
photoview.cpp \
- songview.cpp
+ songview.cpp \
+ thumbnailmodel.cpp
+
+maemo5 {
+ HEADERS += \
+ coverartmodel.h
+
+ SOURCES += \
+ coverartmodel.cpp
+}
diff --git a/examples/mediabrowser/photoview.cpp b/examples/mediabrowser/photoview.cpp
index 92c7eeb969..8111124ad1 100644
--- a/examples/mediabrowser/photoview.cpp
+++ b/examples/mediabrowser/photoview.cpp
@@ -41,15 +41,16 @@
#include "photoview.h"
#include "photodelegate.h"
+#include "thumbnailmodel.h"
#include <QtGui>
#include <qdocumentgallery.h>
-#include <qgalleryquerymodel.h>
+
PhotoView::PhotoView(QAbstractGallery *gallery, QWidget *parent, Qt::WindowFlags flags)
: GalleryView(parent, flags)
- , model(new QGalleryQueryModel(gallery))
+ , model(new ThumbnailModel(gallery))
{
model->setRootType(QDocumentGallery::Image);
@@ -61,7 +62,7 @@ PhotoView::PhotoView(QAbstractGallery *gallery, QWidget *parent, Qt::WindowFlags
<< QDocumentGallery::title);
QListView *view = new QListView;
- view->setIconSize(QSize(124, 124));
+ view->setIconSize(ThumbnailModel::thumbnailSize);
view->setFlow(QListView::TopToBottom);
view->setViewMode(QListView::IconMode);
view->setUniformItemSizes(true);
diff --git a/examples/mediabrowser/thumbnailmodel.cpp b/examples/mediabrowser/thumbnailmodel.cpp
new file mode 100644
index 0000000000..0feca29196
--- /dev/null
+++ b/examples/mediabrowser/thumbnailmodel.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <thumbnailmodel.h>
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qtconcurrentrun.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qimagereader.h>
+
+#if defined(Q_WS_MAEMO_5)
+const QSize ThumbnailModel::thumbnailSize(124, 124);
+#else
+const QSize ThumbnailModel::thumbnailSize(128, 128);
+#endif
+
+ThumbnailModel::ThumbnailModel(QAbstractGallery *gallery, QObject *parent)
+ : QGalleryQueryModel(gallery, parent)
+{
+}
+
+ThumbnailModel::~ThumbnailModel()
+{
+}
+
+QVariant ThumbnailModel::data(const QModelIndex &index, int role) const
+{
+ if (role == Qt::DecorationRole && index.isValid()) {
+ QString id = itemId(index).toString();
+
+ QFutureWatcher<QImage> *future = cache.object(id);
+
+ if (!future) {
+ future = new QFutureWatcher<QImage>;
+
+ QString path = imagePath(index);
+
+ if (!path.isEmpty()) {
+ future->setFuture(QtConcurrent::run(ThumbnailModel::load, path));
+
+ connect(future, SIGNAL(finished()), this, SLOT(thumbnailLoaded()));
+ }
+
+ cache.insert(id, future);
+ }
+
+ return future->result();
+ } else {
+ return QGalleryQueryModel::data(index, role);
+ }
+}
+
+QString ThumbnailModel::imagePath(const QModelIndex &index) const
+{
+ QUrl url = itemUrl(index);
+
+ return url.isValid() ? thumbnailPath(url) : QString();
+}
+
+QString ThumbnailModel::thumbnailPath(const QUrl &url) const
+{
+#if defined(Q_OS_UNIX) && !(defined(Q_OS_SYMBIAN) || defined(Q_OS_MAC))
+#if defined(Q_WS_MAEMO_5)
+ QString thumbnailPath = QDir::homePath()
+ + QLatin1String("/.thumbnails/cropped/")
+ + QCryptographicHash::hash(url.toString().toUtf8(), QCryptographicHash::Md5).toHex()
+ + QLatin1String(".jpeg");
+#else
+ QString thumbnailPath = QDir::homePath()
+ + QLatin1String("/.thumbnails/normal/")
+ + QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Md5).toHex()
+ + QLatin1String(".png");
+#endif
+ if (QFile::exists(thumbnailPath))
+ return thumbnailPath;
+#endif
+
+ return url.path();
+}
+
+void ThumbnailModel::thumbnailLoaded()
+{
+ emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() -1));
+}
+
+QImage ThumbnailModel::load(const QString &fileName)
+{
+ QImageReader reader(fileName);
+ reader.setQuality(25);
+
+ if (reader.supportsOption(QImageIOHandler::Size)) {
+ QSize size = reader.size();
+
+ if (!reader.supportsOption(QImageIOHandler::ScaledSize)
+ && (size.width() > 1280 || size.height() > 1280)) {
+ return QImage();
+ }
+
+ if (size.width() > thumbnailSize.width() || size.height() > thumbnailSize.height())
+ size.scale(thumbnailSize, Qt::KeepAspectRatio);
+
+ reader.setScaledSize(size);
+ } else {
+ reader.setScaledSize(thumbnailSize);
+ }
+
+ return reader.read();
+}
+
diff --git a/examples/mediabrowser/thumbnailmodel.h b/examples/mediabrowser/thumbnailmodel.h
new file mode 100644
index 0000000000..0815148522
--- /dev/null
+++ b/examples/mediabrowser/thumbnailmodel.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef THUMBNAILMODEL_H
+#define THUMBNAILMODEL_H
+
+#include <qgalleryquerymodel.h>
+
+#include <QtCore/qcache.h>
+#include <QtCore/qfuturewatcher.h>
+
+QTM_USE_NAMESPACE
+
+class ThumbnailModel : public QGalleryQueryModel
+{
+ Q_OBJECT
+public:
+ ThumbnailModel(QAbstractGallery *gallery, QObject *parent = 0);
+ ~ThumbnailModel();
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ static const QSize thumbnailSize;
+
+protected:
+ virtual QString imagePath(const QModelIndex &index) const;
+
+ QString thumbnailPath(const QUrl &url) const;
+private slots:
+ void thumbnailLoaded();
+
+private:
+ static QImage load(const QString &fileName);
+
+ mutable QCache<QString, QFutureWatcher<QImage> > cache;
+};
+
+#endif