diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 4e819dc..c7cbf4d 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -14,6 +14,8 @@ add_library( AudioModel.cpp AudioImageProvider.cpp AudioImageProvider.h + ShaderPackMetadata.h + ShaderPackMetadata.cpp ) qt_add_qml_module( @@ -31,6 +33,7 @@ qt_add_qml_module( ShaderPackModel.cpp AudioModel.cpp AudioImageProvider.cpp + ShaderPackMetadata.cpp NO_GENERATE_PLUGIN_SOURCE ) diff --git a/plugin/ShaderPackMetadata.cpp b/plugin/ShaderPackMetadata.cpp new file mode 100644 index 0000000..e69de29 diff --git a/plugin/ShaderPackMetadata.h b/plugin/ShaderPackMetadata.h new file mode 100644 index 0000000..fd27168 --- /dev/null +++ b/plugin/ShaderPackMetadata.h @@ -0,0 +1,138 @@ +#ifndef SHADERPACKMETADATA +#define SHADERPACKMETADATA + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Komplex_global.h" + +class KOMPLEX_EXPORT ShaderPackMetadata : public QObject +{ + Q_OBJECT + QML_ELEMENT + + QString m_author; + QString m_description; + QString m_engine; + QString m_file; + QString m_id; + QString m_license; + QString m_name; + QString m_version; + + Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) + Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) + Q_PROPERTY(QString engine READ engine WRITE setEngine NOTIFY engineChanged) + Q_PROPERTY(QString file READ file WRITE setFile NOTIFY fileChanged) + Q_PROPERTY(QString id READ id WRITE setId NOTIFY idChanged) + Q_PROPERTY(QString license READ license WRITE setLicense NOTIFY licenseChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString version READ version WRITE setVersion NOTIFY versionChanged) + + Q_SIGNALS: + void authorChanged(); + void descriptionChanged(); + void engineChanged(); + void idChanged(); + void licenseChanged(); + void nameChanged(); + void versionChanged(); + void fileChanged(); + + public: + + QString author() const { return m_author; } + void setAuthor(const QString& author) + { + if(author != m_author) + { + m_author = author; + Q_EMIT authorChanged(); + } + } + + QString description() const { return m_description; } + void setDescription(const QString& description) + { + if(description != m_description) + { + m_description = description; + Q_EMIT descriptionChanged(); + } + } + + QString engine() const { return m_engine; } + void setEngine(const QString& engine) + { + if(engine != m_engine) + { + m_engine = engine; + Q_EMIT engineChanged(); + } + } + + QString file() const { return m_file; } + void setFile(const QString& file) + { + if(file != m_file) + { + m_file = file; + Q_EMIT fileChanged(); + } + } + + QString id() const { return m_id; } + void setId(const QString& id) + { + if(id != m_id) + { + m_id = id; + Q_EMIT idChanged(); + } + } + + QString license() const { return m_license; } + void setLicense(const QString& license) + { + if(license != m_license) + { + m_license = license; + Q_EMIT licenseChanged(); + } + } + + QString name() const { return m_name; } + void setName(const QString& name) + { + if(name != m_name) + { + m_name = name; + Q_EMIT nameChanged(); + } + } + + QString version() const { return m_version; } + void setVersion(const QString& version) + { + if(version != m_version) + { + m_version = version; + Q_EMIT versionChanged(); + } + } +}; + +Q_DECLARE_METATYPE(ShaderPackMetadata) +#endif \ No newline at end of file diff --git a/plugin/ShaderPackModel.cpp b/plugin/ShaderPackModel.cpp index c2ad6d0..82bb9c3 100644 --- a/plugin/ShaderPackModel.cpp +++ b/plugin/ShaderPackModel.cpp @@ -10,6 +10,21 @@ ShaderPackModel::ShaderPackModel(QObject *parent) m_videosPath(QString::fromLatin1("/usr/share/komplex/videos")), m_json(QString()) { + m_metadata = new ShaderPackMetadata; + refreshShaderPacks(); +} + +ShaderPackModel::~ShaderPackModel() +{ + const QStringList keys = m_availableShaderPacks.keys(); + + for(const QString &key : keys) + { + ShaderPackMetadata *metadata = m_availableShaderPacks.take(key); + metadata->deleteLater(); + } + + m_metadata->deleteLater(); } void ShaderPackModel::loadJson(const QString &filePath) @@ -88,12 +103,13 @@ void ShaderPackModel::refreshShaderPacks() // Get a list of directories in the shader pack path QStringList shaderPacks = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - QMap verifiedShaderPacks; + QMap verifiedShaderPacks; // Only keep shader packs that contain a valid pack.json file for(const QString &pack : std::as_const(shaderPacks)) { QDir packDir(dir.absoluteFilePath(pack)); + ShaderPackMetadata *metadata = new ShaderPackMetadata; bool valid = false; // Check if the pack directory contains a pack.json file @@ -113,25 +129,35 @@ void ShaderPackModel::refreshShaderPacks() { qWarning("Shader pack %s has invalid JSON: %s at offset %d", qPrintable(pack), qPrintable(error.errorString()), error.offset); + + continue; } - else - valid = true; // JSON is valid + + metadata->setAuthor(doc.object().value(QLatin1String("author")).toString()); + metadata->setDescription(doc.object().value(QLatin1String("description")).toString()); + metadata->setEngine(doc.object().value(QLatin1String("engine")).toString()); + metadata->setFile(packDir.absoluteFilePath(QLatin1String("pack.json"))); + metadata->setId(doc.object().value(QLatin1String("id")).toString()); + metadata->setLicense(doc.object().value(QLatin1String("license")).toString()); + metadata->setName(doc.object().value(QLatin1String("name")).toString()); + metadata->setVersion(doc.object().value(QLatin1String("version")).toString()); + + valid = true; // JSON is valid } } // If valid, add to the list of verified shader packs if(valid) - verifiedShaderPacks.insert(pack, packDir.absoluteFilePath(QString::fromLatin1("pack.json"))); // Store the path to the pack.json file + { + verifiedShaderPacks.insert(metadata->name(), metadata); // Store the path to the pack.json file + } // Otherwise, log a warning else qWarning("Shader pack %s does not contain a valid pack.json file", qPrintable(pack)); } - if(m_availableShaderPacks != verifiedShaderPacks) - { - m_availableShaderPacks = verifiedShaderPacks; - Q_EMIT shaderPacksChanged(); // Emit signal to notify that the list has changed - } + m_availableShaderPacks = verifiedShaderPacks; + Q_EMIT shaderPacksChanged(); // Emit signal to notify that the list has changed setState(Idle); // Reset state to Idle } @@ -146,7 +172,7 @@ void ShaderPackModel::loadShaderPack(const QString &name) return; } - QString filePath = m_availableShaderPacks.value(name); + QString filePath = m_availableShaderPacks.value(name)->file(); loadJson(filePath); // Load the JSON content of the shader pack } @@ -267,4 +293,69 @@ QString ShaderPackModel::cubeMapsPath() const QString ShaderPackModel::videosPath() const { return m_videosPath; +} + +ShaderPackMetadata *ShaderPackModel::metadata() const { return m_metadata; } +void ShaderPackModel::setMetadata(ShaderPackMetadata *metadata) +{ + m_metadata = metadata; + Q_EMIT metadataChanged(); +} + +void ShaderPackModel::loadMetadata(const QString &name) +{ + if(!m_availableShaderPacks.contains(name)) + return; + + m_metadata->setAuthor(m_availableShaderPacks[name]->author()); + m_metadata->setDescription(m_availableShaderPacks[name]->description()); + m_metadata->setEngine(m_availableShaderPacks[name]->engine()); + m_metadata->setFile(m_availableShaderPacks[name]->file()); + m_metadata->setId(m_availableShaderPacks[name]->id()); + m_metadata->setLicense(m_availableShaderPacks[name]->license()); + m_metadata->setName(m_availableShaderPacks[name]->name()); + m_metadata->setVersion(m_availableShaderPacks[name]->version()); + + Q_EMIT metadataChanged(); +} + +void ShaderPackModel::loadMetadataFromFile(const QString &file) +{ + // Load the pack.json data + QFile packFile(QUrl(file).toLocalFile()); + if (packFile.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QByteArray packData = packFile.readAll(); + packFile.close(); // close the file immediately after reading + + // Parse the JSON data to validate it + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(packData, &error); + if (error.error != QJsonParseError::NoError) + { + qWarning("Shader pack %s has invalid JSON: %s at offset %d", + qPrintable(file), qPrintable(error.errorString()), error.offset); + + return; + } + + m_metadata->setAuthor(doc.object().value(QLatin1String("author")).toString()); + m_metadata->setDescription(doc.object().value(QLatin1String("description")).toString()); + m_metadata->setEngine(doc.object().value(QLatin1String("engine")).toString()); + m_metadata->setFile(file); + m_metadata->setId(doc.object().value(QLatin1String("id")).toString()); + m_metadata->setLicense(doc.object().value(QLatin1String("license")).toString()); + m_metadata->setName(doc.object().value(QLatin1String("name")).toString()); + m_metadata->setVersion(doc.object().value(QLatin1String("version")).toString()); + + Q_EMIT metadataChanged(); + } +} + +QString ShaderPackModel::path(const QString &name) +{ + if(!m_availableShaderPacks.contains(name)) + return QString(); + + return m_availableShaderPacks[name]->file(); } \ No newline at end of file diff --git a/plugin/ShaderPackModel.h b/plugin/ShaderPackModel.h index b996c84..4203c71 100644 --- a/plugin/ShaderPackModel.h +++ b/plugin/ShaderPackModel.h @@ -1,3 +1,26 @@ +/* + * Komplex Wallpaper Engine + * Copyright (C) 2025 @DigitalArtifex | github.com/DigitalArtifex + * + * ShaderPackModel.h + * + * This class provides metadata and file data of the komplex packs + * to the QML layer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + #ifndef SHADERPACKMODEL_H #define SHADERPACKMODEL_H @@ -18,13 +41,15 @@ #include #include +#include "ShaderPackMetadata.h" + class KOMPLEX_EXPORT ShaderPackModel : public QObject { Q_OBJECT QML_ELEMENT public: explicit ShaderPackModel(QObject *parent = nullptr); - ~ShaderPackModel() override = default; + ~ShaderPackModel(); // State enum to represent the current state of the model // for the UI and configuration @@ -99,6 +124,20 @@ public: * @return State representing the current state of the model. */ State state() const; + + /**! + * @brief path + * This function returns the path of the requested shader pack + * by name + * + * @return QString representing the filepath + */ + Q_INVOKABLE QString path(const QString &name); + + ShaderPackMetadata *metadata() const; + void setMetadata(ShaderPackMetadata *metadata); + Q_INVOKABLE void loadMetadata(const QString &name); + Q_INVOKABLE void loadMetadataFromFile(const QString &file); QString shaderPackPath() const; QString shaderPackName() const; @@ -121,6 +160,7 @@ Q_SIGNALS: void shaderPacksChanged(); void stateChanged(); void error(const QString &errorString); + void metadataChanged(); private: QString m_shaderPackPath; @@ -132,8 +172,10 @@ private: const QString m_cubeMapsPath; const QString m_videosPath; + ShaderPackMetadata *m_metadata = nullptr; // currently reported metadata + QString m_json; - QMap m_availableShaderPacks; // Maps shader pack names to their file paths + QMap m_availableShaderPacks; // Maps shader pack names to their file paths State m_state = Idle; Q_PROPERTY(QString json READ json WRITE loadJson NOTIFY jsonChanged) @@ -142,6 +184,7 @@ private: Q_PROPERTY(QString shaderPackPath READ shaderPackPath NOTIFY shaderPackPathChanged) Q_PROPERTY(QString shaderPackName READ shaderPackName NOTIFY shaderPackNameChanged) Q_PROPERTY(QString shaderPackInstallPath READ shaderPackInstallPath NOTIFY shaderPackInstallPathChanged) + Q_PROPERTY(ShaderPackMetadata *metadata READ metadata WRITE setMetadata NOTIFY metadataChanged) Q_PROPERTY(QString shadersPath READ shadersPath CONSTANT) Q_PROPERTY(QString imagesPath READ imagesPath CONSTANT) diff --git a/plugin/plugin.cpp b/plugin/plugin.cpp index 39cfd38..258ca70 100644 --- a/plugin/plugin.cpp +++ b/plugin/plugin.cpp @@ -20,6 +20,9 @@ class KOMPLEX_EXPORT KomplexPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid FILE "plugin.json") + + inline static AudioModel *m_model = nullptr; + public: void registerTypes(const char *uri) override { @@ -29,6 +32,10 @@ public: qmlRegisterType(uri, 1, 0, "ShaderPackModel"); } + void unregisterTypes() override + { + } + void initializeEngine(QQmlEngine *engine, const char *uri) override { Q_ASSERT(QLatin1String(uri) == QLatin1String("com.github.digitalartifex.komplex"));