summaryrefslogtreecommitdiff
path: root/doc/src/plugins/places-backend.qdoc
blob: 056967279ef47f9146b42a27564875fffed5bd1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** GNU Free Documentation License
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file.
**
** 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$
**
****************************************************************************/

/*!
\page location-places-backend.html
\title Places Backend
\previouspage {QtLocation Module}

\brief The Places backend is responsible for managing a places datastore whether
       it is located remotely or locally

\section1 Overview

The QPlaceManager interface, provided to clients to allow access to place information,
depends directly on an implementation of QPlaceManagerEngine.  The engine provides
the backend function implementations which are called by the manager.

A places backend implementer needs to derive from QPlaceManagerEngine
and provide implementations for the abstract virtual functions.  Most of these
functions are asynchronous and so implementers will also need to derive
the appropriate \l {Places Reply Classes}{reply classes}.  The reply objects are reponsible for managing
an asynchronous request; they are used to notify when a request is complete
and hold the results of that request.

\section1 Implementing/Inheriting reply objects
A reply object would be inherited as follows:
\snippet snippets/places/requesthandler.h Implement reply pt1
\dots
\snippet snippets/places/requesthandler.h Implement reply pt2

The protected functions of QPlaceSearchReply::setResults() and QPlaceSearchReply::setRequest()
are made publically accessible so the plugin can assign results and requests.  Because
these functions are not publically exported, accessibility is not so much of an issue.
An alternative would have been to declare a friend class in SearchReply.

Typically the engine instance would be made the \c parent of the reply.  If the developer
fails to discard the replies when finished, the engine can clean those upon destruction.
Commonly, the reply also has a pointer reference back to the engine, which may be used
to emit the QPlaceManagerEngine::finished() and QPlaceManagerEngine::error() signals.  This is
just one of many ways the reply could be implemented.

Usually the QPlaceReply::finished() signal of the reply is somehow tied to a notification mechanism of the
implementation e.g. for a network based engine, the reply's finished signal may be
emitted from a slot which is in turn is invoked by a QNetworkReply::finished() signal.
Sometimes however, we may want to emit the QPlaceReply::finished() signal without
depending upon an underlying asynchronous notification mechanism.  This
is a common case when a portion of functionality is not supported.  For example,
a backend may not support search term suggestions, so we need a way to trigger the finished
signal (and error signals), but there's no underlying asynchronous mechanism to do so.  In this case,
the typical approach is to use QMetaObject::invokeMethod() with a Qt::QueuedConnection,
so that the QPlaceReply::finished(), QPlaceReply::error(), QPlaceManagerEngine::finished()
and QPlaceManagerEngine::error() signals are emitted at the next event loop.

\snippet snippets/places/requesthandler.h Trigger done
(\note  the above code is not necessary if there already is an underlying
asynchronous notification mechanism)

Also note that the \c finished signals should always be emitted when a reply is complete, even if
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

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.

\section1 Categories
The categories of a manager engine are relatively static entities; for engines accessing
remote place datastores it may be desirable to cache the category structure rather than
querying a server every time QPlaceManagerEngine::initializeCategories() is called.
Depending on how dynamic the categories are, always downloading the freshest
set of categories may be more appropriate.

\section1 Saving between managers.
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
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.

\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
manager (destnation manager) is used to save selected favorites from the first.  During a search of the origin manager, we may want to
know which ones have been 'favorited' into the destination manager and perhaps display the customized favorite name
rather than the original name.

\section2 Alternative Id cross-referencing
In order to accomplish cross-referencing, there needs to be a link from between the original place and the favorited place
and this is typically handled via an alternative id attribute.  The favorited place contains an alternative id attrbute which has the
id of the original place.

\input place-crossref.qdocinc

There are 3 prerequisites for implementing cross-referencing by alternative id.  The first is that the origin manager must provide the x_provider attribute
with the value being the name of the manager's QGeoServiceProvider.  The attribute label should be kept empty, indicating the attribute should not
be displayed to users.  \note It is generally expected that all managers should set the \c x_provider attribute.

The second is that QPlaceManager::compatiblePlace() of the destination manager use the \c x_provider attribute of the initial place
and set an alternative id attribute of the place to be saved.  The key of the alternative id attribute is \c x_id_<provider name> and
the text value is the id of the initial place.  The \c x_provider attribute should not be passed to the compatible place.  When
it is saved, the x_provider of the saved place is considered to be the destination manager.

The third is that QPlaceManager::matchingPlaces() of the destination manager accept the QPlaceMatchRequest::AlternativeId as a parameter key
and the alternative id attribute key as the value, in this case \c x_id_<provider name> would be the expected value.
This indicates that the ids of places in the QPlaceMatchRequest should be matched against the \c x_id_<provider name> alternative id attributes.

Note that if the destination manager is to facilitate saving and cross-referencing from any arbitrary manager, it internally must
accommodate saving of arbitrary key value pairs since we cannot know the provider names before hand, nor can we know what structure the
ids will be.

\section3 Other methods of linking
If an origin manager does not supply a place id, it may be necessary to provide some other means of cross-referencing/matching.
One approach might be to do so via the place coordinates, if the coordinate of a place in the origin manager is identical or close
to a place in the destination manager, there is a high likelihood that they are the same place.
In this case, the manager might implement QPlaceManager::matchingPlaces() to accept a QPlaceMatchRequest with a parameter key of 'proximity'
and a parameter value of the distance two places must be in order to detect a match.  e.g. if an origin place and destination place are within 50m
of each other, they can be considered the same place.

Generally however it is recommended that cross referencing be implemented via alternative ids as mentioned above.

\section3 User readable vs non-user readable extended attributes
If an attribute is not intended to be readble by end users, the label field should be kept
empty as an indicator of this fact.
*/