Revision control
++ // Copyright (C) 2022 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #include "qplace.h"
++ #include "qplace_p.h"
++
++ #include <QtPositioning/QGeoLocation>
++
++ #ifdef QPLACE_DEBUG
++ #include <QDebug>
++ #endif
++
++ #include <QStringList>
++
++ QT_BEGIN_NAMESPACE
++
++ template<>
++ QPlacePrivate *QSharedDataPointer<QPlacePrivate>::clone()
++ {
++ return d->clone();
++ }
++
++ QT_DEFINE_QSDP_SPECIALIZATION_DTOR(QPlacePrivate)
++
++ /*!
++ \class QPlace
++ \inmodule QtLocation
++ \ingroup QtLocation-places
++ \ingroup QtLocation-places-data
++ \since 5.6
++
++ \brief The QPlace class represents a set of data about a place.
++
++ \input place-definition.qdocinc
++
++ \section1 Contact Information
++ The contact information of a place is based around a common set of
++ \l {Contact Types}{contact types}. To retrieve all the phone numbers
++ of a place, one would do:
++
++ \snippet places/requesthandler.h Phone numbers
++
++ The contact types are string values by design to allow for providers
++ to introduce new contact types.
++
++ For convenience there are a set of functions which return the value
++ of the first contact detail of each type.
++ \list
++ \li QPlace::primaryPhone()
++ \li QPlace::primaryEmail()
++ \li QPlace::primaryWebsite()
++ \li QPlace::primaryFax()
++ \endlist
++
++ \section1 Extended Attributes
++ Places may have additional attributes which are not covered in the formal API.
++ Similar to contacts attributes are based around a common set of
++ \l {Attribute Types}{attribute types}. To retrieve an extended attribute one
++ would do:
++ \snippet places/requesthandler.h Opening hours
++
++ The attribute types are string values by design to allow providers
++ to introduce new attribute types.
++
++ \section1 Content
++ The QPlace object is only meant to be a convenient container to hold
++ rich content such as images, reviews and so on. Retrieval of content
++ should happen via QPlaceManager::getPlaceContent().
++
++ The content is stored as a QPlaceContent::Collection which contains
++ both the index of the content, as well as the content itself. This enables
++ developers to check whether a particular item has already been retrieved
++ and if not, then request that content.
++
++ \section2 Attribution
++ Places have a field for a rich text attribution string. Some providers
++ may require that the attribution be shown when a place is displayed
++ to a user.
++
++ \section2 Categories
++ Different categories may be assigned to a place to indicate that the place
++ is associated with those categories. When saving a place, the only meaningful
++ data is the category id, the rest of the category data is effectively ignored.
++ The category must already exist before saving the place (it is not possible
++ to create a new category, assign it to the place, save the place and expect
++ the category to be created).
++
++ \section1 Saving Caveats
++ \input place-caveats.qdocinc
++ */
++
++ /*!
++ Constructs an empty place object.
++ */
++ QPlace::QPlace()
++ : d_ptr(new QPlacePrivateDefault())
++ {
++ }
++
++ /*!
++ Constructs an place object using \a dd as private implementation.
++ */
++ QPlace::QPlace(const QSharedDataPointer<QPlacePrivate> &dd): d_ptr(dd)
++ {
++ }
++
++
++ /*!
++ Constructs a copy of \a other.
++ */
++ QPlace::QPlace(const QPlace &other) noexcept = default;
++
++ /*!
++ Destroys this place.
++ */
++ QPlace::~QPlace() = default;
++
++ /*!
++ Assigns \a other to this place and returns a reference
++ to this place.
++ */
++ QPlace &QPlace::operator= (const QPlace & other) noexcept
++ {
++ if (this == &other)
++ return *this;
++
++ d_ptr = other.d_ptr;
++ return *this;
++ }
++
++ inline QPlacePrivate *QPlace::d_func()
++ {
++ return static_cast<QPlacePrivate *>(d_ptr.data());
++ }
++
++ inline const QPlacePrivate *QPlace::d_func() const
++ {
++ return static_cast<const QPlacePrivate *>(d_ptr.constData());
++ }
++
++ /*!
++ \fn bool QPlace::operator==(const QPlace &lhs, const QPlace &rhs) noexcept
++
++ Returns true if \a lhs is equal to \a rhs,
++ otherwise returns false.
++ */
++
++ /*!
++ \fn bool QPlace::operator!=(const QPlace &lhs, const QPlace &rhs) noexcept
++
++ Returns true if \a lhs is not equal to \a rhs,
++ otherwise returns false.
++ */
++
++ bool QPlace::isEqual(const QPlace &other) const noexcept
++ {
++ return ( (d_ptr.constData() == other.d_ptr.constData())
++ || (*d_ptr) == (*other.d_ptr));
++ }
++
++ /*!
++ Returns categories that this place belongs to.
++ */
++ QList<QPlaceCategory> QPlace::categories() const
++ {
++ return d_ptr->categories();
++ }
++
++ /*!
++ Sets a single \a category that this place belongs to.
++ */
++ void QPlace::setCategory(const QPlaceCategory &category)
++ {
++ d_ptr->setCategories(QList<QPlaceCategory>());
++ d_ptr->setCategories(QList<QPlaceCategory>() << category);
++ }
++
++ /*!
++ Sets the \a categories that this place belongs to.
++ */
++ void QPlace::setCategories(const QList<QPlaceCategory> &categories)
++ {
++ d_ptr->setCategories(categories);
++ }
++
++ /*!
++ Returns the location of the place.
++ */
++ QGeoLocation QPlace::location() const
++ {
++ return d_ptr->location();
++ }
++
++ /*!
++ Sets the \a location of the place.
++ */
++ void QPlace::setLocation(const QGeoLocation &location)
++ {
++ d_ptr->setLocation(location);
++ }
++
++ /*!
++ Returns an aggregated rating of the place.
++ */
++ QPlaceRatings QPlace::ratings() const
++ {
++ return d_ptr->ratings();
++ }
++
++ /*!
++ Sets the aggregated \a rating of the place.
++ */
++ void QPlace::setRatings(const QPlaceRatings &rating)
++ {
++ d_ptr->setRatings(rating);
++ }
++
++ /*!
++ Returns the supplier of this place.
++ */
++ QPlaceSupplier QPlace::supplier() const
++ {
++ return d_ptr->supplier();
++ }
++
++ /*!
++ Sets the supplier of this place to \a supplier.
++ */
++ void QPlace::setSupplier(const QPlaceSupplier &supplier)
++ {
++ d_ptr->setSupplier(supplier);
++ }
++
++ /*!
++ Returns a collection of content associated with a place.
++ This collection is a map with the key being the index of the content object
++ and value being the content object itself.
++
++ The \a type specifies which kind of content is to be retrieved.
++ */
++ QPlaceContent::Collection QPlace::content(QPlaceContent::Type type) const
++ {
++ return d_ptr->m_contentCollections.value(type);
++ }
++
++ /*!
++ Sets a collection of \a content for the given \a type.
++ */
++ void QPlace::setContent(QPlaceContent::Type type, const QPlaceContent::Collection &content)
++ {
++ d_ptr->m_contentCollections.insert(type, content);
++ }
++
++ /*!
++ Adds a collection of \a content of the given \a type to the place. Any index in \a content
++ that already exists is overwritten.
++ */
++ void QPlace::insertContent(QPlaceContent::Type type, const QPlaceContent::Collection &content)
++ {
++ for (auto iter = content.cbegin(), end = content.cend(); iter != end; ++iter)
++ d_ptr->m_contentCollections[type].insert(iter.key(), iter.value());
++ }
++
++ /*!
++ Returns the total count of content objects of the given \a type.
++ This total count indicates how many the manager/provider should have available.
++ (As opposed to how many objects this place instance is currently assigned).
++
++ A negative count indicates that the total number of items is unknown.
++ By default the total content count is set to 0.
++ */
++ int QPlace::totalContentCount(QPlaceContent::Type type) const
++ {
++ return d_ptr->m_contentCounts.value(type, 0);
++ }
++
++ /*!
++ Sets the \a totalCount of content objects of the given \a type.
++ */
++ void QPlace::setTotalContentCount(QPlaceContent::Type type, int totalCount)
++ {
++ d_ptr->m_contentCounts.insert(type, totalCount);
++ }
++
++ /*!
++ Returns the name of the place.
++ */
++ QString QPlace::name() const
++ {
++ return d_ptr->name();
++ }
++
++ /*!
++ Sets the \a name of the place.
++ */
++ void QPlace::setName(const QString &name)
++ {
++ d_ptr->setName(name);
++ }
++
++ /*!
++ Returns the identifier of the place. The place identifier is only meaningful to the QPlaceManager that
++ generated it and is not transferable between managers. The place identifier is not guaranteed
++ to be universally unique, but unique for the manager that generated it.
++ */
++ QString QPlace::placeId() const
++ {
++ return d_ptr->placeId();
++ }
++
++ /*!
++ Sets the \a identifier of the place.
++ */
++ void QPlace::setPlaceId(const QString &identifier)
++ {
++ d_ptr->setPlaceId(identifier);
++ }
++
++ /*!
++ Returns a rich text attribution string of the place. Note, some providers may have a
++ requirement where the attribution must be shown whenever a place is displayed to an end user.
++ */
++ QString QPlace::attribution() const
++ {
++ return d_ptr->attribution();
++ }
++
++ /*!
++ Sets the \a attribution string of the place.
++ */
++ void QPlace::setAttribution(const QString &attribution)
++ {
++ d_ptr->setAttribution(attribution);
++ }
++
++ /*!
++ Returns the icon of the place.
++ */
++ QPlaceIcon QPlace::icon() const
++ {
++ return d_ptr->icon();
++ }
++
++ /*!
++ Sets the \a icon of the place.
++ */
++ void QPlace::setIcon(const QPlaceIcon &icon)
++ {
++ d_ptr->setIcon(icon);
++ }
++
++ /*!
++ Returns the primary phone number for this place. This accesses the first contact detail
++ of the \l {QPlaceContactDetail::Phone}{phone number type}. If no phone details exist, then an empty string is returned.
++ */
++ QString QPlace::primaryPhone() const
++ {
++ QList<QPlaceContactDetail> phoneNumbers = d_ptr->contacts().value(QPlaceContactDetail::Phone);
++ if (!phoneNumbers.isEmpty())
++ return phoneNumbers.at(0).value();
++ else
++ return QString();
++ }
++
++ /*!
++ Returns the primary fax number for this place. This convenience function accesses the first contact
++ detail of the \l {QPlaceContactDetail::Fax}{fax type}. If no fax details exist, then an empty string is returned.
++ */
++ QString QPlace::primaryFax() const
++ {
++ QList<QPlaceContactDetail> faxNumbers = d_ptr->contacts().value(QPlaceContactDetail::Fax);
++ if (!faxNumbers.isEmpty())
++ return faxNumbers.at(0).value();
++ else
++ return QString();
++ }
++
++ /*!
++ Returns the primary email address for this place. This convenience function accesses the first
++ contact detail of the \l {QPlaceContactDetail::Email}{email type}. If no email addresses exist, then
++ an empty string is returned.
++ */
++ QString QPlace::primaryEmail() const
++ {
++ QList<QPlaceContactDetail> emailAddresses = d_ptr->contacts().value(QPlaceContactDetail::Email);
++ if (!emailAddresses.isEmpty())
++ return emailAddresses.at(0).value();
++ else
++ return QString();
++ }
++
++ /*!
++ Returns the primary website of the place. This convenience function accesses the first
++ contact detail of the \l {QPlaceContactDetail::Website}{website type}. If no websites exist,
++ then an empty string is returned.
++ */
++ QUrl QPlace::primaryWebsite() const
++ {
++ QList<QPlaceContactDetail> websites = d_ptr->contacts().value(QPlaceContactDetail::Website);
++ if (!websites.isEmpty())
++ return QUrl(websites.at(0).value());
++ else
++ return {};
++ }
++
++ /*!
++ Returns true if the details of this place have been fetched,
++ otherwise returns false.
++ */
++ bool QPlace::detailsFetched() const
++ {
++ return d_ptr->detailsFetched();
++ }
++
++ /*!
++ Sets whether the details of this place have been \a fetched or not.
++ */
++ void QPlace::setDetailsFetched(bool fetched)
++ {
++ d_ptr->setDetailsFetched(fetched);
++ }
++
++ /*!
++ Returns the types of extended attributes that this place has.
++ */
++ QStringList QPlace::extendedAttributeTypes() const
++ {
++ return d_ptr->extendedAttributes().keys();
++ }
++
++ /*!
++ Returns the exteded attribute corresponding to the specified \a attributeType.
++ If the place does not have that particular attribute type, a default constructed
++ QPlaceExtendedAttribute is returned.
++ */
++ QPlaceAttribute QPlace::extendedAttribute(const QString &attributeType) const
++ {
++ return d_ptr->extendedAttribute(attributeType);
++ }
++
++ /*!
++ Assigns an \a attribute of the given \a attributeType to a place. If the given \a attributeType
++ already exists in the place, then it is overwritten.
++
++ If \a attribute is a default constructed QPlaceAttribute, then the \a attributeType
++ is removed from the place which means it will not be listed by QPlace::extendedAttributeTypes().
++ */
++ void QPlace::setExtendedAttribute(const QString &attributeType,
++ const QPlaceAttribute &attribute)
++ {
++ if (attribute == QPlaceAttribute())
++ d_ptr->extendedAttributes().remove(attributeType);
++ else
++ d_ptr->extendedAttributes().insert(attributeType, attribute);
++ }
++
++ /*!
++ Remove the attribute of \a attributeType from the place.
++
++ The attribute will no longer be listed by QPlace::extendedAttributeTypes()
++ */
++ void QPlace::removeExtendedAttribute(const QString &attributeType)
++ {
++ setExtendedAttribute(attributeType, QPlaceAttribute());
++ }
++
++ /*!
++ Returns the type of contact details this place has.
++
++ See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}.
++ */
++ QStringList QPlace::contactTypes() const
++ {
++ return d_ptr->contacts().keys();
++ }
++
++ /*!
++ Returns a list of contact details of the specified \a contactType.
++
++ See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}.
++ */
++ QList<QPlaceContactDetail> QPlace::contactDetails(const QString &contactType) const
++ {
++ return d_ptr->contacts().value(contactType);
++ }
++
++ /*!
++ Sets the contact \a details of a specified \a contactType.
++
++ If \a details is empty, then the \a contactType is removed from the place such
++ that it is no longer returned by QPlace::contactTypes().
++
++ See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}.
++ */
++ void QPlace::setContactDetails(const QString &contactType, QList<QPlaceContactDetail> details)
++ {
++ if (details.isEmpty())
++ d_ptr->contacts().remove(contactType);
++ else
++ d_ptr->contacts().insert(contactType, details);
++ }
++
++ /*!
++ Appends a contact \a detail of a specified \a contactType.
++
++ See QPlaceContactDetail for a list of common \l {QPlaceContactDetail::Email}{contact types}.
++ */
++ void QPlace::appendContactDetail(const QString &contactType, const QPlaceContactDetail &detail)
++ {
++ QList<QPlaceContactDetail> details = d_ptr->contacts().value(contactType);
++ details.append(detail);
++ d_ptr->contacts().insert(contactType, details);
++ }
++
++ /*!
++ Removes all the contact details of a given \a contactType.
++
++ The \a contactType is no longer returned when QPlace::contactTypes() is called.
++ */
++ void QPlace::removeContactDetails(const QString &contactType)
++ {
++ d_ptr->contacts().remove(contactType);
++ }
++
++ /*!
++ Sets the visibility of the place to \a visibility.
++ */
++ void QPlace::setVisibility(QLocation::Visibility visibility)
++ {
++ d_ptr->setVisibility(visibility);
++ }
++
++ /*!
++ Returns the visibility of the place.
++
++ The default visibility of a new place is set to QtLocatin::Unspecified visibility.
++ If a place is saved with unspecified visibility the backend chooses an appropriate
++ default visibility to use when saving.
++ */
++ QLocation::Visibility QPlace::visibility() const
++ {
++ return d_ptr->visibility();
++ }
++
++ /*!
++ Returns a boolean indicating whether the all the fields of the place are empty or not.
++ */
++ bool QPlace::isEmpty() const
++ {
++ return d_ptr->isEmpty();
++ }
++
++ /*******************************************************************************
++ *******************************************************************************/
++
++ QPlacePrivate::QPlacePrivate()
++ : QSharedData()
++ {
++ }
++
++ QPlacePrivate::QPlacePrivate(const QPlacePrivate &other)
++ : QSharedData(other),
++ m_contentCollections(other.m_contentCollections),
++ m_contentCounts(other.m_contentCounts)
++ {
++ }
++
++ QPlacePrivate::~QPlacePrivate() {}
++
++ bool QPlacePrivate::operator== (const QPlacePrivate &other) const
++ {
++ return (categories() == other.categories()
++ && location() == other.location()
++ && ratings() == other.ratings()
++ && supplier() == other.supplier()
++ && m_contentCollections == other.m_contentCollections
++ && m_contentCounts == other.m_contentCounts
++ && name() == other.name()
++ && placeId() == other.placeId()
++ && attribution() == other.attribution()
++ && contacts() == other.contacts()
++ && extendedAttributes() == other.extendedAttributes()
++ && visibility() == other.visibility()
++ && icon() == other.icon()
++ );
++ }
++
++
++ bool QPlacePrivate::isEmpty() const
++ {
++ return (categories().isEmpty()
++ && location().isEmpty()
++ && ratings().isEmpty()
++ && supplier().isEmpty()
++ && m_contentCollections.isEmpty()
++ && m_contentCounts.isEmpty()
++ && name().isEmpty()
++ && placeId().isEmpty()
++ && attribution().isEmpty()
++ && contacts().isEmpty()
++ && extendedAttributes().isEmpty()
++ && QLocation::UnspecifiedVisibility == visibility()
++ && icon().isEmpty()
++ );
++ }
++
++ QPlaceAttribute QPlacePrivate::extendedAttribute(const QString &attributeType) const
++ {
++ return extendedAttributes().value(attributeType);
++ }
++
++
++
++ //
++ // Default implementation
++ //
++
++ QPlacePrivateDefault::QPlacePrivateDefault()
++ : QPlacePrivate(), m_visibility(QLocation::UnspecifiedVisibility), m_detailsFetched(false)
++ {
++ }
++
++ QPlacePrivateDefault::QPlacePrivateDefault(const QPlacePrivateDefault &other)
++ : QPlacePrivate(other),
++ m_categories(other.m_categories),
++ m_location(other.m_location),
++ m_ratings(other.m_ratings),
++ m_supplier(other.m_supplier),
++ m_name(other.m_name),
++ m_placeId(other.m_placeId),
++ m_attribution(other.m_attribution),
++ m_extendedAttributes(other.m_extendedAttributes),
++ m_contacts(other.m_contacts),
++ m_visibility(other.m_visibility),
++ m_icon(other.m_icon),
++ m_detailsFetched(other.m_detailsFetched)
++ {
++ }
++
++ QPlacePrivateDefault::~QPlacePrivateDefault()
++ {
++ }
++
++ QPlacePrivate *QPlacePrivateDefault::clone()
++ {
++ return new QPlacePrivateDefault(*this);
++ }
++
++ QList<QPlaceCategory> QPlacePrivateDefault::categories() const
++ {
++ return m_categories;
++ }
++
++ void QPlacePrivateDefault::setCategories(const QList<QPlaceCategory> &categories)
++ {
++ m_categories = categories;
++ }
++
++ QGeoLocation QPlacePrivateDefault::location() const
++ {
++ return m_location;
++ }
++
++ void QPlacePrivateDefault::setLocation(const QGeoLocation &location)
++ {
++ m_location = location;
++ }
++
++ QPlaceRatings QPlacePrivateDefault::ratings() const
++ {
++ return m_ratings;
++ }
++
++ void QPlacePrivateDefault::setRatings(const QPlaceRatings &ratings)
++ {
++ m_ratings = ratings;
++ }
++
++ QPlaceSupplier QPlacePrivateDefault::supplier() const
++ {
++ return m_supplier;
++ }
++
++ void QPlacePrivateDefault::setSupplier(const QPlaceSupplier &supplier)
++ {
++ m_supplier = supplier;
++ }
++
++ QString QPlacePrivateDefault::name() const
++ {
++ return m_name;
++ }
++
++ void QPlacePrivateDefault::setName(const QString &name)
++ {
++ m_name = name;
++ }
++
++ QString QPlacePrivateDefault::placeId() const
++ {
++ return m_placeId;
++ }
++
++ void QPlacePrivateDefault::setPlaceId(const QString &placeIdentifier)
++ {
++ m_placeId = placeIdentifier;
++ }
++
++ QString QPlacePrivateDefault::attribution() const
++ {
++ return m_attribution;
++ }
++
++ void QPlacePrivateDefault::setAttribution(const QString &attribution)
++ {
++ m_attribution = attribution;
++ }
++
++ QLocation::Visibility QPlacePrivateDefault::visibility() const
++ {
++ return m_visibility;
++ }
++
++ void QPlacePrivateDefault::setVisibility(QLocation::Visibility visibility)
++ {
++ m_visibility = visibility;
++ }
++
++ QPlaceIcon QPlacePrivateDefault::icon() const
++ {
++ return m_icon;
++ }
++
++ void QPlacePrivateDefault::setIcon(const QPlaceIcon &icon)
++ {
++ m_icon = icon;
++ }
++
++ bool QPlacePrivateDefault::detailsFetched() const
++ {
++ return m_detailsFetched;
++ }
++
++ void QPlacePrivateDefault::setDetailsFetched(bool fetched)
++ {
++ m_detailsFetched = fetched;
++ }
++
++ QMap<QString, QPlaceAttribute> QPlacePrivateDefault::extendedAttributes() const
++ {
++ return m_extendedAttributes;
++ }
++
++ QMap<QString, QPlaceAttribute> &QPlacePrivateDefault::extendedAttributes()
++ {
++ return m_extendedAttributes;
++ }
++
++ QMap<QString, QList<QPlaceContactDetail> > QPlacePrivateDefault::contacts() const
++ {
++ return m_contacts;
++ }
++
++ QMap<QString, QList<QPlaceContactDetail> > &QPlacePrivateDefault::contacts()
++ {
++ return m_contacts;
++ }
++
++
++
++ QT_END_NAMESPACE