Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdeclarativeplacecontentmodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
7#include "error_messages_p.h"
8
9#include <QtQml/QQmlInfo>
10#include <QtLocation/QGeoServiceProvider>
11#include <QtLocation/QPlaceManager>
12#include <QtLocation/QPlaceContentRequest>
13#include <QtLocation/QPlaceUser>
14
16
165
169
174{
175 return m_place;
176}
177
182{
183 if (m_place != place) {
185
186 int initialCount = m_contentCount;
187 clearData();
188 m_place = place;
190
192 if (initialCount != -1)
194
196 }
197}
198
203{
204 return m_batchSize;
205}
206
211{
212 if (m_batchSize != batchSize) {
213 m_batchSize = batchSize;
215 }
216}
217
222{
223 return m_contentCount;
224}
225
231{
232 m_users.clear();
235
236 m_contentCount = -1;
237
238 if (m_reply) {
239 m_reply->abort();
240 m_reply->deleteLater();
241 m_reply = nullptr;
242 }
243
244 m_nextRequest.clear();
245}
246
251{
253
254 int initialCount = m_contentCount;
255 clearData();
256
257 for (auto i = collection.cbegin(), end = collection.cend(); i != end; ++i) {
258 const QPlaceContent &content = i.value();
259 if (content.type() != m_type)
260 continue;
261
262 m_content.insert(i.key(), content);
263 const auto supplier = content.value(QPlaceContent::ContentSupplier)
265 if (!m_suppliers.contains(supplier.supplierId()))
266 m_suppliers.insert(supplier.supplierId(), supplier);
267 const auto user = content.value(QPlaceContent::ContentUser)
268 .value<QPlaceUser>();
269 if (!m_users.contains(user.userId()))
270 m_users.insert(user.userId(), user);
271 }
272
273 m_contentCount = totalCount;
274
275 if (initialCount != totalCount)
277
279}
280
285{
286 if (parent.isValid())
287 return 0;
288
289 return m_content.count();
290}
291
296{
297 if (!index.isValid())
298 return QVariant();
299
300 if (index.row() >= rowCount(index.parent()) || index.row() < 0)
301 return QVariant();
302
303 const QPlaceContent &content = m_content.value(index.row());
304 if (content.type() != m_type)
305 return QVariant();
306
307 switch (role) {
311 case ContentUserRole:
313 .value<QPlaceUser>().userId()));
316 case ImageUrlRole:
317 return content.value(QPlaceContent::ImageUrl);
318 case ImageIdRole:
319 return content.value(QPlaceContent::ImageId);
321 return content.value(QPlaceContent::ImageMimeType);
322
324 return content.value(QPlaceContent::EditorialText);
326 return content.value(QPlaceContent::EditorialTitle);
329
331 return content.value(QPlaceContent::ReviewDateTime);
332 case ReviewTextRole:
333 return content.value(QPlaceContent::ReviewText);
335 return content.value(QPlaceContent::ReviewLanguage);
336 case ReviewRatingRole:
337 return content.value(QPlaceContent::ReviewRating);
338 case ReviewIdRole:
339 return content.value(QPlaceContent::ReviewId);
340 case ReviewTitleRole:
341 return content.value(QPlaceContent::ReviewTitle);
342 default:
343 return QVariant();
344 }
345}
346
347QHash<int, QByteArray> QDeclarativePlaceContentModel::roleNames() const
348{
349 QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
350 roles.insert(ContentSupplierRole, "supplier");
351 roles.insert(ContentUserRole, "user");
352 roles.insert(ContentAttributionRole, "attribution");
353
354 switch (m_type) {
356 roles.insert(EditorialTextRole, "text");
357 roles.insert(EditorialTitleRole, "title");
358 roles.insert(EditorialLanguageRole, "language");
359 break;
361 roles.insert(ImageUrlRole, "url");
362 roles.insert(ImageIdRole, "imageId");
363 roles.insert(ImageMimeTypeRole, "mimeType");
364 break;
366 roles.insert(ReviewDateTimeRole, "dateTime");
367 roles.insert(ReviewTextRole, "text");
368 roles.insert(ReviewLanguageRole, "language");
369 roles.insert(ReviewRatingRole, "rating");
370 roles.insert(ReviewIdRole, "reviewId");
371 roles.insert(ReviewTitleRole, "title");
372 break;
373 default:
374 break;
375 }
376 return roles;
377}
378
383{
384 if (parent.isValid())
385 return false;
386
387 if (!m_place)
388 return false;
389
390 if (m_contentCount == -1)
391 return true;
392
393 return m_content.count() != m_contentCount;
394}
395
400{
401 if (parent.isValid())
402 return;
403
404 if (!m_place)
405 return;
406
407 if (m_reply)
408 return;
409
410 if (!m_place->plugin())
411 return;
412
413 QDeclarativeGeoServiceProvider *plugin = m_place->plugin();
414
415 QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider();
416 if (!serviceProvider)
417 return;
418
419 QPlaceManager *placeManager = serviceProvider->placeManager();
420 if (!placeManager)
421 return;
422
423 if (m_nextRequest == QPlaceContentRequest()) {
425 request.setContentType(m_type);
426 request.setPlaceId(m_place->place().placeId());
427 request.setLimit(m_batchSize);
428
429 m_reply = placeManager->getPlaceContent(request);
430 } else {
431 m_reply = placeManager->getPlaceContent(m_nextRequest);
432 }
433
435 this, &QDeclarativePlaceContentModel::fetchFinished, Qt::QueuedConnection);
436}
437
444
449{
450 m_complete = true;
452}
453
457void QDeclarativePlaceContentModel::fetchFinished()
458{
459 if (!m_reply)
460 return;
461
462 QPlaceContentReply *reply = m_reply;
463 m_reply = nullptr;
464
465 m_nextRequest = reply->nextPageRequest();
466
467 if (m_contentCount != reply->totalCount()) {
468 m_contentCount = reply->totalCount();
470 }
471
472 if (!reply->content().isEmpty()) {
474
475 //find out which indexes are new and which ones have changed.
476 QList<int> changedIndexes;
477 QList<int> newIndexes;
478 for (auto it = contents.cbegin(), end = contents.cend(); it != end; ++it) {
479 if (!m_content.contains(it.key()))
480 newIndexes.append(it.key());
481 else if (it.value() != m_content.value(it.key()))
482 changedIndexes.append(it.key());
483 }
484
485 //insert new indexes in blocks where within each
486 //block, the indexes are consecutive.
487 int startIndex = -1;
488 for (auto it = newIndexes.cbegin(), end = newIndexes.cend(); it != end; ++it) {
489 int currentIndex = *it;
490 if (startIndex == -1)
491 startIndex = currentIndex;
492
493 auto next = std::next(it);
494 if (next == end || *next > (currentIndex + 1)) {
495 beginInsertRows(QModelIndex(),startIndex,currentIndex);
496 for (int i = startIndex; i <= currentIndex; ++i) {
497 const QPlaceContent &content = contents.value(i);
498
499 m_content.insert(i, content);
500 const auto supplier = content.value(QPlaceContent::ContentSupplier)
502 if (!m_suppliers.contains(supplier.supplierId()))
503 m_suppliers.insert(supplier.supplierId(), supplier);
504 const auto user = content.value(QPlaceContent::ContentUser)
505 .value<QPlaceUser>();
506 if (!m_users.contains(user.userId()))
507 m_users.insert(user.userId(), user);
508 }
510 startIndex = -1;
511 }
512 }
513
514 //modify changed indexes in blocks where within each
515 //block, the indexes are consecutive.
516 startIndex = -1;
517 for (auto it = changedIndexes.cbegin(), end = changedIndexes.cend(); it != end; ++it) {
518 int currentIndex = *it;
519 if (startIndex == -1)
520 startIndex = currentIndex;
521
522 auto next = std::next(it);
523 if (next == end || *next > (currentIndex + 1)) {
524 for (int i = startIndex; i <= currentIndex; ++i) {
525 const QPlaceContent &content = contents.value(i);
526 m_content.insert(i, content);
527 const auto supplier = content.value(QPlaceContent::ContentSupplier)
529 if (!m_suppliers.contains(supplier.supplierId()))
530 m_suppliers.insert(supplier.supplierId(), supplier);
531 const auto user = content.value(QPlaceContent::ContentUser)
532 .value<QPlaceUser>();
533 if (!m_users.contains(user.userId()))
534 m_users.insert(user.userId(), user);
535 }
536 emit dataChanged(index(startIndex),index(currentIndex));
537 startIndex = -1;
538 }
539 }
540
541 // The fetch didn't add any new content and we haven't fetched all content yet. This is
542 // likely due to the model being prepopulated by Place::getDetails(). Keep fetching more
543 // data until new content is available.
544 if (newIndexes.isEmpty() && m_content.count() != m_contentCount)
546 }
547
549}
550
void endResetModel()
Completes a model reset operation.
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This signal is emitted whenever the data in an existing item changes.
virtual QHash< int, QByteArray > roleNames() const
void endInsertRows()
Ends a row insertion operation.
void beginResetModel()
Begins a model reset operation.
void beginInsertRows(const QModelIndex &parent, int first, int last)
Begins a row insertion operation.
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
int rowCount(const QModelIndex &parent) const override
QHash< int, QByteArray > roleNames() const override
QMap< QString, QPlaceSupplier > m_suppliers
void initializeCollection(int totalCount, const QPlaceContent::Collection &collection)
QVariant data(const QModelIndex &index, int role) const override
bool canFetchMore(const QModelIndex &parent) const override
void fetchMore(const QModelIndex &parent) override
QDeclarativePlaceContentModel(QPlaceContent::Type type, QObject *parent=nullptr)
\qmltype EditorialModel \inqmlmodule QtLocation
QDeclarativeGeoServiceProvider * plugin
\inmodule QtLocation
QPlaceManager * placeManager() const
Returns the QPlaceManager made available by the service provider.
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
bool contains(const Key &key) const
Definition qmap.h:341
size_type count(const Key &key) const
Definition qmap.h:404
void clear()
Definition qmap.h:289
\inmodule QtCore
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
\inmodule QtLocation
\inmodule QtLocation
void clear()
Clears the content request.
\inmodule QtLocation
QVariant value(DataTag tag) const
Returns the value stored for the data tag, or an invalid QVariant if there is no data for that tag.
Type
Defines the type of content.
QPlaceContent::Type type() const
Returns the content type.
\inmodule QtLocation
QPlaceContentReply * getPlaceContent(const QPlaceContentRequest &request) const
Retrieves content for a place according to the parameters specified in request.
void finished()
This signal is emitted when this reply has finished processing.
virtual void abort()
Cancels the operation immediately.
\inmodule QtLocation
QString supplierId
\qmlproperty string Supplier::supplierId
\inmodule QtLocation
Definition qplaceuser.h:18
QML_STRUCTURED_VALUEQString userId
\qmlproperty string QtLocation::user::userId
Definition qplaceuser.h:23
QString placeId() const
Returns the identifier of the place.
Definition qplace.cpp:306
const_iterator cbegin() const noexcept
Definition qset.h:138
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:536
QSet< QString >::iterator it
short next
Definition keywords.cpp:445
Combined button and popup list for selecting options.
@ QueuedConnection
GLuint index
[2]
GLuint GLuint end
GLenum type
#define emit
QNetworkRequest request(url)
QNetworkReply * reply