diff options
Diffstat (limited to 'src/base/QXmppFileMetadata.cpp')
| -rw-r--r-- | src/base/QXmppFileMetadata.cpp | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/src/base/QXmppFileMetadata.cpp b/src/base/QXmppFileMetadata.cpp new file mode 100644 index 00000000..35b5b040 --- /dev/null +++ b/src/base/QXmppFileMetadata.cpp @@ -0,0 +1,276 @@ +// SPDX-FileCopyrightText: 2022 Jonah BrĂ¼chert <jbb@kaidan.im> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "QXmppFileMetadata.h" + +#include "QXmppConstants_p.h" +#include "QXmppHash.h" +#include "QXmppUtils.h" +#include "QXmppThumbnail.h" + +#include <utility> + +#include <QDateTime> +#include <QDomElement> +#include <QMimeDatabase> +#include <QMimeType> +#include <QSharedData> + +class QXmppFileMetadataPrivate : public QSharedData +{ +public: + std::optional<QDateTime> date; + std::optional<QString> desc; + QVector<QXmppHash> hashes; + std::optional<uint32_t> height; + std::optional<uint32_t> length; + std::optional<QMimeType> mediaType; + std::optional<QString> name; + std::optional<uint64_t> size; + std::optional<QXmppThumbnail> thumbnail; + std::optional<uint32_t> width; +}; + +/// +/// \class QXmppFileMetadata +/// +/// File metadata from \xep{0446, File metadata element}. +/// +/// \since QXmpp 1.5 +/// + +QXmppFileMetadata::QXmppFileMetadata() + : d(new QXmppFileMetadataPrivate()) +{ +} + +QXMPP_PRIVATE_DEFINE_ROLE_OF_SIX(QXmppFileMetadata) + +/// \cond +QVector<QDomElement> allChildElements(const QDomElement &el, const QString &name) +{ + QVector<QDomElement> out; + + for (auto childEl = el.firstChildElement(name); !childEl.isNull(); childEl = childEl.nextSiblingElement(name)) { + out.push_back(childEl); + } + + return out; +} + +template<typename Func> +QVector<std::invoke_result_t<Func, QDomElement>> forAllChildElements(const QDomElement &el, const QString &name, Func func) +{ + auto elements = allChildElements(el, name); + QVector<std::invoke_result_t<Func, QDomElement>> out; + std::transform(elements.begin(), elements.end(), std::back_inserter(out), func); + return out; +} + +bool QXmppFileMetadata::parse(const QDomElement &el) +{ + if (el.isNull()) + return false; + + if (auto dateEl = el.firstChildElement("date"); !dateEl.isNull()) { + d->date = QXmppUtils::datetimeFromString(dateEl.text()); + } + + if (auto descEl = el.firstChildElement("desc"); !descEl.isNull()) { + d->desc = descEl.text(); + } + + d->hashes = forAllChildElements(el, "hash", [](const auto &el) { + QXmppHash hash; + hash.parse(el); + return hash; + }); + + if (auto heightEl = el.firstChildElement("height"); !heightEl.isNull()) { + d->height = el.firstChildElement("height").text().toUInt(); + } + if (auto lengthEl = el.firstChildElement("length"); !lengthEl.isNull()) { + d->length = lengthEl.text().toUInt(); + } + if (auto mediaTypeEl = el.firstChildElement("media-type"); !mediaTypeEl.isNull()) { + d->mediaType = QMimeDatabase().mimeTypeForName(mediaTypeEl.text()); + } + if (auto nameEl = el.firstChildElement("name"); !nameEl.isNull()) { + d->name = nameEl.text(); + } + if (auto sizeEl = el.firstChildElement("size"); !sizeEl.isNull()) { + d->size = sizeEl.text().toULong(); + } + if (auto thumbEl = el.firstChildElement("thumbnail"); !thumbEl.isNull()) { + d->thumbnail = QXmppThumbnail(); + if (!d->thumbnail->parse(thumbEl)) { + d->thumbnail.reset(); + } + } + if (auto widthEl = el.firstChildElement("width"); !widthEl.isNull()) { + d->width = widthEl.text().toUInt(); + } + return true; +} + +void QXmppFileMetadata::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("file"); + writer->writeDefaultNamespace(ns_file_metadata); + if (d->date) { + writer->writeTextElement("date", QXmppUtils::datetimeToString(*d->date)); + } + + if (d->desc) { + writer->writeTextElement("desc", *d->desc); + } + + for (const auto &hash : d->hashes) { + hash.toXml(writer); + } + + if (d->height) { + writer->writeTextElement("height", QString::number(*d->height)); + } + if (d->length) { + writer->writeTextElement("length", QString::number(*d->length)); + } + if (d->mediaType) { + writer->writeTextElement("media-type", d->mediaType->name()); + } + if (d->name) { + writer->writeTextElement("name", *d->name); + } + if (d->size) { + writer->writeTextElement("size", QString::number(*d->size)); + } + if (d->thumbnail) { + d->thumbnail->toXml(writer); + } + if (d->width) { + writer->writeTextElement("width", QString::number(*d->width)); + } + writer->writeEndElement(); +} +/// \endcond + +/// Returns when the file was last modified +const std::optional<QDateTime> &QXmppFileMetadata::lastModified() const +{ + return d->date; +} + +/// Sets when the file was last modified +void QXmppFileMetadata::setLastModified(const std::optional<QDateTime> &date) +{ + d->date = date; +} + +/// Returns the description of the file +const std::optional<QString> &QXmppFileMetadata::description() const +{ + return d->desc; +} + +/// Sets the description of the file +void QXmppFileMetadata::setDescription(const std::optional<QString> &description) +{ + d->desc = description; +} + +/// Returns the hashes of the file +const QVector<QXmppHash> &QXmppFileMetadata::hashes() const +{ + return d->hashes; +} + +/// Sets the hashes of the file +void QXmppFileMetadata::setHashes(const QVector<QXmppHash> &hashes) +{ + d->hashes = hashes; +} + +/// Returns the height of the image +std::optional<uint32_t> QXmppFileMetadata::height() const +{ + return d->height; +} + +/// Sets the height of the image +void QXmppFileMetadata::setHeight(std::optional<uint32_t> height) +{ + d->height = height; +} + +/// Returns the length of a video or audio file +std::optional<uint32_t> QXmppFileMetadata::length() const +{ + return d->length; +} + +/// Sets the length of a video or audio file +void QXmppFileMetadata::setLength(std::optional<uint32_t> length) +{ + d->length = length; +} + +/// Returns the media type of the file +const std::optional<QMimeType> &QXmppFileMetadata::mediaType() const +{ + return d->mediaType; +} + +/// Sets the media type of the file +void QXmppFileMetadata::setMediaType(std::optional<QMimeType> mediaType) +{ + d->mediaType = std::move(mediaType); +} + +/// Returns the filename +std::optional<QString> QXmppFileMetadata::filename() const +{ + return d->name; +} + +/// Sets the filename +void QXmppFileMetadata::setFilename(std::optional<QString> name) +{ + d->name = std::move(name); +} + +/// Returns the size of the file in bytes +std::optional<uint64_t> QXmppFileMetadata::size() const +{ + return d->size; +} + +/// Sets the size of the file in bytes +void QXmppFileMetadata::setSize(std::optional<uint64_t> size) +{ + d->size = size; +} + +/// Returns the thumbnail reference. +const std::optional<QXmppThumbnail> &QXmppFileMetadata::thumbnail() const +{ + return d->thumbnail; +} + +/// Sets the thumbnail reference. +void QXmppFileMetadata::setThumbnail(const std::optional<QXmppThumbnail> &thumbnail) +{ + d->thumbnail = thumbnail; +} + +/// Returns the width of the image or video. +std::optional<uint32_t> QXmppFileMetadata::width() const +{ + return d->width; +} + +/// Sets the width of the image or video. +void QXmppFileMetadata::setWidth(std::optional<uint32_t> width) +{ + d->width = width; +} |
