summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorabcd <amos.choy@nokia.com>2012-01-27 12:28:28 +1000
committerQt by Nokia <qt-info@nokia.com>2012-01-30 04:40:48 +0100
commit074260af5a59c2a6a9d49cf0b4b9e8a5db5b11f8 (patch)
treec99d3107da3df7971e7062bbdee172c1775aeb2f
parent2250712e52f15dae62e74f2106e2226a42635deb (diff)
downloadqtlocation-074260af5a59c2a6a9d49cf0b4b9e8a5db5b11f8.tar.gz
Refactor Icons
Change-Id: I702e8a1b6f0e80cb990315165f1bf331a82e65a5 Reviewed-by: Aaron McCarthy <aaron.mccarthy@nokia.com>
-rw-r--r--doc/src/plugins/jsondb.qdoc137
-rw-r--r--doc/src/plugins/nokia.qdoc4
-rw-r--r--doc/src/plugins/places-backend.qdoc70
-rw-r--r--doc/src/snippets/declarative/places.qml8
-rw-r--r--doc/src/snippets/places/requesthandler.h2
-rw-r--r--src/imports/location/declarativeplaces/qdeclarativecategory.cpp3
-rw-r--r--src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp189
-rw-r--r--src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h38
-rw-r--r--src/location/places/qplaceicon.cpp140
-rw-r--r--src/location/places/qplaceicon.h27
-rw-r--r--src/location/places/qplaceicon_p.h3
-rw-r--r--src/location/places/qplacemanagerengine.cpp20
-rw-r--r--src/location/places/qplacemanagerengine.h2
-rw-r--r--src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp10
-rw-r--r--src/plugins/geoservices/nokia/places/qplacejsonreviewparser.cpp4
-rw-r--r--src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp7
-rw-r--r--src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h1
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/icon.cpp262
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/icon.h121
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/idreply.cpp210
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/idreply.h19
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/jsonconverter.cpp39
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/jsonconverter.h11
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/nokia_places_jsondb.pro8
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.cpp105
-rw-r--r--src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.h5
-rw-r--r--tests/auto/declarative_core/tst_category.qml7
-rw-r--r--tests/auto/declarative_core/tst_place.qml39
-rw-r--r--tests/auto/declarative_core/tst_placeicon.qml136
-rw-r--r--tests/auto/declarative_core/tst_supplier.qml6
-rw-r--r--tests/auto/geotestplugin/qplacemanagerengine_test.h38
-rw-r--r--tests/auto/qmlinterface/data/TestIcon.qml5
-rw-r--r--tests/auto/qmlinterface/tst_qmlinterface.cpp4
-rw-r--r--tests/auto/qplacemanager_jsondb/qplacemanager_jsondb.pro2
-rw-r--r--tests/auto/qplacemanager_jsondb/resources.qrc11
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_24x24.pngbin0 -> 663 bytes
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_40x40.pngbin0 -> 1834 bytes
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_fullscreen.pngbin0 -> 9779 bytes
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_large.pngbin0 -> 389 bytes
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_medium.pngbin0 -> 264 bytes
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_small.pngbin0 -> 208 bytes
-rw-r--r--tests/auto/qplacemanager_jsondb/resources/icon_small.svg80
-rw-r--r--tests/auto/qplacemanager_jsondb/tst_qplacemanager_jsondb.cpp785
-rw-r--r--tests/auto/qplacesupplier/tst_qplacesupplier.cpp12
44 files changed, 1975 insertions, 595 deletions
diff --git a/doc/src/plugins/jsondb.qdoc b/doc/src/plugins/jsondb.qdoc
index f417c95f..1ac1bf8e 100644
--- a/doc/src/plugins/jsondb.qdoc
+++ b/doc/src/plugins/jsondb.qdoc
@@ -55,8 +55,8 @@ capabiliies are outlined below:
\o Read/Write
\o read/write
\row
- \o Icon url type(see \l {Icon internals} {QPlaceIcon})
- \o full url
+ \o Icons
+ \o yes
\row
\o Search term suggestions
\o no
@@ -123,10 +123,135 @@ available details are fetched during a search. The JsonDb plugin
does not support saving of any other details.
\section3 Icons
-The icon urls for the JsonDb plugin take the form of a file path.
-There can only be one icon image per icon, hence only the
-\l {Icon internals} {full url} is supported. No icon variations are
-supported.
+\section4 Parameter Reference
+The JsonDbPlugin supports the following icon parameter values
+\table
+ \header
+ \o Key
+ \o Value
+ \row
+ \o smallUrl
+ \o Holds the URL for the small icon
+ \row
+ \o smallSize
+ \o Holds the dimensions of the small icon
+ \row
+ \o smallSourceUrl
+ \o Holds the source URL from which the small icon is to be copied from.
+ \row
+ \o mediumUrl
+ \o Holds the URL for the medium sized icon.
+ \row
+ \o mediumSize
+ \o Holds the dimensions of the medium sized icon.
+ \row
+ \o mediumSourceUrl
+ \o Holds the source URL from which the medium icon is to be copied from.
+ \row
+ \o largeUrl
+ \o Holds the URL for the large icon.
+ \row
+ \o largeSize
+ \o Holds the dimensions of the large icon.
+ \row
+ \o largeSourceUrl
+ \o Holds the source URL from which the large icon is to be copied from.
+ \row
+ \o fullscreenUrl
+ \o Holds the URL for the fullscreen icon.
+ \row
+ \o fullscreenSize
+ \o Holds the dimensions of the fullscreen icon.
+ \row
+ \o fullscreenSourceUrl
+ \o Holds the source URL from which the fullscreen icon is to be copied from.
+\endtable
+
+In C++ the value of the URLs must always be a QUrl.
+In QML the values of the URLs may be url or string types.
+
+\section4 Typical Usage
+During a typical place search, the icon parameters might be populated like so
+\code
+smallUrl: file:///foo/bar/icon_s.png
+smallSize: QSize(20,20)
+largeUrl: file:///foo/bar/icon_l.png
+largeSize: QSize(50,50)
+\endcode
+
+Only small and large icons were available in this case. Note that for a given size URL, its dimensions will also be populated.
+These URLs and dimensions are used by the JsonDb plugin to determine the correct URL to return when QPlaceIcon::url() or \l {QtLocation5::Icon::url()} {Icon::url()}
+is called.
+
+If we wish to change the icons we, can simply specify a different set of parameter values and then save the place/category containing the icon.
+\code
+smallUrl: file:///opt/icons/new_icon_small.png
+(smallSize: QSize(20,20)) //optional
+largeUrl: file:///opt/icons/new_icon_large.png
+(largeSize: QSize(50,50)) // optional
+\endcode
+
+All we need to do is set the URLs to where the new icon image is. The size typically does not need to be specified
+since it is generally automatically calculated. In some cases where the size cannot be calculated, e.g. if the
+specified URL cannot currently be accessed, it is necessary to specify a recommended size.
+If the size of the image can be calculated and a size is also specified, then the specified size is ignored.
+
+\section4 Copying icons to a specified destination
+When copying or saving icons, we use the source parameters to hold the URL of the source image we are copying from
+\code
+smallSourceUrl: file:///foo/icon_s.png
+smallUrl: file:///bar/icon_small.png
+(smallSize: QSize(20,20) //optional
+\endcode
+
+Using the parameters above will copy the icon from \c smallSourceUrl to the \c smallUrl. At present both the
+smallSourceUrl and smallUrl must be local file URLs. If the smallUrl already exists, it is overwritten, otherwise it is created.
+\c smallSize typically does not need to be set since an attempt will be made to calculate the icon's size. In some cases where the size cannot be calculated, e.g. if the
+specified URL cannot currently be accessed, it is necessary to specify a recommended size.
+If the size of the image can be calculated and a size is also specified, then the specified size is ignored.
+
+\section4 Copying icons without a specified destination
+It is possible to copy icons, when a place/category is saved, and not have to specify a destination. In this case a data URL will be
+created for the icon in the underlying database. A data URL contains the icon image embedded into the URL itself. A destination
+size is chosen for the icon depending on it's calculated size.
+
+\code
+//input parameters
+smallSourceUrl: file:///foo/icon_small.png
+
+//(1) Result if the source icon's actual size corresponded to small
+smallUrl: data:image/png;base64,iVBORw0K….
+smallSize: QSize(20,20)
+
+//(2) Result if the source icon's actual size corresponded to medium
+mediumUrl: data:image/png;base64,iVBORw0K….
+mediumSize: QSize(30,30)
+\endcode
+
+The above shows that for a given input source URL, an appropriate destination is chosen for the data URL.
+The icon will not necessarily be placed into smallUrl, since the size is calculated and a destination
+chosen. The image at the sourceUrl must always been accessible so that the data URL can be generated,
+consequently this preprequisite also means that a size need not be specified since can always be calculated.
+
+This behaviour of automatically choosing a destination is necessary because when an icon from a different plugin is saved,
+it isn't known whether there is only one URL by the JsonDb plugin. When creating a compatible place from another
+plugin, the JsonDbPlugin tries to get the URLs for the standard small, medium and large sizes. It is possible
+however that all these may end up being the same URL. The JsonDb plugn filters out these duplicates and chooses
+an appropriate destination based on size.
+\code
+//The resultant place's icon after calling QPlaceManager::compatiblePlace()
+smallSourceUrl: file:///bar/foo.png
+mediumSourceUrl: file:///bar/foo.png
+largeSourceUrl: file:///bar/foo.png
+
+//on save, the plugin filters out the duplicates and determines an appropriate size
+//in this case the data URL for the large size has been created.
+largeUrl: data:image/png;base64,qVyOZw0p….
+largeSize: QSize(50,50)
+\endcode
+
+The fullscreen icon is never retrieved and converted into a data URL because data URLs are only meant
+for small icon images.
\section3 Visibility scope
The JsonDb plugin only supports places of the QtLocation::PrivateVisibility scope.
diff --git a/doc/src/plugins/nokia.qdoc b/doc/src/plugins/nokia.qdoc
index 01a57064..44079f10 100644
--- a/doc/src/plugins/nokia.qdoc
+++ b/doc/src/plugins/nokia.qdoc
@@ -145,8 +145,8 @@ and behaviours are outlined below:
\o Read/Write
\o read-only
\row
- \o Icon url type(see \l {Icon internals} {QPlaceIcon})
- \o not supported
+ \o Icons
+ \o No
\row
\o Search term suggestions
\o yes
diff --git a/doc/src/plugins/places-backend.qdoc b/doc/src/plugins/places-backend.qdoc
index 1c9ddd41..3abeb826 100644
--- a/doc/src/plugins/places-backend.qdoc
+++ b/doc/src/plugins/places-backend.qdoc
@@ -83,58 +83,16 @@ Also note that the \c finished signals should always be emitted when a reply is
an error has been encountred, i.e. if there is an error, both the \c error and \c finished signals
should be emitted while if there is no error, only the \c finished signals are emitted.
-\section1 Icon Urls
-
+\section1 Icon URLs
Icon URLs are provided through the QPlaceManagerEngine::constructIconUrl() function.
-Two important concepts regarding icons that needs to be discused
-is that of the \e baseUrl and \e fullUrl.
-A \e {baseUrl} is an incomplete URL similar to the following:
-\code
-http://www.example.com/icons/icon_
-or
-file://home/user/icons/icon_
-or
-http://www.example.com/icons/icon
-or
-file://home/user/icons/icon
-\endcode
-
-A \e {fullUrl} is a complete URL like:
-\code
-http://www.example.com/icons/icon.png
-or
-file://home/user/icons/icon.png
-\endcode
-
-The purpose of the \e {baseUrl} is to accommodate different variations
-of the same icon. e.g. A server may provide icons with dimensions of
-16x16 but also 48x48 to allow for clients which have different form factors.
-Some providers may have a set of icons suited for maps, as well as another
-set more suited for lists. These kinds of engines populate the \e {baseUrl} of a place's
-QPlaceIcon,
-
-The \e {baseUrl} is used in conjunction with the
-requested size and usage flag parameters of
-QPlaceManagerEngine::constructIconUrl() to give the closest matching
-url of the icon. e.g.
-\code
-//base
-http://www.example.com/icons/icon_
-//constructed icons
-http://www.example.com/icons/icon_48_selected.png
-http://www.example.com/icons/icon_16_map.png
-http://www.example.com/icons/icon_16_selected_map.png
-\endcode
-
-If a datastore does not support icon variations, then the \e {fullUrl}
-of the QPlaceIcon should be populated. The \e baseUrl and \e {fullUrl}
-are mutually exclusive, if one is set the other is implicitly cleared.
-If the \e {fullUrl} of an icon is used, then the manager engine should
-always returns the contents of the \e {fullUrl} as is, regardless of
-the variation parameters specified.
-
-\note It is possible for icon URLs to be \l {http://dataurl.net}{data URLs} where the icon image
-itself is embedded into the URL.
+The expected behaviour is that the engine will use the QPlaceIcon::parameters()
+in order to construct an appropriate URL. When a QPlace object is returned
+from the manager either from a search or a query to get place details,
+it is expected the engine will correctly populate the parameters as necessary.
+
+The backend is free to choose what the parameter key and values are, however
+if a backend only ever has one URL per icon it is recommended that the QPlaceIcon::SingleUrl
+be used as the key.
\section1 Categories
The categories of a manager engine are relatively static entities; for engines accessing
@@ -143,12 +101,18 @@ querying a server every time QPlaceManagerEngine::initializeCategories() is call
Depending on how dynamic the categories are, always downloading the freshest
set of categories may be more appropriate.
-\section1 Saving between managers.
+\section1 Saving places to the manager
A place generally cannot be saved directly between managers as is because it contains manager specific data such as icons
-and categories. In order to facilitate saving between managers, engine implementers should implement
+and categories. In order to facilitate saving to one's own manager, engine implementers should implement
the QPlaceManagerEngine::compatiblePlace() function. This function returns a copy of the input place
with properties pruned or modified as necessary such that the copy can be saved into manager.
+Construction of a compatible place may involve ignoring certain properties from the
+original place, e.g. if contact details are not supported, these are left out of the
+compatible place. Other times it may involve modifying certain properties, e.g.
+modifying the icon parameters to facilitate copying or downloading of the original
+place's icon to a location that the backend can access.
+
\section1 Cross-referencing places between managers.
Sometimes a situation may arise where we wish to cross-reference and match places between managers.
Such a situation may arise where one manager provides read-only access to places (origin manager), while another second r/w
diff --git a/doc/src/snippets/declarative/places.qml b/doc/src/snippets/declarative/places.qml
index b937621d..472b0045 100644
--- a/doc/src/snippets/declarative/places.qml
+++ b/doc/src/snippets/declarative/places.qml
@@ -103,10 +103,16 @@ Item {
//! [Icon]
Image {
- source: icon.url(Qt.size(64, 64), Icon.Selected | Icon.List)
+ source: icon.url(Qt.size(64, 64))
}
//! [Icon]
+ Image {
+ //! [Icon default]
+ source: icon.url()
+ //! [Icon default]
+ }
+
//! [PlaceSearchModel]
PlaceSearchModel {
id: searchModel
diff --git a/doc/src/snippets/places/requesthandler.h b/doc/src/snippets/places/requesthandler.h
index 67dad2b2..6b52728a 100644
--- a/doc/src/snippets/places/requesthandler.h
+++ b/doc/src/snippets/places/requesthandler.h
@@ -292,7 +292,7 @@ public:
void icon() {
QPlace place;
//! [icon]
- QUrl iconSourceUrl = place.icon().url(QSize(32,32), QPlaceIcon::Selected | QPlaceIcon::List);
+ QUrl iconSourceUrl = place.icon().url(QSize(32,32));
//A default icon may also be requested like so
iconSourceUrl = place.icon().url();
diff --git a/src/imports/location/declarativeplaces/qdeclarativecategory.cpp b/src/imports/location/declarativeplaces/qdeclarativecategory.cpp
index a564aa5f..473c5af9 100644
--- a/src/imports/location/declarativeplaces/qdeclarativecategory.cpp
+++ b/src/imports/location/declarativeplaces/qdeclarativecategory.cpp
@@ -167,8 +167,7 @@ void QDeclarativeCategory::setCategory(const QPlaceCategory &category)
if (m_icon && m_icon->parent() == this) {
m_icon->setPlugin(m_plugin);
- m_icon->setBaseUrl(m_category.icon().baseUrl());
- m_icon->setFullUrl(m_category.icon().fullUrl());
+ m_icon->setIcon(m_category.icon());
} else if (!m_icon || m_icon->parent() != this){
m_icon = new QDeclarativePlaceIcon(m_category.icon(), m_plugin, this);
emit iconChanged();
diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp b/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp
index 08866b6d..5e59cf19 100644
--- a/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp
+++ b/src/imports/location/declarativeplaces/qdeclarativeplaceicon.cpp
@@ -45,7 +45,6 @@
#include <QtLocation/QPlaceManager>
#include <QtDeclarative/QDeclarativeInfo>
-
QT_USE_NAMESPACE
/*!
@@ -54,34 +53,46 @@ QT_USE_NAMESPACE
\ingroup qml-QtLocation5-places
\since QtLocation 5.0
- \brief The Icon element represents an icon image source which can have multiple states and
- sizes.
+ \brief The Icon element represents an icon image source which can have multiple sizes.
+
+ The Icon element can be used in conjunction with an \l Image element to display an icon.
+ The \l url() function is used to construct an icon URL of a requested size,
+ the icon which most closely matches the requested size is returned.
+
+ The Icon element also has a parameters map which is a set of key value pairs. The precise
+ keys to use depends on the \l {Information about plugins} {plugin backend} being used.
+ The parameters map is used by the \l Plugin to determine which URL to return.
- The Icon element can be used in conjunction with an \l Image element to display an icon in
- multiple states and sizes. The \l url() function is used to construct an icon url from the
- \l baseUrl property and the desired icon size and state. For example the following code will
- display a 64x64 pixel icon for a list in the selected state.
+ In the case where an icon can only possibly have one image URL, the
+ parameter key of \c "singleUrl" can be used with a QUrl value. Any Icon with this
+ parameter will always return the specified URL regardless of the requested icon
+ size and not defer to any Plugin.
+
+ The following code shows how to display a 64x64 pixel icon:
\snippet snippets/declarative/places.qml QtQuick import
\snippet snippets/declarative/places.qml QtLocation import
\codeline
\snippet snippets/declarative/places.qml Icon
+
+ Alternatively, a default sized icon can be specified like so:
+ \snippet snippets/declarative/places.qml Icon default
*/
QDeclarativePlaceIcon::QDeclarativePlaceIcon(QObject *parent)
- : QObject(parent), m_plugin(0)
+ : QObject(parent), m_plugin(0), m_parameters(new QDeclarativePropertyMap(this))
{
}
QDeclarativePlaceIcon::QDeclarativePlaceIcon(const QPlaceIcon &icon, QDeclarativeGeoServiceProvider *plugin, QObject *parent)
- :QObject(parent)
+ : QObject(parent), m_parameters(new QDeclarativePropertyMap(this))
{
- m_baseUrl = icon.baseUrl();
- m_fullUrl = icon.fullUrl();
if (icon.isEmpty())
m_plugin = 0;
else
m_plugin = plugin;
+
+ initParameters(icon.parameters());
}
QDeclarativePlaceIcon::~QDeclarativePlaceIcon()
@@ -90,16 +101,25 @@ QDeclarativePlaceIcon::~QDeclarativePlaceIcon()
QPlaceIcon QDeclarativePlaceIcon::icon() const
{
- QPlaceIcon icon;
+ QPlaceIcon result;
if (m_plugin)
- icon.setManager(manager());
- if (!m_baseUrl.isEmpty())
- icon.setBaseUrl(m_baseUrl);
- else if (!m_fullUrl.isEmpty())
- icon.setFullUrl(m_fullUrl);
+ result.setManager(manager());
+ else
+ result.setManager(0);
+
+ QVariantMap params;
+ foreach (const QString &key, m_parameters->keys()) {
+ QVariant value = m_parameters->value(key);
+ if (value.type() == QVariant::Url && !value.toUrl().isEmpty())
+ params.insert(key, value);
+ else if (value.type() == QVariant::String && !value.toString().isEmpty())
+ params.insert(key, QUrl::fromUserInput(value.toString()));
+ }
+
+ result.setParameters(params);
- return icon;
+ return result;
}
/*!
@@ -119,119 +139,41 @@ QPlaceIcon QDeclarativePlaceIcon::icon() const
*/
void QDeclarativePlaceIcon::setIcon(const QPlaceIcon &src)
{
- bool baseChanged = m_baseUrl != src.baseUrl();
- bool fullChanged = m_fullUrl != src.fullUrl();
-
- if (baseChanged)
- m_baseUrl = src.baseUrl();
- if (fullChanged)
- m_fullUrl = src.fullUrl();
-
- if (baseChanged)
- emit baseUrlChanged();
- if (fullChanged)
- emit fullUrlChanged();
+ initParameters(src.parameters());
}
/*!
- \qmlmethod url Icon::url(size size, IconFlags flags)
-
- Returns a url for the icon best suited to the given \a size and \a flags.
-
- The \a flags parameter is a bitwise or combination of
-
- \table
- \row
- \o Icon.Normal
- \o An icon with no state modifications. This flag indicates that the user is not
- interacting with the icon, but the functionality represented by the icon is
- available.
- \row
- \o Icon.Disabled
- \o An icon with a disabled appearance. This flag indicates that the functionality
- represented by the icon is not available.
- \row
- \o Icon.Active
- \o An icon with an active appearance. This flag indicates that the functionality
- represented by the icon is available and the user is interacting with the icon,
- for example, touching it.
- \row
- \o Icon.Selected
- \o An icon with a selected appearance. This flag indicates that the item represented
- by the icon is selected.
- \row
- \o Icon.Map
- \o An icon intended for display on a \l {QtLocation5::Map}{Map}.
- \row
- \o Icon.List
- \o An icon intended for display in a list.
- \endtable
-
- If the \l fullUrl property is set, this method will return \l fullUrl, otherwise it will
- construct an url from the \l baseUrl and the given \a size and \a flags. If an explicit icon
- for the given set of flags does not exist an url for the closest matched icon will be returned.
-*/
-QUrl QDeclarativePlaceIcon::url(const QSize &size, QDeclarativePlaceIcon::IconFlags flags) const
-{
- return icon().url(size, QPlaceIcon::IconFlags(int(flags)));
-}
+ \qmlmethod url Icon::url(size size)
-/*!
- \qmlproperty url Icon::fullUrl
+ Returns a URL for the icon image that most closely matches the given \a size.
+
+ If no plugin has been assigned to the icon, and the parameters do not contain the 'singleUrl' key, a default constructed URL
+ is returned.
- This property holds the full url of the icon of the place. Setting this property implies that
- the \l baseUrl property is cleared. If this property is set \l url() will always return the
- full url regardless of the of the parameters passed to it.
*/
-QUrl QDeclarativePlaceIcon::fullUrl() const
+QUrl QDeclarativePlaceIcon::url(const QSize &size) const
{
- return m_fullUrl;
+ return icon().url(size);
}
-void QDeclarativePlaceIcon::setFullUrl(const QUrl &url)
-{
- if (m_fullUrl == url)
- return;
-
- m_fullUrl = url;
+/*!
+ \qmlproperty Object Icon::parameters
- if (!m_baseUrl.isEmpty()) {
- m_baseUrl.clear();
- emit baseUrlChanged();
- }
+ This property holds the parameters of the icon and is a map. These parameters
+ are used by the plugin to return the appropriate URL when url() is called and to
+ specify locations to save to when saving icons.
- emit fullUrlChanged();
-}
-
-/*!
- \qmlproperty url Icon::baseUrl
+ Consult the \l {Information about plugins} {plugin documentation}
+ for what parameters are supported and how they should be used.
- This property holds the base url which is used to construct a complete icon url by the
- \l url() method. Settings this property implies that the \l fullUrl property is cleared.
+ Note, due to limitations of the QDeclarativePropertyMap, it is not possible
+ to declaratively specify the parameters in QML, assignment of parameters keys
+ and values can only be accomplished by javascript.
- An example base url might be \c {http://example.com/icon}. Depending on the parameters passed
- to \l url() the returned complete url may be something like
- \c {http://example.com/icon_32x32_selected.png}. The format of the url returned by \l url() is
- dependent on the \l plugin.
*/
-QUrl QDeclarativePlaceIcon::baseUrl() const
+QDeclarativePropertyMap *QDeclarativePlaceIcon::parameters() const
{
- return m_baseUrl;
-}
-
-void QDeclarativePlaceIcon::setBaseUrl(const QUrl &url)
-{
- if (m_baseUrl == url)
- return;
-
- m_baseUrl = url;
-
- if (!m_fullUrl.isEmpty()) {
- m_fullUrl.clear();
- emit fullUrlChanged();
- }
-
- emit baseUrlChanged();
+ return m_parameters;
}
/*!
@@ -287,4 +229,17 @@ QPlaceManager *QDeclarativePlaceIcon::manager() const
return placeManager;
}
-
+void QDeclarativePlaceIcon::initParameters(const QVariantMap &parameterMap)
+{
+ //clear out old parameters
+ foreach (const QString &key, m_parameters->keys())
+ m_parameters->clear(key);
+
+ foreach (const QString &key, parameterMap.keys()) {
+ QVariant value = parameterMap.value(key);
+ if (value.type() == QVariant::Url)
+ m_parameters->insert(key, value);
+ else if (value.type() == QVariant::String)
+ m_parameters->insert(key, QUrl::fromUserInput(value.toString()));
+ }
+}
diff --git a/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h b/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h
index 011f7cab..6b49a173 100644
--- a/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h
+++ b/src/imports/location/declarativeplaces/qdeclarativeplaceicon_p.h
@@ -46,35 +46,23 @@
#include <qplaceicon.h>
#include <QtDeclarative/qdeclarative.h>
+#include <QtDeclarative/QDeclarativePropertyMap>
#include <QObject>
QT_BEGIN_NAMESPACE
+class QDeclarativePropertyMap;
+
class QDeclarativePlaceIcon : public QObject
{
Q_OBJECT
- Q_ENUMS(IconFlag)
- Q_FLAGS(IconFlags)
Q_PROPERTY(QPlaceIcon icon READ icon WRITE setIcon)
- Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl NOTIFY baseUrlChanged)
- Q_PROPERTY(QUrl fullUrl READ fullUrl WRITE setFullUrl NOTIFY fullUrlChanged)
+ Q_PROPERTY(QObject *parameters READ parameters NOTIFY parametersChanged)
Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
public:
- enum IconFlag {
- Normal = QPlaceIcon::Normal,
- Disabled = QPlaceIcon::Disabled,
- Active = QPlaceIcon::Active,
- Selected = QPlaceIcon::Selected,
-
- Map = QPlaceIcon::Map,
- List = QPlaceIcon::List
- };
-
- Q_DECLARE_FLAGS(IconFlags, IconFlag)
-
explicit QDeclarativePlaceIcon(QObject* parent = 0);
QDeclarativePlaceIcon(const QPlaceIcon &src, QDeclarativeGeoServiceProvider *plugin, QObject* parent = 0);
~QDeclarativePlaceIcon();
@@ -82,32 +70,26 @@ public:
QPlaceIcon icon() const;
void setIcon(const QPlaceIcon &src);
- Q_INVOKABLE QUrl url(const QSize &size = QSize(), QDeclarativePlaceIcon::IconFlags flags = Normal) const;
-
- QUrl fullUrl() const;
- void setFullUrl(const QUrl &fullUrl);
+ Q_INVOKABLE QUrl url(const QSize &size = QSize()) const;
- QUrl baseUrl() const;
- void setBaseUrl(const QUrl &baseUrl);
+ QDeclarativePropertyMap *parameters() const;
void setPlugin(QDeclarativeGeoServiceProvider *plugin);
QDeclarativeGeoServiceProvider *plugin() const;
signals:
- void baseUrlChanged();
- void fullUrlChanged();
void pluginChanged();
+ void parametersChanged(); //in practice is never emitted since parameters cannot be re-assigned
+ //the declaration is needed to avoid warnings about non-notifyable properties
private:
QPlaceManager *manager() const;
- QUrl m_baseUrl;
- QUrl m_fullUrl;
+ void initParameters(const QVariantMap &parameterMap);
QDeclarativeGeoServiceProvider *m_plugin;
+ QDeclarativePropertyMap *m_parameters;
};
QT_END_NAMESPACE
-Q_DECLARE_OPERATORS_FOR_FLAGS(QT_PREPEND_NAMESPACE(QDeclarativePlaceIcon::IconFlags))
-
#endif
diff --git a/src/location/places/qplaceicon.cpp b/src/location/places/qplaceicon.cpp
index 850bfd0a..0c0d39ef 100644
--- a/src/location/places/qplaceicon.cpp
+++ b/src/location/places/qplaceicon.cpp
@@ -46,7 +46,6 @@
QT_USE_NAMESPACE
-
QPlaceIconPrivate::QPlaceIconPrivate()
: QSharedData(), manager(0)
{
@@ -55,8 +54,7 @@ QPlaceIconPrivate::QPlaceIconPrivate()
QPlaceIconPrivate::QPlaceIconPrivate(const QPlaceIconPrivate&other)
: QSharedData(other),
manager(other.manager),
- baseUrl(other.baseUrl),
- fullUrl(other.fullUrl)
+ parameters(other.parameters)
{
}
@@ -67,16 +65,14 @@ QPlaceIconPrivate::~QPlaceIconPrivate()
QPlaceIconPrivate &QPlaceIconPrivate::operator=(const QPlaceIconPrivate &other)
{
manager = other.manager;
- baseUrl = other.baseUrl;
- fullUrl = other.fullUrl;
+ parameters = other.parameters;
return *this;
}
bool QPlaceIconPrivate::operator == (const QPlaceIconPrivate &other) const
{
return manager == other.manager
- && baseUrl == other.baseUrl
- && fullUrl == other.fullUrl;
+ && parameters == other.parameters;
}
/*!
@@ -90,60 +86,28 @@ bool QPlaceIconPrivate::operator == (const QPlaceIconPrivate &other) const
\section2 Usage
The typical usage of an icon is to use the url() function to specify
- a preferred size and set of flags.
+ a preferred icon size.
\snippet snippets/places/requesthandler.h icon
- Note that the parameters are \e {preferred} only. If a manager backend
- does not support one or more of the specified parameters, the url of the icon that most
+ The icons are typically backend dependent, if a manager backend does not support a given size, the URL of the icon that most
closely matches those parameters is returned.
- \target Icon internals
- \section2 Internals
- Icons are tightly coupled to a particular manager and always have a pointer
- to that manager. The icon does not have ownership of this pointer.
-
- The internals of the icon work by specifying either a \e {base} or a
- \e {full} url.
-
- A \e {base} url may be an incomplete url of the form \e {http://example.com/icon}.
- When a set of icon parameters is provided to the url() function, the manager
- constructs a complete icon url such as \e {http://example.com/icon_32x32_selected.png}.
-
- A \e {full} url is a complete url which may look something like \e {http://example.com/myicon.png}
- When a full url is specified the url() will always return the complete url.
+ The icon class also has a key-value set of parameters. The precise keys one
+ needs to use depends on the \l {Information about plugins} {plugin backend} being used. These parameters influence
+ which icon URL is returned by the manager and may also be used to specify icon URL locations when saving icons.
- Only one \e {base} or \e {full} url may be specified for a single icon, setting one implies clearing the other.
- Whether full and or base urls are supported depends on the manager backend.
-
- Any valid URL may be returned by the backend, but it would typically
- be either a http://, file://, or data:// URL.
+ If there is only ever one image for an icon, then QPlaceIcon::SingleUrl can be used as a parameter
+ key with a QUrl as the associated value. If this key is set, then the url() function will always return the specified URL
+ and not defer to any manager.
*/
/*!
- \enum QPlaceIcon::IconFlag
-
- This enum is used to specify different icon states and types.
-
- The state flags are:
- \value Normal An icon with no state modifications. This flag indicates that the user is not
- interacting with the icon, but the functionality represented by the icon is
- available.
- \value Disabled An icon with a disabled appearance. This flag indicates that the functionality
- represented by the icon is not available.
- \value Active An icon with an active appearance. This flag indicates that the functionality
- represented by the icon is available and the user is interacting with the icon,
- for example, touching it.
- \value Selected An icon with a selected appearance. This flag indicates that the item represented
- by the icon is selected.
-
-
- The type flags are:
- \value Map An icon intended for display on a map
- \value List An icon intended for display in a list.
-
- You can use at most one state and one type flag at a time.
+ Parameter key for an icon that always has a single image URL. The paramter value to be used with this key
+ is a QUrl. An icon with this parameter set will always return the specified URL regardless
+ of the requested size when url() is called.
*/
+const QString QPlaceIcon::SingleUrl(QLatin1String("singleUrl"));
/*!
Constructs an icon.
@@ -192,70 +156,47 @@ bool QPlaceIcon::operator==(const QPlaceIcon &other) const
*/
/*!
- Returns an icon url according to the given \a size and \a flags.
- If a base url has been set by setBaseUrl(), the url to the image that best
- fits the specified parameters is returned.
-
- If a full url has been set by setFullUrl(), the full url is returned.
+ Returns an icon URL according to the given \a size.
- If no manager has been assigned to the icon a default constructed QUrl
+ If no manager has been assigned to the icon, and the parameters do not contain the QPlaceIcon::SingleUrl key, a default constructed QUrl
is returned.
*/
-QUrl QPlaceIcon::url(const QSize &size, QPlaceIcon::IconFlags flags) const
+QUrl QPlaceIcon::url(const QSize &size) const
{
- if (!d->manager)
- return QUrl();
-
- if (!d->fullUrl.isEmpty())
- return d->fullUrl;
+ if (d->parameters.contains(QPlaceIcon::SingleUrl)) {
+ QVariant value = d->parameters.value(QPlaceIcon::SingleUrl);
+ if (value.type() == QVariant::Url)
+ return value.toUrl();
+ return QUrl();
+ }
- return d->manager->d->constructIconUrl(*this, size, flags);
-}
-
-/*!
- Sets a full \a url of the resource that represents the image of this
- icon. Because a full URL is being set, specifying different
- sizes and flags into the url() function will have no effect.
-
- When calling the this function, the baseUrl() is implictly
- cleared.
-*/
-void QPlaceIcon::setFullUrl(const QUrl &url)
-{
- d->fullUrl = url;
- d->baseUrl.clear();
-}
+ if (!d->manager)
+ return QUrl();
-/*!
- Returns a the full url that the icon is based off.
- \sa baseUrl()
-*/
-QUrl QPlaceIcon::fullUrl() const
-{
- return d->fullUrl;
+ return d->manager->d->constructIconUrl(*this, size);
}
/*!
- Returns a base url that the complete icon url is based off.
+ Returns a set of parameters for the icon that are manager/plugin specific.
+ These parameters are used by the manager to return the appropriate
+ URL when url() is called and to specify locations to save to
+ when saving icons.
- E.g. the base url may be http://example.com/icon.
- When calling the url() function the, base url may be used to construct: http://example.com/icon_32x32_selected.png
+ Consult the \l {Information about plugins} {plugin documentation}
+ for what parameters are supported and how they should be used.
*/
-QUrl QPlaceIcon::baseUrl() const
+QVariantMap QPlaceIcon::parameters() const
{
- return d->baseUrl;
+ return d->parameters;
}
/*!
- Sets a base \a url that the complete icon url returned by url() is based off.
-
- When calling this function, the fullUrl() is implicitly cleared.
+ Sets the parameters of the icon.
*/
-void QPlaceIcon::setBaseUrl(const QUrl &url)
+void QPlaceIcon::setParameters(const QVariantMap &parameters)
{
- d->baseUrl = url;
- d->fullUrl.clear();
+ d->parameters = parameters;
}
/*!
@@ -280,7 +221,6 @@ void QPlaceIcon::setManager(QPlaceManager *manager)
*/
bool QPlaceIcon::isEmpty() const
{
- return (d->baseUrl.isEmpty()
- && d->fullUrl.isEmpty()
- && d->manager == 0);
+ return (d->manager == 0
+ && d->parameters.isEmpty());
}
diff --git a/src/location/places/qplaceicon.h b/src/location/places/qplaceicon.h
index 337ee1c7..110dd045 100644
--- a/src/location/places/qplaceicon.h
+++ b/src/location/places/qplaceicon.h
@@ -60,19 +60,7 @@ class QPlaceIconPrivate;
class Q_LOCATION_EXPORT QPlaceIcon
{
public:
- Q_ENUMS(QPlaceIcon::IconType)
-
- enum IconFlag {
- Normal = 0,
- Disabled = 1,
- Active = 2,
- Selected = 4,
-
- Map = 8,
- List = 16
- };
-
- Q_DECLARE_FLAGS(IconFlags, IconFlag)
+ static const QString SingleUrl;
QPlaceIcon();
QPlaceIcon(const QPlaceIcon &other);
@@ -85,25 +73,20 @@ public:
return !(*this == other);
}
- QUrl url(const QSize &size = QSize(), IconFlags flags = 0) const;
-
- void setFullUrl(const QUrl &url);
- QUrl fullUrl() const;
-
- QUrl baseUrl() const;
- void setBaseUrl(const QUrl &url);
+ QUrl url(const QSize &size = QSize()) const;
QPlaceManager *manager() const;
void setManager(QPlaceManager *manager);
+ QVariantMap parameters() const;
+ void setParameters(const QVariantMap &parameters);
+
bool isEmpty() const;
private:
QSharedDataPointer<QPlaceIconPrivate> d;
};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QPlaceIcon::IconFlags)
-
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QPlaceIcon)
diff --git a/src/location/places/qplaceicon_p.h b/src/location/places/qplaceicon_p.h
index 10032ff2..378254c6 100644
--- a/src/location/places/qplaceicon_p.h
+++ b/src/location/places/qplaceicon_p.h
@@ -71,8 +71,7 @@ public:
bool operator == (const QPlaceIconPrivate &other) const;
QPlaceManager *manager;
- QUrl baseUrl;
- QUrl fullUrl;
+ QVariantMap parameters;
};
QT_END_NAMESPACE
diff --git a/src/location/places/qplacemanagerengine.cpp b/src/location/places/qplacemanagerengine.cpp
index 868b35b0..524fa89e 100644
--- a/src/location/places/qplacemanagerengine.cpp
+++ b/src/location/places/qplacemanagerengine.cpp
@@ -45,6 +45,8 @@
#include <QtCore/QMetaType>
+#include "qplaceicon.h"
+
QT_BEGIN_NAMESPACE
/*!
@@ -171,6 +173,17 @@ QPlaceMatchReply * QPlaceManagerEngine::matchingPlaces(const QPlaceMatchRequest
return reply;
}
+/*!
+ QUrl QPlaceManagerEngine::constructIconUrl(const QPlaceIcon &icon, const QSize &size)
+
+ Constructs an icon url from a given \a icon, \a size. The URL of the icon
+ image that most closely matches the given parameters is returned.
+*/
+QUrl QPlaceManagerEngine::constructIconUrl(const QPlaceIcon &icon, const QSize &size) const
+{
+ return QUrl();
+}
+
QPlaceManagerEnginePrivate::QPlaceManagerEnginePrivate()
: managerVersion(-1), manager(0)
{
@@ -289,13 +302,6 @@ QPlaceManagerEnginePrivate::~QPlaceManagerEnginePrivate()
*/
/*!
- \fn QUrl QPlaceManagerEngine::constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags)
-
- Constructs an icon url from a given \a icon, \a size and \a flags. The URL of the icon
- image that most closely matches the given parameters is returned.
-*/
-
-/*!
\fn QPlaceManager::ManagerFeatures QPlaceManagerEngine::supportedFeatures() const
Returns a set of flags indicating what particular features this manager engine instance supports.
diff --git a/src/location/places/qplacemanagerengine.h b/src/location/places/qplacemanagerengine.h
index 21dada99..9dc4d089 100644
--- a/src/location/places/qplacemanagerengine.h
+++ b/src/location/places/qplacemanagerengine.h
@@ -88,7 +88,7 @@ public:
virtual QList<QLocale> locales() const = 0;
virtual void setLocales(const QList<QLocale> &locales) = 0;
- virtual QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags) = 0;
+ virtual QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const;
virtual QPlace compatiblePlace(const QPlace &original) const;
diff --git a/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp b/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp
index 1ab297e0..0b2eac73 100644
--- a/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp
+++ b/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp
@@ -211,7 +211,7 @@ QPlace QPlaceJSonDetailsParser::buildPlace(const QJSValue &placeValue, QPlaceMan
buildPlace(placeValue, &newPlace);
}
- if (!newPlace.icon().baseUrl().isEmpty() || !newPlace.icon().fullUrl().isEmpty()) {
+ if (!newPlace.icon().parameters().isEmpty()) {
QPlaceIcon icon = newPlace.icon();
icon.setManager(manager);
newPlace.setIcon(icon);
@@ -301,7 +301,9 @@ void QPlaceJSonDetailsParser::processMainProvider(const QJSValue &placeValue, QP
value = placeValue.property(place_provider_url);
if (value.isValid() && !value.toString().isEmpty()){
QPlaceIcon icon;
- icon.setBaseUrl(value.toString());
+ QVariantMap iconParams;
+ iconParams.insert(QPlaceIcon::SingleUrl, QUrl(value.toString()));
+ icon.setParameters(iconParams);
//Note: the icon manager is set in QPlaceJSonDetailsParser::buildPlace()
sup.setIcon(icon);
}
@@ -600,7 +602,9 @@ void QPlaceJSonDetailsParser::processPremiumContent(const QJSValue &content, QPl
value = content.property(place_premiumcontent_content_providerIconUrl_element);
if (value.isValid() && !value.toString().isEmpty()) {
QPlaceIcon icon;
- icon.setFullUrl(QUrl::fromEncoded(value.toString().toAscii()));
+ QVariantMap iconParams;
+ iconParams.insert(QPlaceIcon::SingleUrl, QUrl::fromEncoded(value.toString().toAscii()));
+ icon.setParameters(iconParams);
//note: the icon manager is set in QPlaceJSonDetailsParser::buildPlace()
supplier.setIcon(icon);
}
diff --git a/src/plugins/geoservices/nokia/places/qplacejsonreviewparser.cpp b/src/plugins/geoservices/nokia/places/qplacejsonreviewparser.cpp
index 9503b0a2..9b6325c6 100644
--- a/src/plugins/geoservices/nokia/places/qplacejsonreviewparser.cpp
+++ b/src/plugins/geoservices/nokia/places/qplacejsonreviewparser.cpp
@@ -157,7 +157,9 @@ QPlaceReview QPlaceJSonReviewParser::buildReview(const QJSValue &review, QPlaceM
value = review.property(review_vendoricon_element);
if (value.isValid() && !value.toString().isEmpty()) {
QPlaceIcon icon;
- icon.setFullUrl(QUrl::fromEncoded(value.toString().toAscii()));
+ QVariantMap iconParams;
+ iconParams.insert(QPlaceIcon::SingleUrl, QUrl::fromEncoded(value.toString().toAscii()));
+ icon.setParameters(iconParams);
icon.setManager(manager);
supplier.setIcon(icon);
}
diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp
index a5c92d84..8c8831ad 100644
--- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp
@@ -315,13 +315,6 @@ void QPlaceManagerEngineNokia::setLocales(const QList<QLocale> &locales)
QPlaceRestManager::instance()->setLocales(locales);
}
-QUrl QPlaceManagerEngineNokia::constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags)
-{
- Q_UNUSED(icon)
- Q_UNUSED(size)
- Q_UNUSED(flags)
- return QUrl();
-}
QPlaceManager::ManagerFeatures QPlaceManagerEngineNokia::supportedFeatures() const
{
diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h
index a8d014d2..8df05753 100644
--- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h
+++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h
@@ -90,7 +90,6 @@ public:
QList<QLocale> locales() const;
void setLocales(const QList<QLocale> &locales);
- QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags);
QPlaceManager::ManagerFeatures supportedFeatures() const;
private slots:
diff --git a/src/plugins/geoservices/nokia_places_jsondb/icon.cpp b/src/plugins/geoservices/nokia_places_jsondb/icon.cpp
new file mode 100644
index 00000000..f3f87b83
--- /dev/null
+++ b/src/plugins/geoservices/nokia_places_jsondb/icon.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "icon.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QFile>
+#include <QtCore/QDebug>
+#include <QtGui/QImageReader>
+
+const QSize Icon::SmallSize(QSize(20,20));
+const QSize Icon::MediumSize(QSize(30,30));
+const QSize Icon::LargeSize(QSize(50,50));
+const QSize Icon::FullscreenSize(QSize(320,480));
+
+const QLatin1String Icon::SmallSource("smallSourceUrl");
+const QLatin1String Icon::MediumSource("mediumSourceUrl");
+const QLatin1String Icon::LargeSource("largeSourceUrl");
+const QLatin1String Icon::FullscreenSource("fullscreenSourceUrl");
+
+const QLatin1String Icon::SmallDestination("smallUrl");
+const QLatin1String Icon::MediumDestination("mediumUrl");
+const QLatin1String Icon::LargeDestination("largeUrl");
+const QLatin1String Icon::FullscreenDestination("fullscreenUrl");
+
+const QLatin1String Icon::SmallDestinationSize("smallSize");
+const QLatin1String Icon::MediumDestinationSize("mediumSize");
+const QLatin1String Icon::LargeDestinationSize("largeSize");
+const QLatin1String Icon::FullscreenDestinationSize("fullscreenSize");
+
+Icon::Icon(const QUrl &sourceUrl, const QUrl &destinationUrl, const QString &destination)
+ : m_sourceUrl(sourceUrl), m_destinationUrl(destinationUrl),
+ m_destination(destination), m_error(QPlaceReply::NoError)
+{
+}
+
+void Icon::initialize()
+{
+ if (m_sourceUrl.scheme().compare(QLatin1String("file"), Qt::CaseInsensitive) == 0) {
+ initImage(m_sourceUrl);
+ } else if (m_sourceUrl.scheme().compare(QLatin1String("data"), Qt::CaseInsensitive) == 0) {
+ initImage(m_sourceUrl);
+ } else if (m_sourceUrl.isEmpty() && !m_destinationUrl.isEmpty()) {
+ //see if we can get the image and hence size of the icon directly from the destinationUrl
+ //if we can't then just set the size to the user specified size.
+ if (!initImage(m_destinationUrl)) {
+ if (m_specifiedSize == QSize()) {
+ m_error = QPlaceReply::BadArgumentError;
+ m_errorString = QLatin1String("Cannot obtain size of destination icon url");
+ } else {
+ m_error = QPlaceReply::NoError; //reset error back to empty because the inability
+ m_errorString = QString(); //to access the destination url is not an error.
+
+ m_size = m_specifiedSize;
+ }
+ }
+ } else {
+ m_error = QPlaceReply::BadArgumentError;
+ m_errorString = QLatin1String("Unrecognised source icon URL scheme");
+ }
+
+ emit initializationFinished();
+}
+
+bool Icon::copy() const
+{
+ QFile file(m_destinationUrl.toLocalFile());
+ if (!file.open(QIODevice::WriteOnly)) {
+ if (file.error() == QFile::PermissionsError) {
+ m_error = QPlaceReply::PermissionsError;
+ m_errorString = QString::fromLatin1("Insufficient permissions to write icon to ") + m_destinationUrl.toLocalFile();
+ } else {
+ m_error = QPlaceReply::UnknownError;
+ m_errorString = QString::fromLatin1("Could not write icon to ") + m_destinationUrl.toLocalFile();
+ }
+ return false;
+ }
+
+ if (file.write(m_payload) == -1) {
+ m_error = QPlaceReply::UnknownError;
+ m_errorString = QString::fromLatin1("Unable to save to icon to ") + m_destinationUrl.toLocalFile();
+
+ return false;
+ }
+
+ return true;
+}
+
+QSize Icon::size() const
+{
+ return m_size;
+}
+
+QSize Icon::specifiedSize() const
+{
+ return m_specifiedSize;
+}
+
+void Icon::setSpecifiedSize(const QSize &size)
+{
+ m_specifiedSize = size;
+}
+
+QUrl Icon::sourceUrl() const
+{
+ return m_sourceUrl;
+}
+
+QUrl Icon::destinationUrl() const
+{
+ return m_destinationUrl;
+}
+
+void Icon::setDestinationDataUrl()
+{
+ QString mimeType = imageFormatToMimeType(m_inputFormat);
+ m_destinationUrl = QUrl(QString::fromLatin1("data:") + mimeType + QLatin1String(";base64,") + m_payload.toBase64());
+}
+
+QString Icon::destination() const
+{
+ return m_destination;
+}
+
+void Icon::setDestination(const QString &destination)
+{
+ m_destination = destination;
+}
+
+QPlaceReply::Error Icon::error() const
+{
+ return m_error;
+}
+
+QString Icon::errorString() const
+{
+ return m_errorString;
+}
+
+bool Icon::initImage(const QUrl &url)
+{
+ if (url.scheme().compare(QLatin1String("file"), Qt::CaseInsensitive) == 0) {
+ QString fileName = url.toLocalFile();
+ if (!fileName.isEmpty() && QFile::exists(fileName)) {
+ QFile file(fileName);
+ file.open(QIODevice::ReadOnly);
+ m_payload = file.readAll();
+ file.close();
+
+ QImageReader imageReader(fileName);
+ m_inputFormat = imageReader.format();
+
+ if (m_inputFormat.isEmpty()) {
+ m_error = QPlaceReply::UnsupportedError;
+ m_errorString = "Format of input file could not be detected";
+ return false;
+ }
+ m_size = imageReader.size();
+ return true;
+ } else {
+ m_error = QPlaceReply::BadArgumentError;
+ m_errorString = QString::fromLatin1("Icon file does not exist:") + url.toString();
+ return false;
+ }
+ } else if (url.scheme().compare(QLatin1String("data"), Qt::CaseInsensitive) == 0) {
+ QByteArray data = QByteArray::fromPercentEncoding(url.toEncoded());
+ data.remove(0,5);
+ int pos = data.indexOf(',');
+ if (pos != -1) {
+ m_payload = QByteArray::fromBase64(data.mid(pos + 1));
+ data.truncate(pos);
+
+ if (!data.endsWith(";base64")) {
+ m_error = QPlaceReply::BadArgumentError;
+ m_errorString = "Icon data urls must be base 64 encoded";
+ return false;
+ }
+
+ m_size = QImage::fromData(m_payload).size();
+ QBuffer buffer(&m_payload);
+ buffer.open(QIODevice::ReadOnly);
+ m_inputFormat = QImageReader::imageFormat(&buffer);
+ return true;
+ } else {
+ m_error = QPlaceReply::BadArgumentError;
+ m_errorString = "Could not parse icon data url";
+ return false;
+ }
+ } else {
+ m_error = QPlaceReply::BadArgumentError;
+ m_errorString = "Unsupported url scheme";
+ return false;
+ }
+}
+
+QString Icon::imageFormatToMimeType(const QByteArray &format)
+{
+ if (format == "bmp")
+ return QLatin1String("image/bmp");
+ else if (format == "gif")
+ return QLatin1String("image/gif");
+ else if (format == "jpg" || format == "jpeg")
+ return QLatin1String("image/jpeg");
+ else if (format == "mng")
+ return QLatin1String("video/x-mng");
+ else if (format == "png")
+ return QLatin1String("image/png");
+ else if (format == "pbm")
+ return QLatin1String("image/x-portable-bitmap");
+ else if (format == "pgm")
+ return QLatin1String("image/x-portable-graymap");
+ else if (format == "ppm")
+ return QLatin1String("image/x-portable-pixmap");
+ else if (format == "tiff")
+ return QLatin1String("image/tiff");
+ else if (format == "xbm")
+ return QLatin1String("image/x-xbitmap");
+ else if (format == "xpm")
+ return QLatin1String("image/x-xpixmap");
+ else if (format == "svg")
+ return QLatin1String("image/svg+xml");
+ else
+ return QString();
+}
diff --git a/src/plugins/geoservices/nokia_places_jsondb/icon.h b/src/plugins/geoservices/nokia_places_jsondb/icon.h
new file mode 100644
index 00000000..4e0bd735
--- /dev/null
+++ b/src/plugins/geoservices/nokia_places_jsondb/icon.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ICON_H
+#define ICON_H
+
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+#include <QtGui/QImage>
+#include <QtLocation/QPlaceReply>
+
+class Icon : public QObject
+{
+ Q_OBJECT
+public:
+
+ enum ErrorCode {
+ NoError,
+ Error
+ };
+
+ static const QSize SmallSize;
+ static const QSize MediumSize;
+ static const QSize LargeSize;
+ static const QSize FullscreenSize;
+
+ static const QLatin1String SmallSource;
+ static const QLatin1String MediumSource;
+ static const QLatin1String LargeSource;
+ static const QLatin1String FullscreenSource;
+
+ static const QLatin1String SmallDestination;
+ static const QLatin1String MediumDestination;
+ static const QLatin1String LargeDestination;
+ static const QLatin1String FullscreenDestination;
+
+ static const QLatin1String SmallDestinationSize;
+ static const QLatin1String MediumDestinationSize;
+ static const QLatin1String LargeDestinationSize;
+ static const QLatin1String FullscreenDestinationSize;
+
+ Icon(const QUrl &sourceUrl, const QUrl &destinationUrl, const QString &destination);
+
+ void initialize();
+
+ bool copy() const;
+
+ QSize size() const;
+
+ QSize specifiedSize() const;
+ void setSpecifiedSize(const QSize &size);
+
+ QUrl sourceUrl() const;
+
+ QUrl destinationUrl() const;
+ void setDestinationDataUrl();
+
+ QString destination() const;
+ void setDestination(const QString &destination);
+
+ QPlaceReply::Error error() const;
+ QString errorString() const;
+
+Q_SIGNALS:
+ void initializationFinished();
+
+private:
+ bool initImage(const QUrl &url);
+ static QString imageFormatToMimeType(const QByteArray &format);
+
+ QByteArray m_inputFormat;
+ QUrl m_sourceUrl;
+ QUrl m_destinationUrl;
+ QString m_destination;
+ QSize m_specifiedSize;
+ QSize m_size;
+ QByteArray m_payload;
+
+ mutable QPlaceReply::Error m_error;
+ mutable QString m_errorString;
+};
+
+#endif
diff --git a/src/plugins/geoservices/nokia_places_jsondb/idreply.cpp b/src/plugins/geoservices/nokia_places_jsondb/idreply.cpp
index d583b77e..d9e1db6e 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/idreply.cpp
+++ b/src/plugins/geoservices/nokia_places_jsondb/idreply.cpp
@@ -46,6 +46,7 @@
#include <QtAddOnJsonDb/jsondb-client.h>
#include <QtAddOnJsonDb/jsondb-error.h>
#include <QtCore/QDebug>
+#include <QtCore/QFile>
#include <QtCore/QUuid>
@@ -89,7 +90,7 @@ void IdReply::start()
}
SavePlaceReply::SavePlaceReply(QPlaceManagerEngineJsonDb *engine)
- : IdReply(QPlaceIdReply::SavePlace, engine)
+ : IdReply(QPlaceIdReply::SavePlace, engine), currIconIndex(0)
{
}
@@ -142,6 +143,150 @@ void SavePlaceReply::enterGetCategoriesState()
m_reqId = db()->find(queryObj);
}
+void SavePlaceReply::enterGetIconsState()
+{
+ m_state = SavePlaceReply::GetIcons;
+ QStringList prefixes;
+ prefixes << "small" << "medium" << "large" << "fullscreen";
+
+ QList<QUrl> uniqueInputUrls; //unique source urls that have been supplied without associated destinations
+ foreach (const QString &prefix, prefixes) {
+ bool ok;
+ QUrl sourceUrl = convertToUrl(m_place.icon().parameters().value(prefix + QLatin1String("SourceUrl"), QUrl()), &ok);
+ if (!ok) {
+ triggerDone(QPlaceReply::BadArgumentError, QString::fromLatin1("icon parameter for key: ") + prefix + QLatin1String("SourceUrl")
+ + QLatin1String(" was not a QUrl object"));
+ return;
+ }
+ QUrl destinationUrl = convertToUrl(m_place.icon().parameters().value(prefix + QLatin1String("Url"), QUrl()), &ok);
+ if (!ok) {
+ triggerDone(QPlaceReply::BadArgumentError, QString::fromLatin1("icon parameter for key: ") + prefix + QLatin1String("Url")
+ + QLatin1String(" was not a QUrl object"));
+ return;
+ }
+
+ if (destinationUrl.isEmpty()) {
+ if (sourceUrl.isEmpty() || uniqueInputUrls.contains(sourceUrl))
+ continue;
+ else
+ uniqueInputUrls.append(sourceUrl);
+ }
+
+ QString destination;
+ if (!destinationUrl.isEmpty())
+ destination = prefix + QLatin1String("Url");
+
+ Icon *icon = new Icon(sourceUrl, destinationUrl, destination);
+ if (m_place.icon().parameters().contains(prefix + QLatin1String("Size")))
+ icon->setSpecifiedSize(m_place.icon().parameters().value(prefix + QLatin1String("Size")).toSize());
+
+ m_icons.append(icon);
+ }
+
+ processIcons();
+}
+
+void SavePlaceReply::processIcons()
+{
+ if (qobject_cast<Icon *>(sender())) {
+ Icon *senderIcon = qobject_cast<Icon *>(sender());
+ if (senderIcon->error() != QPlaceReply::NoError) {
+ triggerDone(senderIcon->error(), senderIcon->errorString());
+ return;
+ }
+ }
+
+ if (currIconIndex < m_icons.count()) {
+ Icon *icon = m_icons.at(currIconIndex);
+ connect(icon, SIGNAL(initializationFinished()), this, SLOT(processIcons()), Qt::QueuedConnection);
+ icon->initialize();
+ currIconIndex++;
+ return;
+ } else {
+ QVariantMap thumbnailsMap;
+ QVariantMap thumbnailMap;
+
+ bool error = false;
+
+ //try to set destinations for icons which were not already set
+ QStringList specifiedDestinations;
+ foreach (Icon *icon, m_icons) {
+ if (!icon->destination().isEmpty())
+ specifiedDestinations.append(icon->destination());
+ }
+
+ //try to set small,medium and large destinations if they haven't already been explicitly specified
+ //and there are icons with unspecified destinations. (essentially we are creating data urls if necessary)
+ if (!specifiedDestinations.contains(Icon::SmallDestination))
+ trySetDestination(Icon::SmallDestination);
+
+ if (!specifiedDestinations.contains(Icon::MediumDestination))
+ trySetDestination(Icon::MediumDestination);
+
+ if (!specifiedDestinations.contains(Icon::LargeDestination))
+ trySetDestination(Icon::LargeDestination);
+
+ //Note that we don't try and set the destination for full screen thumbnails
+ //since data urls are meant to be just for small images
+
+ foreach (Icon *icon, m_icons) {
+ thumbnailMap.clear();
+ if (icon->error() != QPlaceReply::NoError) {
+ triggerDone(icon->error(), icon->errorString());
+ error = true;
+ break;
+ }
+
+ if (!icon->sourceUrl().isEmpty()
+ && icon->destinationUrl().scheme().compare(QLatin1String("file")) == 0) {
+ if (!icon->copy()) {
+ triggerDone(icon->error(), icon->errorString());
+ error = true;
+ break;
+ }
+ }
+
+ thumbnailMap.insert(JsonConverter::Url, icon->destinationUrl().toString());
+ if (icon->size().isValid()) {
+ thumbnailMap.insert(JsonConverter::Height, icon->size().height());
+ thumbnailMap.insert(JsonConverter::Width, icon->size().width());
+ } else {
+ //size of icon could not be calculated, therefore rely on manually specified size
+ if (!icon->specifiedSize().isValid()) {
+ triggerDone(QPlaceReply::BadArgumentError, QLatin1String("Size of icon could not be generated nor was it validly specified"));
+ error = true;
+ break;
+ }
+ thumbnailMap.insert(JsonConverter::Height, icon->specifiedSize().height());
+ thumbnailMap.insert(JsonConverter::Width, icon->specifiedSize().width());
+ }
+
+ if (icon->destination() == Icon::SmallDestination)
+ thumbnailsMap.insert(JsonConverter::Small, thumbnailMap);
+ else if (icon->destination() == Icon::MediumDestination)
+ thumbnailsMap.insert(JsonConverter::Medium, thumbnailMap);
+ else if (icon->destination() == Icon::LargeDestination)
+ thumbnailsMap.insert(JsonConverter::Large, thumbnailMap);
+ else
+ thumbnailsMap.insert(JsonConverter::Fullscreen, thumbnailMap);
+ }
+
+ if (!error) {
+ m_placeMap.insert(JsonConverter::Thumbnails, thumbnailsMap);
+
+ //proceed to save
+ m_state = SavePlaceReply::Saving;
+ if (m_place.placeId().isEmpty())
+ m_reqId = db()->create(m_placeMap);
+ else
+ m_reqId = db()->update(m_placeMap);
+ }
+
+ qDeleteAll(m_icons);
+ m_icons.clear();
+ }
+}
+
void SavePlaceReply::processResponse(int id, const QVariant &data)
{
if (id != m_reqId)
@@ -176,12 +321,8 @@ void SavePlaceReply::processResponse(int id, const QVariant &data)
m_placeMap.insert(JsonConverter::AllCategoryUuids, allCategoryUuids);
m_placeMap = JsonConverter::addToJsonMap(m_placeMap, m_place);
- m_state = SavePlaceReply::Saving;
- if (m_place.placeId().isEmpty())
- m_reqId = db()->create(m_placeMap);
- else
- m_reqId = db()->update(m_placeMap);
-
+ enterGetIconsState();
+ return;
} else if (m_state == SavePlaceReply::Saving) {
/*
Expected data format
@@ -217,6 +358,61 @@ void SavePlaceReply::processError(int id, int code, const QString &jsonDbErrorSt
}
}
+void SavePlaceReply::trySetDestination(const QString &destination)
+{
+ static int threshold;
+ int height;
+
+ //assumption is that icons are squarish
+ //so we can rely on height as a means to detect which size bucket
+ //the icon belongs to
+ if (destination == Icon::SmallDestination) {
+ threshold = (Icon::SmallSize.height() + Icon::MediumSize.height()) / 2;
+ height = Icon::SmallSize.height();
+ } else if (destination == Icon::MediumDestination) {
+ threshold = (Icon::MediumSize.height() + Icon::LargeSize.height()) / 2;
+ height = Icon::MediumSize.height();
+ } else if (destination == Icon::LargeDestination) {
+ threshold = Icon::LargeSize.height() * 2;
+ height = Icon::LargeSize.height();
+ } //note fullscreen thumbnails should not be set as data urls.
+
+ Icon *currIcon = 0;
+ foreach (Icon *icon, m_icons) {
+ if (icon->destination().isEmpty()
+ && icon->size().height() < threshold
+ && (currIcon == 0 || qAbs(icon->size().height() - height) < qAbs(currIcon->size().height() - height))) {
+ if (currIcon)
+ currIcon->setDestination(QString());
+ currIcon = icon;
+ currIcon->setDestination(destination);
+ }
+ }
+ if (currIcon)
+ currIcon->setDestinationDataUrl();
+}
+
+QUrl SavePlaceReply::convertToUrl(const QVariant &var, bool *ok)
+{
+ if (ok)
+ *ok = false;
+
+ switch (var.type()) {
+ case (QVariant::Url): {
+ if (ok)
+ *ok = true;
+ QUrl url = var.toUrl();
+ if (url.scheme().isEmpty())
+ return QUrl::fromUserInput(url.toString());
+ else
+ return url;
+ break;
+ }
+ default:
+ return QUrl();
+ }
+}
+
//-------RemovePlaceReply
RemovePlaceReply::RemovePlaceReply(QPlaceManagerEngineJsonDb *engine)
diff --git a/src/plugins/geoservices/nokia_places_jsondb/idreply.h b/src/plugins/geoservices/nokia_places_jsondb/idreply.h
index e82bfdd8..cd97fbbc 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/idreply.h
+++ b/src/plugins/geoservices/nokia_places_jsondb/idreply.h
@@ -44,6 +44,7 @@
#include <QtCore/QObject>
#include <QtLocation/QPlaceIdReply>
+#include "icon.h"
#include "macro.h"
#include "qplacemanagerengine_jsondb.h"
@@ -82,10 +83,18 @@ class SavePlaceReply : public IdReply
enum State {
Initial,
CheckIfExists,
+ GetIcons,
GetCategories,
Saving
};
+ enum IconDestination {
+ Small,
+ Medium,
+ Large,
+ FullScreen
+ };
+
public:
SavePlaceReply(QPlaceManagerEngineJsonDb *engine);
virtual ~SavePlaceReply();
@@ -93,16 +102,26 @@ public:
void setPlace(const QPlace &place);
void start();
void enterGetCategoriesState();
+ void enterGetIconsState();
private slots:
+ void processIcons();
+
void processResponse(int id, const QVariant &data);
void processError(int id, int code, const QString &errorString);
private:
+ void trySetDestination(const QString &destination);
+ QUrl convertToUrl(const QVariant &var, bool *ok);
+
+private:
QPlace m_place;
int m_reqId;
State m_state;
QVariantMap m_placeMap;
+ QList<Icon *> m_icons;
+ int currIconIndex;
+ QStringList m_specifiedDestinations;
};
class RemovePlaceReply : public IdReply
diff --git a/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.cpp b/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.cpp
index bb60e41f..11c25129 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.cpp
+++ b/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.cpp
@@ -95,7 +95,6 @@ QVariantMap JsonConverter::addToJsonMap(const QVariant &var, const QPlaceCategor
map.insert(JsonConverter::Type, JsonConverter::CategoryType);
map.insert(JsonConverter::Name, category.name());
- map.insert(JsonConverter::IconUrl, category.icon().fullUrl().toString());
return map;
}
@@ -169,8 +168,6 @@ QVariantMap JsonConverter::addToJsonMap(const QVariant &var, const QPlace &place
}
map.insert(JsonConverter::Emails, emailsJson);
- map.insert(JsonConverter::IconUrl, place.icon().fullUrl().toString());
-
QStringList categoryUuids;
foreach (const QPlaceCategory &category, place.categories())
categoryUuids.append(category.categoryId());
@@ -276,13 +273,6 @@ QPlace JsonConverter::convertJsonMapToPlace(const QVariantMap &placeMap,
place.appendContactDetail(QPlaceContactDetail::Email, detail);
}
- if (placeMap.keys().contains(JsonConverter::IconUrl) && !placeMap.value(JsonConverter::IconUrl).toString().isEmpty()) {
- QPlaceIcon icon;
- icon.setFullUrl(QUrl(placeMap.value(JsonConverter::IconUrl).toUrl()));
- icon.setManager(engine->manager());
- place.setIcon(icon);
- }
-
QStringList categoryUuidList = placeMap.value(JsonConverter::CategoryUuids).toStringList();
QPlaceCategory cat;
QList<QPlaceCategory> categories;
@@ -305,6 +295,28 @@ QPlace JsonConverter::convertJsonMapToPlace(const QVariantMap &placeMap,
}
}
+ QVariantMap iconParameters;
+ QVariantMap thumbnails = placeMap.value(JsonConverter::Thumbnails).toMap();
+
+ QList<QLatin1String> sizes;
+ sizes << JsonConverter::Small << JsonConverter::Medium << JsonConverter::Large << JsonConverter::Fullscreen;
+
+ foreach (const QLatin1String &size, sizes) {
+ if (thumbnails.contains(size)) {
+ QVariantMap thumbnail = thumbnails.value(size).toMap();
+ iconParameters.insert(QString(size) + QLatin1String("Url"), QUrl::fromUserInput(thumbnail.value(JsonConverter::Url).toString()));
+ QSize sizeDimensions = QSize(thumbnail.value(JsonConverter::Width).toInt(), thumbnail.value(JsonConverter::Height).toInt());
+ iconParameters.insert(QString(size) + QLatin1String("Size"), sizeDimensions);
+ }
+ }
+
+ if (!thumbnails.isEmpty()) {
+ QPlaceIcon icon;
+ icon.setParameters(iconParameters);
+ icon.setManager(engine->manager());
+ place.setIcon(icon);
+ }
+
return place;
}
@@ -315,12 +327,5 @@ QPlaceCategory JsonConverter::convertJsonMapToCategory(const QVariantMap &catego
category.setName(categoryMap.value(JsonConverter::Name).toString());
category.setCategoryId(categoryMap.value(JsonConverter::Uuid).toString());
- if (categoryMap.keys().contains(JsonConverter::IconUrl) && !categoryMap.value(JsonConverter::IconUrl).toString().isEmpty()) {
- QPlaceIcon icon;
- icon.setFullUrl(QUrl(categoryMap.value(JsonConverter::IconUrl).toUrl()));
- icon.setManager(engine->manager());
- category.setIcon(icon);
- }
-
return category;
}
diff --git a/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.h b/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.h
index b078c213..0ad36d43 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.h
+++ b/src/plugins/geoservices/nokia_places_jsondb/jsonconverter.h
@@ -119,10 +119,17 @@ namespace JsonConverter
static QLatin1String Value("value");
static QLatin1String Url("url");
- static QLatin1String IconUrl("iconUrl");
-
static QLatin1String ExtendedAttributes("extendedAttributes");
static QLatin1String Text("text");
+
+ static QLatin1String Height("height");
+ static QLatin1String Width("width");
+
+ static QLatin1String Thumbnails("thumbnails");
+ static QLatin1String Small("small");
+ static QLatin1String Medium("medium");
+ static QLatin1String Large("large");
+ static QLatin1String Fullscreen("fullscreen");
}
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia_places_jsondb/nokia_places_jsondb.pro b/src/plugins/geoservices/nokia_places_jsondb/nokia_places_jsondb.pro
index 901ff697..e62a07f7 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/nokia_places_jsondb.pro
+++ b/src/plugins/geoservices/nokia_places_jsondb/nokia_places_jsondb.pro
@@ -1,7 +1,7 @@
load(qt_module)
TARGET = qtgeoservices_nokia_places_jsondb
-QT += location
+QT += location gui
load(qt_plugin)
@@ -19,7 +19,8 @@ HEADERS += \
reply.h \
unsupportedreplies.h \
macro.h \
- idreply.h
+ idreply.h \
+ icon.h
SOURCES += \
qgeoserviceproviderplugin_jsondb.cpp \
@@ -29,7 +30,8 @@ SOURCES += \
searchreply.cpp \
detailsreply.cpp \
reply.cpp \
- idreply.cpp
+ idreply.cpp \
+ icon.cpp
INCLUDEPATH += $$QT.location.includes
diff --git a/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.cpp b/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.cpp
index 27ed14c3..9c1a3ec8 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.cpp
+++ b/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.cpp
@@ -257,10 +257,8 @@ QPlace QPlaceManagerEngineJsonDb::compatiblePlace(const QPlace &original) const
foreach (const QString &contactType, original.contactTypes())
place.setContactDetails(contactType, original.contactDetails(contactType));
-
place.setVisibility(QtLocation::UnspecifiedVisibility);
-
QStringList attributeTypes = original.extendedAttributeTypes();
foreach (const QString &attributeType, attributeTypes) {
if (attributeType.startsWith(QLatin1String("x_id")))
@@ -274,15 +272,76 @@ QPlace QPlaceManagerEngineJsonDb::compatiblePlace(const QPlace &original) const
alternativeId);
}
+ QVariantMap parameters;
+ QPlaceIcon originalIcon = original.icon();
+ if (!originalIcon.isEmpty()) {
+ if (originalIcon.parameters().contains(QPlaceIcon::SingleUrl)) {
+ parameters.insert(Icon::MediumSource, originalIcon.url(Icon::MediumSize));
+ } else if (originalIcon.manager()) {
+ if (!originalIcon.url(Icon::SmallSize).isEmpty())
+ parameters.insert(Icon::SmallSource, originalIcon.url(Icon::SmallSize));
+ if (!originalIcon.url(Icon::MediumSize).isEmpty())
+ parameters.insert(Icon::MediumSource, originalIcon.url(Icon::MediumSize));
+ if (!originalIcon.url(Icon::LargeSize).isEmpty())
+ parameters.insert(Icon::LargeSource, originalIcon.url(Icon::LargeSize));
+ }
+ }
+
+ if (!parameters.isEmpty()) {
+ QPlaceIcon icon;
+ icon.setParameters(parameters);
+ icon.setManager(manager());
+ place.setIcon(icon);
+ }
+
return place;
}
-QUrl QPlaceManagerEngineJsonDb::constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags)
+
+QUrl QPlaceManagerEngineJsonDb::constructIconUrl(const QPlaceIcon &icon, const QSize &size) const
{
- Q_UNUSED(size)
- Q_UNUSED(flags)
+ QList<QPair<int, QUrl> > candidates;
+ //TODO: possible optimizations
+ QMap<QString, QSize> sizeDictionary;
+ sizeDictionary.insert(Icon::SmallDestination, Icon::SmallSize);
+
+ sizeDictionary.insert(Icon::MediumDestination, Icon::MediumSize);
+ sizeDictionary.insert(Icon::LargeDestination, Icon::LargeSize);
+ sizeDictionary.insert(Icon::FullscreenDestination, Icon::FullscreenSize);
+
+ QStringList sizeKeys;
+ sizeKeys << "small" << "medium" << "large"
+ << "fullscreen";
+
+ foreach (const QString &sizeKey, sizeKeys) {
+ if (icon.parameters().contains(sizeKey + QLatin1String("Url"))) {
+ QSize destSize = icon.parameters().value(sizeKey + QLatin1String("Size")).toSize();
+ if (destSize.isEmpty()) {
+ candidates.append(QPair<int, QUrl>(sizeDictionary.value(sizeKey + QLatin1String("Url")).height(),
+ icon.parameters().value(sizeKey + QLatin1String("Url")).toUrl()));
+ } else {
+ candidates.append(QPair<int, QUrl>(destSize.height(),
+ icon.parameters().value(sizeKey + QLatin1String("Url")).toUrl()));
+ }
+ }
+ }
- return icon.fullUrl();
+ if (candidates.isEmpty())
+ return QUrl();
+ else if (candidates.count() == 1) {
+ return candidates.first().second;
+ } else {
+ //we assume icons are squarish so we can use height to
+ //determine which particular icon to return
+ int requestedHeight = size.height();
+
+ for (int i = 0; i < candidates.count() - 1; ++i) {
+ int thresholdHeight = (candidates.at(i).first + candidates.at(i+1).first) / 2;
+ if (requestedHeight < thresholdHeight)
+ return candidates.at(i).second;
+ }
+ return candidates.last().second;
+ }
}
QPlaceManager::ManagerFeatures QPlaceManagerEngineJsonDb::supportedFeatures() const
@@ -321,23 +380,6 @@ void QPlaceManagerEngineJsonDb::processJsonDbError(int id, int code, const QStri
}
}
-bool QPlaceManagerEngineJsonDb::waitForRequest(int reqId, QVariantMap *variantMap) const
-{
- m_helperMap.insert(reqId, QVariant());
- m_eventLoop.exec(QEventLoop::AllEvents);
-
- QVariant response = m_helperMap.value(reqId);
- if (response.type() == QVariant::Bool) {
- if (variantMap)
- *variantMap = QVariantMap();
- return false;
- } else {
- if (variantMap)
- *variantMap = response.toMap();
- return true;
- }
-}
-
void QPlaceManagerEngineJsonDb::processJsonDbNotification(const QString &notifyUuid, const QtAddOn::JsonDb::JsonDbNotification &notification)
{
Q_ASSERT(notifyUuid == m_notificationUuid);
@@ -366,3 +408,20 @@ void QPlaceManagerEngineJsonDb::processJsonDbNotification(const QString &notifyU
emit categoryRemoved(category.categoryId(), parentId);
}
}
+
+bool QPlaceManagerEngineJsonDb::waitForRequest(int reqId, QVariantMap *variantMap) const
+{
+ m_helperMap.insert(reqId, QVariant());
+ m_eventLoop.exec(QEventLoop::AllEvents);
+
+ QVariant response = m_helperMap.value(reqId);
+ if (response.type() == QVariant::Bool) {
+ if (variantMap)
+ *variantMap = QVariantMap();
+ return false;
+ } else {
+ if (variantMap)
+ *variantMap = response.toMap();
+ return true;
+ }
+}
diff --git a/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.h b/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.h
index bb419774..7eef23f7 100644
--- a/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.h
+++ b/src/plugins/geoservices/nokia_places_jsondb/qplacemanagerengine_jsondb.h
@@ -83,6 +83,8 @@ public:
QPlaceIdReply *saveCategory(const QPlaceCategory &category, const QString &parentId);
QPlaceIdReply *removeCategory(const QString &categoryId);
+ QPlaceMatchReply * matchingPlaces(const QPlaceMatchRequest &request);
+
QPlaceReply *initializeCategories();
QString parentCategoryId(const QString &categoryId) const;
QStringList childrenCategoryIds(const QString &categoryId) const;
@@ -94,7 +96,7 @@ public:
void setLocales(const QList<QLocale> &locales);
QPlace compatiblePlace(const QPlace &original) const;
- QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags);
+ QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const;
QPlaceManager::ManagerFeatures supportedFeatures() const;
JsonDbClient *db() { return m_db;}
@@ -106,7 +108,6 @@ public:
.arg(JsonConverter::Type).arg(JsonConverter::CategoryType).arg(JsonConverter::Uuid).arg(categoryUuid);
}
- QPlaceMatchReply * matchingPlaces(const QPlaceMatchRequest &request);
public slots:
void processJsonDbResponse(int id, const QVariant &data);
void processJsonDbError(int id, int code, const QString &error);
diff --git a/tests/auto/declarative_core/tst_category.qml b/tests/auto/declarative_core/tst_category.qml
index 65378631..4cf0c7ba 100644
--- a/tests/auto/declarative_core/tst_category.qml
+++ b/tests/auto/declarative_core/tst_category.qml
@@ -69,7 +69,9 @@ TestCase {
visibility: Category.DeviceVisibility
icon: Icon {
- fullUrl: "http://example.com/icons/test-category.png"
+ Component.onCompleted: {
+ parameters.singleUrl = "http://example.com/icons/test-category.png"
+ }
}
}
@@ -80,7 +82,8 @@ TestCase {
compare(qmlCategory.status, Category.Ready);
compare(qmlCategory.plugin, testPlugin);
verify(qmlCategory.icon);
- compare(qmlCategory.icon.fullUrl, "http://example.com/icons/test-category.png");
+ compare(qmlCategory.icon.url(), "http://example.com/icons/test-category.png");
+ compare(qmlCategory.icon.parameters.singleUrl, "http://example.com/icons/test-category.png");
compare(qmlCategory.icon.plugin, qmlCategory.plugin);
}
diff --git a/tests/auto/declarative_core/tst_place.qml b/tests/auto/declarative_core/tst_place.qml
index 77acc7ab..c4d5c46d 100644
--- a/tests/auto/declarative_core/tst_place.qml
+++ b/tests/auto/declarative_core/tst_place.qml
@@ -105,8 +105,10 @@ TestCase {
supplierId: "supplier-id-1"
url: "http://www.example.com/supplier-id-1/"
icon: Icon{
- fullUrl: "http://www.example.com/supplier-id-1/icon"
plugin: testPlugin
+ Component.onCompleted: {
+ parameters.singleUrl = "http://www.example.com/supplier-id-1/icon"
+ }
}
}
@@ -124,7 +126,9 @@ TestCase {
]
icon: Icon {
- fullUrl: "http://example.com/test-place.png"
+ Component.onCompleted: {
+ savePlace.icon.parameters.singleUrl = "http://example.com/test-place.png";
+ }
}
}
@@ -182,10 +186,17 @@ TestCase {
if (place1.supplier.icon !== null && place2.supplier.icon === null)
return false;
if (place1.supplier.icon !== null && place2.supplier.icon !== null) {
- if (place1.supplier.icon.fullUrl !== place2.supplier.icon.fullUrl)
- return false;
- if (place1.supplier.icon.baseUrl !== place2.supplier.icon.baseUrl)
+ if (place1.supplier.icon.parameters.keys().length !== place2.supplier.icon.parameters.keys().length) {
return false;
+ }
+
+ var keys = place1.supplier.icon.parameters.keys() + place2.supplier.icon.parameters.keys();
+ for (var i = 0; i < keys.length; ++i) {
+ if (place1.supplier.icon.parameters[keys[i]] != place2.supplier.icon.parameters[keys[i]]) {
+ return false;
+ }
+ }
+
if (place1.supplier.icon.plugin !== place2.supplier.icon.plugin)
return false;
}
@@ -270,13 +281,18 @@ TestCase {
console.log(place1.icon.plugin + " " + place2.icon.plugin);
return false;
}
- if (place1.icon.baseUrl !== place2.icon.baseUrl) {
+
+ if (place1.icon.parameters.keys().length !== place2.icon.parameters.keys().length) {
console.log("f4");
return false;
}
- if (place1.icon.fullUrl !== place2.icon.fullUrl) {
- console.log("f5");
- return false;
+
+ var keys = place1.icon.parameters.keys() + place2.icon.parameters.keys();
+ for (var i = 0; i < keys.length; ++i) {
+ if (place1.icon.parameters[keys[i]]
+ != place2.icon.parameters[keys[i]]) {
+ return false;
+ }
}
}
@@ -309,16 +325,12 @@ TestCase {
compare(emptyPlace.location.address.state, '');
compare(emptyPlace.location.address.country, '');
- compare(emptyPlace.icon.fullUrl, '');
- compare(emptyPlace.icon.baseUrl, '');
compare(emptyPlace.icon.plugin, null);
compare(emptyPlace.supplier.name, '');
compare(emptyPlace.supplier.supplierId, '');
compare(emptyPlace.supplier.url, '');
- compare(emptyPlace.supplier.icon.fullUrl, '');
- compare(emptyPlace.supplier.icon.baseUrl, '');
compare(emptyPlace.supplier.icon.plugin, null);
compare(emptyPlace.reviewModel.totalCount, -1);
@@ -525,7 +537,6 @@ TestCase {
// SignalSpy.wait() doesn't seem to work here
//signalSpy.wait();
wait(0);
-
compare(savePlace.status, Place.Error);
// try again without an invalid placeId
diff --git a/tests/auto/declarative_core/tst_placeicon.qml b/tests/auto/declarative_core/tst_placeicon.qml
index 2023eecb..f35a0b0a 100644
--- a/tests/auto/declarative_core/tst_placeicon.qml
+++ b/tests/auto/declarative_core/tst_placeicon.qml
@@ -51,55 +51,60 @@ TestCase {
Icon { id: emptyIcon }
function test_empty() {
- compare(emptyIcon.baseUrl, "");
- compare(emptyIcon.fullUrl, "");
compare(emptyIcon.plugin, null);
+ compare(emptyIcon.parameters.keys().length, 0)
}
+
Icon {
- id: qmlIconBase
+ id: qmlIconSingleUrl
+ }
- plugin: testPlugin
+ function test_qmlSingleUrlIcon() {
+ qmlIconSingleUrl.parameters.singleUrl = "http://example.com/icon.png"
- baseUrl: "http://example.com/icon"
- }
+ var u = qmlIconSingleUrl.url(Qt.size(64, 64));
+ compare(u, "http://example.com/icon.png");
- function test_qmlConstructedIconBase() {
- compare(qmlIconBase.baseUrl, "http://example.com/icon");
- compare(qmlIconBase.fullUrl, "");
- compare(qmlIconBase.plugin, testPlugin);
+ u = qmlIconSingleUrl.url(Qt.size(20, 20));
+ compare(u, "http://example.com/icon.png");
- var u = qmlIconBase.url(Qt.size(64, 64), Icon.Normal | Icon.List);
- verify(u !== "");
- verify(u !== "http://example.com/icon");
+ qmlIconSingleUrl.parameters.singleUrl = "/home/user/icon.png"
+ u = qmlIconSingleUrl.url(Qt.size(20, 20));
+ compare(u, "file:///home/user/icon.png");
}
- Icon {
- id: qmlIconFull
+ Plugin {
+ id: testPlugin
+ name: "qmlgeo.test.plugin"
+ }
+ Icon {
+ id: qmlIconParams
plugin: testPlugin
-
- fullUrl: "http://example.com/icon.png"
}
- function test_qmlConstructedIconFull() {
- compare(qmlIconFull.baseUrl, "");
- compare(qmlIconFull.fullUrl, "http://example.com/icon.png");
- compare(qmlIconFull.plugin, testPlugin);
-
- var u = qmlIconFull.url(Qt.size(64, 64), Icon.Normal | Icon.List);
- compare(u, qmlIconFull.fullUrl);
+ function test_qmlIconParams() {
+ compare(qmlIconParams.plugin, testPlugin);
+ qmlIconParams.parameters.s = "http://example.com/icon_small.png"
+ qmlIconParams.parameters.m = "http://example.com/icon_medium.png"
+ qmlIconParams.parameters.l = "http://example.com/icon_large.png"
+
+ compare(qmlIconParams.url(Qt.size(10, 10)), "http://example.com/icon_small.png");
+ compare(qmlIconParams.url(Qt.size(20, 20)), "http://example.com/icon_small.png");
+ compare(qmlIconParams.url(Qt.size(24, 24)), "http://example.com/icon_small.png");
+ compare(qmlIconParams.url(Qt.size(25, 25)), "http://example.com/icon_medium.png");
+ compare(qmlIconParams.url(Qt.size(30, 30)), "http://example.com/icon_medium.png");
+ compare(qmlIconParams.url(Qt.size(39, 39)), "http://example.com/icon_medium.png");
+ compare(qmlIconParams.url(Qt.size(40, 40)), "http://example.com/icon_large.png");
+ compare(qmlIconParams.url(Qt.size(50, 50)), "http://example.com/icon_large.png");
+ compare(qmlIconParams.url(Qt.size(60, 60)), "http://example.com/icon_large.png");
}
Icon {
id: testIcon
}
- Plugin {
- id: testPlugin
- name: "qmlgeo.test.plugin"
- }
-
function test_setAndGet_data() {
return [
{ tag: "plugin", property: "plugin", signal: "pluginChanged", value: testPlugin },
@@ -133,77 +138,4 @@ TestCase {
signalSpy.destroy();
}
-
- Icon {
- id: baseIcon
- plugin: testPlugin
- }
-
- function test_baseUrl() {
- var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy");
- signalSpy.target = baseIcon;
- signalSpy.signalName = "baseUrlChanged";
-
- // set baseUrl to something new
- var baseUrl = "http://example.com/base-icon"
- baseIcon.baseUrl = baseUrl;
- compare(baseIcon.baseUrl, baseUrl);
- compare(signalSpy.count, 1);
- verify(baseIcon.fullUrl, "");
-
- // set property to the same value (signals spy should not increase)
- baseIcon.baseUrl = baseUrl;
- compare(baseIcon.baseUrl, baseUrl);
- compare(signalSpy.count, 1);
- verify(baseIcon.fullUrl, "");
-
- // verify that url() method returns something different
- var url = baseIcon.url(Qt.size(64, 64), Icon.Normal | Icon.List);
- verify(url != "");
- verify(url != baseUrl);
-
- // reset property
- baseIcon.baseUrl = "";
- compare(baseIcon.baseUrl, "");
- compare(signalSpy.count, 2);
- verify(baseIcon.fullUrl, "");
-
- signalSpy.destroy();
- }
-
- Icon {
- id: fullIcon
- plugin: testPlugin
- }
-
- function test_fullUrl() {
- var signalSpy = Qt.createQmlObject('import QtTest 1.0; SignalSpy {}', testCase, "SignalSpy");
- signalSpy.target = fullIcon;
- signalSpy.signalName = "fullUrlChanged";
-
- // set fullUrl to something new
- var fullUrl = "http://example.com/full-icon.png"
- fullIcon.fullUrl = fullUrl;
- compare(fullIcon.fullUrl, fullUrl);
- compare(signalSpy.count, 1);
- verify(fullIcon.baseUrl, "");
-
- // set property to the same value (signals spy should not increase)
- fullIcon.fullUrl = fullUrl;
- compare(fullIcon.fullUrl, fullUrl);
- compare(signalSpy.count, 1);
- verify(fullIcon.baseUrl, "");
-
- // verify that url() method returns something different
- var url = fullIcon.url(Qt.size(64, 64), Icon.Normal | Icon.List);
- compare(url, fullUrl);
-
- // reset property
- fullIcon.fullUrl = "";
- compare(fullIcon.fullUrl, "");
- compare(signalSpy.count, 2);
- verify(fullIcon.baseUrl, "");
-
- signalSpy.destroy();
- }
}
diff --git a/tests/auto/declarative_core/tst_supplier.qml b/tests/auto/declarative_core/tst_supplier.qml
index 71fc894d..809a9d2a 100644
--- a/tests/auto/declarative_core/tst_supplier.qml
+++ b/tests/auto/declarative_core/tst_supplier.qml
@@ -65,7 +65,9 @@ TestCase {
url: "http://example.com/test-supplier-id"
icon: Icon {
- fullUrl: "http://example.com/icons/test-supplier.png"
+ Component.onCompleted: {
+ parameters.singleUrl = "http://example.com/icons/test-supplier.png"
+ }
}
}
@@ -74,7 +76,7 @@ TestCase {
compare(qmlSupplier.name, "Test Supplier");
compare(qmlSupplier.url, "http://example.com/test-supplier-id");
verify(qmlSupplier.icon);
- compare(qmlSupplier.icon.fullUrl, "http://example.com/icons/test-supplier.png");
+ compare(qmlSupplier.icon.parameters.singleUrl, "http://example.com/icons/test-supplier.png");
}
Supplier {
diff --git a/tests/auto/geotestplugin/qplacemanagerengine_test.h b/tests/auto/geotestplugin/qplacemanagerengine_test.h
index 897ad452..f634b57f 100644
--- a/tests/auto/geotestplugin/qplacemanagerengine_test.h
+++ b/tests/auto/geotestplugin/qplacemanagerengine_test.h
@@ -358,12 +358,40 @@ public:
m_locales = locales;
}
- QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size, QPlaceIcon::IconFlags flags)
- {
- Q_UNUSED(flags)
+ QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const {
+ QList<QPair<int, QUrl> > candidates;
+
+ QMap<QString, int> sizeDictionary;
+ sizeDictionary.insert(QLatin1String("s"), 20);
+ sizeDictionary.insert(QLatin1String("m"), 30);
+ sizeDictionary.insert(QLatin1String("l"), 50);
+
+ QStringList sizeKeys;
+ sizeKeys << QLatin1String("s") << QLatin1String("m") << QLatin1String("l");
+
+ foreach (const QString &sizeKey, sizeKeys)
+ {
+ if (icon.parameters().contains(sizeKey))
+ candidates.append(QPair<int, QUrl>(sizeDictionary.value(sizeKey),
+ icon.parameters().value(sizeKey).toUrl()));
+ }
- const QString url = icon.baseUrl().toString() + QLatin1String("_%1x%2.png");
- return url.arg(size.width()).arg(size.height());
+ if (candidates.isEmpty())
+ return QUrl();
+ else if (candidates.count() == 1) {
+ return candidates.first().second;
+ } else {
+ //we assume icons are squarish so we can use height to
+ //determine which particular icon to return
+ int requestedHeight = size.height();
+
+ for (int i = 0; i < candidates.count() - 1; ++i) {
+ int thresholdHeight = (candidates.at(i).first + candidates.at(i+1).first) / 2;
+ if (requestedHeight < thresholdHeight)
+ return candidates.at(i).second;
+ }
+ return candidates.last().second;
+ }
}
QPlaceManager::ManagerFeatures supportedFeatures() const {
diff --git a/tests/auto/qmlinterface/data/TestIcon.qml b/tests/auto/qmlinterface/data/TestIcon.qml
index c880f352..a3c9af09 100644
--- a/tests/auto/qmlinterface/data/TestIcon.qml
+++ b/tests/auto/qmlinterface/data/TestIcon.qml
@@ -39,8 +39,11 @@
**
****************************************************************************/
+import QtQuick 2.0
import QtLocation 5.0
Icon {
- fullUrl: "http://www.example.com/test-icon.png"
+ Component.onCompleted: {
+ parameters.singleUrl = "http://www.example.com/test-icon.png"
+ }
}
diff --git a/tests/auto/qmlinterface/tst_qmlinterface.cpp b/tests/auto/qmlinterface/tst_qmlinterface.cpp
index d17332a1..ed3c5985 100644
--- a/tests/auto/qmlinterface/tst_qmlinterface.cpp
+++ b/tests/auto/qmlinterface/tst_qmlinterface.cpp
@@ -123,7 +123,9 @@ tst_qmlinterface::tst_qmlinterface()
m_category.setName(QLatin1String("Test category"));
m_category.setCategoryId(QLatin1String("test-category-id"));
- m_icon.setFullUrl(QUrl(QLatin1String("http://www.example.com/test-icon.png")));
+ QVariantMap iconParams;
+ iconParams.insert(QPlaceIcon::SingleUrl, QUrl(QLatin1String("http://www.example.com/test-icon.png")));
+ m_icon.setParameters(iconParams);
m_ratings.setAverage(3.5);
m_ratings.setMaximum(5.0);
diff --git a/tests/auto/qplacemanager_jsondb/qplacemanager_jsondb.pro b/tests/auto/qplacemanager_jsondb/qplacemanager_jsondb.pro
index f62eef4b..c6c60c19 100644
--- a/tests/auto/qplacemanager_jsondb/qplacemanager_jsondb.pro
+++ b/tests/auto/qplacemanager_jsondb/qplacemanager_jsondb.pro
@@ -13,4 +13,4 @@ QT += location testlib
DEFINES += QT_ADDON_JSONDB_LIB
QT += jsondb
-
+RESOURCES += resources.qrc
diff --git a/tests/auto/qplacemanager_jsondb/resources.qrc b/tests/auto/qplacemanager_jsondb/resources.qrc
new file mode 100644
index 00000000..6e3eac22
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources.qrc
@@ -0,0 +1,11 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>resources/icon_small.png</file>
+ <file>resources/icon_small.svg</file>
+ <file>resources/icon_24x24.png</file>
+ <file>resources/icon_medium.png</file>
+ <file>resources/icon_40x40.png</file>
+ <file>resources/icon_large.png</file>
+ <file>resources/icon_fullscreen.png</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_24x24.png b/tests/auto/qplacemanager_jsondb/resources/icon_24x24.png
new file mode 100644
index 00000000..79eff158
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_24x24.png
Binary files differ
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_40x40.png b/tests/auto/qplacemanager_jsondb/resources/icon_40x40.png
new file mode 100644
index 00000000..56104673
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_40x40.png
Binary files differ
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_fullscreen.png b/tests/auto/qplacemanager_jsondb/resources/icon_fullscreen.png
new file mode 100644
index 00000000..7b7623da
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_fullscreen.png
Binary files differ
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_large.png b/tests/auto/qplacemanager_jsondb/resources/icon_large.png
new file mode 100644
index 00000000..8b5a8620
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_large.png
Binary files differ
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_medium.png b/tests/auto/qplacemanager_jsondb/resources/icon_medium.png
new file mode 100644
index 00000000..9dcc536c
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_medium.png
Binary files differ
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_small.png b/tests/auto/qplacemanager_jsondb/resources/icon_small.png
new file mode 100644
index 00000000..8cc6e328
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_small.png
Binary files differ
diff --git a/tests/auto/qplacemanager_jsondb/resources/icon_small.svg b/tests/auto/qplacemanager_jsondb/resources/icon_small.svg
new file mode 100644
index 00000000..fdc33b8b
--- /dev/null
+++ b/tests/auto/qplacemanager_jsondb/resources/icon_small.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="20"
+ height="20"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47 r22583"
+ sodipodi:docname="New document 1">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="3.959798"
+ inkscape:cx="88.740598"
+ inkscape:cy="2.2479901"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1302"
+ inkscape:window-height="747"
+ inkscape:window-x="211"
+ inkscape:window-y="312"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1032.3622)">
+ <path
+ sodipodi:type="star"
+ style="fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:#0ee219;stroke-width:0.2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="path2820"
+ sodipodi:sides="3"
+ sodipodi:cx="182.85715"
+ sodipodi:cy="392.36218"
+ sodipodi:r1="126.2327"
+ sodipodi:r2="89.473007"
+ sodipodi:arg1="1.6614562"
+ sodipodi:arg2="2.7086538"
+ inkscape:flatsided="false"
+ inkscape:rounded="0.0069814382"
+ inkscape:randomized="0"
+ d="m 171.42858,518.07647 c -0.78186,-0.0711 -69.45999,-87.4641 -69.78937,-88.17675 -0.32937,-0.71265 -22.392028,-109.65054 -21.939542,-110.29211 0.452485,-0.64157 110.476132,-16.42207 111.257992,-16.35099 0.78186,0.0711 106.15616,35.4332 106.48554,36.14585 0.32937,0.71265 -41.01614,103.88617 -41.46863,104.52774 -0.45248,0.64157 -83.76413,74.21734 -84.54599,74.14626 z"
+ transform="matrix(0.07116921,0,0,0.0639748,-3.1540812,1016.272)" />
+ </g>
+</svg>
diff --git a/tests/auto/qplacemanager_jsondb/tst_qplacemanager_jsondb.cpp b/tests/auto/qplacemanager_jsondb/tst_qplacemanager_jsondb.cpp
index 2ffbcbdc..0499e382 100644
--- a/tests/auto/qplacemanager_jsondb/tst_qplacemanager_jsondb.cpp
+++ b/tests/auto/qplacemanager_jsondb/tst_qplacemanager_jsondb.cpp
@@ -43,6 +43,7 @@
#include <QString>
#include <QtTest/QtTest>
#include <QtCore/qnumeric.h>
+#include <QtGui/QImageReader>
#include <qgeoboundingbox.h>
#include <qgeoboundingcircle.h>
@@ -82,6 +83,16 @@ QT_USE_NAMESPACE
class tst_QPlaceManagerJsonDb : public QObject
{
Q_OBJECT
+ enum UrlCorrectnes {
+ ValidUrl,
+ NoSchemeUrl
+ };
+
+ enum DestinationExists {
+ Exists,
+ DoesNotExist
+ };
+
public:
tst_QPlaceManagerJsonDb();
@@ -102,7 +113,6 @@ private Q_SLOTS:
void searchWithLexicalPlaceNameHint();
void searchWithDistanceHint();
void searchByCategory();
- void icons();
void unsupportedFunctions();
void supportedFeatures();
void categoryFunctions();
@@ -114,6 +124,18 @@ private Q_SLOTS:
void compatiblePlace();
void extendedAttribute();
void matchingPlaces();
+ void iconSourceDestination();
+ void iconSourceDestination_data();
+ void iconSourceOnly();
+ void iconSourceOnly_data();
+ void iconDestinationOnly();
+ void iconDestinationOnly_data();
+ void iconSavedFromDifferentManager();
+ void iconFormats();
+ void iconFormats_data();
+ void iconUrls();
+ void iconUrls_data();
+ void constructIconUrl();
private:
bool doSavePlace(const QPlace &place,
@@ -158,12 +180,54 @@ private:
bool compareResults(const QList<QPlaceSearchResult> &results, const QList<QPlace> &expectedResults);
+ QImage dataUrlToImage(const QUrl &url);
+
+ static const QString SmallSource;
+ static const QString SmallDestination;
+ static const QString SmallDestinationSize;
+ static const QString MediumSource;
+ static const QString MediumDestination;
+ static const QString MediumDestinationSize;
+ static const QString LargeSource;
+ static const QString LargeDestination;
+ static const QString LargeDestinationSize;
+ static const QString FullscreenSource;
+ static const QString FullscreenDestination;
+ static const QString FullscreenDestinationSize;
+
+ static const QSize SmallSize;
+ static const QSize MediumSize;
+ static const QSize LargeSize;
+ static const QSize FullscreenSize;
+
QGeoServiceProvider *provider;
QPlaceManager *placeManager;
QCoreApplication *coreApp;
JsonDbCleaner *dbCleaner ;
};
+//These constants are equivalent to those from the jsondb plugin icon class
+const QString tst_QPlaceManagerJsonDb::SmallSource("smallSourceUrl");
+const QString tst_QPlaceManagerJsonDb::SmallDestination("smallUrl");
+const QString tst_QPlaceManagerJsonDb::SmallDestinationSize("smallSize");
+
+const QString tst_QPlaceManagerJsonDb::MediumSource("mediumSourceUrl");
+const QString tst_QPlaceManagerJsonDb::MediumDestination("mediumUrl");
+const QString tst_QPlaceManagerJsonDb::MediumDestinationSize("mediumSize");
+
+const QString tst_QPlaceManagerJsonDb::LargeSource("largeSourceUrl");
+const QString tst_QPlaceManagerJsonDb::LargeDestination("largeUrl");
+const QString tst_QPlaceManagerJsonDb::LargeDestinationSize("largeSize");
+
+const QString tst_QPlaceManagerJsonDb::FullscreenSource("fullscreenSourceUrl");
+const QString tst_QPlaceManagerJsonDb::FullscreenDestination("fullscreenUrl");
+const QString tst_QPlaceManagerJsonDb::FullscreenDestinationSize("fullscreenSize");
+
+const QSize tst_QPlaceManagerJsonDb::SmallSize = QSize(20,20);
+const QSize tst_QPlaceManagerJsonDb::MediumSize = QSize(30,30);
+const QSize tst_QPlaceManagerJsonDb::LargeSize = QSize(50, 50);
+const QSize tst_QPlaceManagerJsonDb::FullscreenSize = QSize(320, 480);
+
tst_QPlaceManagerJsonDb::tst_QPlaceManagerJsonDb()
{
//We need a QCoreApplication instance for
@@ -182,7 +246,7 @@ void tst_QPlaceManagerJsonDb::initTestCase()
qRegisterMetaType<QPlaceIdReply *>();
QStringList providers = QGeoServiceProvider::availableServiceProviders();
- providers.contains("nokia_places_jsondb");
+ QVERIFY(providers.contains("nokia_places_jsondb"));
provider = new QGeoServiceProvider("nokia_places_jsondb");
placeManager = provider->placeManager();
@@ -242,7 +306,6 @@ void tst_QPlaceManagerJsonDb::saveAndRemovePlace()
//try removing a place that does not exist;
QVERIFY(doRemovePlace(place, QPlaceReply::PlaceDoesNotExistError));
-
place.setVisibility(QtLocation::PublicVisibility);
QVERIFY(doSavePlace(place, QPlaceReply::UnsupportedError, 0));
@@ -1079,58 +1142,6 @@ void tst_QPlaceManagerJsonDb::searchByCategory()
QCOMPARE(places.at(0), krustyBurger);
}
-void tst_QPlaceManagerJsonDb::icons()
-{
- QPlaceIcon icon;
- icon.setManager(placeManager);
- icon.setFullUrl(QUrl(QLatin1String("/icons/placeicon.jpg")));
-
- //check that we can get the url from the icon
- QCOMPARE(icon.url(), QUrl(QLatin1String("/icons/placeicon.jpg")));
-
- //check that we can save and retrieve a place with the icon
- //intact.
- QPlace place;
- place.setIcon(icon);
- QString placeId;
- QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
-
- QPlace retrievedPlace;
- QVERIFY(doFetchDetails(placeId, &retrievedPlace));
- QCOMPARE(retrievedPlace.icon().url(), QUrl(QLatin1String("/icons/placeicon.jpg")));
-
- QPlaceIcon categoryIcon;
- categoryIcon.setManager(placeManager);
- categoryIcon.setFullUrl(QUrl(QLatin1String("/icons/motel.jpg")));
-
- QPlaceCategory motel;
- motel.setIcon(categoryIcon);
- QString categoryId;
- QVERIFY(doSaveCategory(motel, "", QPlaceReply::NoError, &categoryId));
- motel.setCategoryId(categoryId);
-
- QList<QPlaceCategory> categories = placeManager->childCategories();
- QCOMPARE(categories.count(), 1);
- QCOMPARE(categories.at(0).icon().url(), QUrl(QLatin1String("/icons/motel.jpg")));
-
- //test modification of an icon of an existin category
- categoryIcon.setFullUrl(QUrl(QLatin1String("/icons/motel2.jpg")));
- motel.setIcon(categoryIcon);
- QVERIFY(doSaveCategory(motel, "", QPlaceReply::NoError, &categoryId));
-
- categories = placeManager->childCategories();
- QCOMPARE(categories.count(), 1);
- QCOMPARE(categories.at(0).icon().url(), QUrl(QLatin1String("/icons/motel2.jpg")));
-
- //try saving an empty icon to the category
- motel.setIcon(QPlaceIcon());
- QVERIFY(doSaveCategory(motel, "", QPlaceReply::NoError, &categoryId));
- categories = placeManager->childCategories();
- QCOMPARE(categories.count(), 1);
- QCOMPARE(categories.at(0).icon().url(), QUrl());
- QVERIFY(categories.at(0).icon().isEmpty());
-}
-
void tst_QPlaceManagerJsonDb::unsupportedFunctions()
{
QPlace place;
@@ -1456,6 +1467,9 @@ void tst_QPlaceManagerJsonDb::categoryNotifications()
void tst_QPlaceManagerJsonDb::compatiblePlace()
{
+ QGeoServiceProvider geoTest("qmlgeo.test.plugin");
+ QPlaceManager *geoTestManager = geoTest.placeManager();
+
QPlace place;
place.setPlaceId(QLatin1String("123"));
place.setName(QLatin1String("Moe's Tavern"));
@@ -1499,6 +1513,15 @@ void tst_QPlaceManagerJsonDb::compatiblePlace()
attribute.setLabel(QLatin1String("Smoking"));
attribute.setText(QLatin1String("Yes"));
+ QPlaceIcon icon;
+ QVariantMap iconParams;
+ iconParams.insert("s", "www.example.com/small.png");
+ iconParams.insert("m", "www.example.com/medium.png");
+ iconParams.insert("l", "www.example.com/large.png");
+ icon.setParameters(iconParams);
+ icon.setManager(geoTestManager);
+ place.setIcon(icon);
+
place.setExtendedAttribute(QLatin1String("Smoking"), attribute);
place.setVisibility(QtLocation::PublicVisibility);
@@ -1524,6 +1547,10 @@ void tst_QPlaceManagerJsonDb::compatiblePlace()
QVERIFY(compatPlace.content(QPlaceContent::EditorialType).isEmpty());
QCOMPARE(compatPlace.totalContentCount(QPlaceContent::ImageType), 0);
+ QCOMPARE(compatPlace.icon().parameters().value(SmallSource).toString(), QLatin1String("www.example.com/small.png"));
+ QCOMPARE(compatPlace.icon().parameters().value(MediumSource).toString(), QLatin1String("www.example.com/medium.png"));
+ QCOMPARE(compatPlace.icon().parameters().value(LargeSource).toString(), QLatin1String("www.example.com/large.png"));
+
QVERIFY(compatPlace.extendedAttributeTypes().isEmpty());
QCOMPARE(compatPlace.extendedAttribute(QLatin1String("Smoking")), QPlaceAttribute());
@@ -1615,6 +1642,633 @@ void tst_QPlaceManagerJsonDb::matchingPlaces()
QCOMPARE(places.at(2), place2Saved);
}
+void tst_QPlaceManagerJsonDb::iconSourceDestination()
+{
+ //We test that an input source icon is correctly copied to it's specified destination
+ //Source and Destination urls are provided
+ QFETCH(QString, sourceIconResource);
+ QFETCH(QSize, iconSize);
+ QFETCH(QString, iconType);
+ QFETCH(QString, source);
+ QFETCH(QString, specifiedDestination);
+
+ for (int destUrlCorrectness = ValidUrl; destUrlCorrectness != (NoSchemeUrl +1); ++destUrlCorrectness) {
+ for (int destFileExists = Exists; destFileExists != (DoesNotExist + 1); ++destFileExists) {
+ QPlace place;
+ place.setName("place");
+ QPlaceIcon icon;
+ QVariantMap iconParams;
+
+ QTemporaryFile sourceIconFile;
+
+ if (iconType.startsWith(QLatin1String("file"))) {
+ QImage sourceIconImage(sourceIconResource);
+ sourceIconFile.open();
+ sourceIconImage.save(sourceIconFile.fileName(), QImageReader::imageFormat(sourceIconResource));
+ if (iconType == QLatin1String("file"))
+ iconParams.insert(source, QUrl::fromLocalFile(sourceIconFile.fileName()));
+ else if (iconType == QLatin1String("file_improperUrl"))
+ iconParams.insert(source, QUrl(sourceIconFile.fileName()));
+ else
+ qFatal("Unknown icon type");
+ } else if (iconType == QLatin1String("dataUrl")) {
+ QFile sourceIcon(sourceIconResource);
+ sourceIcon.open(QIODevice::ReadOnly);
+ QString mimeType;
+ if (QImageReader::imageFormat(sourceIconResource) == "png")
+ mimeType = QLatin1String("image/png");
+ QUrl dataUrl(QString::fromLatin1("data:") + mimeType + QLatin1String(";base64,") + sourceIcon.readAll().toBase64());
+ iconParams.insert(source, dataUrl);
+ }
+
+ QTemporaryDir tempDir;
+ QVERIFY(tempDir.isValid());
+ QString destIconFileName = tempDir.path() + QLatin1String("/tempFile");
+ if (destFileExists == Exists) {
+ QFile destFile(destIconFileName);
+ destFile.open(QIODevice::ReadWrite);
+ destFile.close();
+ }//else must be creating a new destination file
+
+ if (destUrlCorrectness == ValidUrl)
+ iconParams.insert(specifiedDestination, QUrl::fromLocalFile(destIconFileName));
+ else //must be no scheme url
+ iconParams.insert(specifiedDestination, QUrl(destIconFileName));
+
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+
+ QString placeId;
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+
+ QPlace retrievedPlace;
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+
+ QVERIFY(retrievedPlace.icon().parameters().contains(specifiedDestination));
+
+ QUrl retrievedUrl = retrievedPlace.icon().parameters().value(specifiedDestination).toUrl();
+
+ QImage retrievedImage;
+
+ QVERIFY(retrievedUrl.scheme().compare(QLatin1String("file"), Qt::CaseInsensitive) == 0);
+ retrievedImage = QImage(retrievedUrl.toLocalFile());
+
+ QCOMPARE(retrievedImage.size(), iconSize);
+ }
+ }
+}
+
+void tst_QPlaceManagerJsonDb::iconSourceDestination_data()
+{
+ QTest::addColumn<QString>("sourceIconResource");
+ QTest::addColumn<QSize>("iconSize");
+ QTest::addColumn<QString>("iconType");
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("specifiedDestination");
+
+ //Specify source and destionation, expect file to be copied into destination file
+ QTest::newRow("source destination small file") << ":/resources/icon_small.png" << QSize(20,20) << "file" << SmallSource << SmallDestination;
+ QTest::newRow("source destination medium file") << ":/resources/icon_medium.png" << QSize(30,30) << "file" << MediumSource << MediumDestination;
+ QTest::newRow("source destination large file") << ":/resources/icon_large.png" << QSize(50,50) << "file" << LargeSource << LargeDestination;
+ QTest::newRow("source destination fullscreen file") << ":/resources/icon_fullscreen.png" << QSize(320,480) << "file" << FullscreenSource << FullscreenDestination;
+
+ //Specify source and destination, expect data url to be copied into destination url
+ QTest::newRow("source destination small dataUrl") << ":/resources/icon_small.png" << QSize(20,20) << "dataUrl" << SmallSource << SmallDestination;
+ QTest::newRow("source destination medium dataUrl") << ":/resources/icon_medium.png" << QSize(30,30) << "dataUrl" << MediumSource << MediumDestination;
+ QTest::newRow("source destination large dataUrl") << ":/resources/icon_large.png" << QSize(50,50) << "dataUrl" << LargeSource << LargeDestination;
+ QTest::newRow("source destination fullscreen dataUrl") << ":/resources/icon_fullscreen.png" << QSize(320,480) << "dataUrl" << FullscreenSource << FullscreenDestination;
+
+ //try using improper source file urls, e.g. /some/path rather than file:///some/path
+ QTest::newRow("source destination small file_improperUrl") << ":/resources/icon_small.png" << QSize(20,20) << "file_improperUrl" << SmallSource << SmallDestination;
+ QTest::newRow("source destination medium file_improperUrl") << ":/resources/icon_medium.png" << QSize(30,30) << "file_improperUrl" << MediumSource << MediumDestination;
+ QTest::newRow("source destination large file_improperUrl") << ":/resources/icon_large.png" << QSize(50,50) << "file_improperUrl" << LargeSource << LargeDestination;
+ QTest::newRow("source destination fullscreen file_improperUrl") << ":/resources/icon_fullscreen.png" << QSize(320,480) << "file_improperUrl" << FullscreenSource << FullscreenDestination;
+}
+
+void tst_QPlaceManagerJsonDb::iconSourceOnly()
+{
+ //We test that a dataUrl is generated from the given input icon
+ //Soucre urls are provided while destination urls
+ QFETCH(QString, sourceIconResource);
+ QFETCH(QSize, iconSize);
+ QFETCH(QString, iconType);
+ QFETCH(QString, source);
+ QFETCH(QString, expectedDestination);
+
+ QPlace place;
+ place.setName("place");
+ QPlaceIcon icon;
+ QVariantMap iconParams;
+
+ QTemporaryFile sourceIconFile;
+ if (iconType.startsWith(QLatin1String("file"))) {
+ QImage sourceIconImage(sourceIconResource);
+ sourceIconFile.open();
+ sourceIconImage.save(sourceIconFile.fileName(), QImageReader::imageFormat(sourceIconResource));
+ if (iconType == QLatin1String("file"))
+ iconParams.insert(source, QUrl::fromLocalFile(sourceIconFile.fileName()));
+ else if (iconType == QLatin1String("file_improperUrl"))
+ iconParams.insert(source, QUrl(sourceIconFile.fileName()));
+ else
+ qFatal("Unknown iconType");
+ } else if (iconType == QLatin1String("dataUrl")) {
+ QFile sourceIcon(sourceIconResource);
+ sourceIcon.open(QIODevice::ReadOnly);
+ QString mimeType;
+ if (QImageReader::imageFormat(sourceIconResource) == "png")
+ mimeType = QLatin1String("image/png");
+ else
+ qFatal("Unexpected image format");
+ QUrl dataUrl(QString::fromLatin1("data:") + mimeType + QLatin1String(";base64,") + sourceIcon.readAll().toBase64());
+ iconParams.insert(source, dataUrl);
+ } else if (iconType == QLatin1String("unaccessible_webUrl")) {
+ iconParams.insert(source, QUrl(sourceIconResource));
+ }
+
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QString placeId;
+
+ if (iconType == QLatin1String("unaccessible_webUrl")) {
+ QVERIFY(doSavePlace(place,QPlaceReply::BadArgumentError));
+ } else {
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+ QPlace retrievedPlace;
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ if (expectedDestination != QString()) {
+ QVERIFY(retrievedPlace.icon().parameters().contains(expectedDestination));
+
+ QUrl retrievedUrl = retrievedPlace.icon().parameters().value(expectedDestination).toUrl();
+ QImage retrievedImage;
+ if (expectedDestination != QString())
+ QVERIFY(retrievedUrl.scheme().compare(QLatin1String("data"), Qt::CaseInsensitive) == 0);
+ retrievedImage = dataUrlToImage(retrievedUrl);
+ QCOMPARE(retrievedImage.size(), iconSize);
+ }
+ }
+}
+
+void tst_QPlaceManagerJsonDb::iconSourceOnly_data()
+{
+ QTest::addColumn<QString>("sourceIconResource");
+ QTest::addColumn<QSize>("iconSize");
+ QTest::addColumn<QString>("iconType");
+ QTest::addColumn<QString>("source");
+ QTest::addColumn<QString>("expectedDestination");
+
+ //input icon is a file
+ QTest::newRow("source small file") << ":/resources/icon_small.png" << SmallSize << "file" << SmallSource << SmallDestination;
+ QTest::newRow("source medium file") << ":/resources/icon_medium.png" << MediumSize << "file" << MediumSource << MediumDestination;
+ QTest::newRow("source large file") << ":/resources/icon_large.png" << LargeSize << "file" << LargeSource << LargeDestination;
+ QTest::newRow("source fullscreen file") << ":/resources/icon_fullscreen.png" << FullscreenSize << "file" << FullscreenSource << ""; //fullscreen icons shouldn't be saved as data urls
+
+ //input is a file but an improper url (e.g of the format /some/path instead of file:///some/path)
+ QTest::newRow("source small file_improperUrl") << ":/resources/icon_small.png" << SmallSize << "file_improperUrl" << SmallSource << SmallDestination;
+ QTest::newRow("source medium file_improperUrl") << ":/resources/icon_medium.png" << MediumSize << "file_improperUrl" << MediumSource << MediumDestination;
+ QTest::newRow("source large file_improperUrl") << ":/resources/icon_large.png" << LargeSize << "file_improperUrl" << LargeSource << LargeDestination;
+ QTest::newRow("source fullscreen file_improperUrl") << ":/resources/icon_fullscreen.png" << FullscreenSize << "file_improperUrl" << FullscreenSource << ""; //fullscreen icons shouldn't be saved as data urls
+
+ //input icon is a data url
+ QTest::newRow("source small dataUrl") << ":/resources/icon_small.png" << SmallSize << "dataUrl" << SmallSource << SmallDestination;
+ QTest::newRow("source medium dataUrl") << ":/resources/icon_medium.png" << MediumSize << "dataUrl" << MediumSource << MediumDestination;
+ QTest::newRow("source large dataUrl") << ":/resources/icon_large.png" << LargeSize << "dataUrl" << LargeSource << LargeDestination;
+ QTest::newRow("source fullscreen dataUrl") << ":/resources/icon_fullscreen.png" << FullscreenSize << "dataUrl" << FullscreenSource << ""; //fullscreen icons shouldn't be saved as data urls
+
+ //input icon is a non reachable url
+ QTest::newRow("source small unaccessible_webUrl") << "www.example.com/icon_small.png" << SmallSize << "unaccessible_webUrl" << SmallSource << SmallDestination;
+ QTest::newRow("source medium unaccessible_webUrl") << "www.example.com/icon_medium.png" << MediumSize << "unaccessible_webUrl" << MediumSource << MediumDestination;
+ QTest::newRow("source large unaccessible_webUrl") << "www.example.com/icon_large.png" << LargeSize << "unaccessible_webUrl" << LargeSource << LargeDestination;
+ QTest::newRow("source fullscreen unaccessible_webUrl") << "www.example.com/icon_fullscreen.png" << FullscreenSize << "unaccessible_webUrl" << FullscreenSource << ""; //fullscreen icons shouldn't be saved as data urls
+}
+
+void tst_QPlaceManagerJsonDb::iconDestinationOnly()
+{
+ //We test when a destination url is provided, that it is correctly saved
+ //No soure urls are provided while destination urls are.
+ QFETCH(QString, destination);
+ QFETCH(QUrl, destinationUrl);
+ QFETCH(QSize, specifiedSize);
+ QFETCH(QString, iconResource); //empty reosurce indicates icon is not reachable/accessible
+
+ QString destinationSize = destination;
+ destinationSize.replace(QLatin1String("Url"), QLatin1String("Size"));
+
+ QVariantMap iconParams;
+
+ QTemporaryFile destinationFile;
+ QSize size;
+ if (destinationUrl.toString().startsWith("_autogenerated_file_")) {
+ QImage iconImage(iconResource);
+ destinationFile.open();
+ iconImage.save(destinationFile.fileName(), QImageReader::imageFormat(iconResource));
+ size = iconImage.size();
+
+ if (destinationUrl == QUrl("_autogenerated_file_no_scheme_url_"))
+ destinationUrl = QUrl::fromLocalFile(destinationFile.fileName());
+ else
+ destinationUrl = QUrl::fromLocalFile(destinationFile.fileName());
+ } else if (destinationUrl == QUrl("_data_url_")) {
+ QFile iconFile(iconResource);
+ iconFile.open(QIODevice::ReadOnly);
+
+ QString mimeType;
+ if (QImageReader::imageFormat(iconResource) == "png")
+ mimeType = QLatin1String("image/png");
+
+ QImage iconImage(iconResource);
+ size = iconImage.size();
+
+ destinationUrl = QUrl(QString::fromLatin1("data:") + mimeType + QLatin1String(";base64,") + iconFile.readAll().toBase64());
+ }
+
+ iconParams.insert(destination, destinationUrl);
+
+ if (!specifiedSize.isEmpty())
+ iconParams.insert(destinationSize, specifiedSize);
+
+ QPlace place;
+ place.setName("Place");
+ QPlaceIcon icon;
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QString placeId;
+
+ if (specifiedSize.isEmpty() && iconResource.isEmpty()) {
+ QVERIFY(doSavePlace(place, QPlaceReply::BadArgumentError));
+ return;
+ } else {
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+ }
+
+ QPlace retrievedPlace;
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(destination));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destination).toUrl(), destinationUrl);
+
+ if (!specifiedSize.isEmpty() && iconResource.isEmpty()) {
+ QVERIFY(retrievedPlace.icon().parameters().contains(destinationSize));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destinationSize).toSize(), specifiedSize);
+ } else {
+ QCOMPARE(retrievedPlace.icon().parameters().value(destinationSize).toSize(), size);
+ }
+}
+
+void tst_QPlaceManagerJsonDb::iconDestinationOnly_data()
+{
+ QTest::addColumn<QString>("destination");
+ QTest::addColumn<QUrl>("destinationUrl");
+ QTest::addColumn<QSize>("specifiedSize");
+ QTest::addColumn<QString>("iconResource");
+
+ //destination url is local file, no size is specified
+ QTest::newRow("destination small file no_size_provided") << SmallDestination << QUrl("_autogenerated_file_") << QSize() << ":/resources/icon_small.png";
+ QTest::newRow("destination medium file no_size_provided") << MediumDestination << QUrl("_autogenerated_file_") << QSize() << ":/resources/icon_medium.png";
+ QTest::newRow("destination large file no_size_provided") << LargeDestination << QUrl("_autogenerated_file_") << QSize() << ":/resources/icon_large.png";
+ QTest::newRow("destination fullscreen file no_size_provided") << FullscreenDestination << QUrl("_autogenerated_file_") << QSize() << ":/resources/icon_fullscreen.png";
+
+ //destination url is local file, no size is specified, the url has no scheme
+ QTest::newRow("destination small file no_size_provided") << SmallDestination << QUrl("_autogenerated_file_no_scheme_url_") << QSize() << ":/resources/icon_small.png";
+ QTest::newRow("destination medium file no_size_provided") << MediumDestination << QUrl("_autogenerated_file_no_scheme_url_") << QSize() << ":/resources/icon_medium.png";
+ QTest::newRow("destination large file no_size_provided") << LargeDestination << QUrl("_autogenerated_file_no_scheme_url_") << QSize() << ":/resources/icon_large.png";
+ QTest::newRow("destination fullscreen file no_size_provided") << FullscreenDestination << QUrl("_autogenerated_file_no_scheme_url_") << QSize() << ":/resources/icon_fullscreen.png";
+
+ //destination url is local file and an (inaccurate) size is specified, (the actual size of file should take precedence)
+ QTest::newRow("destination small file size_provided") << SmallDestination << QUrl("_autogenerated_file_") << QSize(86,99) << ":/resources/icon_small.png";
+ QTest::newRow("destination medium file size_provided") << MediumDestination << QUrl("_autogenerated_file_") << QSize(86, 99) << ":/resources/icon_medium.png";
+ QTest::newRow("destination large file size_provided") << LargeDestination << QUrl("_autogenerated_file_") << QSize(86, 99) << ":/resources/icon_large.png";
+ QTest::newRow("destination fulscreen file size_provided") << FullscreenDestination << QUrl("_autogenerated_file_") << QSize(86, 99) << ":/resources/icon_fullscreen.png";
+
+ //destination url is a data url, no size is specified
+ QTest::newRow("destination small dataurl no_size_provided") << SmallDestination << QUrl("_data_url_") << QSize() << ":/resources/icon_small.png";
+ QTest::newRow("destination medium dataurl no_size_provided") << MediumDestination << QUrl("_data_url_") << QSize() << ":/resources/icon_medium.png";
+ QTest::newRow("destination large dataurl no_size_provided") << LargeDestination << QUrl("_data_url_") << QSize() << ":/resources/icon_large.png";
+ QTest::newRow("destination fullscreen dataurl no_size_provided") << FullscreenDestination << QUrl("_data_url_") << QSize() << ":/resources/icon_fullscreen.png";
+
+ //destination url is a data url, and an (inaccurate) size is specified, (the actual size of the icon should take precedence)
+ QTest::newRow("destination small dataurl size_provided") << SmallDestination << QUrl("_data_url_") << QSize(86,99) << ":/resources/icon_small.png";
+ QTest::newRow("destination medium dataurl size_provided") << MediumDestination << QUrl("_data_url_") << QSize(86, 99) << ":/resources/icon_medium.png";
+ QTest::newRow("destination large dataurl size_provided") << LargeDestination << QUrl("_data_url_") << QSize(86, 99) << ":/resources/icon_large.png";
+ QTest::newRow("destination fullscreen dataurl size_provided") << FullscreenDestination << QUrl("_data_url_") << QSize(86, 99) << ":/resources/icon_fullscreen.png";
+
+ //destination url is not accessible and size is specified
+ QTest::newRow("destination small unaccessible_webUrl size_provided") << SmallDestination << QUrl("http://www.example.com/iconS.png") << SmallSize << "";
+ QTest::newRow("destination medium unaccessible_webUrl size_provided") << MediumDestination << QUrl("http://www.example.com/iconM.png") << MediumSize << "" ;
+ QTest::newRow("destination large unaccessible_webUrl size_provided") << LargeDestination << QUrl("http://www.example.com/iconL.png") << LargeSize << "";
+ QTest::newRow("destination fullscreen unaccessible_webUrl size_provided") << FullscreenDestination << QUrl("http://www.example.com/iconF.png") << FullscreenSize << "";
+
+ //destination url is accessible and no size is provided, expect failure to save
+ QTest::newRow("destination small unaccessible_webUrl no_size_provided") << SmallDestination << QUrl("http://www.example.com/iconS.png") << QSize() << "";
+ QTest::newRow("destination medium unaccessible_webUrl no_size_provided") << MediumDestination << QUrl("http://www.example.com/iconM.png") << QSize() << "" ;
+ QTest::newRow("destination large unaccessible_webUrl no_size_provided") << LargeDestination << QUrl("http://www.example.com/iconL.png") << QSize() << "";
+ QTest::newRow("destination fullscreen unaccessible_webUrl no_size_provided") << FullscreenDestination << QUrl("http://www.example.com/iconL.png") << QSize() << "";
+}
+
+void tst_QPlaceManagerJsonDb::iconSavedFromDifferentManager()
+{
+ QGeoServiceProvider geoTest("qmlgeo.test.plugin");
+ QPlaceManager *geoTestManager = geoTest.placeManager();
+
+ QPlaceIcon icon;
+ icon.setManager(geoTestManager);
+ QVariantMap iconParams;
+
+ QTemporaryFile sourceIconFile;
+ QImage sourceIconImage(":/resources/icon_small.png");
+ sourceIconFile.open();
+ sourceIconImage.save(sourceIconFile.fileName(), "png");
+
+ //try an icon from another manager which different icons for each size variant
+ //check that we get correctly generated data urls
+ iconParams.insert("s", QUrl::fromLocalFile(":/resources/icon_small.png"));
+ iconParams.insert("m", QUrl::fromLocalFile(":/resources/icon_medium.png"));
+ iconParams.insert("l", QUrl::fromLocalFile(":/resources/icon_large.png"));
+ iconParams.insert("f", QUrl::fromLocalFile(":/resources/icon_fullscreen.png"));
+ icon.setParameters(iconParams);
+
+ QPlace place;
+ place.setName("Place");
+ place.setIcon(icon);
+
+ QPlace compatiblePlace = placeManager->compatiblePlace(place);
+ QString placeId;
+ QVERIFY(doSavePlace(compatiblePlace,QPlaceReply::NoError, &placeId));
+
+ QPlace retrievedPlace;
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(SmallDestination));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(SmallDestinationSize));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(MediumDestination));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(MediumDestinationSize));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(LargeDestination));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(LargeDestinationSize));
+
+ //we don't expect fullscreen icon urls to be download into data urls
+ //data urls are only meant for small icons
+ QVERIFY(!retrievedPlace.icon().parameters().keys().contains(FullscreenDestination));
+
+ QImage smallImage = dataUrlToImage(retrievedPlace.icon().parameters().value(SmallDestination).toUrl());
+ QImage mediumImage = dataUrlToImage(retrievedPlace.icon().parameters().value(MediumDestination).toUrl());
+ QImage largeImage = dataUrlToImage(retrievedPlace.icon().parameters().value(LargeDestination).toUrl());
+
+ QCOMPARE(smallImage.size(), SmallSize);
+ QCOMPARE(mediumImage.size(), MediumSize);
+ QCOMPARE(largeImage.size(), LargeSize);
+
+ QCOMPARE(retrievedPlace.icon().parameters().value(SmallDestinationSize).toSize(), SmallSize);
+ QCOMPARE(retrievedPlace.icon().parameters().value(MediumDestinationSize).toSize(), MediumSize);
+ QCOMPARE(retrievedPlace.icon().parameters().value(LargeDestinationSize).toSize(), LargeSize);
+
+ //try an icon from another manaager which has only a single size variant
+ //check that we get only one size variant
+ iconParams.clear();
+ iconParams.insert("s", QUrl::fromLocalFile(":/resources/icon_small.png"));
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ compatiblePlace = placeManager->compatiblePlace(place);
+ QVERIFY(doSavePlace(compatiblePlace,QPlaceReply::NoError, &placeId));
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+
+ QCOMPARE(retrievedPlace.icon().parameters().keys().count(), 2);
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(SmallDestination));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(SmallDestinationSize));
+ smallImage = dataUrlToImage(retrievedPlace.icon().parameters().value(SmallDestination).toUrl());
+ QCOMPARE(smallImage.size(), SmallSize);
+ QSize size = retrievedPlace.icon().parameters().value(SmallDestinationSize).toSize();
+ QCOMPARE(size, SmallSize);
+
+ //try an icon from a manager which has sizes which don't exactly match the standard expected icons
+ //sizes, check that dataUrls are generated for the appropriate size variant
+ iconParams.clear();
+ iconParams.insert("m", QUrl::fromLocalFile(":/resources/icon_24x24.png"));
+ iconParams.insert("l", QUrl::fromLocalFile(":/resources/icon_40x40.png"));
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ compatiblePlace = placeManager->compatiblePlace(place);
+ QVERIFY(doSavePlace(compatiblePlace,QPlaceReply::NoError, &placeId));
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ QCOMPARE(retrievedPlace.icon().parameters().keys().count(), 4);
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(SmallDestination));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(SmallDestinationSize));
+ smallImage = dataUrlToImage(retrievedPlace.icon().parameters().value(SmallDestination).toUrl());
+ QCOMPARE(smallImage.size(), QSize(24,24));
+ size = retrievedPlace.icon().parameters().value(SmallDestinationSize).toSize();
+ QCOMPARE(size, QSize(24,24));
+
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(LargeDestination));
+ QVERIFY(retrievedPlace.icon().parameters().keys().contains(LargeDestinationSize));
+ smallImage = dataUrlToImage(retrievedPlace.icon().parameters().value(LargeDestination).toUrl());
+ QCOMPARE(smallImage.size(), QSize(40,40));
+ size = retrievedPlace.icon().parameters().value(LargeDestinationSize).toSize();
+ QCOMPARE(size, QSize(40,40));
+}
+
+void tst_QPlaceManagerJsonDb::iconFormats()
+{
+ QFETCH(QByteArray, imageFormat);
+ QFETCH(QString, mimeType);
+
+ QTemporaryFile sourceIconFile;
+ sourceIconFile.open();
+ QImage sourceIconImage;
+
+ if (imageFormat == "svg") {
+ QFile file(":/resources/icon_small.svg");
+ file.open(QIODevice::ReadOnly);
+ sourceIconFile.write(file.readAll());
+ sourceIconFile.close();
+ } else {
+ QVERIFY(sourceIconImage.load(":/resources/icon_small.png"));
+ QVERIFY(sourceIconImage.save(&sourceIconFile, imageFormat));
+ }
+
+ QVariantMap iconParams;
+ iconParams.insert(SmallSource, QUrl::fromLocalFile(sourceIconFile.fileName()));
+
+ QPlace place;
+ place.setName("place");
+ QPlaceIcon icon;
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+
+ QString placeId;
+
+ if (imageFormat == "tiff")
+ QEXPECT_FAIL("", "tiff format known to fail as documented in QTBUG-23898", Abort);
+
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+
+ QPlace retrievedPlace;
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+
+ QRegExp regExp("^data:(.*);.*$");
+ regExp.indexIn(retrievedPlace.icon().parameters().value(SmallDestination).toUrl().toString());
+ QCOMPARE(regExp.cap(1), mimeType);
+}
+
+void tst_QPlaceManagerJsonDb::iconFormats_data()
+{
+ QTest::addColumn<QByteArray>("imageFormat");
+ QTest::addColumn<QString>("mimeType");
+
+ QTest::newRow("bmp") << QByteArray("bmp") << "image/bmp";
+ QTest::newRow("jpg") << QByteArray("jpg") << "image/jpeg";
+ QTest::newRow("jpeg") << QByteArray("jpeg") << "image/jpeg";
+ QTest::newRow("png") << QByteArray("png") << "image/png";
+ QTest::newRow("pbm") << QByteArray("pbm") << "image/x-portable-bitmap";
+ QTest::newRow("pgm") << QByteArray("pgm") << "image/x-portable-graymap";
+ QTest::newRow("ppm") << QByteArray("ppm") << "image/x-portable-pixmap";
+ QTest::newRow("tiff") << QByteArray("tiff") << "image/tiff";
+ QTest::newRow("xbm") << QByteArray("xbm") << "image/x-xbitmap";
+ QTest::newRow("xpm") << QByteArray("xpm") << "image/x-xpixmap";
+ QTest::newRow("svg") << QByteArray("svg") << "image/svg+xml";
+}
+
+void tst_QPlaceManagerJsonDb::iconUrls()
+{
+ QFETCH(QString, sizeType);
+ QFETCH(QSize, size);
+
+ QString source = sizeType + QLatin1String("SourceUrl");
+ QString destination = sizeType + QLatin1String("Url");
+ QString destinationSize = sizeType + QLatin1String("Size");
+
+ QPlace place;
+ place.setName("place");
+ QPlaceIcon icon;
+ QVariantMap iconParams;
+
+ //test conversion to valid url, in this care using a valid file scheme
+ iconParams.insert(destination, QUrl("/home/user/icon.png"));
+ iconParams.insert(destinationSize, size);
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+
+ QString placeId;
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+
+ QPlace retrievedPlace;
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destination).toUrl(), QUrl("file:///home/user/icon.png"));
+
+ //test conversion to valid url,
+ iconParams.insert(destination, QUrl("qrc:/home/user/icon.png"));
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destination).toUrl(), QUrl("qrc:///home/user/icon.png"));
+
+ iconParams.insert(destination, QUrl("qrc:///home/user/icon.png"));
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destination).toUrl(), QUrl("qrc:///home/user/icon.png"));
+
+ //test urls that are non-encoded and encoded
+ iconParams.insert(destination, QUrl("qrc:///home/user/i con.png"));
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destination).toUrl(), QUrl("qrc:///home/user/i con.png"));
+
+ iconParams.insert(destination, QUrl("qrc:///home/user/ico%20n.png"));
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QVERIFY(doSavePlace(place,QPlaceReply::NoError, &placeId));
+ QVERIFY(doFetchDetails(placeId, &retrievedPlace));
+ QCOMPARE(retrievedPlace.icon().parameters().value(destination).toUrl(), QUrl("qrc:///home/user/ico n.png"));
+
+ //try using a QString instead of a url in the parameters
+ iconParams.insert(destination, "www.example.com");
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QVERIFY(doSavePlace(place,QPlaceReply::BadArgumentError, &placeId));
+
+ //try using a QString instead of a url in the parameters
+ iconParams.insert(source, "www.example.com");
+ icon.setParameters(iconParams);
+ place.setIcon(icon);
+ QVERIFY(doSavePlace(place,QPlaceReply::BadArgumentError, &placeId));
+}
+
+void tst_QPlaceManagerJsonDb::iconUrls_data()
+{
+ QTest::addColumn<QString>("sizeType");
+ QTest::addColumn<QSize>("size");
+
+ QTest::newRow("small") << "small" << SmallSize;
+ QTest::newRow("medium") << "medium" << MediumSize;
+ QTest::newRow("large") << "large" << LargeSize;
+ QTest::newRow("fullscreen") << "fullscreen" << FullscreenSize;
+}
+
+void tst_QPlaceManagerJsonDb::constructIconUrl()
+{
+ QPlaceIcon icon;
+ QVariantMap iconParams;
+
+ //try with all possible size buckets set
+ iconParams.insert(SmallDestination, QUrl("http://www.example.com/icon_small.png"));
+ iconParams.insert(SmallDestinationSize, SmallSize);
+ iconParams.insert(MediumDestination, QUrl("http://www.example.com/icon_medium.png"));
+ iconParams.insert(MediumDestinationSize, MediumSize);
+ iconParams.insert(LargeDestination, QUrl("http://www.example.com/icon_large.png"));
+ iconParams.insert(LargeDestinationSize, LargeSize);
+ iconParams.insert(FullscreenDestination, QUrl("http://www.example.com/icon_fullscreen.png"));
+ iconParams.insert(FullscreenDestinationSize, FullscreenSize);
+
+ icon.setParameters(iconParams);
+ icon.setManager(placeManager);
+
+ QCOMPARE(icon.url(SmallSize), QUrl("http://www.example.com/icon_small.png"));
+ QCOMPARE(icon.url(MediumSize), QUrl("http://www.example.com/icon_medium.png"));
+ QCOMPARE(icon.url(LargeSize), QUrl("http://www.example.com/icon_large.png"));
+ QCOMPARE(icon.url(FullscreenSize), QUrl("http://www.example.com/icon_fullscreen.png"));
+
+ //try with only a single destination icon set
+ iconParams.clear();
+ iconParams.insert(LargeDestination, QUrl("http://www.example.com/icon_large.png"));
+ iconParams.insert(LargeDestinationSize, LargeSize);
+ icon.setParameters(iconParams);
+
+ QCOMPARE(icon.url(SmallSize), QUrl("http://www.example.com/icon_large.png"));
+ QCOMPARE(icon.url(MediumSize), QUrl("http://www.example.com/icon_large.png"));
+ QCOMPARE(icon.url(LargeSize), QUrl("http://www.example.com/icon_large.png"));
+ QCOMPARE(icon.url(FullscreenSize), QUrl("http://www.example.com/icon_large.png"));
+
+ //try requesting non-standard sizes and don't populate all size buckets
+ iconParams.clear();
+ iconParams.insert(SmallDestination, QUrl("http://www.example.com/icon_small.png"));
+ iconParams.insert(SmallDestinationSize, SmallSize);
+ iconParams.insert(LargeDestination, QUrl("http://www.example.com/icon_large.png"));
+ iconParams.insert(LargeDestinationSize, LargeSize);
+ icon.setParameters(iconParams);
+
+ QCOMPARE(icon.url(QSize(10,10)), QUrl("http://www.example.com/icon_small.png"));
+ QCOMPARE(icon.url(QSize(34,34)), QUrl("http://www.example.com/icon_small.png"));
+ QCOMPARE(icon.url(QSize(35,35)), QUrl("http://www.example.com/icon_large.png"));
+ QCOMPARE(icon.url(QSize(60,60)), QUrl("http://www.example.com/icon_large.png"));
+
+ //try the icons themselves haveing non standard sizes
+ iconParams.clear();
+ iconParams.insert(SmallDestination, QUrl("http://www.example.com/icon_small.png"));
+ iconParams.insert(SmallDestinationSize, QSize(25,25));
+ iconParams.insert(LargeDestination, QUrl("http://www.example.com/icon_large.png"));
+ iconParams.insert(LargeDestinationSize, QSize(35,35));
+ icon.setParameters(iconParams);
+
+ QCOMPARE(icon.url(QSize(24,24)), QUrl("http://www.example.com/icon_small.png"));
+ QCOMPARE(icon.url(QSize(29,29)), QUrl("http://www.example.com/icon_small.png"));
+ QCOMPARE(icon.url(QSize(30,30)), QUrl("http://www.example.com/icon_large.png"));
+ QCOMPARE(icon.url(QSize(60,60)), QUrl("http://www.example.com/icon_large.png"));
+
+ //TODO: edge case testing for all combinations
+}
+
void tst_QPlaceManagerJsonDb::cleanup()
{
QSignalSpy cleanSpy(dbCleaner, SIGNAL(dbCleaned()));
@@ -1634,6 +2288,7 @@ bool tst_QPlaceManagerJsonDb::doSavePlace(const QPlace &place,
if (saveReply->id().isEmpty() && expectedError == QPlaceReply::NoError) {
qWarning("ID is empty in reply for save operation");
+ qWarning() << "Error string = " << saveReply->errorString();
isSuccessful = false;
}
@@ -1851,6 +2506,26 @@ bool tst_QPlaceManagerJsonDb::compareResults(const QList<QPlaceSearchResult> &re
return actualPlaceCoords == expectedPlaceCoords;
}
+QImage tst_QPlaceManagerJsonDb::dataUrlToImage(const QUrl &url)
+{
+ QByteArray data = QByteArray::fromPercentEncoding(url.toEncoded());
+ data.remove(0,5);
+ int pos = data.indexOf(',');
+ if (pos != -1) {
+ QByteArray payload = QByteArray::fromBase64(data.mid(pos + 1));
+ data.truncate(pos);
+
+ if (!data.endsWith(";base64")) {
+ qWarning() << "Data url payload not base64 encoded";
+ return QImage();
+ }
+
+ return QImage::fromData(payload);
+ }
+
+ return QImage();
+}
+
QTEST_APPLESS_MAIN(tst_QPlaceManagerJsonDb)
#include "tst_qplacemanager_jsondb.moc"
diff --git a/tests/auto/qplacesupplier/tst_qplacesupplier.cpp b/tests/auto/qplacesupplier/tst_qplacesupplier.cpp
index 1c23d052..f10f6cc1 100644
--- a/tests/auto/qplacesupplier/tst_qplacesupplier.cpp
+++ b/tests/auto/qplacesupplier/tst_qplacesupplier.cpp
@@ -107,14 +107,16 @@ void tst_QPlaceSupplier::iconTest()
QPlaceSupplier testObj;
QVERIFY(testObj.icon().isEmpty());
QPlaceIcon icon;
- icon.setFullUrl(QUrl::fromEncoded("http://example.com/icon.png"));
+ QVariantMap iconParams;
+ iconParams.insert(QPlaceIcon::SingleUrl, QUrl::fromEncoded("http://example.com/icon.png"));
+ icon.setParameters(iconParams);
testObj.setIcon(icon);
QCOMPARE(testObj.icon(), icon);
- QCOMPARE(testObj.icon().fullUrl(), QUrl::fromEncoded("http://example.com/icon.png"));
+ QCOMPARE(testObj.icon().url(), QUrl::fromEncoded("http://example.com/icon.png"));
testObj.setIcon(QPlaceIcon());
QVERIFY(testObj.icon().isEmpty());
- QCOMPARE(testObj.icon().fullUrl(), QUrl());
+ QCOMPARE(testObj.icon().url(), QUrl());
}
void tst_QPlaceSupplier::operatorsTest()
@@ -122,7 +124,9 @@ void tst_QPlaceSupplier::operatorsTest()
QPlaceSupplier testObj;
testObj.setName(QLatin1String("Acme"));
QPlaceIcon icon;
- icon.setFullUrl(QUrl::fromEncoded("http://example.com/testUrl"));
+ QVariantMap iconParams;
+ iconParams.insert(QPlaceIcon::SingleUrl, QUrl::fromEncoded("http://example.com/icon.png"));
+ icon.setParameters(iconParams);
testObj.setIcon(icon);
testObj.setSupplierId(QLatin1String("34292"));