1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtLocation module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #include "qdeclarativesearchmodelbase_p.h"
38 #include "qdeclarativeplace_p.h"
39 #include "error_messages_p.h"
40 
41 #include <QtCore/QCoreApplication>
42 #include <QtQml/QQmlInfo>
43 #include <QtLocation/QGeoServiceProvider>
44 #include <QtLocation/QPlaceManager>
45 #include <QtLocation/QPlaceSearchRequest>
46 #include <QtLocation/QPlaceSearchReply>
47 #include <QtPositioning/QGeoCircle>
48 #include <QtPositioning/QGeoPolygon>
49 #include <QtLocation/private/qdeclarativegeoroute_p.h>
50 #include <QtLocation/private/qplacesearchrequest_p.h>
51 
52 QT_BEGIN_NAMESPACE
53 
QDeclarativeSearchModelBase(QObject * parent)54 QDeclarativeSearchModelBase::QDeclarativeSearchModelBase(QObject *parent)
55 :   QAbstractListModel(parent), m_plugin(0), m_reply(0), m_complete(false), m_status(Null)
56 {
57 }
58 
~QDeclarativeSearchModelBase()59 QDeclarativeSearchModelBase::~QDeclarativeSearchModelBase()
60 {
61 }
62 
63 /*!
64     \internal
65 */
plugin() const66 QDeclarativeGeoServiceProvider *QDeclarativeSearchModelBase::plugin() const
67 {
68     return m_plugin;
69 }
70 
71 /*!
72     \internal
73 */
setPlugin(QDeclarativeGeoServiceProvider * plugin)74 void QDeclarativeSearchModelBase::setPlugin(QDeclarativeGeoServiceProvider *plugin)
75 {
76     if (m_plugin == plugin)
77         return;
78 
79     initializePlugin(plugin);
80 
81     if (m_complete)
82         emit pluginChanged();
83 }
84 
85 /*!
86     \internal
87 */
searchArea() const88 QVariant QDeclarativeSearchModelBase::searchArea() const
89 {
90     QGeoShape s = m_request.searchArea();
91     if (s.type() == QGeoShape::RectangleType)
92         return QVariant::fromValue(QGeoRectangle(s));
93     else if (s.type() == QGeoShape::CircleType)
94         return QVariant::fromValue(QGeoCircle(s));
95     else if (s.type() == QGeoShape::PolygonType)
96         return QVariant::fromValue(QGeoPolygon(s));
97     else
98         return QVariant::fromValue(s);
99 }
100 
101 /*!
102     \internal
103 */
setSearchArea(const QVariant & searchArea)104 void QDeclarativeSearchModelBase::setSearchArea(const QVariant &searchArea)
105 {
106     QGeoShape s;
107     QDeclarativeGeoRoute *route = nullptr;
108     bool routeSearchArea = false;
109     if (searchArea.userType() == qMetaTypeId<QGeoRectangle>())
110         s = searchArea.value<QGeoRectangle>();
111     else if (searchArea.userType() == qMetaTypeId<QGeoCircle>())
112         s = searchArea.value<QGeoCircle>();
113     else if (searchArea.userType() == qMetaTypeId<QGeoShape>())
114         s = searchArea.value<QGeoShape>();
115     else if (int(searchArea.type()) == qMetaTypeId<QObject *>()) {
116         route = searchArea.value<QDeclarativeGeoRoute *>();
117         if (!route)
118             return;
119         routeSearchArea = true;
120     }
121 
122     QPlaceSearchRequestPrivate *rp = QPlaceSearchRequestPrivate::get(m_request);
123     // Invalidating the other thing
124     if (routeSearchArea)
125         m_request.setSearchArea(QGeoShape());
126     else
127         rp->routeSearchArea = QGeoRoute();
128 
129     if (m_request.searchArea() == s
130             && (!route || rp->routeSearchArea == route->route()))
131         return;
132 
133     if (routeSearchArea)
134         rp->routeSearchArea = route->route();
135     else
136         m_request.setSearchArea(s);
137     emit searchAreaChanged();
138 }
139 
140 /*!
141     \internal
142 */
limit() const143 int QDeclarativeSearchModelBase::limit() const
144 {
145     return m_request.limit();
146 }
147 
148 /*!
149     \internal
150 */
setLimit(int limit)151 void QDeclarativeSearchModelBase::setLimit(int limit)
152 {
153     if (m_request.limit() == limit)
154         return;
155 
156     m_request.setLimit(limit);
157     emit limitChanged();
158 }
159 
160 /*!
161     \internal
162 */
previousPagesAvailable() const163 bool QDeclarativeSearchModelBase::previousPagesAvailable() const
164 {
165     return m_previousPageRequest != QPlaceSearchRequest();
166 }
167 
168 /*!
169     \internal
170 */
nextPagesAvailable() const171 bool QDeclarativeSearchModelBase::nextPagesAvailable() const
172 {
173     return m_nextPageRequest != QPlaceSearchRequest();
174 }
175 
176 /*!
177     \internal
178 */
status() const179 QDeclarativeSearchModelBase::Status QDeclarativeSearchModelBase::status() const
180 {
181     return m_status;
182 }
183 
184 /*!
185     \internal
186 */
setStatus(Status status,const QString & errorString)187 void QDeclarativeSearchModelBase::setStatus(Status status, const QString &errorString)
188 {
189     Status prevStatus = m_status;
190 
191     m_status = status;
192     m_errorString = errorString;
193 
194     if (prevStatus != m_status)
195         emit statusChanged();
196 }
197 
198 /*!
199     \internal
200 */
update()201 void QDeclarativeSearchModelBase::update()
202 {
203     if (m_reply)
204         return;
205 
206     setStatus(Loading);
207 
208     if (!m_plugin) {
209         clearData();
210         setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET));
211         return;
212     }
213 
214     QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
215     if (!serviceProvider) {
216         clearData();
217         setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR)
218                          .arg(m_plugin->name()));
219         return;
220     }
221 
222     QPlaceManager *placeManager = serviceProvider->placeManager();
223     if (!placeManager) {
224         clearData();
225         setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
226                          .arg(m_plugin->name()).arg(serviceProvider->errorString()));
227         return;
228     }
229 
230     m_reply = sendQuery(placeManager, m_request);
231     if (!m_reply) {
232         clearData();
233         setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, UNABLE_TO_MAKE_REQUEST));
234         return;
235     }
236 
237     m_reply->setParent(this);
238     connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished()));
239     connect(m_reply, SIGNAL(contentUpdated()), this, SLOT(onContentUpdated()));
240 }
241 
242 /*!
243     \internal
244 */
cancel()245 void QDeclarativeSearchModelBase::cancel()
246 {
247     if (!m_reply)
248         return;
249 
250     if (!m_reply->isFinished())
251         m_reply->abort();
252 
253     if (m_reply) {
254         m_reply->deleteLater();
255         m_reply = 0;
256     }
257 
258     setStatus(Ready);
259 }
260 
261 /*!
262     \internal
263 */
reset()264 void QDeclarativeSearchModelBase::reset()
265 {
266     beginResetModel();
267     clearData();
268     setStatus(Null);
269     endResetModel();
270 }
271 
272 /*!
273     \internal
274 */
errorString() const275 QString QDeclarativeSearchModelBase::errorString() const
276 {
277     return m_errorString;
278 }
279 
280 /*!
281     \internal
282 */
previousPage()283 void QDeclarativeSearchModelBase::previousPage()
284 {
285     if (m_previousPageRequest == QPlaceSearchRequest())
286         return;
287 
288     m_request = m_previousPageRequest;
289     update();
290 }
291 
292 /*!
293     \internal
294 */
nextPage()295 void QDeclarativeSearchModelBase::nextPage()
296 {
297     if (m_nextPageRequest == QPlaceSearchRequest())
298         return;
299 
300     m_request = m_nextPageRequest;
301     update();
302 }
303 
304 /*!
305     \internal
306 */
clearData(bool suppressSignal)307 void QDeclarativeSearchModelBase::clearData(bool suppressSignal)
308 {
309     Q_UNUSED(suppressSignal);
310 }
311 
312 /*!
313     \internal
314 */
classBegin()315 void QDeclarativeSearchModelBase::classBegin()
316 {
317 }
318 
319 /*!
320     \internal
321 */
componentComplete()322 void QDeclarativeSearchModelBase::componentComplete()
323 {
324     m_complete = true;
325 }
326 
327 /*!
328     \internal
329 */
initializePlugin(QDeclarativeGeoServiceProvider * plugin)330 void QDeclarativeSearchModelBase::initializePlugin(QDeclarativeGeoServiceProvider *plugin)
331 {
332     beginResetModel();
333     if (plugin != m_plugin) {
334         if (m_plugin)
335             disconnect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(pluginNameChanged()));
336         if (plugin)
337             connect(plugin, SIGNAL(nameChanged(QString)), this, SLOT(pluginNameChanged()));
338         m_plugin = plugin;
339     }
340 
341     if (m_plugin) {
342         QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
343         if (serviceProvider) {
344             QPlaceManager *placeManager = serviceProvider->placeManager();
345             if (placeManager) {
346                 if (placeManager->childCategoryIds().isEmpty()) {
347                     QPlaceReply *reply = placeManager->initializeCategories();
348                     connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));
349                 }
350             }
351         }
352     }
353 
354     endResetModel();
355 }
356 
onContentUpdated()357 void QDeclarativeSearchModelBase::onContentUpdated()
358 {
359 
360 }
361 
362 /*!
363     \internal
364 */
pluginNameChanged()365 void QDeclarativeSearchModelBase::pluginNameChanged()
366 {
367     initializePlugin(m_plugin);
368 }
369 
370 /*!
371     \internal
372 */
setPreviousPageRequest(const QPlaceSearchRequest & previous)373 void QDeclarativeSearchModelBase::setPreviousPageRequest(const QPlaceSearchRequest &previous)
374 {
375     if (m_previousPageRequest == previous)
376         return;
377 
378     m_previousPageRequest = previous;
379     emit previousPagesAvailableChanged();
380 }
381 
setNextPageRequest(const QPlaceSearchRequest & next)382 void QDeclarativeSearchModelBase::setNextPageRequest(const QPlaceSearchRequest &next)
383 {
384     if (m_nextPageRequest == next)
385         return;
386 
387     m_nextPageRequest = next;
388     emit nextPagesAvailableChanged();
389 }
390 
391 QT_END_NAMESPACE
392