10#include <QtCore/QCoreApplication>
11#include <QtCore/QMetaObject>
12#include <QtQml/QQmlEngine>
13#include <QtQml/QQmlInfo>
14#include <QtLocation/QGeoServiceProvider>
15#include <QtLocation/QPlaceAttribute>
16#include <QtLocation/QPlaceManager>
17#include <QtLocation/QPlaceDetailsReply>
18#include <QtLocation/QPlaceReply>
19#include <QtLocation/QPlaceIdReply>
20#include <QtLocation/QPlaceContactDetail>
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
152QDeclarativePlace::QDeclarativePlace(QObject *parent)
154 m_extendedAttributes(QQmlPropertyMap::create(
this)),
155 m_contactDetails(
new QDeclarativeContactDetails(
this))
157 connect(m_contactDetails, &QDeclarativeContactDetails::valueChanged,
158 this, &QDeclarativePlace::contactsModified);
163QDeclarativePlace::QDeclarativePlace(
const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent)
165 m_extendedAttributes(QQmlPropertyMap::create(
this)),
166 m_contactDetails(
new QDeclarativeContactDetails(
this)),
171 connect(m_contactDetails, &QDeclarativeContactDetails::valueChanged,
172 this, &QDeclarativePlace::contactsModified);
177QDeclarativePlace::~QDeclarativePlace()
182void QDeclarativePlace::componentComplete()
188
189
190
191
192void QDeclarativePlace::setPlugin(QDeclarativeGeoServiceProvider *plugin)
194 if (m_plugin == plugin)
199 emit pluginChanged();
201 if (m_plugin->isAttached()) {
204 connect(m_plugin, &QDeclarativeGeoServiceProvider::attached,
205 this, &QDeclarativePlace::pluginReady);
209void QDeclarativePlace::pluginReady()
211 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
212 QPlaceManager *placeManager = serviceProvider->placeManager();
213 if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) {
214 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
215 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
220QDeclarativeGeoServiceProvider *QDeclarativePlace::plugin()
const
226
227
228
229
230QDeclarativePlaceReviewModel *QDeclarativePlace::reviewModel()
232 if (!m_reviewModel) {
233 m_reviewModel =
new QDeclarativePlaceReviewModel(
this);
234 m_reviewModel->setPlace(
this);
237 return m_reviewModel;
241
242
243
244
245QDeclarativePlaceImageModel *QDeclarativePlace::imageModel()
248 m_imageModel =
new QDeclarativePlaceImageModel(
this);
249 m_imageModel->setPlace(
this);
256
257
258
259
260QDeclarativePlaceEditorialModel *QDeclarativePlace::editorialModel()
262 if (!m_editorialModel) {
263 m_editorialModel =
new QDeclarativePlaceEditorialModel(
this);
264 m_editorialModel->setPlace(
this);
267 return m_editorialModel;
271
272
273void QDeclarativePlace::setPlace(
const QPlace &src)
275 QPlace previous = m_src;
278 if (previous.categories() != m_src.categories()) {
279 synchronizeCategories();
280 emit categoriesChanged();
283 if (m_location && m_location->parent() ==
this) {
284 m_location->setLocation(m_src.location());
285 }
else if (!m_location || m_location->parent() !=
this) {
286 m_location =
new QDeclarativeGeoLocation(m_src.location(),
this);
287 emit locationChanged();
290 if (previous.ratings() != m_src.ratings())
291 emit ratingsChanged();
292 if (previous.supplier() != m_src.supplier())
293 emit supplierChanged();
294 if (previous.icon() != m_src.icon())
296 if (previous.name() != m_src.name())
298 if (previous.placeId() != m_src.placeId())
299 emit placeIdChanged();
300 if (previous.attribution() != m_src.attribution())
301 emit attributionChanged();
302 if (previous.detailsFetched() != m_src.detailsFetched())
303 emit detailsFetchedChanged();
304 if (previous.primaryPhone() != m_src.primaryPhone())
305 emit primaryPhoneChanged();
306 if (previous.primaryFax() != m_src.primaryFax())
307 emit primaryFaxChanged();
308 if (previous.primaryEmail() != m_src.primaryEmail())
309 emit primaryEmailChanged();
310 if (previous.primaryWebsite() != m_src.primaryWebsite())
311 emit primaryWebsiteChanged();
313 if (m_reviewModel && m_src.totalContentCount(QPlaceContent::ReviewType) >= 0) {
314 m_reviewModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ReviewType),
315 m_src.content(QPlaceContent::ReviewType));
317 if (m_imageModel && m_src.totalContentCount(QPlaceContent::ImageType) >= 0) {
318 m_imageModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ImageType),
319 m_src.content(QPlaceContent::ImageType));
321 if (m_editorialModel && m_src.totalContentCount(QPlaceContent::EditorialType) >= 0) {
322 m_editorialModel->initializeCollection(m_src.totalContentCount(QPlaceContent::EditorialType),
323 m_src.content(QPlaceContent::EditorialType));
326 pullExtendedAttributes();
327 synchronizeContacts();
330QPlace QDeclarativePlace::place()
const
336 QPlace result = m_src;
339 QList<QPlaceCategory> categories;
340 for (QDeclarativeCategory *value : std::as_const(m_categories))
341 categories.append(value->category());
343 result.setCategories(categories);
346 result.setLocation(m_location ? m_location->location() : QGeoLocation());
349 QList<QPlaceContactDetail> cppDetails;
350 for (
const QString &key : m_contactDetails->keys()) {
352 if (m_contactDetails->value(key).typeId() == QMetaType::QVariantList) {
353 const QVariantList detailsVarList = m_contactDetails->value(key).toList();
354 for (
const QVariant &detailVar : detailsVarList)
355 cppDetails.append(detailVar.value<QPlaceContactDetail>());
357 cppDetails.append(m_contactDetails->value(key).value<QPlaceContactDetail>());
359 result.setContactDetails(key, cppDetails);
366
367
368
369
370
371void QDeclarativePlace::setLocation(QDeclarativeGeoLocation *location)
373 if (m_location == location)
376 if (m_location && m_location->parent() ==
this)
379 m_location = location;
380 emit locationChanged();
383QDeclarativeGeoLocation *QDeclarativePlace::location()
const
389
390
391
392
393
394void QDeclarativePlace::setRatings(
const QPlaceRatings &rating)
396 if (m_src.ratings() != rating) {
397 m_src.setRatings(rating);
398 emit ratingsChanged();
402QPlaceRatings QDeclarativePlace::ratings()
const
404 return m_src.ratings();
408
409
410
411
412
413void QDeclarativePlace::setSupplier(
const QPlaceSupplier &supplier)
415 if (m_src.supplier() != supplier) {
416 m_src.setSupplier(supplier);
417 emit supplierChanged();
421QPlaceSupplier QDeclarativePlace::supplier()
const
423 return m_src.supplier();
427
428
429
430
431QPlaceIcon QDeclarativePlace::icon()
const
436void QDeclarativePlace::setIcon(
const QPlaceIcon &icon)
438 if (m_src.icon() != icon) {
445
446
447
448
449void QDeclarativePlace::setName(
const QString &name)
451 if (m_src.name() != name) {
457QString QDeclarativePlace::name()
const
463
464
465
466
467
468
469
470
471
472
473void QDeclarativePlace::setPlaceId(
const QString &placeId)
475 if (m_src.placeId() != placeId) {
476 m_src.setPlaceId(placeId);
477 emit placeIdChanged();
481QString QDeclarativePlace::placeId()
const
483 return m_src.placeId();
487
488
489
490
491
492
493
494void QDeclarativePlace::setAttribution(
const QString &attribution)
496 if (m_src.attribution() != attribution) {
497 m_src.setAttribution(attribution);
498 emit attributionChanged();
502QString QDeclarativePlace::attribution()
const
504 return m_src.attribution();
508
509
510
511
512
513
514
515
516bool QDeclarativePlace::detailsFetched()
const
518 return m_src.detailsFetched();
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558void QDeclarativePlace::setStatus(Status status,
const QString &errorString)
560 Status originalStatus = m_status;
562 m_errorString = errorString;
564 if (originalStatus != m_status)
565 emit statusChanged();
568QDeclarativePlace::Status QDeclarativePlace::status()
const
574
575
576void QDeclarativePlace::finished()
581 if (m_reply->error() == QPlaceReply::NoError) {
582 switch (m_reply->type()) {
583 case (QPlaceReply::IdReply) : {
584 QPlaceIdReply *idReply = qobject_cast<QPlaceIdReply *>(m_reply);
586 switch (idReply->operationType()) {
587 case QPlaceIdReply::SavePlace:
588 setPlaceId(idReply->id());
590 case QPlaceIdReply::RemovePlace:
598 case (QPlaceReply::DetailsReply): {
599 QPlaceDetailsReply *detailsReply = qobject_cast<QPlaceDetailsReply *>(m_reply);
600 setPlace(detailsReply->place());
608 m_errorString.clear();
610 m_reply->deleteLater();
613 setStatus(QDeclarativePlace::Ready);
615 QString errorString = m_reply->errorString();
617 m_reply->deleteLater();
620 setStatus(QDeclarativePlace::Error, errorString);
625
626
627void QDeclarativePlace::contactsModified(
const QString &key,
const QVariant &)
629 primarySignalsEmission(key);
633
634
635void QDeclarativePlace::cleanupDeletedCategories()
637 for (QDeclarativeCategory * category : m_categoriesToBeDeleted) {
638 if (category->parent() ==
this)
641 m_categoriesToBeDeleted.clear();
645
646
647
648
649
650
651
652
653
654void QDeclarativePlace::getDetails()
656 QPlaceManager *placeManager = manager();
660 m_reply = placeManager->getPlaceDetails(placeId());
661 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
662 setStatus(QDeclarativePlace::Fetching);
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683void QDeclarativePlace::save()
685 QPlaceManager *placeManager = manager();
689 m_reply = placeManager->savePlace(place());
690 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
691 setStatus(QDeclarativePlace::Saving);
695
696
697
698
699
700
701
702
703void QDeclarativePlace::remove()
705 QPlaceManager *placeManager = manager();
709 m_reply = placeManager->removePlace(place().placeId());
710 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
711 setStatus(QDeclarativePlace::Removing);
715
716
717
718
719
720QString QDeclarativePlace::errorString()
const
722 return m_errorString;
726
727
728
729
730
731
732
733
734QString QDeclarativePlace::primaryPhone()
const
736 return primaryValue(QPlaceContactDetail::Phone);
740
741
742
743
744
745
746
747QString QDeclarativePlace::primaryFax()
const
749 return primaryValue(QPlaceContactDetail::Fax);
753
754
755
756
757
758
759
760QString QDeclarativePlace::primaryEmail()
const
762 return primaryValue(QPlaceContactDetail::Email);
766
767
768
769
770
771
772
774QUrl QDeclarativePlace::primaryWebsite()
const
776 return QUrl(primaryValue(QPlaceContactDetail::Website));
780
781
782
783
784
785QQmlPropertyMap *QDeclarativePlace::extendedAttributes()
const
787 return m_extendedAttributes;
791
792
793
794
795
796QDeclarativeContactDetails *QDeclarativePlace::contactDetails()
const
798 return m_contactDetails;
802
803
804
805
806
807QQmlListProperty<QDeclarativeCategory> QDeclarativePlace::categories()
809 return QQmlListProperty<QDeclarativeCategory>(
this,
818
819
820void QDeclarativePlace::category_append(QQmlListProperty<QDeclarativeCategory> *prop,
821 QDeclarativeCategory *value)
823 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
825 if (object->m_categoriesToBeDeleted.contains(value))
826 object->m_categoriesToBeDeleted.removeAll(value);
828 if (!object->m_categories.contains(value)) {
829 object->m_categories.append(value);
830 QList<QPlaceCategory> list = object->m_src.categories();
831 list.append(value->category());
832 object->m_src.setCategories(list);
834 emit object->categoriesChanged();
839
840
841qsizetype QDeclarativePlace::category_count(QQmlListProperty<QDeclarativeCategory> *prop)
843 return static_cast<QDeclarativePlace *>(prop->object)->m_categories.count();
847
848
849QDeclarativeCategory *QDeclarativePlace::category_at(QQmlListProperty<QDeclarativeCategory> *prop,
852 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
853 QDeclarativeCategory *res = NULL;
854 if (object->m_categories.count() > index && index > -1) {
855 res = object->m_categories[index];
861
862
863void QDeclarativePlace::category_clear(QQmlListProperty<QDeclarativeCategory> *prop)
865 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
866 if (object->m_categories.isEmpty())
869 for (
auto *category : std::as_const(object->m_categories)) {
870 if (category->parent() == object)
871 object->m_categoriesToBeDeleted.append(category);
874 object->m_categories.clear();
875 object->m_src.setCategories(QList<QPlaceCategory>());
876 emit object->categoriesChanged();
877 QMetaObject::invokeMethod(object,
"cleanupDeletedCategories", Qt::QueuedConnection);
881
882
883void QDeclarativePlace::synchronizeCategories()
885 qDeleteAll(m_categories);
886 m_categories.clear();
887 for (
const QPlaceCategory &value : m_src.categories()) {
888 QDeclarativeCategory *declarativeValue =
new QDeclarativeCategory(value, m_plugin,
this);
889 m_categories.append(declarativeValue);
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920QDeclarativePlace::Visibility QDeclarativePlace::visibility()
const
922 return static_cast<QDeclarativePlace::Visibility>(m_src.visibility());
925void QDeclarativePlace::setVisibility(Visibility visibility)
927 if (
static_cast<QDeclarativePlace::Visibility>(m_src.visibility()) == visibility)
930 m_src.setVisibility(
static_cast<QLocation::Visibility>(visibility));
931 emit visibilityChanged();
935
936
937
938
939QDeclarativePlace *QDeclarativePlace::favorite()
const
944void QDeclarativePlace::setFavorite(QDeclarativePlace *favorite)
947 if (m_favorite == favorite)
950 if (m_favorite && m_favorite->parent() ==
this)
953 m_favorite = favorite;
954 emit favoriteChanged();
958
959
960
961
962
963void QDeclarativePlace::copyFrom(QDeclarativePlace *original)
965 QPlaceManager *placeManager = manager();
969 setPlace(placeManager->compatiblePlace(original->place()));
973
974
975
976
977
978
979void QDeclarativePlace::initializeFavorite(QDeclarativeGeoServiceProvider *plugin)
981 if (m_favorite == 0) {
982 QDeclarativePlace *place =
new QDeclarativePlace(
this);
983 place->setPlugin(plugin);
984 place->copyFrom(
this);
990
991
992void QDeclarativePlace::pullExtendedAttributes()
994 const QStringList keys = m_extendedAttributes->keys();
995 for (
const QString &key : keys)
996 m_extendedAttributes->clear(key);
998 const QStringList attributeTypes = m_src.extendedAttributeTypes();
999 for (
const QString &attributeType : attributeTypes) {
1000 m_extendedAttributes->insert(attributeType,
1001 QVariant::fromValue(m_src.extendedAttribute(attributeType)));
1004 emit extendedAttributesChanged();
1008
1009
1010void QDeclarativePlace::synchronizeContacts()
1013 for (
const QString &contactType : m_contactDetails->keys()) {
1014 const QList<QVariant> contacts = m_contactDetails->value(contactType).toList();
1015 for (
const QVariant &var : contacts) {
1016 QObject *obj = var.value<QObject *>();
1017 if (obj->parent() ==
this)
1020 m_contactDetails->insert(contactType, QVariantList());
1024 for (
const QString &contactType : m_src.contactTypes()) {
1025 const QList<QPlaceContactDetail> sourceContacts = m_src.contactDetails(contactType);
1026 QVariantList declContacts;
1027 for (
const QPlaceContactDetail &sourceContact : sourceContacts)
1028 declContacts.append(QVariant::fromValue(sourceContact));
1029 m_contactDetails->insert(contactType, declContacts);
1031 primarySignalsEmission();
1035
1036
1037
1038
1039
1040void QDeclarativePlace::primarySignalsEmission(
const QString &type)
1042 if (type.isEmpty() || type == QPlaceContactDetail::Phone) {
1043 if (m_prevPrimaryPhone != primaryPhone()) {
1044 m_prevPrimaryPhone = primaryPhone();
1045 emit primaryPhoneChanged();
1047 if (!type.isEmpty())
1051 if (type.isEmpty() || type == QPlaceContactDetail::Email) {
1052 if (m_prevPrimaryEmail != primaryEmail()) {
1053 m_prevPrimaryEmail = primaryEmail();
1054 emit primaryEmailChanged();
1056 if (!type.isEmpty())
1060 if (type.isEmpty() || type == QPlaceContactDetail::Website) {
1061 if (m_prevPrimaryWebsite != primaryWebsite()) {
1062 m_prevPrimaryWebsite = primaryWebsite();
1063 emit primaryWebsiteChanged();
1065 if (!type.isEmpty())
1069 if (type.isEmpty() || type == QPlaceContactDetail::Fax) {
1070 if (m_prevPrimaryFax != primaryFax()) {
1071 m_prevPrimaryFax = primaryFax();
1072 emit primaryFaxChanged();
1078
1079
1080
1081
1082
1083QPlaceManager *QDeclarativePlace::manager()
1085 if (m_status != QDeclarativePlace::Ready && m_status != QDeclarativePlace::Error)
1090 m_reply->deleteLater();
1095 qmlWarning(
this) << QStringLiteral(
"Plugin is not assigned to place.");
1099 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
1100 if (!serviceProvider)
1103 QPlaceManager *placeManager = serviceProvider->placeManager();
1105 if (!placeManager) {
1106 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
1107 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
1111 return placeManager;
1115
1116
1117QString QDeclarativePlace::primaryValue(
const QString &contactType)
const
1119 QVariant value = m_contactDetails->value(contactType);
1120 if (value.userType() == qMetaTypeId<QJSValue>())
1121 value = value.value<QJSValue>().toVariant();
1123 if (value.userType() == QMetaType::QVariantList) {
1124 QVariantList detailList = m_contactDetails->value(contactType).toList();
1125 if (!detailList.isEmpty())
1126 return detailList.at(0).value<QPlaceContactDetail>().value();
1127 }
else if (value.metaType() == QMetaType::fromType<QPlaceContactDetail>()) {
1128 return value.value<QPlaceContactDetail>().value();
Combined button and popup list for selecting options.