diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index 7dbbc91d..e124712b 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -32,6 +32,7 @@ set(APPSTREAMQT_SRC release.cpp bundle.cpp suggested.cpp + metadata.cpp contentrating.cpp launchable.cpp translation.cpp @@ -48,6 +49,7 @@ set(APPSTREAMQT_PUBLIC_HEADERS release.h bundle.h suggested.h + metadata.h contentrating.h launchable.h translation.h diff --git a/qt/metadata.cpp b/qt/metadata.cpp new file mode 100644 index 00000000..f3dff2c4 --- /dev/null +++ b/qt/metadata.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2016 Matthias Klumpp + * Copyright (C) 2017 Jan Grulich + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the license, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include "appstream.h" +#include "metadata.h" +#include "chelpers.h" + +#include + +using namespace AppStream; + +class AppStream::MetadataData : public QSharedData { +public: + MetadataData() + { + m_metadata = as_metadata_new(); + } + + MetadataData(AsMetadata *metadata) + : m_metadata(metadata) + { + g_object_ref(m_metadata); + } + + ~MetadataData() + { + g_object_unref(m_metadata); + } + + bool operator==(const MetadataData& rd) const + { + return rd.m_metadata == m_metadata; + } + + AsMetadata *metadata() const + { + return m_metadata; + } + + AsMetadata* m_metadata; +}; + +AppStream::Metadata::FormatKind AppStream::Metadata::stringToFormatKind(const QString& kindString) +{ + if (kindString == QLatin1String("xml")) { + return FormatKind::FormatKindXml; + } else if (kindString == QLatin1String("yaml")) { + return FormatKind::FormatKindYaml; + } + return FormatKind::FormatKindUnknown; +} + +QString AppStream::Metadata::formatKindToString(AppStream::Metadata::FormatKind kind) +{ + if (kind == FormatKind::FormatKindXml) { + return QLatin1String("xml"); + } else if (kind == FormatKind::FormatKindYaml) { + return QLatin1String("yaml"); + } + return QLatin1String("unknown"); +} + +typedef QHash VersionMap; +Q_GLOBAL_STATIC_WITH_ARGS(VersionMap, versionMap, ( { + { Metadata::FormatVersionV06, QLatin1String("0.6") }, + { Metadata::FormatVersionV07, QLatin1String("0.7") }, + { Metadata::FormatVersionV08, QLatin1String("0.8") }, + { Metadata::FormatVersionV09, QLatin1String("0.9") }, + { Metadata::FormatVersionV010, QLatin1String("0.10") }, + { Metadata::FormatVersionV011, QLatin1String("0.11") }, + } +)); + +AppStream::Metadata::FormatVersion AppStream::Metadata::stringToFormatVersion(const QString& formatVersionString) +{ + return versionMap->key(formatVersionString, AppStream::Metadata::FormatVersionV010); +} + +QString AppStream::Metadata::formatVersionToString(AppStream::Metadata::FormatVersion version) +{ + const QString value = versionMap->value(version); + if (value.isEmpty()) { + return QLatin1String("?.??"); + } + return value; +} + +Metadata::Metadata() + : d(new MetadataData()) +{} + +Metadata::Metadata(_AsMetadata* metadata) + : d(new MetadataData(metadata)) +{} + +Metadata::Metadata(const Metadata &metadata) = default; + +Metadata::~Metadata() = default; + +Metadata& Metadata::operator=(const Metadata &metadata) = default; + +bool Metadata::operator==(const Metadata &other) const +{ + if (this->d == other.d) { + return true; + } + if (this->d && other.d) { + return *(this->d) == *other.d; + } + return false; +} + +_AsMetadata * AppStream::Metadata::asMetadata() const +{ + return d->metadata(); +} + +AppStream::Metadata::MetadataError AppStream::Metadata::parseFile(const QString& file, AppStream::Metadata::FormatKind format) +{ + g_autoptr(GError) error = nullptr; + g_autoptr(GFile) gFile = g_file_new_for_path(qPrintable(file)); + as_metadata_parse_file(d->m_metadata, gFile, (AsFormatKind) format, &error); + + if (error != nullptr) { + return static_cast(error->code); + } + + return AppStream::Metadata::MetadataErrorNoError; +} + +AppStream::Metadata::MetadataError AppStream::Metadata::parse(const QString& data, AppStream::Metadata::FormatKind format) +{ + g_autoptr(GError) error = nullptr; + as_metadata_parse(d->m_metadata, qPrintable(data), (AsFormatKind) format, &error); + + if (error != nullptr) { + return static_cast(error->code); + } + + return AppStream::Metadata::MetadataErrorNoError; +} + +AppStream::Metadata::MetadataError AppStream::Metadata::parseDesktopData(const QString& data, const QString& cid) +{ + g_autoptr(GError) error = nullptr; + as_metadata_parse_desktop_data(d->m_metadata, qPrintable(data), qPrintable(cid), &error); + + if (error != nullptr) { + return static_cast(error->code); + } + + return AppStream::Metadata::MetadataErrorNoError; +} + +AppStream::Component AppStream::Metadata::component() const +{ + auto component = as_metadata_get_component(d->m_metadata); + if (component == nullptr) + return AppStream::Component(); + return AppStream::Component(component); +} + +QList AppStream::Metadata::components() const +{ + QList res; + + auto components = as_metadata_get_components(d->m_metadata); + res.reserve(components->len); + for (uint i = 0; i < components->len; i++) { + auto component = AS_COMPONENT (g_ptr_array_index (components, i)); + res.append(Component(component)); + } + return res; +} + +void AppStream::Metadata::clearComponents() +{ + as_metadata_clear_components(d->m_metadata); +} + +void AppStream::Metadata::addComponent(const AppStream::Component& component) +{ + as_metadata_add_component(d->m_metadata, component.asComponent()); +} + +QString AppStream::Metadata::componentToMetainfo(AppStream::Metadata::FormatKind format) const +{ + return valueWrap(as_metadata_component_to_metainfo(d->m_metadata, (AsFormatKind) format, nullptr)); +} + +AppStream::Metadata::MetadataError AppStream::Metadata::saveMetainfo(const QString& fname, AppStream::Metadata::FormatKind format) +{ + g_autoptr(GError) error = nullptr; + as_metadata_save_metainfo(d->m_metadata, qPrintable(fname), (AsFormatKind) format, &error); + + if (error != nullptr) { + return static_cast(error->code); + } + + return AppStream::Metadata::MetadataErrorNoError; +} + +QString AppStream::Metadata::componentsToCollection(AppStream::Metadata::FormatKind format) const +{ + return valueWrap(as_metadata_components_to_collection(d->m_metadata, (AsFormatKind) format, nullptr)); +} + +AppStream::Metadata::MetadataError AppStream::Metadata::saveCollection(const QString& collection, AppStream::Metadata::FormatKind format) +{ + g_autoptr(GError) error = nullptr; + as_metadata_save_collection(d->m_metadata, qPrintable(collection), (AsFormatKind) format, &error); + + if (error != nullptr) { + return static_cast(error->code); + } + + return AppStream::Metadata::MetadataErrorNoError; +} + +AppStream::Metadata::FormatVersion AppStream::Metadata::formatVersion() const +{ + return static_cast(as_metadata_get_format_version(d->m_metadata)); +} + +void AppStream::Metadata::setFormatVersion(AppStream::Metadata::FormatVersion formatVersion) +{ + as_metadata_set_format_version(d->m_metadata, (AsFormatVersion) formatVersion); +} + +AppStream::Metadata::FormatStyle AppStream::Metadata::formatStyle() const +{ + return static_cast(as_metadata_get_format_style(d->m_metadata)); +} + +void AppStream::Metadata::setFormatStyle(AppStream::Metadata::FormatStyle format) +{ + as_metadata_set_format_style(d->m_metadata, (AsFormatStyle) format); +} + +QString AppStream::Metadata::locale() const +{ + return valueWrap(as_metadata_get_locale(d->m_metadata)); +} + +void AppStream::Metadata::setLocale(const QString& locale) +{ + as_metadata_set_locale(d->m_metadata, qPrintable(locale)); +} + +QString AppStream::Metadata::origin() const +{ + return valueWrap(as_metadata_get_origin(d->m_metadata)); +} + +void AppStream::Metadata::setOrigin(const QString& origin) +{ + as_metadata_set_origin(d->m_metadata, qPrintable(origin)); +} + +bool AppStream::Metadata::updateExisting() const +{ + return as_metadata_get_update_existing(d->m_metadata); +} + +void AppStream::Metadata::setUpdateExisting(bool updateExisting) +{ + as_metadata_set_update_existing(d->m_metadata, updateExisting); +} + +bool AppStream::Metadata::writeHeader() const +{ + return as_metadata_get_write_header(d->m_metadata); +} + +void AppStream::Metadata::setWriteHeader(bool writeHeader) +{ + as_metadata_set_write_header(d->m_metadata, writeHeader); +} + +QString AppStream::Metadata::architecture() const +{ + return valueWrap(as_metadata_get_architecture(d->m_metadata)); +} + +void AppStream::Metadata::setArchitecture(const QString& architecture) +{ + as_metadata_set_architecture(d->m_metadata, qPrintable(architecture)); +} + +QDebug operator<<(QDebug s, const AppStream::Metadata& metadata) +{ + QStringList list; + foreach (const AppStream::Component& component, metadata.components()) { + list << component.id(); + } + s.nospace() << "AppStream::Metadata(" << list << ")"; + return s.space(); +} diff --git a/qt/metadata.h b/qt/metadata.h new file mode 100644 index 00000000..814efb55 --- /dev/null +++ b/qt/metadata.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2016 Matthias Klumpp + * Copyright (C) 2017 Jan Grulich + * + * Licensed under the GNU Lesser General Public License Version 2.1 + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the license, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef APPSTREAMQT_METADATA_H +#define APPSTREAMQT_METADATA_H + +#include +#include +#include +#include "appstreamqt_export.h" + +#include "component.h" + +struct _AsMetadata; +namespace AppStream { + +class MetadataData; +class APPSTREAMQT_EXPORT Metadata { + Q_GADGET + public: + enum FormatStyle { + FormatStyleUnknown, + FormatStyleMetainfo, + FormatStyleCollection + }; + Q_ENUM(FormatStyle) + + enum FormatKind { + FormatKindUnknown, + FormatKindXml, + FormatKindYaml, + FormatKindDesktopEntry + }; + Q_ENUM(FormatKind) + + enum FormatVersion { + FormatVersionV06, + FormatVersionV07, + FormatVersionV08, + FormatVersionV09, + FormatVersionV010, + FormatVersionV011 + }; + Q_ENUM(FormatVersion) + + enum MetadataError { + /* + * Needed to identify whether parsing was successful or not + */ + MetadataErrorNoError = -1, + MetadataErrorFailed, + MetadataErrorParse, + MetadataErrorFormatUnexpected, + MetadataErrorNoComponent, + MetadataErrorValueMissing + }; + Q_ENUM(MetadataError) + + static FormatKind stringToFormatKind(const QString& kindString); + static QString formatKindToString(FormatKind format); + + static FormatVersion stringToFormatVersion(const QString& formatVersionString); + static QString formatVersionToString(FormatVersion version); + + Metadata(); + explicit Metadata(_AsMetadata *metadata); + Metadata(const Metadata& metadata); + ~Metadata(); + + Metadata& operator=(const Metadata& metadata); + bool operator==(const Metadata& r) const; + + /** + * \returns the internally stored AsMetadata + */ + _AsMetadata *asMetadata() const; + + MetadataError parseFile(const QString& file, FormatKind format); + + MetadataError parse(const QString& data, FormatKind format); + + MetadataError parseDesktopData(const QString& data, const QString& cid); + + AppStream::Component component() const; + QList components() const; + void clearComponents(); + void addComponent(const AppStream::Component& component); + + QString componentToMetainfo(FormatKind format) const; + + MetadataError saveMetainfo(const QString& fname, FormatKind format); + + QString componentsToCollection(FormatKind format) const; + + MetadataError saveCollection(const QString& collection, FormatKind format); + + FormatVersion formatVersion() const; + void setFormatVersion(FormatVersion formatVersion); + + FormatStyle formatStyle() const; + void setFormatStyle(FormatStyle format); + + QString locale() const; + void setLocale(const QString& locale); + + QString origin() const; + void setOrigin(const QString& origin); + + bool updateExisting() const; + void setUpdateExisting(bool updateExisting); + + bool writeHeader() const; + void setWriteHeader(bool writeHeader); + + QString architecture() const; + void setArchitecture(const QString& architecture); + + private: + QSharedDataPointer d; +}; +} + +APPSTREAMQT_EXPORT QDebug operator<<(QDebug s, const AppStream::Metadata& metadata); + +#endif // APPSTREAMQT_METADATA_H +