9#include <QtCore/QCoreApplication>
10#include <QtCore/QMetaObject>
11#include <QtQml/QQmlEngine>
12#include <QtQml/QQmlInfo>
13#include <QtLocation/QGeoServiceProvider>
14#include <QtLocation/QPlaceAttribute>
15#include <QtLocation/QPlaceManager>
16#include <QtLocation/QPlaceDetailsReply>
17#include <QtLocation/QPlaceReply>
18#include <QtLocation/QPlaceIdReply>
19#include <QtLocation/QPlaceContactDetail>
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
151QDeclarativePlace::QDeclarativePlace(QObject *parent)
153 m_extendedAttributes(QQmlPropertyMap::create(
this)),
154 m_contactDetails(
new QDeclarativeContactDetails(
this))
156 connect(m_contactDetails, &QDeclarativeContactDetails::valueChanged,
157 this, &QDeclarativePlace::contactsModified);
162QDeclarativePlace::QDeclarativePlace(
const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent)
164 m_extendedAttributes(QQmlPropertyMap::create(
this)),
165 m_contactDetails(
new QDeclarativeContactDetails(
this)),
170 connect(m_contactDetails, &QDeclarativeContactDetails::valueChanged,
171 this, &QDeclarativePlace::contactsModified);
176QDeclarativePlace::~QDeclarativePlace()
181void QDeclarativePlace::componentComplete()
187
188
189
190
191void QDeclarativePlace::setPlugin(QDeclarativeGeoServiceProvider *plugin)
193 if (m_plugin == plugin)
198 emit pluginChanged();
200 if (m_plugin->isAttached()) {
203 connect(m_plugin, &QDeclarativeGeoServiceProvider::attached,
204 this, &QDeclarativePlace::pluginReady);
208void QDeclarativePlace::pluginReady()
210 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
211 QPlaceManager *placeManager = serviceProvider->placeManager();
212 if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) {
213 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
214 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
219QDeclarativeGeoServiceProvider *QDeclarativePlace::plugin()
const
225
226
227
228
229QDeclarativePlaceReviewModel *QDeclarativePlace::reviewModel()
231 if (!m_reviewModel) {
232 m_reviewModel =
new QDeclarativePlaceReviewModel(
this);
233 m_reviewModel->setPlace(
this);
236 return m_reviewModel;
240
241
242
243
244QDeclarativePlaceImageModel *QDeclarativePlace::imageModel()
247 m_imageModel =
new QDeclarativePlaceImageModel(
this);
248 m_imageModel->setPlace(
this);
255
256
257
258
259QDeclarativePlaceEditorialModel *QDeclarativePlace::editorialModel()
261 if (!m_editorialModel) {
262 m_editorialModel =
new QDeclarativePlaceEditorialModel(
this);
263 m_editorialModel->setPlace(
this);
266 return m_editorialModel;
270
271
272void QDeclarativePlace::setPlace(
const QPlace &src)
274 QPlace previous = m_src;
277 if (previous.categories() != m_src.categories()) {
278 synchronizeCategories();
279 emit categoriesChanged();
282 if (m_location && m_location->parent() ==
this) {
283 m_location->setLocation(m_src.location());
284 }
else if (!m_location || m_location->parent() !=
this) {
285 m_location =
new QDeclarativeGeoLocation(m_src.location(),
this);
286 emit locationChanged();
289 if (previous.ratings() != m_src.ratings())
290 emit ratingsChanged();
291 if (previous.supplier() != m_src.supplier())
292 emit supplierChanged();
293 if (previous.icon() != m_src.icon())
295 if (previous.name() != m_src.name())
297 if (previous.placeId() != m_src.placeId())
298 emit placeIdChanged();
299 if (previous.attribution() != m_src.attribution())
300 emit attributionChanged();
301 if (previous.detailsFetched() != m_src.detailsFetched())
302 emit detailsFetchedChanged();
303 if (previous.primaryPhone() != m_src.primaryPhone())
304 emit primaryPhoneChanged();
305 if (previous.primaryFax() != m_src.primaryFax())
306 emit primaryFaxChanged();
307 if (previous.primaryEmail() != m_src.primaryEmail())
308 emit primaryEmailChanged();
309 if (previous.primaryWebsite() != m_src.primaryWebsite())
310 emit primaryWebsiteChanged();
312 if (m_reviewModel && m_src.totalContentCount(QPlaceContent::ReviewType) >= 0) {
313 m_reviewModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ReviewType),
314 m_src.content(QPlaceContent::ReviewType));
316 if (m_imageModel && m_src.totalContentCount(QPlaceContent::ImageType) >= 0) {
317 m_imageModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ImageType),
318 m_src.content(QPlaceContent::ImageType));
320 if (m_editorialModel && m_src.totalContentCount(QPlaceContent::EditorialType) >= 0) {
321 m_editorialModel->initializeCollection(m_src.totalContentCount(QPlaceContent::EditorialType),
322 m_src.content(QPlaceContent::EditorialType));
325 pullExtendedAttributes();
326 synchronizeContacts();
329QPlace QDeclarativePlace::place()
const
335 QPlace result = m_src;
338 QList<QPlaceCategory> categories;
339 for (QDeclarativeCategory *value : std::as_const(m_categories))
340 categories.append(value->category());
342 result.setCategories(categories);
345 result.setLocation(m_location ? m_location->location() : QGeoLocation());
348 QList<QPlaceContactDetail> cppDetails;
349 for (
const QString &key : m_contactDetails->keys()) {
351 if (m_contactDetails->value(key).typeId() == QMetaType::QVariantList) {
352 const QVariantList detailsVarList = m_contactDetails->value(key).toList();
353 for (
const QVariant &detailVar : detailsVarList)
354 cppDetails.append(detailVar.value<QPlaceContactDetail>());
356 cppDetails.append(m_contactDetails->value(key).value<QPlaceContactDetail>());
358 result.setContactDetails(key, cppDetails);
365
366
367
368
369
370void QDeclarativePlace::setLocation(QDeclarativeGeoLocation *location)
372 if (m_location == location)
375 if (m_location && m_location->parent() ==
this)
378 m_location = location;
379 emit locationChanged();
382QDeclarativeGeoLocation *QDeclarativePlace::location()
const
388
389
390
391
392
393void QDeclarativePlace::setRatings(
const QPlaceRatings &rating)
395 if (m_src.ratings() != rating) {
396 m_src.setRatings(rating);
397 emit ratingsChanged();
401QPlaceRatings QDeclarativePlace::ratings()
const
403 return m_src.ratings();
407
408
409
410
411
412void QDeclarativePlace::setSupplier(
const QPlaceSupplier &supplier)
414 if (m_src.supplier() != supplier) {
415 m_src.setSupplier(supplier);
416 emit supplierChanged();
420QPlaceSupplier QDeclarativePlace::supplier()
const
422 return m_src.supplier();
426
427
428
429
430QPlaceIcon QDeclarativePlace::icon()
const
435void QDeclarativePlace::setIcon(
const QPlaceIcon &icon)
437 if (m_src.icon() != icon) {
444
445
446
447
448void QDeclarativePlace::setName(
const QString &name)
450 if (m_src.name() != name) {
456QString QDeclarativePlace::name()
const
462
463
464
465
466
467
468
469
470
471
472void QDeclarativePlace::setPlaceId(
const QString &placeId)
474 if (m_src.placeId() != placeId) {
475 m_src.setPlaceId(placeId);
476 emit placeIdChanged();
480QString QDeclarativePlace::placeId()
const
482 return m_src.placeId();
486
487
488
489
490
491
492
493void QDeclarativePlace::setAttribution(
const QString &attribution)
495 if (m_src.attribution() != attribution) {
496 m_src.setAttribution(attribution);
497 emit attributionChanged();
501QString QDeclarativePlace::attribution()
const
503 return m_src.attribution();
507
508
509
510
511
512
513
514
515bool QDeclarativePlace::detailsFetched()
const
517 return m_src.detailsFetched();
521
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
557void QDeclarativePlace::setStatus(Status status,
const QString &errorString)
559 Status originalStatus = m_status;
561 m_errorString = errorString;
563 if (originalStatus != m_status)
564 emit statusChanged();
567QDeclarativePlace::Status QDeclarativePlace::status()
const
573
574
575void QDeclarativePlace::finished()
580 if (m_reply->error() == QPlaceReply::NoError) {
581 switch (m_reply->type()) {
582 case (QPlaceReply::IdReply) : {
583 QPlaceIdReply *idReply = qobject_cast<QPlaceIdReply *>(m_reply);
585 switch (idReply->operationType()) {
586 case QPlaceIdReply::SavePlace:
587 setPlaceId(idReply->id());
589 case QPlaceIdReply::RemovePlace:
597 case (QPlaceReply::DetailsReply): {
598 QPlaceDetailsReply *detailsReply = qobject_cast<QPlaceDetailsReply *>(m_reply);
599 setPlace(detailsReply->place());
607 m_errorString.clear();
609 m_reply->deleteLater();
612 setStatus(QDeclarativePlace::Ready);
614 QString errorString = m_reply->errorString();
616 m_reply->deleteLater();
619 setStatus(QDeclarativePlace::Error, errorString);
624
625
626void QDeclarativePlace::contactsModified(
const QString &key,
const QVariant &)
628 primarySignalsEmission(key);
632
633
634void QDeclarativePlace::cleanupDeletedCategories()
636 for (QDeclarativeCategory * category : m_categoriesToBeDeleted) {
637 if (category->parent() ==
this)
640 m_categoriesToBeDeleted.clear();
644
645
646
647
648
649
650
651
652
653void QDeclarativePlace::getDetails()
655 QPlaceManager *placeManager = manager();
659 m_reply = placeManager->getPlaceDetails(placeId());
660 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
661 setStatus(QDeclarativePlace::Fetching);
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682void QDeclarativePlace::save()
684 QPlaceManager *placeManager = manager();
688 m_reply = placeManager->savePlace(place());
689 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
690 setStatus(QDeclarativePlace::Saving);
694
695
696
697
698
699
700
701
702void QDeclarativePlace::remove()
704 QPlaceManager *placeManager = manager();
708 m_reply = placeManager->removePlace(place().placeId());
709 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
710 setStatus(QDeclarativePlace::Removing);
714
715
716
717
718
719QString QDeclarativePlace::errorString()
const
721 return m_errorString;
725
726
727
728
729
730
731
732
733QString QDeclarativePlace::primaryPhone()
const
735 return primaryValue(QPlaceContactDetail::Phone);
739
740
741
742
743
744
745
746QString QDeclarativePlace::primaryFax()
const
748 return primaryValue(QPlaceContactDetail::Fax);
752
753
754
755
756
757
758
759QString QDeclarativePlace::primaryEmail()
const
761 return primaryValue(QPlaceContactDetail::Email);
765
766
767
768
769
770
771
773QUrl QDeclarativePlace::primaryWebsite()
const
775 return QUrl(primaryValue(QPlaceContactDetail::Website));
779
780
781
782
783
784QQmlPropertyMap *QDeclarativePlace::extendedAttributes()
const
786 return m_extendedAttributes;
790
791
792
793
794
795QDeclarativeContactDetails *QDeclarativePlace::contactDetails()
const
797 return m_contactDetails;
801
802
803
804
805
806QQmlListProperty<QDeclarativeCategory> QDeclarativePlace::categories()
808 return QQmlListProperty<QDeclarativeCategory>(
this,
817
818
819void QDeclarativePlace::category_append(QQmlListProperty<QDeclarativeCategory> *prop,
820 QDeclarativeCategory *value)
822 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
824 if (object->m_categoriesToBeDeleted.contains(value))
825 object->m_categoriesToBeDeleted.removeAll(value);
827 if (!object->m_categories.contains(value)) {
828 object->m_categories.append(value);
829 QList<QPlaceCategory> list = object->m_src.categories();
830 list.append(value->category());
831 object->m_src.setCategories(list);
833 emit object->categoriesChanged();
838
839
840qsizetype QDeclarativePlace::category_count(QQmlListProperty<QDeclarativeCategory> *prop)
842 return static_cast<QDeclarativePlace *>(prop->object)->m_categories.count();
846
847
848QDeclarativeCategory *QDeclarativePlace::category_at(QQmlListProperty<QDeclarativeCategory> *prop,
851 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
852 QDeclarativeCategory *res = NULL;
853 if (object->m_categories.count() > index && index > -1) {
854 res = object->m_categories[index];
860
861
862void QDeclarativePlace::category_clear(QQmlListProperty<QDeclarativeCategory> *prop)
864 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
865 if (object->m_categories.isEmpty())
868 for (
auto *category : std::as_const(object->m_categories)) {
869 if (category->parent() == object)
870 object->m_categoriesToBeDeleted.append(category);
873 object->m_categories.clear();
874 object->m_src.setCategories(QList<QPlaceCategory>());
875 emit object->categoriesChanged();
876 QMetaObject::invokeMethod(object,
"cleanupDeletedCategories", Qt::QueuedConnection);
880
881
882void QDeclarativePlace::synchronizeCategories()
884 qDeleteAll(m_categories);
885 m_categories.clear();
886 for (
const QPlaceCategory &value : m_src.categories()) {
887 QDeclarativeCategory *declarativeValue =
new QDeclarativeCategory(value, m_plugin,
this);
888 m_categories.append(declarativeValue);
893
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
919QDeclarativePlace::Visibility QDeclarativePlace::visibility()
const
921 return static_cast<QDeclarativePlace::Visibility>(m_src.visibility());
924void QDeclarativePlace::setVisibility(Visibility visibility)
926 if (
static_cast<QDeclarativePlace::Visibility>(m_src.visibility()) == visibility)
929 m_src.setVisibility(
static_cast<QLocation::Visibility>(visibility));
930 emit visibilityChanged();
934
935
936
937
938QDeclarativePlace *QDeclarativePlace::favorite()
const
943void QDeclarativePlace::setFavorite(QDeclarativePlace *favorite)
946 if (m_favorite == favorite)
949 if (m_favorite && m_favorite->parent() ==
this)
952 m_favorite = favorite;
953 emit favoriteChanged();
957
958
959
960
961
962void QDeclarativePlace::copyFrom(QDeclarativePlace *original)
964 QPlaceManager *placeManager = manager();
968 setPlace(placeManager->compatiblePlace(original->place()));
972
973
974
975
976
977
978void QDeclarativePlace::initializeFavorite(QDeclarativeGeoServiceProvider *plugin)
980 if (m_favorite == 0) {
981 QDeclarativePlace *place =
new QDeclarativePlace(
this);
982 place->setPlugin(plugin);
983 place->copyFrom(
this);
989
990
991void QDeclarativePlace::pullExtendedAttributes()
993 const QStringList keys = m_extendedAttributes->keys();
994 for (
const QString &key : keys)
995 m_extendedAttributes->clear(key);
997 const QStringList attributeTypes = m_src.extendedAttributeTypes();
998 for (
const QString &attributeType : attributeTypes) {
999 m_extendedAttributes->insert(attributeType,
1000 QVariant::fromValue(m_src.extendedAttribute(attributeType)));
1003 emit extendedAttributesChanged();
1007
1008
1009void QDeclarativePlace::synchronizeContacts()
1012 for (
const QString &contactType : m_contactDetails->keys()) {
1013 const QList<QVariant> contacts = m_contactDetails->value(contactType).toList();
1014 for (
const QVariant &var : contacts) {
1015 QObject *obj = var.value<QObject *>();
1016 if (obj->parent() ==
this)
1019 m_contactDetails->insert(contactType, QVariantList());
1023 for (
const QString &contactType : m_src.contactTypes()) {
1024 const QList<QPlaceContactDetail> sourceContacts = m_src.contactDetails(contactType);
1025 QVariantList declContacts;
1026 for (
const QPlaceContactDetail &sourceContact : sourceContacts)
1027 declContacts.append(QVariant::fromValue(sourceContact));
1028 m_contactDetails->insert(contactType, declContacts);
1030 primarySignalsEmission();
1034
1035
1036
1037
1038
1039void QDeclarativePlace::primarySignalsEmission(
const QString &type)
1041 if (type.isEmpty() || type == QPlaceContactDetail::Phone) {
1042 if (m_prevPrimaryPhone != primaryPhone()) {
1043 m_prevPrimaryPhone = primaryPhone();
1044 emit primaryPhoneChanged();
1046 if (!type.isEmpty())
1050 if (type.isEmpty() || type == QPlaceContactDetail::Email) {
1051 if (m_prevPrimaryEmail != primaryEmail()) {
1052 m_prevPrimaryEmail = primaryEmail();
1053 emit primaryEmailChanged();
1055 if (!type.isEmpty())
1059 if (type.isEmpty() || type == QPlaceContactDetail::Website) {
1060 if (m_prevPrimaryWebsite != primaryWebsite()) {
1061 m_prevPrimaryWebsite = primaryWebsite();
1062 emit primaryWebsiteChanged();
1064 if (!type.isEmpty())
1068 if (type.isEmpty() || type == QPlaceContactDetail::Fax) {
1069 if (m_prevPrimaryFax != primaryFax()) {
1070 m_prevPrimaryFax = primaryFax();
1071 emit primaryFaxChanged();
1077
1078
1079
1080
1081
1082QPlaceManager *QDeclarativePlace::manager()
1084 if (m_status != QDeclarativePlace::Ready && m_status != QDeclarativePlace::Error)
1089 m_reply->deleteLater();
1094 qmlWarning(
this) << QStringLiteral(
"Plugin is not assigned to place.");
1098 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
1099 if (!serviceProvider)
1102 QPlaceManager *placeManager = serviceProvider->placeManager();
1104 if (!placeManager) {
1105 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
1106 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
1110 return placeManager;
1114
1115
1116QString QDeclarativePlace::primaryValue(
const QString &contactType)
const
1118 QVariant value = m_contactDetails->value(contactType);
1119 if (value.userType() == qMetaTypeId<QJSValue>())
1120 value = value.value<QJSValue>().toVariant();
1122 if (value.userType() == QMetaType::QVariantList) {
1123 QVariantList detailList = m_contactDetails->value(contactType).toList();
1124 if (!detailList.isEmpty())
1125 return detailList.at(0).value<QPlaceContactDetail>().value();
1126 }
else if (value.metaType() == QMetaType::fromType<QPlaceContactDetail>()) {
1127 return value.value<QPlaceContactDetail>().value();
Combined button and popup list for selecting options.