From f2aadfefa283aafc88131c643b97acd28989ac20 Mon Sep 17 00:00:00 2001 From: Cochise César Date: Mon, 10 Jan 2022 01:27:06 -0300 Subject: Implement XEP-0080: User Location --- src/base/QXmppGeolocItem.cpp | 202 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 src/base/QXmppGeolocItem.cpp (limited to 'src/base/QXmppGeolocItem.cpp') diff --git a/src/base/QXmppGeolocItem.cpp b/src/base/QXmppGeolocItem.cpp new file mode 100644 index 00000000..bef54b69 --- /dev/null +++ b/src/base/QXmppGeolocItem.cpp @@ -0,0 +1,202 @@ +// SPDX-FileCopyrightText: 2022 Cochise César +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "QXmppGeolocItem.h" + +#include "QXmppConstants_p.h" +#include "QXmppUtils.h" + +#include +#include + +/// \cond +class QXmppGeolocItemPrivate : public QSharedData +{ +public: + std::optional accuracy; + QString country; + QString locality; + std::optional latitude; + std::optional longitude; +}; +/// \endcond + +/// +/// \class QXmppGeolocItem +/// +/// This class represents a PubSub item for \xep{0080, User Location}. +/// +/// \since QXmpp 1.5 +/// + +/// +/// Default constructor +/// +QXmppGeolocItem::QXmppGeolocItem() + : d(new QXmppGeolocItemPrivate) +{ +} + +/// Copy-constructor. +QXmppGeolocItem::QXmppGeolocItem(const QXmppGeolocItem &other) = default; + +QXmppGeolocItem::~QXmppGeolocItem() = default; + +/// Assignment operator. +QXmppGeolocItem &QXmppGeolocItem::operator=(const QXmppGeolocItem &other) = default; + +/// +/// Returns the horizontal GPS error in meters. +/// +std::optional QXmppGeolocItem::accuracy() const +{ + return d->accuracy; +} + +/// +/// Sets the horizontal GPS error. +/// +void QXmppGeolocItem::setAccuracy(std::optional accuracy) +{ + d->accuracy = std::move(accuracy); +} + +/// +/// Returns the country. +/// +QString QXmppGeolocItem::country() const +{ + return d->country; +} + +/// +/// Sets the country. +/// +void QXmppGeolocItem::setCountry(QString country) +{ + d->country = std::move(country); +} + +/// +/// Returns the latitude in decimal degrees. +/// +std::optional QXmppGeolocItem::latitude() const +{ + return d->latitude; +} + +/// +/// Sets the latitude. +/// +void QXmppGeolocItem::setLatitude(std::optional lat) +{ + if (lat && (*lat > 90 || *lat < -90)) { + d->latitude.reset(); + return; + } + d->latitude = std::move(lat); +} + +/// +/// Returns the locality such as a town or a city. +/// +QString QXmppGeolocItem::locality() const +{ + return d->locality; +} + +/// +/// Sets the locality. +/// +void QXmppGeolocItem::setLocality(QString locality) +{ + d->locality = std::move(locality); +} + +/// +/// Returns the longitude in decimal degrees. +/// +std::optional QXmppGeolocItem::longitude() const +{ + return d->longitude; +} + +/// +/// Sets the longitude. +/// +void QXmppGeolocItem::setLongitude(std::optional lon) +{ + if (lon && (*lon > 180 || *lon < -180)) { + d->longitude.reset(); + return; + } + d->longitude = std::move(lon); +} + +/// +/// Returns true, if the element is a valid \xep{0080}: User Location PubSub item. +/// +bool QXmppGeolocItem::isItem(const QDomElement &itemElement) +{ + auto isPayloadValid = [](const QDomElement &payload) -> bool { + return payload.tagName() == QStringLiteral("geoloc") && + payload.namespaceURI() == ns_geoloc; + }; + + return QXmppPubSubItem::isItem(itemElement, isPayloadValid); +} + +/// \cond +std::optional parseOptDouble(const QDomElement &element) +{ + bool ok = false; + if (auto val = element.text().toDouble(&ok); ok) { + return val; + } + return {}; +} + +void QXmppGeolocItem::parsePayload(const QDomElement &tune) +{ + for (auto child = tune.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) { + const auto tagName = child.tagName(); + if (tagName == QStringLiteral("accuracy")) { + d->accuracy = parseOptDouble(child); + } else if (tagName == QStringLiteral("country")) { + d->country = child.text(); + } else if (tagName == QStringLiteral("lat")) { + setLatitude(parseOptDouble(child)); + } else if (tagName == QStringLiteral("locality")) { + d->locality = child.text(); + } else if (tagName == QStringLiteral("lon")) { + setLongitude(parseOptDouble(child)); + } + } +} + +auto writeTextEl(QXmlStreamWriter *writer, const QString &name, const std::optional &val) +{ + if (val.has_value()) { + writer->writeTextElement(name, QString::number(*val)); + } +} +auto writeTextEl(QXmlStreamWriter *writer, const QString &name, const QString &val) +{ + helperToXmlAddTextElement(writer, name, val); +} + +void QXmppGeolocItem::serializePayload(QXmlStreamWriter *writer) const +{ + writer->writeStartElement(QStringLiteral("geoloc")); + writer->writeDefaultNamespace(ns_geoloc); + + writeTextEl(writer, QStringLiteral("accuracy"), d->accuracy); + writeTextEl(writer, QStringLiteral("country"), d->country); + writeTextEl(writer, QStringLiteral("lat"), d->latitude); + writeTextEl(writer, QStringLiteral("locality"), d->locality); + writeTextEl(writer, QStringLiteral("lon"), d->longitude); + + writer->writeEndElement(); +} +/// \endcond -- cgit v1.2.3