749 lines
17 KiB
C++
749 lines
17 KiB
C++
#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;
|
|
} |