summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2017-12-22 18:17:19 +0100
committerPaolo Angelelli <paolo.angelelli@qt.io>2018-07-05 06:09:56 +0000
commitf8df5799b68fcb8690462b6dce226e6ce9bac282 (patch)
treec88fbdc8b4bd28662cfe3c14d665c4744fc29057
parent5ccc595db4e9282f6a58f8712550eda935a6eecb (diff)
downloadqtlocation-f8df5799b68fcb8690462b6dce226e6ce9bac282.tar.gz
Enable incremental updates in PlaceSearchModel
This way pages can be changed without resetting the model. To achieve this, new members into QPlaceSearchRequestPrivate are introduced, to keep the relationship between a request for one page, and the previous or the next page. In this way sparse population of the model becomes possible. Change-Id: Ic8db0281408f3500ba83f78c7e152ee0b68cd099 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/imports/location/location.cpp1
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp80
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h8
-rw-r--r--src/location/places/places.pri1
-rw-r--r--src/location/places/qplacesearchrequest.cpp44
-rw-r--r--src/location/places/qplacesearchrequest.h2
-rw-r--r--src/location/places/qplacesearchrequest_p.h79
-rw-r--r--src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp10
-rw-r--r--src/plugins/geoservices/osm/qplacemanagerengineosm.cpp2
-rw-r--r--src/plugins/geoservices/osm/qplacesearchreplyosm.cpp7
10 files changed, 203 insertions, 31 deletions
diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp
index fc2b62c3..b632836f 100644
--- a/src/imports/location/location.cpp
+++ b/src/imports/location/location.cpp
@@ -189,6 +189,7 @@ public:
// Register the 5.12 types
minor = 12;
qmlRegisterType<QDeclarativeGeoMapItemView, 12>(uri, major, minor, "MapItemView");
+ qmlRegisterType<QDeclarativeSearchResultModel, 12>(uri, major, minor, "PlaceSearchModel");
// Register the latest Qt version as QML type version
qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
index ed99da1c..73e43240 100644
--- a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
@@ -47,6 +47,7 @@
#include <QtLocation/QPlaceMatchReply>
#include <QtLocation/QPlaceResult>
#include <QtLocation/QPlaceProposedSearchResult>
+#include <QtLocation/private/qplacesearchrequest_p.h>
QT_BEGIN_NAMESPACE
@@ -260,6 +261,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \qmlproperty bool PlaceSearchModel::incremental
+
+ This property controls how paging will affect the PlaceSearchModel.
+ If true, calling \l previousPage or \l nextPage will not reset the model,
+ but new results will instead be appended to the model.
+ Default is false.
+
+ \since QtLocation 5.12
+*/
+
+
+/*!
\qmlmethod void PlaceSearchModel::update()
Updates the model based on the provided query parameters. The model will be populated with a
@@ -733,6 +746,9 @@ void QDeclarativeSearchResultModel::queryFinished()
return;
QPlaceReply *reply = m_reply;
m_reply = 0;
+ if (!m_incremental)
+ m_pages.clear();
+
if (reply->error() != QPlaceReply::NoError) {
m_resultsBuffer.clear();
updateLayout();
@@ -745,7 +761,14 @@ void QDeclarativeSearchResultModel::queryFinished()
QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
Q_ASSERT(searchReply);
+ const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
+ if (!rpimpl->related || !m_incremental)
+ m_pages.clear();
m_resultsBuffer = searchReply->results();
+ bool alreadyLoaded = false;
+ if (m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))
+ alreadyLoaded = true;
+ m_pages.insert(rpimpl->page, m_resultsBuffer);
setPreviousPageRequest(searchReply->previousPageRequest());
setNextPageRequest(searchReply->nextPageRequest());
@@ -785,6 +808,8 @@ void QDeclarativeSearchResultModel::queryFinished()
}
request.setResults(m_resultsBuffer);
+ if (alreadyLoaded)
+ m_resultsBuffer.clear();
m_reply = favoritesManager->matchingPlaces(request);
connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished()));
}
@@ -823,14 +848,24 @@ void QDeclarativeSearchResultModel::queryFinished()
*/
void QDeclarativeSearchResultModel::updateLayout(const QList<QPlace> &favoritePlaces)
{
- int oldRowCount = rowCount();
+ const int oldRowCount = rowCount();
+ int start = 0;
- beginResetModel();
- clearData(true);
- m_results = m_resultsBuffer;
- m_resultsBuffer.clear();
+ if (m_incremental) {
+ if (!m_resultsBuffer.size())
+ return;
+
+ beginInsertRows(QModelIndex(), oldRowCount , oldRowCount + m_resultsBuffer.size() - 1);
+ m_results = resultsFromPages();
+ start = oldRowCount;
+ } else {
+ beginResetModel();
+ clearData(true);
+ m_results = m_resultsBuffer;
+ }
- for (int i = 0; i < m_results.count(); ++i) {
+ m_resultsBuffer.clear();
+ for (int i = start; i < m_results.count(); ++i) {
const QPlaceSearchResult &result = m_results.at(i);
if (result.type() == QPlaceSearchResult::PlaceResult) {
@@ -851,7 +886,10 @@ void QDeclarativeSearchResultModel::updateLayout(const QList<QPlace> &favoritePl
m_icons.append(icon);
}
- endResetModel();
+ if (m_incremental)
+ endInsertRows();
+ else
+ endResetModel();
if (m_results.count() != oldRowCount)
emit rowCountChanged();
}
@@ -882,11 +920,39 @@ void QDeclarativeSearchResultModel::placeRemoved(const QString &placeId)
delete m_places.at(row);
m_places.removeAt(row);
m_results.removeAt(row);
+ removePageRow(row);
endRemoveRows();
emit rowCountChanged();
}
+QList<QPlaceSearchResult> QDeclarativeSearchResultModel::resultsFromPages() const
+{
+ QList<QPlaceSearchResult> res;
+ QMapIterator<int, QList<QPlaceSearchResult>> i(m_pages);
+ while (i.hasNext()) {
+ i.next();
+ res.append(i.value());
+ }
+ return res;
+}
+
+void QDeclarativeSearchResultModel::removePageRow(int row)
+{
+ QMapIterator<int, QList<QPlaceSearchResult>> i(m_pages);
+ int scanned = 0;
+ while (i.hasNext()) {
+ i.next();
+ QList<QPlaceSearchResult> page = i.value();
+ scanned += page.size();
+ if (row >= scanned)
+ continue;
+ page.removeAt(row - scanned + page.size());
+ m_pages.insert(i.key(), page);
+ return;
+ }
+}
+
/*!
\internal
*/
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h b/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
index 77526fd0..037b91ad 100644
--- a/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
@@ -72,6 +72,8 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSearchResultModel : public QDeclarat
Q_PROPERTY(QDeclarativeGeoServiceProvider *favoritesPlugin READ favoritesPlugin WRITE setFavoritesPlugin NOTIFY favoritesPluginChanged)
Q_PROPERTY(QVariantMap favoritesMatchParameters READ favoritesMatchParameters WRITE setFavoritesMatchParameters NOTIFY favoritesMatchParametersChanged)
+ Q_PROPERTY(bool incremental MEMBER m_incremental NOTIFY incrementalChanged REVISION 12)
+
Q_ENUMS(SearchResultType RelevanceHint)
public:
@@ -137,6 +139,7 @@ Q_SIGNALS:
void favoritesPluginChanged();
void favoritesMatchParametersChanged();
void dataChanged();
+ void incrementalChanged();
protected:
QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request);
@@ -162,9 +165,13 @@ private:
};
int getRow(const QString &placeId) const;
+ QList<QPlaceSearchResult> resultsFromPages() const;
+ void removePageRow(int row);
+
QList<QDeclarativeCategory *> m_categories;
QLocation::VisibilityScope m_visibilityScope;
+ QMap<int, QList<QPlaceSearchResult>> m_pages;
QList<QPlaceSearchResult> m_results;
QList<QPlaceSearchResult> m_resultsBuffer;
QList<QDeclarativePlace *> m_places;
@@ -172,6 +179,7 @@ private:
QDeclarativeGeoServiceProvider *m_favoritesPlugin;
QVariantMap m_matchParameters;
+ bool m_incremental = false;
};
QT_END_NAMESPACE
diff --git a/src/location/places/places.pri b/src/location/places/places.pri
index 1a3796fc..5a766b61 100644
--- a/src/location/places/places.pri
+++ b/src/location/places/places.pri
@@ -24,6 +24,7 @@ PUBLIC_HEADERS += \
places/qplacecontentrequest.h \
places/qplacematchrequest.h \
places/qplacesearchrequest.h \
+ places/qplacesearchrequest_p.h \
#reply classes
places/qplacereply.h \
places/qplacedetailsreply.h \
diff --git a/src/location/places/qplacesearchrequest.cpp b/src/location/places/qplacesearchrequest.cpp
index c2d993e3..49e782c5 100644
--- a/src/location/places/qplacesearchrequest.cpp
+++ b/src/location/places/qplacesearchrequest.cpp
@@ -35,37 +35,17 @@
****************************************************************************/
#include "qplacesearchrequest.h"
+#include "qplacesearchrequest_p.h"
#include "qgeocoordinate.h"
#include "qgeoshape.h"
#include <QtCore/QSharedData>
#include <QtCore/QList>
#include <QtCore/QVariant>
+#include <QDebug>
QT_BEGIN_NAMESPACE
-class QPlaceSearchRequestPrivate : public QSharedData
-{
-public:
- QPlaceSearchRequestPrivate();
- QPlaceSearchRequestPrivate(const QPlaceSearchRequestPrivate &other);
- ~QPlaceSearchRequestPrivate();
-
- QPlaceSearchRequestPrivate &operator=(const QPlaceSearchRequestPrivate &other);
- bool operator==(const QPlaceSearchRequestPrivate &other) const;
-
- void clear();
-
- QString searchTerm;
- QList<QPlaceCategory> categories;
- QGeoShape searchArea;
- QString recommendationId;
- QLocation::VisibilityScope visibilityScope;
- QPlaceSearchRequest::RelevanceHint relevanceHint;
- int limit;
- QVariant searchContext;
-};
-
QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate()
: QSharedData(),
visibilityScope(QLocation::UnspecifiedVisibility),
@@ -83,7 +63,9 @@ QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate(const QPlaceSearchRequest
visibilityScope(other.visibilityScope),
relevanceHint(other.relevanceHint),
limit(other.limit),
- searchContext(other.searchContext)
+ searchContext(other.searchContext),
+ related(other.related),
+ page(other.page)
{
}
@@ -102,6 +84,8 @@ QPlaceSearchRequestPrivate &QPlaceSearchRequestPrivate::operator=(const QPlaceSe
relevanceHint = other.relevanceHint;
limit = other.limit;
searchContext = other.searchContext;
+ related = other.related;
+ page = other.page;
}
return *this;
@@ -117,6 +101,8 @@ bool QPlaceSearchRequestPrivate::operator==(const QPlaceSearchRequestPrivate &ot
relevanceHint == other.relevanceHint &&
limit == other.limit &&
searchContext == other.searchContext;
+
+ // deliberately not testing related and page. comparing only the content.
}
void QPlaceSearchRequestPrivate::clear()
@@ -129,6 +115,18 @@ void QPlaceSearchRequestPrivate::clear()
visibilityScope = QLocation::UnspecifiedVisibility;
relevanceHint = QPlaceSearchRequest::UnspecifiedHint;
searchContext.clear();
+ related = false;
+ page = 0;
+}
+
+const QPlaceSearchRequestPrivate *QPlaceSearchRequestPrivate::get(const QPlaceSearchRequest &request)
+{
+ return request.d_ptr.constData();
+}
+
+QPlaceSearchRequestPrivate *QPlaceSearchRequestPrivate::get(QPlaceSearchRequest &request)
+{
+ return request.d_ptr.data();
}
/*!
diff --git a/src/location/places/qplacesearchrequest.h b/src/location/places/qplacesearchrequest.h
index 09654503..d6611017 100644
--- a/src/location/places/qplacesearchrequest.h
+++ b/src/location/places/qplacesearchrequest.h
@@ -98,6 +98,8 @@ private:
QSharedDataPointer<QPlaceSearchRequestPrivate> d_ptr;
inline QPlaceSearchRequestPrivate *d_func();
inline const QPlaceSearchRequestPrivate *d_func() const;
+
+ friend class QPlaceSearchRequestPrivate;
};
QT_END_NAMESPACE
diff --git a/src/location/places/qplacesearchrequest_p.h b/src/location/places/qplacesearchrequest_p.h
new file mode 100644
index 00000000..98a747b0
--- /dev/null
+++ b/src/location/places/qplacesearchrequest_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLACESEARCHREQUEST_P_H
+#define QPLACESEARCHREQUEST_P_H
+
+#include "qplacesearchrequest.h"
+#include "qgeocoordinate.h"
+#include "qgeoshape.h"
+
+#include <QtCore/QSharedData>
+#include <QtCore/QList>
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QPlaceSearchRequestPrivate : public QSharedData
+{
+public:
+ QPlaceSearchRequestPrivate();
+ QPlaceSearchRequestPrivate(const QPlaceSearchRequestPrivate &other);
+ ~QPlaceSearchRequestPrivate();
+
+ QPlaceSearchRequestPrivate &operator=(const QPlaceSearchRequestPrivate &other);
+ bool operator==(const QPlaceSearchRequestPrivate &other) const;
+
+ void clear();
+ static const QPlaceSearchRequestPrivate *get(const QPlaceSearchRequest &request);
+ static QPlaceSearchRequestPrivate *get(QPlaceSearchRequest &request);
+
+ QString searchTerm;
+ QList<QPlaceCategory> categories;
+ QGeoShape searchArea;
+ QString recommendationId;
+ QLocation::VisibilityScope visibilityScope;
+ QPlaceSearchRequest::RelevanceHint relevanceHint;
+ int limit;
+ QVariant searchContext;
+ bool related = false;
+ int page = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QPLACESEARCHREQUEST_P_H
diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp
index 9808b539..28aa930f 100644
--- a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp
+++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp
@@ -46,6 +46,7 @@
#include <QtLocation/QPlaceIcon>
#include <QtLocation/QPlaceResult>
#include <QtLocation/QPlaceProposedSearchResult>
+#include <QtLocation/private/qplacesearchrequest_p.h>
#include <QtCore/QDebug>
@@ -113,15 +114,24 @@ void QPlaceSearchReplyHere::replyFinished()
results.append(parseSearchResult(item));
}
+ QPlaceSearchRequest r_orig = request();
+ QPlaceSearchRequestPrivate *rpimpl_orig = QPlaceSearchRequestPrivate::get(r_orig);
+
if (resultsObject.contains(QStringLiteral("next"))) {
QPlaceSearchRequest request;
request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("next")).toString()));
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(request);
+ rpimpl->related = true;
+ rpimpl->page = rpimpl_orig->page + 1;
setNextPageRequest(request);
}
if (resultsObject.contains(QStringLiteral("previous"))) {
QPlaceSearchRequest request;
request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("previous")).toString()));
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(request);
+ rpimpl->related = true;
+ rpimpl->page = rpimpl_orig->page - 1;
setPreviousPageRequest(request);
}
diff --git a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp
index 3c201e41..be66414f 100644
--- a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp
+++ b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp
@@ -191,7 +191,7 @@ QPlaceSearchReply *QPlaceManagerEngineOsm::search(const QPlaceSearchRequest &req
this, SLOT(replyError(QPlaceReply::Error,QString)));
if (m_debugQuery)
- reply->requestUrl = requestUrl.toString();
+ reply->requestUrl = requestUrl.url(QUrl::None);
return reply;
}
diff --git a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp
index 0228a975..80c50d1b 100644
--- a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp
+++ b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp
@@ -48,6 +48,7 @@
#include <QtPositioning/QGeoRectangle>
#include <QtLocation/QPlaceResult>
#include <QtLocation/QPlaceSearchRequest>
+#include <QtLocation/private/qplacesearchrequest_p.h>
QT_BEGIN_NAMESPACE
@@ -135,6 +136,9 @@ void QPlaceSearchReplyOsm::replyFinished()
parameters.insert(QStringLiteral("ExcludePlaceIds"), epi);
r.setSearchContext(parameters);
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(r);
+ rpimpl->related = true;
+ rpimpl->page--;
setPreviousPageRequest(r);
}
@@ -147,6 +151,9 @@ void QPlaceSearchReplyOsm::replyFinished()
parameters.insert(QStringLiteral("ExcludePlaceIds"), epi);
r.setSearchContext(parameters);
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(r);
+ rpimpl->related = true;
+ rpimpl->page++;
setNextPageRequest(r);
}