Inital commit of the Komplex Hub

This commit is contained in:
Digital Artifex
2026-06-02 15:11:36 -04:00
commit 96a7c71a29
290 changed files with 21517 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
add_library(
KomplexHubPlugin
STATIC
)
qt_add_qml_module(
KomplexHubPlugin
URI
KomplexHubPlugin
VERSION
1.0
SOURCES
SettingsManager.h
SettingsManager.cpp
InstalledPackManager.h
InstalledPackManager.cpp
SOURCES WallpaperMetaData.h
)
target_compile_definitions(
KomplexHubPlugin
PUBLIC
KOMPLEX_PLUGIN
)
+275
View File
@@ -0,0 +1,275 @@
#include "InstalledPackManager.h"
InstalledPackManager::InstalledPackManager(QObject *parent)
: QAbstractListModel{parent}
{
m_installDirectoryUri = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
m_installDirectoryUri += QString("/.local/share/komplex/packs");
// load in wallpapers on init
rescan();
}
auto InstalledPackManager::rowCount(const QModelIndex &parent) const -> int
{
Q_UNUSED(parent)
return m_installedWallpapers.size();
}
auto InstalledPackManager::data(const QModelIndex &index, int role) const -> QVariant
{
if(index.row() < 0 || index.row() >= m_installedWallpapers.count())
{
return QVariant();
}
QVariant data;
switch(static_cast<DataRole>(role))
{
case UriRole:
data = m_installedWallpapers[index.row()].uri;
break;
case AuthorRole:
data = m_installedWallpapers[index.row()].author;
break;
case DescriptionRole:
data = m_installedWallpapers[index.row()].description;
break;
case NameRole:
data = m_installedWallpapers[index.row()].name;
break;
case ThumbnailRole:
data = m_installedWallpapers[index.row()].thumbnail;
break;
case DateRole:
data = m_installedWallpapers[index.row()].installDate;
break;
}
return data;
}
auto InstalledPackManager::index(int row, int column, const QModelIndex &parent) const -> QModelIndex
{
Q_UNUSED(parent)
return createIndex(row, column, &m_installedWallpapers.at(row));
}
auto InstalledPackManager::columnCount(const QModelIndex &parent) const -> int
{
Q_UNUSED(parent)
return 0;
}
auto InstalledPackManager::parent(const QModelIndex &index) const -> QModelIndex
{
Q_UNUSED(index)
return QModelIndex();
}
auto InstalledPackManager::setData(const QModelIndex &index, const QVariant &value, int role) -> bool
{
if(index.row() < 0 || index.row() >= m_installedWallpapers.count())
{
return false;
}
switch(static_cast<DataRole>(role))
{
case UriRole:
m_installedWallpapers[index.row()].uri = value.toString();
break;
case AuthorRole:
m_installedWallpapers[index.row()].author = value.toString();
break;
case DescriptionRole:
m_installedWallpapers[index.row()].description = value.toString();
break;
case NameRole:
m_installedWallpapers[index.row()].name = value.toString();
break;
case ThumbnailRole:
m_installedWallpapers[index.row()].thumbnail = value.toString();
break;
case DateRole:
return false;
break;
}
return true;
}
auto InstalledPackManager::installedWallpapers() const -> QList<WallpaperMetaData>
{
return m_installedWallpapers;
}
auto InstalledPackManager::resetInstalledWallpapers() -> void
{
m_installedWallpapers.clear();
Q_EMIT installedWallpapersChanged();
}
auto InstalledPackManager::rescan() -> void
{
setState(Loading);
m_installedWallpapers.clear();
QDir installDirectory(m_installDirectoryUri);
QStringList packLocations = installDirectory.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for(const QString &packLocation : std::as_const(packLocations))
{
QDir packDirectory(installDirectory.absoluteFilePath(packLocation));
if(!packDirectory.exists() || !packDirectory.exists(QString("pack.json")))
{
continue;
}
QString packFileLocation = packDirectory.absoluteFilePath(QString("pack.json"));
QFile packFile(packFileLocation);
if(!packFile.open(QFile::ReadOnly))
{
continue;
}
QByteArray packFileData = packFile.readAll();
packFile.close();
QJsonParseError documentError;
QJsonDocument document = QJsonDocument::fromJson(packFileData, &documentError);
if(documentError.error != QJsonParseError::NoError)
{
continue;
}
QJsonObject rootObject = document.object();
if(!rootObject.contains(QString("author")) ||
!rootObject.contains(QString("description")) ||
!rootObject.contains(QString("name")))
{
continue;
}
QFileInfo packFileInfo(packFile);
WallpaperMetaData data
{
packDirectory.absoluteFilePath(QString("pack.json")),
rootObject["name"].toString(),
rootObject["author"].toString(),
rootObject["description"].toString(),
QString("file://") + packDirectory.absoluteFilePath(QString("thumbnail.jpg")),
packFileInfo.birthTime()
};
m_installedWallpapers.append(data);
}
Q_EMIT installedWallpapersChanged();
setState(Idle);
}
auto InstalledPackManager::uninstall(QString uri) -> bool
{
QUrl url(uri);
url.setScheme(QString("file"));
QFileInfo info(url.toLocalFile());
QDir installDirectory = info.absoluteDir();
QFileInfo directoryInfo(installDirectory.absolutePath());
if(!directoryInfo.exists())
{
setErrorString(QString("Install directory does not exist"));
return false;
}
// could not get QDir::rmdir to rm a symlink dir
if(directoryInfo.isSymbolicLink())
{
QProcess process;
QString command("unlink \"");
command += url.toLocalFile() + QString("\"");
process.startCommand(command);
if(!process.waitForStarted())
{
setErrorString(QString("Process Failed To Start"));
return false;
}
if(!process.waitForFinished())
{
setErrorString(QString("Process Timeout"));
return false;
}
if(process.exitCode() != 0 || process.exitStatus() != QProcess::NormalExit)
{
setErrorString(process.readAllStandardError());
return false;
}
return true;
}
if(!installDirectory.rmdir(installDirectory.absolutePath()))
{
setErrorString(QString("Install directory could not be removed"));
return false;
}
return true;
}
auto InstalledPackManager::state() const -> InstalledPackManager::State
{
return m_state;
}
auto InstalledPackManager::setState(State state) -> void
{
if (m_state == state)
{
return;
}
m_state = state;
emit stateChanged();
}
auto InstalledPackManager::resetState() -> void
{
setState(Idle); // TODO: Adapt to use your actual default value
}
auto InstalledPackManager::roleNames() const -> QHash<int, QByteArray>
{
return m_dataRoles;
}
auto InstalledPackManager::errorString() const -> QString
{
return m_errorString;
}
auto InstalledPackManager::setErrorString(const QString &errorString) -> void
{
if (m_errorString == errorString)
{
return;
}
m_errorString = errorString;
emit errorStringChanged();
}
+129
View File
@@ -0,0 +1,129 @@
#ifndef INSTALLEDPACKMANAGER_H
#define INSTALLEDPACKMANAGER_H
#include <QObject>
#include <QQmlEngine>
#include <QList>
#include <QStandardPaths>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QAbstractListModel>
#include <QProcess>
#include "WallpaperMetaData.h"
class InstalledPackManager : public QAbstractListModel
{
Q_OBJECT
QML_ELEMENT
public:
enum State
{
Idle,
Loading,
Error
};
Q_ENUM(State)
enum DataRole {
UriRole = Qt::UserRole + 1,
AuthorRole,
DescriptionRole,
NameRole,
ThumbnailRole,
DateRole
};
Q_ENUM(DataRole)
explicit InstalledPackManager(QObject *parent = nullptr);
auto rowCount(const QModelIndex &parent = QModelIndex()) const -> int override;
auto data(const QModelIndex &index, int role = Qt::DisplayRole) const -> QVariant override;
auto index(
int row,
int column,
const QModelIndex &parent = QModelIndex()
) const -> QModelIndex override;
auto columnCount(
const QModelIndex &parent = QModelIndex()
) const -> int override;
auto parent(const QModelIndex &index) const -> QModelIndex override;
auto setData(
const QModelIndex &index,
const QVariant &value,
int role = Qt::EditRole
) -> bool override;
auto installedWallpapers() const -> QList<WallpaperMetaData>;
auto resetInstalledWallpapers() -> void;
Q_INVOKABLE auto rescan() -> void;
Q_INVOKABLE auto uninstall(QString uri) -> bool;
auto state() const -> State;
auto setState(State state) -> void;
auto resetState() -> void;
auto roleNames() const -> QHash<int, QByteArray> override;
auto errorString() const -> QString;
auto setErrorString(const QString &errorString) -> void;
signals:
auto installedWallpapersChanged() -> void;
auto stateChanged() -> void;
auto errorStringChanged() -> void;
private:
static inline const QHash<int, QByteArray> m_dataRoles =
{
{
static_cast<int>(UriRole),
QByteArray("uri")
},
{
static_cast<int>(AuthorRole),
QByteArray("author")
},
{
static_cast<int>(DescriptionRole),
QByteArray("description")
},
{
static_cast<int>(NameRole),
QByteArray("name")
},
{
static_cast<int>(ThumbnailRole),
QByteArray("thumbnail")
},
{
static_cast<int>(DateRole),
QByteArray("installDate")
}
};
State m_state = Idle;
QString m_errorString = QString();
QString m_installDirectoryUri;
QList<WallpaperMetaData> m_installedWallpapers;
Q_PROPERTY(QList<WallpaperMetaData> installedWallpapers READ installedWallpapers RESET resetInstalledWallpapers NOTIFY installedWallpapersChanged FINAL)
Q_PROPERTY(State state READ state WRITE setState RESET resetState NOTIFY stateChanged FINAL)
Q_PROPERTY(QString errorString READ errorString WRITE setErrorString NOTIFY errorStringChanged FINAL)
};
Q_DECLARE_METATYPE(InstalledPackManager)
#endif // INSTALLEDPACKMANAGER_H
+10
View File
@@ -0,0 +1,10 @@
#ifndef KOMPLEX_GLOBAL_H
#define KOMPLEX_GLOBAL_H
#ifdef KOMPLEX_PLUGIN
#define KOMPLEX_EXPORT Q_DECL_EXPORT
#else
#define KOMPLEX_EXPORT Q_DECL_IMPORT
#endif
#endif // KOMPLEX_GLOBAL_H
+749
View File
@@ -0,0 +1,749 @@
#include "SettingsManager.h"
#include <qassert.h>
#include <qcontainerfwd.h>
#include <qjsondocument.h>
#include <qjsonobject.h>
#include <qjsonparseerror.h>
#include <qprocess.h>
#include <qstringview.h>
SettingsManager::SettingsManager(QObject *parent) : QObject(parent)
{
m_homeLocation = QStandardPaths::writableLocation(QStandardPaths::HomeLocation).at(0);
m_shaderPackLocation = m_homeLocation + QString("/.local/share/komplex/packs");
m_configLocation = m_homeLocation + QString("/.config/plasma-org.kde.plasma.desktop-appletsrc");
// load available shader packs
QDir shaderPackDirectory(m_shaderPackLocation);
if(shaderPackDirectory.exists())
{
QStringList shaderPackDirectoryList = shaderPackDirectory.entryList(
QDir::Dirs | QDir::NoDotAndDotDot
);
for(const QString &shaderPackDirectoryListing : std::as_const(shaderPackDirectoryList))
{
QDir installedShaderPackDirectory(shaderPackDirectory.absoluteFilePath(shaderPackDirectoryListing));
if(!installedShaderPackDirectory.exists("pack.json"))
{
continue;
}
QString uri = installedShaderPackDirectory.absoluteFilePath(QString("pack.json"));
QString name = packNameFromUri(uri);
if(name.isNull() || name.isEmpty())
{
continue;
}
WallpaperLocationData metadata {
.name = name,
.uri = installedShaderPackDirectory.absoluteFilePath("pack.json")
};
m_availableShaderPacksMetadata.append(metadata);
}
}
m_shaderPackIndex = indexOfShaderPack();
}
SettingsManager::~SettingsManager()
{
}
auto SettingsManager::get(const QString &key) -> QString
{
QProcess process;
QString command("kreadconfig6");
QString result = QString();
command = QString("kreadconfig6 --file ");
command += homeLocation() + QString("/.config/plasma-org.kde.plasma.desktop-appletsrc");
command += QString(" --group \"Containments\" --group \"25\" --group \"Wallpaper\"");
command += QString(" --group \"com.github.digitalartifex.komplex\" --group \"General\" --key");
command += QString(" \"") + key + QString("\"");
process.startCommand(command);
if(!process.waitForStarted())
{
Q_EMIT error(QString("Process Failed To Start"), process.errorString());
}
if(!process.waitForFinished())
{
Q_EMIT error(QString("Process Timeout"), process.errorString());
}
if(process.exitCode() == 0 && process.exitStatus() == QProcess::NormalExit)
{
result = process.readAllStandardOutput();
if(result.endsWith(QString("\n")))
{
result.removeLast();
}
}
else
{
QString error(process.readAll());
Q_EMIT this->error(QString("Read Error"), error);
}
return result;
}
auto SettingsManager::set(const QString &key, const QVariant &value) -> bool
{
// construct the command to kwriteconfig6
QString command = QString("kwriteconfig6 --file ");
command += homeLocation() + QString("/.config/plasma-org.kde.plasma.desktop-appletsrc");
command += QString(" --group \"Containments\" --group \"25\" --group \"Wallpaper\"");
command += QString(" --group \"com.github.digitalartifex.komplex\" --group \"General\" --key");
command += QString(" \"") + key + QString("\" ") + value.toString();
// start the process
QProcess process;
process.startCommand(command);
// throw error if failed to start
if(!process.waitForStarted())
{
Q_EMIT error(QString("Process Failed To Start"), process.errorString());
return false;
}
// throw error if there was a timeout
if(!process.waitForFinished())
{
Q_EMIT error(QString("Process Timeout"), process.errorString());
return false;
}
// throw error if there was an ERRNO or issue running the process
if(process.exitCode() != 0 || process.exitStatus() != QProcess::NormalExit)
{
Q_EMIT this->error(QString("Write Error"), process.readAllStandardError());
return false;
}
// success
return true;
}
auto SettingsManager::shaderPack() -> QString
{
m_shaderPack = get(QString("shader_package"));
//update pack name
QString packName = packNameFromUri(m_shaderPack);
setShaderPackName(packName);
return m_shaderPack;
}
auto SettingsManager::setShaderPack(const QString &uri) -> void
{
QString packName = packNameFromUri(uri);
if(uri != m_shaderPack)
{
if(!set(QString("shader_package"), uri))
{
return;
}
m_shaderPack = uri;
Q_EMIT shaderPackChanged();
}
setShaderPackName(packName);
}
auto SettingsManager::shaderPackName() const -> QString
{
return m_shaderPackName;
}
auto SettingsManager::availableShaderPacks() -> QStringList
{
QStringList availableShaderPacks;
for(const WallpaperLocationData &data : std::as_const(m_availableShaderPacksMetadata))
{
availableShaderPacks.append(data.name);
}
return availableShaderPacks;
}
auto SettingsManager::homeLocation() const -> QString
{
return m_homeLocation;
}
auto SettingsManager::configLocation() const -> QString
{
return m_configLocation;
}
auto SettingsManager::shaderPackLocation() const -> QString
{
return m_shaderPackLocation;
}
auto SettingsManager::shaderPackIndex() const -> qint64
{
return m_shaderPackIndex;
}
auto SettingsManager::setShaderPackIndex(qint64 shaderPackIndex) -> void
{
if (m_shaderPackIndex == shaderPackIndex)
{
return;
}
m_shaderPackIndex = shaderPackIndex;
emit shaderPackIndexChanged();
}
auto SettingsManager::setShaderPackName(const QString &shaderPackName) -> void
{
if (m_shaderPackName == shaderPackName)
{
return;
}
m_shaderPackName = shaderPackName;
emit shaderPackNameChanged();
}
auto SettingsManager::resolutionX() -> quint64
{
QString value = get(QString("resolution_x"));
if(value.isNull() || value.isEmpty())
{
setResolutionX(1920);
}
else
{
quint64 convertedValue = value.toULongLong();
if(convertedValue != m_resolutionX)
{
m_resolutionX = convertedValue;
Q_EMIT resolutionXChanged();
}
}
return m_resolutionX;
}
auto SettingsManager::setResolutionX(quint64 resolutionX) -> void
{
if (m_resolutionX == resolutionX)
{
return;
}
if(!set(QString("resolution_x"), resolutionX))
{
return;
}
m_resolutionX = resolutionX;
emit resolutionXChanged();
}
auto SettingsManager::resolutionY() -> quint64
{
QString value = get(QString("resolution_y"));
if(value.isNull() || value.isEmpty())
{
setResolutionY(1080);
}
else
{
quint64 convertedValue = value.toULongLong();
if(convertedValue != m_resolutionY)
{
m_resolutionY = convertedValue;
Q_EMIT resolutionYChanged();
}
}
return m_resolutionY;
}
auto SettingsManager::setResolutionY(quint64 resolutionY) -> void
{
if (m_resolutionY == resolutionY)
{
return;
}
if(!set(QString("resolution_y"), resolutionY))
{
return;
}
m_resolutionY = resolutionY;
emit resolutionYChanged();
}
auto SettingsManager::targetFramerate() -> quint64
{
QString value = get(QString("framerate"));
if(value.isNull() || value.isEmpty())
{
setTargetFramerate(60);
}
else
{
bool okay = false;
quint64 convertedValue = value.toULongLong(&okay);
if(!okay)
{
setTargetFramerate(60);
}
if(convertedValue != m_targetFramerate)
{
m_targetFramerate = convertedValue;
Q_EMIT targetFramerateChanged();
}
}
return m_targetFramerate;
}
auto SettingsManager::setTargetFramerate(quint64 targetFramerate) -> void
{
if (m_targetFramerate == targetFramerate)
return;
if(!set(QString("framerate"), targetFramerate))
return;
m_targetFramerate = targetFramerate;
emit targetFramerateChanged();
}
auto SettingsManager::shaderSpeed() -> qreal
{
QString value = get(QString("shaderSpeed"));
if(value.isNull() || value.isEmpty())
{
setShaderSpeed(1.0);
}
else
{
bool okay = false;
qreal convertedValue = value.toFloat(&okay);
if(!okay)
setShaderSpeed(1.0);
if(convertedValue != m_shaderSpeed)
{
m_shaderSpeed = convertedValue;
Q_EMIT shaderSpeedChanged();
}
}
return m_shaderSpeed;
}
auto SettingsManager::setShaderSpeed(qreal shaderSpeed) -> void
{
if (qFuzzyCompare(m_shaderSpeed, shaderSpeed))
{
return;
}
if(!set(QString("shaderSpeed"), shaderSpeed))
{
return;
}
m_shaderSpeed = shaderSpeed;
emit shaderSpeedChanged();
}
auto SettingsManager::mouseTrackingEnabled() -> bool
{
QString value = get(QString("mouseAllowed"));
if(value.isNull() || value.isEmpty())
{
setTargetFramerate(60);
}
else
{
bool convertedValue = value.trimmed().compare("true", Qt::CaseInsensitive);
if(convertedValue != m_mouseTrackingEnabled)
{
m_mouseTrackingEnabled = convertedValue;
Q_EMIT targetFramerateChanged();
}
}
return m_mouseTrackingEnabled;
}
auto SettingsManager::setMouseTrackingEnabled(bool mouseTrackingEnabled) -> void
{
if (m_mouseTrackingEnabled == mouseTrackingEnabled)
{
return;
}
if(!set(QString("mouseAllowed"), mouseTrackingEnabled ? QString("true") : QString("false")))
{
return;
}
m_mouseTrackingEnabled = mouseTrackingEnabled;
emit mouseTrackingEnabledChanged();
}
auto SettingsManager::mouseTrackingBias() -> qreal
{
QString value = get(QString("mouseSpeedBias"));
if(value.isNull() || value.isEmpty())
{
setMouseTrackingBias(1.0);
}
else
{
bool okay = false;
qreal convertedValue = value.toFloat(&okay);
if(!okay)
{
setMouseTrackingBias(1.0);
}
if(convertedValue != m_mouseTrackingBias)
{
m_mouseTrackingBias = convertedValue;
Q_EMIT mouseTrackingBiasChanged();
}
}
return m_mouseTrackingBias;
}
auto SettingsManager::setMouseTrackingBias(qreal mouseTrackingBias) -> void
{
if (qFuzzyCompare(m_mouseTrackingBias, mouseTrackingBias))
{
return;
}
if(!set(QString("mouseSpeedBias"), mouseTrackingBias))
{
return;
}
m_mouseTrackingBias = mouseTrackingBias;
emit mouseTrackingBiasChanged();
}
auto SettingsManager::pauseMode() -> quint8
{
QString value = get(QString("pauseMode"));
if(value.isNull() || value.isEmpty())
{
setPauseMode(1);
}
else
{
bool okay = false;
quint64 convertedValue = value.toULongLong(&okay);
if(!okay)
{
setPauseMode(60);
}
if(convertedValue != m_pauseMode)
{
m_pauseMode = convertedValue;
Q_EMIT pauseModeChanged();
}
}
return m_pauseMode;
}
auto SettingsManager::setPauseMode(quint8 pauseMode) -> void
{
if (m_pauseMode == pauseMode)
{
return;
}
if(!set(QString("pauseMode"), pauseMode))
{
return;
}
m_pauseMode = pauseMode;
emit pauseModeChanged();
}
auto SettingsManager::resetPauseMode() -> void
{
setPauseMode(1);
}
auto SettingsManager::onlyCheckActiveScreen() -> bool
{
QString value = get(QString("checkActiveScreen"));
if(value.isNull() || value.isEmpty())
{
setOnlyCheckActiveScreen(false);
}
else
{
bool convertedValue = value.trimmed().compare("true", Qt::CaseInsensitive);
if(convertedValue != m_onlyCheckActiveScreen)
{
m_onlyCheckActiveScreen = convertedValue;
Q_EMIT onlyCheckActiveScreenChanged();
}
}
return m_onlyCheckActiveScreen;
}
auto SettingsManager::setOnlyCheckActiveScreen(bool onlyCheckActiveScreen) -> void
{
if (m_onlyCheckActiveScreen == onlyCheckActiveScreen)
{
return;
}
if(!set(QString("checkActiveScreen"), onlyCheckActiveScreen ? QString("true") : QString("false")))
{
return;
}
m_onlyCheckActiveScreen = onlyCheckActiveScreen;
emit onlyCheckActiveScreenChanged();
}
auto SettingsManager::resetOnlyCheckActiveScreen() -> void
{
setOnlyCheckActiveScreen(false); // TODO: Adapt to use your actual default value
}
auto SettingsManager::excludedWindows() -> QStringList
{
QString value = get(QString("excludeWindows"));
QStringList convertedValue = value.split(QChar(','), Qt::SkipEmptyParts);
if(convertedValue != m_excludedWindows)
{
m_excludedWindows = convertedValue;
Q_EMIT excludedWindowsChanged();
}
return m_excludedWindows;
}
auto SettingsManager::setExcludedWindows(const QStringList &excludedWindows) -> void
{
if (m_excludedWindows == excludedWindows)
{
return;
}
if(!set(QString("excludeWindows"), excludedWindows.join(QChar(','))))
{
return;
}
m_excludedWindows = excludedWindows;
emit excludedWindowsChanged();
}
auto SettingsManager::resetExcludedWindows() -> void
{
setExcludedWindows(QStringList{}); // TODO: Adapt to use your actual default value
}
auto SettingsManager::running() -> bool
{
QString value = get(QString("running"));
if(value.isNull() || value.isEmpty())
{
setRunning(true);
}
else
{
bool convertedValue = value.trimmed().compare("true", Qt::CaseInsensitive);
if(convertedValue != m_running)
{
m_running = convertedValue;
Q_EMIT runningChanged();
}
}
return m_running;
}
auto SettingsManager::setRunning(bool running) -> void
{
if (m_running == running)
{
return;
}
if(!set(QString("running"), running))
{
return;
}
m_running = running;
emit runningChanged();
}
auto SettingsManager::resetRunning() -> void
{
setRunning(true); // TODO: Adapt to use your actual default value
}
auto SettingsManager::jsonFromFile(const QString &uri) -> QJsonDocument
{
QUrl url = QUrl(uri);
url.setScheme(QString("file"));
QFile file(url.toLocalFile());
if(!file.exists())
{
return {};
}
if(!file.open(QFile::ReadOnly))
{
Q_EMIT error(QString("File Error"), file.errorString());
return {};
}
QByteArray fileData = file.readAll();
if(fileData.length() != file.size())
{
Q_EMIT error(QString("File Read Error"), file.errorString());
return {};
}
QJsonParseError documentError;
QJsonDocument document = QJsonDocument::fromJson(fileData, &documentError);
if(documentError.error != QJsonParseError::NoError)
{
switch (documentError.error) {
case QJsonParseError::NoError:
case QJsonParseError::UnterminatedObject:
case QJsonParseError::MissingNameSeparator:
case QJsonParseError::UnterminatedArray:
case QJsonParseError::MissingValueSeparator:
case QJsonParseError::IllegalValue:
case QJsonParseError::TerminationByNumber:
case QJsonParseError::IllegalNumber:
case QJsonParseError::IllegalEscapeSequence:
case QJsonParseError::IllegalUTF8String:
case QJsonParseError::UnterminatedString:
case QJsonParseError::MissingObject:
case QJsonParseError::DeepNesting:
case QJsonParseError::DocumentTooLarge:
case QJsonParseError::GarbageAtEnd:
//eventually we'll have a different message for each fail state
Q_EMIT error(QString("Json Error"), documentError.errorString());
break;
}
return {};
}
return document;
}
auto SettingsManager::packNameFromUri(const QString &uri) -> QString
{
QJsonDocument document = jsonFromFile(uri);
if(document.isNull())
{
Q_EMIT error(QString("File Error"), QString("File contains no json data"));
return {};
}
QJsonObject rootObject = document.object();
if(!rootObject.contains(QString("name")))
{
Q_EMIT error(QString("Json Error"), QString("Json is not a Komplex Pack"));
return {};
}
return rootObject["name"].toString();
}
auto SettingsManager::uriFromPackName(const QString &name) -> QString
{
Q_ASSERT_X(false,"SettingsManager","uriFromPackName not implemented");
}
auto SettingsManager::indexOfShaderPack(QString uri) -> qint64
{
if(uri.isNull() || uri.isEmpty())
uri = shaderPack();
QUrl url = QUrl(uri);
url.setScheme(QString("file"));
// determine current shader pack index
qint64 index = -1;
for(int i = 0; i < m_availableShaderPacksMetadata.count(); ++i)
{
if(m_availableShaderPacksMetadata[i].uri == url.toLocalFile())
{
index = i;
break;
}
}
return index;
}
+227
View File
@@ -0,0 +1,227 @@
/*
* Komplex Wallpaper Engine
* Copyright (C) 2026 @DigitalArtifex | github.com/DigitalArtifex
*
* SettingsManager.h
*
* This class provides access to Komplex Wallpaper settings via kwrite/
* kreadconfig
*
* 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 <https://www.gnu.org/licenses/>
*/
#ifndef SETTINGSMANAGER_H
#define SETTINGSMANAGER_H
#include "Komplex_global.h"
#include <QVariant>
#include <QObject>
#include <QString>
#include <QFile>
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonParseError>
#include <QStandardPaths>
#include <QDir>
#include <QMap>
#include <QProcess>
#include <QEventLoop>
#include <QtQml/qqmlregistration.h>
#include <qjsondocument.h>
#include <qobject.h>
class SettingsManager;
struct KOMPLEX_EXPORT WallpaperLocationData
{
QString name;
QString uri;
};
Q_DECLARE_METATYPE(WallpaperLocationData)
class KOMPLEX_EXPORT SettingsManager : public QObject
{
Q_OBJECT
QML_ELEMENT
public:
explicit SettingsManager(QObject *parent = nullptr);
~SettingsManager();
/**!
* @brief get
* This function gets the current setting for the supplied key.
* The value will need to be converted from a string to the type
* needed in code
*
* @param key The key of the setting to retrieve
* @returns The value of the supplied key, as a string
*/
[[nodiscard]]
Q_INVOKABLE auto get(const QString &key) -> QString;
/**!
* @brief set
* This function sets the given value for the supplied key
*
* @param key The key of the setting
* @param value The value to set for the key
*/
[[nodiscard]]
Q_INVOKABLE auto set(const QString &key, const QVariant &value) -> bool;
[[nodiscard]]
auto shaderPack() -> QString;
auto setShaderPack(const QString &uri) -> void;
[[nodiscard]]
auto shaderPackName() const -> QString;
[[nodiscard]]
auto availableShaderPacks() -> QStringList;
[[nodiscard]]
auto homeLocation() const -> QString;
[[nodiscard]]
auto configLocation() const -> QString;
[[nodiscard]]
auto shaderPackLocation() const -> QString;
[[nodiscard]]
auto shaderPackIndex() const -> qint64;
auto setShaderPackIndex(qint64 shaderPackIndex) -> void;
auto setShaderPackName(const QString &shaderPackName) -> void;
[[nodiscard]]
auto resolutionX() -> quint64;
auto setResolutionX(quint64 resolutionX) -> void;
[[nodiscard]]
auto resolutionY() -> quint64;
auto setResolutionY(quint64 resolutionY) -> void;
[[nodiscard]]
auto targetFramerate() -> quint64;
auto setTargetFramerate(quint64 targetFramerate) -> void;
[[nodiscard]]
auto shaderSpeed() -> qreal;
auto setShaderSpeed(qreal shaderSpeed) -> void;
[[nodiscard]]
auto mouseTrackingEnabled() -> bool;
auto setMouseTrackingEnabled(bool mouseTrackingEnabled) -> void;
[[nodiscard]]
auto mouseTrackingBias() -> qreal;
auto setMouseTrackingBias(qreal mouseTrackingBias) -> void;
[[nodiscard]]
auto pauseMode() -> quint8;
auto setPauseMode(quint8 pauseMode) -> void;
auto resetPauseMode() -> void;
[[nodiscard]]
auto onlyCheckActiveScreen() -> bool;
auto setOnlyCheckActiveScreen(bool onlyCheckActiveScreen) -> void;
auto resetOnlyCheckActiveScreen() -> void;
[[nodiscard]]
auto excludedWindows() -> QStringList;
auto setExcludedWindows(const QStringList &excludedWindows) -> void;
auto resetExcludedWindows() -> void;
[[nodiscard]]
auto running() -> bool;
auto setRunning(bool running) -> void;
auto resetRunning() -> void;
signals:
auto shaderPackChanged() -> void;
auto shaderPackNameChanged() -> void;
auto availableShaderPacksChanged() -> void;
auto error(const QString&, const QString&) -> void;
auto shaderPackIndexChanged() -> void;
auto resolutionXChanged() -> void;
auto resolutionYChanged() -> void;
auto targetFramerateChanged() -> void;
auto shaderSpeedChanged() -> void;
auto mouseTrackingEnabledChanged() -> void;
auto mouseTrackingBiasChanged() -> void;
auto pauseModeChanged() -> void;
auto onlyCheckActiveScreenChanged() -> void;
auto excludedWindowsChanged() -> void;
auto runningChanged() -> void;
private:
QString m_homeLocation;
QString m_configLocation;
QString m_shaderPackLocation;
QString m_shaderPack = QString();
QString m_shaderPackName = QString();
qint64 m_shaderPackIndex = -1;
qreal m_shaderSpeed = 1.0;
QStringList m_availableShaderPacks = QStringList();
QList<WallpaperLocationData> m_availableShaderPacksMetadata;
quint64 m_resolutionX = 0;
quint64 m_resolutionY = 0;
quint64 m_targetFramerate = 60;
bool m_mouseTrackingEnabled = false;
qreal m_mouseTrackingBias = 1.0;
quint8 m_pauseMode = 1;
bool m_onlyCheckActiveScreen = false;
QStringList m_excludedWindows;
bool m_running = true;
QJsonDocument jsonFromFile(const QString &uri);
QString packNameFromUri(const QString &uri);
QString uriFromPackName(const QString &name);
qint64 indexOfShaderPack(QString uri = QString());
Q_PROPERTY(QString shaderPack READ shaderPack WRITE setShaderPack NOTIFY shaderPackChanged);
Q_PROPERTY(QString shaderPackName READ shaderPackName NOTIFY shaderPackNameChanged);
Q_PROPERTY(QStringList availableShaderPacks READ availableShaderPacks NOTIFY availableShaderPacksChanged);
Q_PROPERTY(qint64 shaderPackIndex READ shaderPackIndex WRITE setShaderPackIndex NOTIFY shaderPackIndexChanged FINAL)
Q_PROPERTY(quint64 resolutionX READ resolutionX WRITE setResolutionX NOTIFY resolutionXChanged FINAL)
Q_PROPERTY(quint64 resolutionY READ resolutionY WRITE setResolutionY NOTIFY resolutionYChanged FINAL)
Q_PROPERTY(quint64 targetFramerate READ targetFramerate WRITE setTargetFramerate NOTIFY targetFramerateChanged FINAL)
Q_PROPERTY(qreal shaderSpeed READ shaderSpeed WRITE setShaderSpeed NOTIFY shaderSpeedChanged FINAL)
Q_PROPERTY(bool mouseTrackingEnabled READ mouseTrackingEnabled WRITE setMouseTrackingEnabled NOTIFY mouseTrackingEnabledChanged FINAL)
Q_PROPERTY(qreal mouseTrackingBias READ mouseTrackingBias WRITE setMouseTrackingBias NOTIFY mouseTrackingBiasChanged FINAL)
Q_PROPERTY(quint8 pauseMode READ pauseMode WRITE setPauseMode RESET resetPauseMode NOTIFY pauseModeChanged FINAL)
Q_PROPERTY(bool onlyCheckActiveScreen READ onlyCheckActiveScreen WRITE setOnlyCheckActiveScreen RESET resetOnlyCheckActiveScreen NOTIFY onlyCheckActiveScreenChanged FINAL)
Q_PROPERTY(QStringList excludedWindows READ excludedWindows WRITE setExcludedWindows RESET resetExcludedWindows NOTIFY excludedWindowsChanged FINAL)
Q_PROPERTY(bool running READ running WRITE setRunning RESET resetRunning NOTIFY runningChanged FINAL)
};
Q_DECLARE_METATYPE(SettingsManager)
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef WALLPAPERMETADATA_H
#define WALLPAPERMETADATA_H
#include "Komplex_global.h"
#include <QObject>
#include <QString>
#include <QByteArray>
#include <QDateTime>
struct KOMPLEX_EXPORT WallpaperMetaData {
QString uri;
QString name;
QString author;
QString description;
QString thumbnail;
QDateTime installDate;
};
Q_DECLARE_METATYPE(WallpaperMetaData)
#endif // WALLPAPERMETADATA_H