Commit 2c3847f8 authored by Aleksi Suomalainen's avatar Aleksi Suomalainen

[provider] Image provider from MeeGo Harmattan libs.

parent 6e8fc4dc
......@@ -26,14 +26,20 @@ HEADERS += \
hacks.h \
nemowindow.h \
nemopage.h \
qquickfilteringmousearea.h
qquickfilteringmousearea.h \
nemoimageprovider.h \
themedaemon/mlocalthemedaemonclient.h \
themedaemon/mabstractthemedaemonclient.h
SOURCES += \
qquicknemocontrolsextensionplugin.cpp \
hacks.cpp \
nemowindow.cpp \
nemopage.cpp \
qquickfilteringmousearea.cpp
qquickfilteringmousearea.cpp \
nemoimageprovider.cpp \
themedaemon/mlocalthemedaemonclient.cpp \
themedaemon/mabstractthemedaemonclient.cpp
target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH
......
/*
* Copyright (C) 2013 Aleksi Suomalainen <suomalainen.aleksi@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "nemoimageprovider.h"
NemoImageProvider::NemoImageProvider() :
QQuickImageProvider(QQuickImageProvider::Image),
m_client(new MLocalThemeDaemonClient())
{
}
QImage NemoImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
Q_UNUSED(size);
Q_UNUSED(requestedSize);
return m_client->readImage(id);
}
#ifndef NEMOIMAGEPROVIDER_H
#define NEMOIMAGEPROVIDER_H
/*
* Copyright (C) 2013 Aleksi Suomalainen <suomalainen.aleksi@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <QQuickImageProvider>
#include <QDebug>
#include "themedaemon/mlocalthemedaemonclient.h"
class NemoImageProvider : public QQuickImageProvider
{
public:
explicit NemoImageProvider();
QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
private:
MLocalThemeDaemonClient* m_client;
};
#endif // NEMOIMAGEPROVIDER_H
......@@ -24,6 +24,7 @@
#include "nemowindow.h"
#include "nemopage.h"
#include "qquickfilteringmousearea.h"
#include "nemoimageprovider.h"
QQuickNemoControlsExtensionPlugin::QQuickNemoControlsExtensionPlugin(QObject *parent) :
QQmlExtensionPlugin(parent)
......@@ -48,5 +49,6 @@ void QQuickNemoControlsExtensionPlugin::registerTypes(const char *uri)
void QQuickNemoControlsExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
{
QQmlExtensionPlugin::initializeEngine(engine,uri);
engine->addImageProvider(QLatin1String("theme"), new NemoImageProvider);
}
/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** This file is part of the Qt Components project.
**
** $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 "mabstractthemedaemonclient.h"
MAbstractThemeDaemonClient::MAbstractThemeDaemonClient(QObject *parent) :
QObject(parent)
{
}
MAbstractThemeDaemonClient::~MAbstractThemeDaemonClient()
{
}
/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** This file is part of the Qt Components project.
**
** $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 MABSTRACTTHEMEDAEMONCLIENT_H
#define MABSTRACTTHEMEDAEMONCLIENT_H
#include <QObject>
#include <QPixmap>
/**
* \brief Interface for a client to request pixmaps from the themedaemon server.
*/
class MAbstractThemeDaemonClient : public QObject
{
Q_OBJECT
public:
MAbstractThemeDaemonClient(QObject *parent = 0);
virtual ~MAbstractThemeDaemonClient();
/**
* \param id Identifier of the pixmap.
* \param requestedSize Requested size of the pixmap. If the size is invalid,
* the returned pixmap will have the original size. Otherwise
* the pixmap gets scaled to the requested size.
*/
virtual QPixmap requestPixmap(const QString &id, const QSize &requestedSize) = 0;
};
#endif
/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** This file is part of the Qt Components project.
**
** $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 "mlocalthemedaemonclient.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QSettings>
MLocalThemeDaemonClient::MLocalThemeDaemonClient(const QString &testPath, QObject *parent) :
MAbstractThemeDaemonClient(parent),
m_pixmapCache(),
m_imageDirNodes()
#ifdef HAVE_MLITE
, themeItem("/meegotouch/theme/name")
#endif
{
QStringList themeRoots;
QString themeRoot = testPath;
bool testMode = false;
if (themeRoot.isEmpty())
themeRoot = qgetenv("M_THEME_DIR");
else
testMode = true;
if (themeRoot.isEmpty()) {
#if defined(THEME_DIR)
themeRoot = THEME_DIR;
#else
# ifdef Q_OS_WIN
themeRoot = "c:\\";
# else
themeRoot = "/usr/share/themes";
# endif
#endif
}
if (testMode == false) {
QString themeName;
# if !defined(THEME_NAME)
# define THEME_NAME "glacier"
# endif
#ifdef HAVE_MLITE
qDebug() << Q_FUNC_INFO << "Theme: " << themeItem.value(THEME_NAME).toString();
themeName = themeItem.value(THEME_NAME).toString();
#else
qDebug() << Q_FUNC_INFO << "Theme: " << THEME_NAME << " (hardcoded)";
themeName = QLatin1String(THEME_NAME);
#endif
// find out the inheritance chain for the new theme
QString nextTheme = themeName;
QSet<QString> inheritanceChain;
while (true) {
// Determine whether this is an m theme:
const QString themeIndexFileName = themeRoot + QDir::separator() + nextTheme + QDir::separator() + "index.theme";
// it needs to be a valid ini file
const QSettings themeIndexFile(themeIndexFileName, QSettings::IniFormat);
qDebug() << Q_FUNC_INFO << themeIndexFileName;
if (themeIndexFile.status() != QSettings::NoError) {
qWarning() << Q_FUNC_INFO << "Theme" << themeName << "does not exist! Falling back to " << THEME_NAME;
break;
}
// we need to have X-MeeGoTouch-Metatheme group in index.theme
if (!themeIndexFile.childGroups().contains(QString("X-MeeGoTouch-Metatheme"))) {
qWarning() << Q_FUNC_INFO << "Theme" << themeName << " is invalid";
break;
}
inheritanceChain.insert(nextTheme);
// the paths should be stored in reverse order than in the inheritance chain
themeRoots.prepend(themeRoot + QDir::separator() + nextTheme + QDir::separator() + QLatin1String("meegotouch"));
QString parentTheme = themeIndexFile.value("X-MeeGoTouch-Metatheme/X-Inherits", "").toString();
if (parentTheme.isEmpty()) {
break;
}
nextTheme = parentTheme;
// check that there are no cyclic dependencies
if (inheritanceChain.contains(parentTheme)) {
qFatal("%s: cyclic dependency in theme: %s", Q_FUNC_INFO, themeName.toUtf8().constData());
}
}
} else {
qDebug() << Q_FUNC_INFO << "Theme: test mode: " << themeRoot;
themeRoots += themeRoot;
}
for (int i = 0; i < themeRoots.size(); ++i) {
if (themeRoots.at(i).endsWith(QDir::separator()))
themeRoots[i].truncate(themeRoots.at(i).length() - 1);
buildHash(themeRoots.at(i) + QDir::separator() + "icons", QStringList() << "*.svg" << "*.png" << "*.jpg");
}
m_imageDirNodes.append(ImageDirNode("icons" , QStringList() << ".svg" << ".png" << ".jpg"));
qDebug() << "LocalThemeDaemonClient: Looking for assets in" << themeRoots;
}
MLocalThemeDaemonClient::~MLocalThemeDaemonClient()
{
}
QPixmap MLocalThemeDaemonClient::requestPixmap(const QString &id, const QSize &requestedSize)
{
QPixmap pixmap;
qDebug() << "ID requested: " << id;
QSize size = requestedSize;
if (size.width() < 1) {
size.rwidth() = 0;
}
if (size.height() < 1) {
size.rheight() = 0;
}
const PixmapIdentifier pixmapId(id, size);
pixmap = m_pixmapCache.value(pixmapId);
if (pixmap.isNull()) {
// The pixmap is not cached yet. Decode the image and
// store it into the cache as pixmap.
const QImage image = readImage(id);
if (!image.isNull()) {
pixmap = QPixmap::fromImage(image);
if (requestedSize.isValid() && (pixmap.size() != requestedSize)) {
pixmap = pixmap.scaled(requestedSize);
}
m_pixmapCache.insert(pixmapId, pixmap);
}
}
return pixmap;
}
QImage MLocalThemeDaemonClient::readImage(const QString &id) const
{
if (!id.isEmpty()) {
foreach (const ImageDirNode &imageDirNode, m_imageDirNodes) {
foreach (const QString &suffix, imageDirNode.suffixList) {
QString imageFilePathString = m_filenameHash.value(id + suffix);
if (!imageFilePathString.isNull()) {
imageFilePathString.append(QDir::separator() + id + suffix);
QImage image(imageFilePathString);
if (!image.isNull()) {
return image;
}
}
}
}
qDebug() << "Unknown theme image:" << id;
}
return QImage();
}
void MLocalThemeDaemonClient::buildHash(const QDir& rootDir, const QStringList& nameFilter)
{
// XXX: this code is wildly inefficient, we should be able to do it
// with a single loop over files & dirs
QDir rDir = rootDir;
rDir.setNameFilters(nameFilter);
QStringList files = rDir.entryList(QDir::Files);
foreach (const QString &filename, files) {
m_filenameHash.insert(filename, rootDir.absolutePath());
}
QStringList dirList = rootDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
foreach(const QString &nextDirString, dirList){
QDir nextDir(rootDir.absolutePath() + QDir::separator() + nextDirString);
buildHash(nextDir, nameFilter);
}
}
MLocalThemeDaemonClient::PixmapIdentifier::PixmapIdentifier() :
imageId(), size()
{
}
MLocalThemeDaemonClient::PixmapIdentifier::PixmapIdentifier(const QString &imageId, const QSize &size) :
imageId(imageId), size(size)
{
}
bool MLocalThemeDaemonClient::PixmapIdentifier::operator==(const PixmapIdentifier &other) const
{
return imageId == other.imageId && size == other.size;
}
bool MLocalThemeDaemonClient::PixmapIdentifier::operator!=(const PixmapIdentifier &other) const
{
return imageId != other.imageId || size != other.size;
}
MLocalThemeDaemonClient::ImageDirNode::ImageDirNode(const QString &directory, const QStringList &suffixList) :
directory(directory),
suffixList(suffixList)
{
}
uint qHash(const MLocalThemeDaemonClient::PixmapIdentifier &id)
{
using ::qHash;
const uint idHash = qHash(id.imageId);
const uint widthHash = qHash(id.size.width());
const uint heightHash = qHash(id.size.height());
// Twiddle the bits a little, taking a cue from Qt's own qHash() overloads
return idHash ^ (widthHash << 8) ^ (widthHash >> 24) ^ (heightHash << 24) ^ (heightHash >> 8);
}
/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** This file is part of the Qt Components project.
**
** $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 MLOCALTHEMEDAEMONCLIENT_H
#define MLOCALTHEMEDAEMONCLIENT_H
#include <themedaemon/mabstractthemedaemonclient.h>
#include <QHash>
#include <QPixmap>
#include <QString>
#ifdef HAVE_MLITE
#include <mgconfitem.h>
#endif
class QDir;
/**
* \brief Allows to request pixmaps from a local themedaemon server.
*
* The requested pixmaps are cached so that multiple requests of the
* same pixmap can be handled fast.
*/
class MLocalThemeDaemonClient : public MAbstractThemeDaemonClient
{
Q_OBJECT
public:
/**
* \param path File path where the icons and images are located.
* If no file path is provided, the default path defined
* by the define THEME_DIR is used.
* \param parent Parent object.
*/
MLocalThemeDaemonClient(const QString &testPath = QString(), QObject *parent = 0);
virtual ~MLocalThemeDaemonClient();
/**
* \see MAbstractThemeDaemonClient::requestPixmap()
*/
virtual QPixmap requestPixmap(const QString &id, const QSize &requestedSize);
/**
* Reads the image \a id from the available directories specified
* by m_imageDirNodes.
*/
QImage readImage(const QString &id) const;
private:
void buildHash(const QDir& rootDir, const QStringList& nameFilter);
/**
* Cache entry that identifies a pixmap by a string-ID and size.
*/
struct PixmapIdentifier
{
PixmapIdentifier();
PixmapIdentifier(const QString &imageId, const QSize &size);
QString imageId;
QSize size;
bool operator==(const PixmapIdentifier &other) const;
bool operator!=(const PixmapIdentifier &other) const;
};
struct ImageDirNode
{
ImageDirNode(const QString &directory, const QStringList &suffixList);
QString directory;
QStringList suffixList;
};
QHash<PixmapIdentifier, QPixmap> m_pixmapCache;
QList<ImageDirNode> m_imageDirNodes;
QHash<QString, QString> m_filenameHash;
#ifdef HAVE_MLITE
MGConfItem themeItem;
#endif
friend uint qHash(const MLocalThemeDaemonClient::PixmapIdentifier &id);
friend class tst_MLocalThemeDaemonClient; // Unit tests
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment