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
150QDeclarativePlace::QDeclarativePlace(QObject *parent)
152 m_extendedAttributes(
new QQmlPropertyMap(
this)),
153 m_contactDetails(
new QDeclarativeContactDetails(
this))
155 connect(m_contactDetails, &QDeclarativeContactDetails::valueChanged,
156 this, &QDeclarativePlace::contactsModified);
161QDeclarativePlace::QDeclarativePlace(
const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent)
163 m_extendedAttributes(
new QQmlPropertyMap(
this)),
164 m_contactDetails(
new QDeclarativeContactDetails(
this)),
169 connect(m_contactDetails, &QDeclarativeContactDetails::valueChanged,
170 this, &QDeclarativePlace::contactsModified);
175QDeclarativePlace::~QDeclarativePlace()
180void QDeclarativePlace::componentComplete()
186
187
188
189
190void QDeclarativePlace::setPlugin(QDeclarativeGeoServiceProvider *plugin)
192 if (m_plugin == plugin)
197 emit pluginChanged();
199 if (m_plugin->isAttached()) {
202 connect(m_plugin, &QDeclarativeGeoServiceProvider::attached,
203 this, &QDeclarativePlace::pluginReady);
207void QDeclarativePlace::pluginReady()
209 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
210 QPlaceManager *placeManager = serviceProvider->placeManager();
211 if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) {
212 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
213 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
218QDeclarativeGeoServiceProvider *QDeclarativePlace::plugin()
const
224
225
226
227
228QDeclarativePlaceReviewModel *QDeclarativePlace::reviewModel()
230 if (!m_reviewModel) {
231 m_reviewModel =
new QDeclarativePlaceReviewModel(
this);
232 m_reviewModel->setPlace(
this);
235 return m_reviewModel;
239
240
241
242
243QDeclarativePlaceImageModel *QDeclarativePlace::imageModel()
246 m_imageModel =
new QDeclarativePlaceImageModel(
this);
247 m_imageModel->setPlace(
this);
254
255
256
257
258QDeclarativePlaceEditorialModel *QDeclarativePlace::editorialModel()
260 if (!m_editorialModel) {
261 m_editorialModel =
new QDeclarativePlaceEditorialModel(
this);
262 m_editorialModel->setPlace(
this);
265 return m_editorialModel;
269
270
271void QDeclarativePlace::setPlace(
const QPlace &src)
273 QPlace previous = m_src;
276 if (previous.categories() != m_src.categories()) {
277 synchronizeCategories();
278 emit categoriesChanged();
281 if (m_location && m_location->parent() ==
this) {
282 m_location->setLocation(m_src.location());
283 }
else if (!m_location || m_location->parent() !=
this) {
284 m_location =
new QDeclarativeGeoLocation(m_src.location(),
this);
285 emit locationChanged();
288 if (previous.ratings() != m_src.ratings())
289 emit ratingsChanged();
290 if (previous.supplier() != m_src.supplier())
291 emit supplierChanged();
292 if (previous.icon() != m_src.icon())
294 if (previous.name() != m_src.name())
296 if (previous.placeId() != m_src.placeId())
297 emit placeIdChanged();
298 if (previous.attribution() != m_src.attribution())
299 emit attributionChanged();
300 if (previous.detailsFetched() != m_src.detailsFetched())
301 emit detailsFetchedChanged();
302 if (previous.primaryPhone() != m_src.primaryPhone())
303 emit primaryPhoneChanged();
304 if (previous.primaryFax() != m_src.primaryFax())
305 emit primaryFaxChanged();
306 if (previous.primaryEmail() != m_src.primaryEmail())
307 emit primaryEmailChanged();
308 if (previous.primaryWebsite() != m_src.primaryWebsite())
309 emit primaryWebsiteChanged();
311 if (m_reviewModel && m_src.totalContentCount(QPlaceContent::ReviewType) >= 0) {
312 m_reviewModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ReviewType),
313 m_src.content(QPlaceContent::ReviewType));
315 if (m_imageModel && m_src.totalContentCount(QPlaceContent::ImageType) >= 0) {
316 m_imageModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ImageType),
317 m_src.content(QPlaceContent::ImageType));
319 if (m_editorialModel && m_src.totalContentCount(QPlaceContent::EditorialType) >= 0) {
320 m_editorialModel->initializeCollection(m_src.totalContentCount(QPlaceContent::EditorialType),
321 m_src.content(QPlaceContent::EditorialType));
324 pullExtendedAttributes();
325 synchronizeContacts();
328QPlace QDeclarativePlace::place()
const
334 QPlace result = m_src;
337 QList<QPlaceCategory> categories;
338 for (QDeclarativeCategory *value : std::as_const(m_categories))
339 categories.append(value->category());
341 result.setCategories(categories);
344 result.setLocation(m_location ? m_location->location() : QGeoLocation());
347 QList<QPlaceContactDetail> cppDetails;
348 for (
const QString &key : m_contactDetails->keys()) {
350 if (m_contactDetails->value(key).typeId() == QMetaType::QVariantList) {
351 const QVariantList detailsVarList = m_contactDetails->value(key).toList();
352 for (
const QVariant &detailVar : detailsVarList)
353 cppDetails.append(detailVar.value<QPlaceContactDetail>());
355 cppDetails.append(m_contactDetails->value(key).value<QPlaceContactDetail>());
357 result.setContactDetails(key, cppDetails);
364
365
366
367
368
369void QDeclarativePlace::setLocation(QDeclarativeGeoLocation *location)
371 if (m_location == location)
374 if (m_location && m_location->parent() ==
this)
377 m_location = location;
378 emit locationChanged();
381QDeclarativeGeoLocation *QDeclarativePlace::location()
const
387
388
389
390
391
392void QDeclarativePlace::setRatings(
const QPlaceRatings &rating)
394 if (m_src.ratings() != rating) {
395 m_src.setRatings(rating);
396 emit ratingsChanged();
400QPlaceRatings QDeclarativePlace::ratings()
const
402 return m_src.ratings();
406
407
408
409
410
411void QDeclarativePlace::setSupplier(
const QPlaceSupplier &supplier)
413 if (m_src.supplier() != supplier) {
414 m_src.setSupplier(supplier);
415 emit supplierChanged();
419QPlaceSupplier QDeclarativePlace::supplier()
const
421 return m_src.supplier();
425
426
427
428
429QPlaceIcon QDeclarativePlace::icon()
const
434void QDeclarativePlace::setIcon(
const QPlaceIcon &icon)
436 if (m_src.icon() != icon) {
443
444
445
446
447void QDeclarativePlace::setName(
const QString &name)
449 if (m_src.name() != name) {
455QString QDeclarativePlace::name()
const
461
462
463
464
465
466
467
468
469
470
471void QDeclarativePlace::setPlaceId(
const QString &placeId)
473 if (m_src.placeId() != placeId) {
474 m_src.setPlaceId(placeId);
475 emit placeIdChanged();
479QString QDeclarativePlace::placeId()
const
481 return m_src.placeId();
485
486
487
488
489
490
491
492void QDeclarativePlace::setAttribution(
const QString &attribution)
494 if (m_src.attribution() != attribution) {
495 m_src.setAttribution(attribution);
496 emit attributionChanged();
500QString QDeclarativePlace::attribution()
const
502 return m_src.attribution();
506
507
508
509
510
511
512
513
514bool QDeclarativePlace::detailsFetched()
const
516 return m_src.detailsFetched();
520
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
556void QDeclarativePlace::setStatus(Status status,
const QString &errorString)
558 Status originalStatus = m_status;
560 m_errorString = errorString;
562 if (originalStatus != m_status)
563 emit statusChanged();
566QDeclarativePlace::Status QDeclarativePlace::status()
const
572
573
574void QDeclarativePlace::finished()
579 if (m_reply->error() == QPlaceReply::NoError) {
580 switch (m_reply->type()) {
581 case (QPlaceReply::IdReply) : {
582 QPlaceIdReply *idReply = qobject_cast<QPlaceIdReply *>(m_reply);
584 switch (idReply->operationType()) {
585 case QPlaceIdReply::SavePlace:
586 setPlaceId(idReply->id());
588 case QPlaceIdReply::RemovePlace:
596 case (QPlaceReply::DetailsReply): {
597 QPlaceDetailsReply *detailsReply = qobject_cast<QPlaceDetailsReply *>(m_reply);
598 setPlace(detailsReply->place());
606 m_errorString.clear();
608 m_reply->deleteLater();
611 setStatus(QDeclarativePlace::Ready);
613 QString errorString = m_reply->errorString();
615 m_reply->deleteLater();
618 setStatus(QDeclarativePlace::Error, errorString);
623
624
625void QDeclarativePlace::contactsModified(
const QString &key,
const QVariant &)
627 primarySignalsEmission(key);
631
632
633void QDeclarativePlace::cleanupDeletedCategories()
635 for (QDeclarativeCategory * category : m_categoriesToBeDeleted) {
636 if (category->parent() ==
this)
639 m_categoriesToBeDeleted.clear();
643
644
645
646
647
648
649
650
651
652void QDeclarativePlace::getDetails()
654 QPlaceManager *placeManager = manager();
658 m_reply = placeManager->getPlaceDetails(placeId());
659 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
660 setStatus(QDeclarativePlace::Fetching);
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681void QDeclarativePlace::save()
683 QPlaceManager *placeManager = manager();
687 m_reply = placeManager->savePlace(place());
688 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
689 setStatus(QDeclarativePlace::Saving);
693
694
695
696
697
698
699
700
701void QDeclarativePlace::remove()
703 QPlaceManager *placeManager = manager();
707 m_reply = placeManager->removePlace(place().placeId());
708 connect(m_reply, &QPlaceReply::finished,
this, &QDeclarativePlace::finished);
709 setStatus(QDeclarativePlace::Removing);
713
714
715
716
717
718QString QDeclarativePlace::errorString()
const
720 return m_errorString;
724
725
726
727
728
729
730
731
732QString QDeclarativePlace::primaryPhone()
const
734 return primaryValue(QPlaceContactDetail::Phone);
738
739
740
741
742
743
744
745QString QDeclarativePlace::primaryFax()
const
747 return primaryValue(QPlaceContactDetail::Fax);
751
752
753
754
755
756
757
758QString QDeclarativePlace::primaryEmail()
const
760 return primaryValue(QPlaceContactDetail::Email);
764
765
766
767
768
769
770
772QUrl QDeclarativePlace::primaryWebsite()
const
774 return QUrl(primaryValue(QPlaceContactDetail::Website));
778
779
780
781
782
783QQmlPropertyMap *QDeclarativePlace::extendedAttributes()
const
785 return m_extendedAttributes;
789
790
791
792
793
794QDeclarativeContactDetails *QDeclarativePlace::contactDetails()
const
796 return m_contactDetails;
800
801
802
803
804
805QQmlListProperty<QDeclarativeCategory> QDeclarativePlace::categories()
807 return QQmlListProperty<QDeclarativeCategory>(
this,
816
817
818void QDeclarativePlace::category_append(QQmlListProperty<QDeclarativeCategory> *prop,
819 QDeclarativeCategory *value)
821 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
823 if (object->m_categoriesToBeDeleted.contains(value))
824 object->m_categoriesToBeDeleted.removeAll(value);
826 if (!object->m_categories.contains(value)) {
827 object->m_categories.append(value);
828 QList<QPlaceCategory> list = object->m_src.categories();
829 list.append(value->category());
830 object->m_src.setCategories(list);
832 emit object->categoriesChanged();
837
838
839qsizetype QDeclarativePlace::category_count(QQmlListProperty<QDeclarativeCategory> *prop)
841 return static_cast<QDeclarativePlace *>(prop->object)->m_categories.count();
845
846
847QDeclarativeCategory *QDeclarativePlace::category_at(QQmlListProperty<QDeclarativeCategory> *prop,
850 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
851 QDeclarativeCategory *res = NULL;
852 if (object->m_categories.count() > index && index > -1) {
853 res = object->m_categories[index];
859
860
861void QDeclarativePlace::category_clear(QQmlListProperty<QDeclarativeCategory> *prop)
863 QDeclarativePlace *object =
static_cast<QDeclarativePlace *>(prop->object);
864 if (object->m_categories.isEmpty())
867 for (
auto *category : std::as_const(object->m_categories)) {
868 if (category->parent() == object)
869 object->m_categoriesToBeDeleted.append(category);
872 object->m_categories.clear();
873 object->m_src.setCategories(QList<QPlaceCategory>());
874 emit object->categoriesChanged();
875 QMetaObject::invokeMethod(object,
"cleanupDeletedCategories", Qt::QueuedConnection);
879
880
881void QDeclarativePlace::synchronizeCategories()
883 qDeleteAll(m_categories);
884 m_categories.clear();
885 for (
const QPlaceCategory &value : m_src.categories()) {
886 QDeclarativeCategory *declarativeValue =
new QDeclarativeCategory(value, m_plugin,
this);
887 m_categories.append(declarativeValue);
892
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
918QDeclarativePlace::Visibility QDeclarativePlace::visibility()
const
920 return static_cast<QDeclarativePlace::Visibility>(m_src.visibility());
923void QDeclarativePlace::setVisibility(Visibility visibility)
925 if (
static_cast<QDeclarativePlace::Visibility>(m_src.visibility()) == visibility)
928 m_src.setVisibility(
static_cast<QLocation::Visibility>(visibility));
929 emit visibilityChanged();
933
934
935
936
937QDeclarativePlace *QDeclarativePlace::favorite()
const
942void QDeclarativePlace::setFavorite(QDeclarativePlace *favorite)
945 if (m_favorite == favorite)
948 if (m_favorite && m_favorite->parent() ==
this)
951 m_favorite = favorite;
952 emit favoriteChanged();
956
957
958
959
960
961void QDeclarativePlace::copyFrom(QDeclarativePlace *original)
963 QPlaceManager *placeManager = manager();
967 setPlace(placeManager->compatiblePlace(original->place()));
971
972
973
974
975
976
977void QDeclarativePlace::initializeFavorite(QDeclarativeGeoServiceProvider *plugin)
979 if (m_favorite == 0) {
980 QDeclarativePlace *place =
new QDeclarativePlace(
this);
981 place->setPlugin(plugin);
982 place->copyFrom(
this);
988
989
990void QDeclarativePlace::pullExtendedAttributes()
992 const QStringList keys = m_extendedAttributes->keys();
993 for (
const QString &key : keys)
994 m_extendedAttributes->clear(key);
996 const QStringList attributeTypes = m_src.extendedAttributeTypes();
997 for (
const QString &attributeType : attributeTypes) {
998 m_extendedAttributes->insert(attributeType,
999 QVariant::fromValue(m_src.extendedAttribute(attributeType)));
1002 emit extendedAttributesChanged();
1006
1007
1008void QDeclarativePlace::synchronizeContacts()
1011 for (
const QString &contactType : m_contactDetails->keys()) {
1012 const QList<QVariant> contacts = m_contactDetails->value(contactType).toList();
1013 for (
const QVariant &var : contacts) {
1014 QObject *obj = var.value<QObject *>();
1015 if (obj->parent() ==
this)
1018 m_contactDetails->insert(contactType, QVariantList());
1022 for (
const QString &contactType : m_src.contactTypes()) {
1023 const QList<QPlaceContactDetail> sourceContacts = m_src.contactDetails(contactType);
1024 QVariantList declContacts;
1025 for (
const QPlaceContactDetail &sourceContact : sourceContacts)
1026 declContacts.append(QVariant::fromValue(sourceContact));
1027 m_contactDetails->insert(contactType, declContacts);
1029 primarySignalsEmission();
1033
1034
1035
1036
1037
1038void QDeclarativePlace::primarySignalsEmission(
const QString &type)
1040 if (type.isEmpty() || type == QPlaceContactDetail::Phone) {
1041 if (m_prevPrimaryPhone != primaryPhone()) {
1042 m_prevPrimaryPhone = primaryPhone();
1043 emit primaryPhoneChanged();
1045 if (!type.isEmpty())
1049 if (type.isEmpty() || type == QPlaceContactDetail::Email) {
1050 if (m_prevPrimaryEmail != primaryEmail()) {
1051 m_prevPrimaryEmail = primaryEmail();
1052 emit primaryEmailChanged();
1054 if (!type.isEmpty())
1058 if (type.isEmpty() || type == QPlaceContactDetail::Website) {
1059 if (m_prevPrimaryWebsite != primaryWebsite()) {
1060 m_prevPrimaryWebsite = primaryWebsite();
1061 emit primaryWebsiteChanged();
1063 if (!type.isEmpty())
1067 if (type.isEmpty() || type == QPlaceContactDetail::Fax) {
1068 if (m_prevPrimaryFax != primaryFax()) {
1069 m_prevPrimaryFax = primaryFax();
1070 emit primaryFaxChanged();
1076
1077
1078
1079
1080
1081QPlaceManager *QDeclarativePlace::manager()
1083 if (m_status != QDeclarativePlace::Ready && m_status != QDeclarativePlace::Error)
1088 m_reply->deleteLater();
1093 qmlWarning(
this) << QStringLiteral(
"Plugin is not assigned to place.");
1097 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
1098 if (!serviceProvider)
1101 QPlaceManager *placeManager = serviceProvider->placeManager();
1103 if (!placeManager) {
1104 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
1105 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
1109 return placeManager;
1113
1114
1115QString QDeclarativePlace::primaryValue(
const QString &contactType)
const
1117 QVariant value = m_contactDetails->value(contactType);
1118 if (value.userType() == qMetaTypeId<QJSValue>())
1119 value = value.value<QJSValue>().toVariant();
1121 if (value.userType() == QMetaType::QVariantList) {
1122 QVariantList detailList = m_contactDetails->value(contactType).toList();
1123 if (!detailList.isEmpty())
1124 return detailList.at(0).value<QPlaceContactDetail>().value();
1125 }
else if (value.metaType() == QMetaType::fromType<QPlaceContactDetail>()) {
1126 return value.value<QPlaceContactDetail>().value();