diff options
Diffstat (limited to 'archived/projt-launcher/launcher/settings')
12 files changed, 1548 insertions, 0 deletions
diff --git a/archived/projt-launcher/launcher/settings/INIFile.cpp b/archived/projt-launcher/launcher/settings/INIFile.cpp new file mode 100644 index 0000000000..31ce19f4ca --- /dev/null +++ b/archived/projt-launcher/launcher/settings/INIFile.cpp @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * + * + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2023 flowln <flowlnlnln@gmail.com> + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ======================================================================== */ + +#include "settings/INIFile.h" +#include <FileSystem.h> + +#include <QDebug> +#include <QFile> +#include <QStringList> +#include <QTemporaryFile> +#include <QTextStream> + +#include <QSettings> +#include "Json.h" + +INIFile::INIFile() +{} + +bool INIFile::saveFile(QString fileName) +{ + if (!contains("ConfigVersion")) + insert("ConfigVersion", "1.3"); + QSettings _settings_obj{ fileName, QSettings::Format::IniFormat }; + _settings_obj.setFallbacksEnabled(false); + _settings_obj.clear(); + + for (Iterator iter = begin(); iter != end(); iter++) + _settings_obj.setValue(iter.key(), iter.value()); + + _settings_obj.sync(); + + if (auto status = _settings_obj.status(); status != QSettings::Status::NoError) + { + // Shouldn't be possible! + Q_ASSERT(status != QSettings::Status::FormatError); + + if (status == QSettings::Status::AccessError) + qCritical() << "An access error occurred (e.g. trying to write to a read-only file)."; + + return false; + } + + return true; +} + +QString unescape(QString orig) +{ + QString out; + QChar prev = QChar::Null; + for (auto c : orig) + { + if (prev == '\\') + { + if (c == 'n') + out += '\n'; + else if (c == 't') + out += '\t'; + else if (c == '#') + out += '#'; + else + out += c; + prev = QChar::Null; + } + else + { + if (c == '\\') + { + prev = c; + continue; + } + out += c; + prev = QChar::Null; + } + } + return out; +} + +QString unquote(QString str) +{ + if ((str.contains(QChar(';')) || str.contains(QChar('=')) || str.contains(QChar(','))) && str.endsWith("\"") + && str.startsWith("\"")) + { +#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0) + str = str.remove(0, 1); + str = str.remove(str.size() - 1, 1); +#else + str = str.removeFirst().removeLast(); +#endif + } + return str; +} + +bool parseOldFileFormat(QIODevice& device, QSettings::SettingsMap& map) +{ + QTextStream in(device.readAll()); +#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0) + in.setCodec("UTF-8"); +#endif + + QStringList lines = in.readAll().split('\n'); + for (int i = 0; i < lines.count(); i++) + { + QString& lineRaw = lines[i]; + // Ignore comments. + int commentIndex = 0; + QString line = lineRaw; + // Search for comments until no more escaped # are available + while ((commentIndex = line.indexOf('#', commentIndex + 1)) != -1) + { + if (commentIndex > 0 && line.at(commentIndex - 1) == '\\') + { + continue; + } + line = line.left(lineRaw.indexOf('#')).trimmed(); + } + + int eqPos = line.indexOf('='); + if (eqPos == -1) + continue; + QString key = line.left(eqPos).trimmed(); + QString valueStr = line.right(line.length() - eqPos - 1).trimmed(); + + valueStr = unquote(unescape(valueStr)); + + QVariant value(valueStr); + map.insert(key, value); + } + + return true; +} + +QVariant migrateQByteArrayToBase64(QString key, QVariant value) +{ + static const QStringList otherByteArrays = { "MainWindowState", "MainWindowGeometry", "ConsoleWindowState", + "ConsoleWindowGeometry", "PagedGeometry", "NewInstanceGeometry", + "ModDownloadGeometry", "RPDownloadGeometry", "TPDownloadGeometry", + "ShaderDownloadGeometry" }; + if (key.startsWith("WideBarVisibility_") || (key.startsWith("UI/") && key.endsWith("_Page/Columns"))) + { + return QString::fromUtf8(value.toByteArray().toBase64()); + } + if (otherByteArrays.contains(key)) + { + return QString::fromUtf8(value.toByteArray()); + } + if (key == "linkedInstances") + { + return Json::fromStringList(value.toStringList()); + } + if (key == "Env") + { + return Json::fromMap(value.toMap()); + } + return value; +} + +bool INIFile::loadFile(QString fileName) +{ + QSettings _settings_obj{ fileName, QSettings::Format::IniFormat }; + _settings_obj.setFallbacksEnabled(false); + + if (auto status = _settings_obj.status(); status != QSettings::Status::NoError) + { + if (status == QSettings::Status::AccessError) + qCritical() << "An access error occurred (e.g. trying to write to a read-only file)."; + if (status == QSettings::Status::FormatError) + qCritical() << "A format error occurred (e.g. loading a malformed INI file)."; + return false; + } + if (!_settings_obj.value("ConfigVersion").isValid()) + { + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly)) + return false; + QSettings::SettingsMap map; + parseOldFileFormat(file, map); + file.close(); + for (auto&& key : map.keys()) + { + auto value = migrateQByteArrayToBase64(key, map.value(key)); + insert(key, value); + } + insert("ConfigVersion", "1.3"); + } + else if (_settings_obj.value("ConfigVersion").toString() == "1.1") + { + for (auto&& key : _settings_obj.allKeys()) + { + auto value = migrateQByteArrayToBase64(key, _settings_obj.value(key)); + if (auto valueStr = value.toString(); + (valueStr.contains(QChar(';')) || valueStr.contains(QChar('=')) || valueStr.contains(QChar(','))) + && valueStr.endsWith("\"") && valueStr.startsWith("\"")) + { + insert(key, unquote(valueStr)); + } + else + { + insert(key, value); + } + } + insert("ConfigVersion", "1.3"); + } + else if (_settings_obj.value("ConfigVersion").toString() == "1.2") + { + for (auto&& key : _settings_obj.allKeys()) + { + auto value = migrateQByteArrayToBase64(key, _settings_obj.value(key)); + insert(key, value); + } + insert("ConfigVersion", "1.3"); + } + else + { + for (auto&& key : _settings_obj.allKeys()) + { + insert(key, _settings_obj.value(key)); + } + } + return true; +} + +bool INIFile::loadFile(QByteArray data) +{ + QTemporaryFile file; + if (!file.open()) + return false; + file.write(data); + file.flush(); + file.close(); + auto loaded = loadFile(file.fileName()); + file.remove(); + return loaded; +} + +QVariant INIFile::get(QString key, QVariant def) const +{ + if (!this->contains(key)) + return def; + else + return this->operator[](key); +} + +void INIFile::set(QString key, QVariant val) +{ + this->operator[](key) = val; +} diff --git a/archived/projt-launcher/launcher/settings/INIFile.h b/archived/projt-launcher/launcher/settings/INIFile.h new file mode 100644 index 0000000000..b3c7003e08 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/INIFile.h @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-3.0-only +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * + * + * Prism Launcher - Minecraft Launcher + * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2023 flowln <flowlnlnln@gmail.com> + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ======================================================================== */ + +#pragma once + +#include <QIODevice> +#include <QString> +#include <QVariant> + +#include <QJsonArray> +#include <QJsonDocument> + +// Sectionless INI parser (for instance config files) +class INIFile : public QMap<QString, QVariant> +{ + public: + explicit INIFile(); + + bool loadFile(QString fileName); + bool loadFile(QByteArray data); + bool saveFile(QString fileName); + + QVariant get(QString key, QVariant def) const; + void set(QString key, QVariant val); +}; diff --git a/archived/projt-launcher/launcher/settings/INISettingsObject.cpp b/archived/projt-launcher/launcher/settings/INISettingsObject.cpp new file mode 100644 index 0000000000..72c9f32e0d --- /dev/null +++ b/archived/projt-launcher/launcher/settings/INISettingsObject.cpp @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#include "INISettingsObject.h" +#include "Setting.h" + +#include <QDebug> +#include <QFile> + +INISettingsObject::INISettingsObject(QStringList paths, QObject* parent) : SettingsObject(parent) +{ + auto first_path = paths.constFirst(); + for (auto path : paths) + { + if (!QFile::exists(path)) + continue; + + if (path != first_path && QFile::exists(path)) + { + // Copy the fallback to the preferred path. + QFile::copy(path, first_path); + qDebug() << "Copied settings from" << path << "to" << first_path; + break; + } + } + + m_filePath = first_path; + m_ini.loadFile(first_path); +} + +INISettingsObject::INISettingsObject(QString path, QObject* parent) : SettingsObject(parent) +{ + m_filePath = path; + m_ini.loadFile(path); +} + +void INISettingsObject::setFilePath(const QString& filePath) +{ + m_filePath = filePath; +} + +bool INISettingsObject::reload() +{ + return m_ini.loadFile(m_filePath) && SettingsObject::reload(); +} + +void INISettingsObject::suspendSave() +{ + m_suspendSave = true; +} + +void INISettingsObject::resumeSave() +{ + m_suspendSave = false; + if (m_doSave) + { + m_ini.saveFile(m_filePath); + } +} + +void INISettingsObject::changeSetting(const Setting& setting, QVariant value) +{ + if (contains(setting.id())) + { + // valid value -> set the main config, remove all the sysnonyms + if (value.isValid()) + { + auto list = setting.configKeys(); + m_ini.set(list.takeFirst(), value); + for (auto iter : list) + m_ini.remove(iter); + } + // invalid -> remove all (just like resetSetting) + else + { + for (auto iter : setting.configKeys()) + m_ini.remove(iter); + } + doSave(); + } +} + +void INISettingsObject::doSave() +{ + if (m_suspendSave) + { + m_doSave = true; + } + else + { + m_ini.saveFile(m_filePath); + } +} + +void INISettingsObject::resetSetting(const Setting& setting) +{ + // if we have the setting, remove all the synonyms. ALL OF THEM + if (contains(setting.id())) + { + for (auto iter : setting.configKeys()) + m_ini.remove(iter); + doSave(); + } +} + +QVariant INISettingsObject::retrieveValue(const Setting& setting) +{ + // if we have the setting, return value of the first matching synonym + if (contains(setting.id())) + { + for (auto iter : setting.configKeys()) + { + if (m_ini.contains(iter)) + return m_ini[iter]; + } + } + return QVariant(); +} diff --git a/archived/projt-launcher/launcher/settings/INISettingsObject.h b/archived/projt-launcher/launcher/settings/INISettingsObject.h new file mode 100644 index 0000000000..881a6d6fd7 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/INISettingsObject.h @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ +#pragma once + +#include <QObject> + +#include "settings/INIFile.h" + +#include "settings/SettingsObject.h" + +/*! + * \brief A settings object that stores its settings in an INIFile. + */ +class INISettingsObject : public SettingsObject +{ + Q_OBJECT + public: + /** 'paths' is a list of INI files to try, in order, for fallback support. */ + explicit INISettingsObject(QStringList paths, QObject* parent = nullptr); + + explicit INISettingsObject(QString path, QObject* parent = nullptr); + + /*! + * \brief Gets the path to the INI file. + * \return The path to the INI file. + */ + virtual QString filePath() const + { + return m_filePath; + } + + /*! + * \brief Sets the path to the INI file and reloads it. + * \param filePath The INI file's new path. + */ + virtual void setFilePath(const QString& filePath); + + bool reload() override; + + void suspendSave() override; + void resumeSave() override; + + protected slots: + virtual void changeSetting(const Setting& setting, QVariant value) override; + virtual void resetSetting(const Setting& setting) override; + + protected: + virtual QVariant retrieveValue(const Setting& setting) override; + void doSave(); + + protected: + INIFile m_ini; + QString m_filePath; +}; diff --git a/archived/projt-launcher/launcher/settings/OverrideSetting.cpp b/archived/projt-launcher/launcher/settings/OverrideSetting.cpp new file mode 100644 index 0000000000..34caf8ab45 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/OverrideSetting.cpp @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#include "OverrideSetting.h" + +OverrideSetting::OverrideSetting(std::shared_ptr<Setting> other, std::shared_ptr<Setting> gate) + : Setting(other->configKeys(), QVariant()) +{ + Q_ASSERT(other); + Q_ASSERT(gate); + m_other = other; + m_gate = gate; +} + +bool OverrideSetting::isOverriding() const +{ + return m_gate->get().toBool(); +} + +QVariant OverrideSetting::defValue() const +{ + return m_other->get(); +} + +QVariant OverrideSetting::get() const +{ + if (isOverriding()) + { + return Setting::get(); + } + return m_other->get(); +} + +void OverrideSetting::reset() +{ + Setting::reset(); +} + +void OverrideSetting::set(QVariant value) +{ + Setting::set(value); +} diff --git a/archived/projt-launcher/launcher/settings/OverrideSetting.h b/archived/projt-launcher/launcher/settings/OverrideSetting.h new file mode 100644 index 0000000000..97cc342bfc --- /dev/null +++ b/archived/projt-launcher/launcher/settings/OverrideSetting.h @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#pragma once + +#include <QObject> +#include <memory> + +#include "Setting.h" + +/*! + * \brief A setting that 'overrides another.' + * This means that the setting's default value will be the value of another setting. + * The other setting can be (and usually is) a part of a different SettingsObject + * than this one. + */ +class OverrideSetting : public Setting +{ + Q_OBJECT + public: + explicit OverrideSetting(std::shared_ptr<Setting> overridden, std::shared_ptr<Setting> gate); + + virtual QVariant defValue() const; + virtual QVariant get() const; + virtual void set(QVariant value); + virtual void reset(); + + private: + bool isOverriding() const; + + protected: + std::shared_ptr<Setting> m_other; + std::shared_ptr<Setting> m_gate; +}; diff --git a/archived/projt-launcher/launcher/settings/PassthroughSetting.cpp b/archived/projt-launcher/launcher/settings/PassthroughSetting.cpp new file mode 100644 index 0000000000..feeaa0dffa --- /dev/null +++ b/archived/projt-launcher/launcher/settings/PassthroughSetting.cpp @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#include "PassthroughSetting.h" + +PassthroughSetting::PassthroughSetting(std::shared_ptr<Setting> other, std::shared_ptr<Setting> gate) + : Setting(other->configKeys(), QVariant()) +{ + Q_ASSERT(other); + m_other = other; + m_gate = gate; +} + +bool PassthroughSetting::isOverriding() const +{ + if (!m_gate) + { + return false; + } + return m_gate->get().toBool(); +} + +QVariant PassthroughSetting::defValue() const +{ + if (isOverriding()) + { + return m_other->get(); + } + return m_other->defValue(); +} + +QVariant PassthroughSetting::get() const +{ + if (isOverriding()) + { + return Setting::get(); + } + return m_other->get(); +} + +void PassthroughSetting::reset() +{ + if (isOverriding()) + { + Setting::reset(); + } + m_other->reset(); +} + +void PassthroughSetting::set(QVariant value) +{ + if (isOverriding()) + { + Setting::set(value); + } + m_other->set(value); +} diff --git a/archived/projt-launcher/launcher/settings/PassthroughSetting.h b/archived/projt-launcher/launcher/settings/PassthroughSetting.h new file mode 100644 index 0000000000..401879c942 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/PassthroughSetting.h @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#pragma once + +#include <QObject> +#include <memory> + +#include "Setting.h" + +/*! + * \brief A setting that 'overrides another.' based on the value of a 'gate' setting + * If 'gate' evaluates to true, the override stores and returns data + * If 'gate' evaluates to false, the original does, + */ +class PassthroughSetting : public Setting +{ + Q_OBJECT + public: + explicit PassthroughSetting(std::shared_ptr<Setting> overridden, std::shared_ptr<Setting> gate); + + virtual QVariant defValue() const; + virtual QVariant get() const; + virtual void set(QVariant value); + virtual void reset(); + + private: + bool isOverriding() const; + + protected: + std::shared_ptr<Setting> m_other; + std::shared_ptr<Setting> m_gate; +}; diff --git a/archived/projt-launcher/launcher/settings/Setting.cpp b/archived/projt-launcher/launcher/settings/Setting.cpp new file mode 100644 index 0000000000..0f96f23117 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/Setting.cpp @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#include "Setting.h" +#include "settings/SettingsObject.h" + +Setting::Setting(QStringList synonyms, QVariant defVal) : QObject(), m_synonyms(synonyms), m_defVal(defVal) +{} + +QVariant Setting::get() const +{ + SettingsObject* sbase = m_storage; + if (!sbase) + { + return defValue(); + } + else + { + QVariant test = sbase->retrieveValue(*this); + if (!test.isValid()) + return defValue(); + return test; + } +} + +QVariant Setting::defValue() const +{ + return m_defVal; +} + +void Setting::set(QVariant value) +{ + emit SettingChanged(*this, value); +} + +void Setting::reset() +{ + emit settingReset(*this); +} diff --git a/archived/projt-launcher/launcher/settings/Setting.h b/archived/projt-launcher/launcher/settings/Setting.h new file mode 100644 index 0000000000..1553d5f4eb --- /dev/null +++ b/archived/projt-launcher/launcher/settings/Setting.h @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#pragma once + +#include <QObject> +#include <QStringList> +#include <QVariant> +#include <memory> + +class SettingsObject; + +/*! + * + */ +class Setting : public QObject +{ + Q_OBJECT + public: + /** + * Construct a Setting + * + * Synonyms are all the possible names used in the settings object, in order of preference. + * First synonym is the ID, which identifies the setting in ProjT Launcher. + * + * defVal is the default value that will be returned when the settings object + * doesn't have any value for this setting. + */ + explicit Setting(QStringList synonyms, QVariant defVal = QVariant()); + + /*! + * \brief Gets this setting's ID. + * This is used to refer to the setting within the application. + * \warning Changing the ID while the setting is registered with a SettingsObject results in + * undefined behavior. + * \return The ID of the setting. + */ + virtual QString id() const + { + return m_synonyms.first(); + } + + /*! + * \brief Gets this setting's config file key. + * This is used to store the setting's value in the config file. It is usually + * the same as the setting's ID, but it can be different. + * \return The setting's config file key. + */ + virtual QStringList configKeys() const + { + return m_synonyms; + } + + /*! + * \brief Gets this setting's value as a QVariant. + * This is done by calling the SettingsObject's retrieveValue() function. + * If this Setting doesn't have a SettingsObject, this returns an invalid QVariant. + * \return QVariant containing this setting's value. + * \sa value() + */ + virtual QVariant get() const; + + /*! + * \brief Gets this setting's default value. + * \return The default value of this setting. + */ + virtual QVariant defValue() const; + + signals: + /*! + * \brief Signal emitted when this Setting object's value changes. + * \param setting A reference to the Setting that changed. + * \param value This Setting object's new value. + */ + void SettingChanged(const Setting& setting, QVariant value); + + /*! + * \brief Signal emitted when this Setting object's value resets to default. + * \param setting A reference to the Setting that changed. + */ + void settingReset(const Setting& setting); + + public slots: + /*! + * \brief Changes the setting's value. + * This is done by emitting the SettingChanged() signal which will then be + * handled by the SettingsObject object and cause the setting to change. + * \param value The new value. + */ + virtual void set(QVariant value); + + /*! + * \brief Reset the setting to default + * This is done by emitting the settingReset() signal which will then be + * handled by the SettingsObject object and cause the setting to change. + */ + virtual void reset(); + + protected: + friend class SettingsObject; + SettingsObject* m_storage; + QStringList m_synonyms; + QVariant m_defVal; +}; diff --git a/archived/projt-launcher/launcher/settings/SettingsObject.cpp b/archived/projt-launcher/launcher/settings/SettingsObject.cpp new file mode 100644 index 0000000000..1bb6a40827 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/SettingsObject.cpp @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#include "settings/SettingsObject.h" +#include <QDebug> +#include "PassthroughSetting.h" +#include "settings/OverrideSetting.h" +#include "settings/Setting.h" + +#include <QVariant> + +SettingsObject::SettingsObject(QObject* parent) : QObject(parent) +{} + +SettingsObject::~SettingsObject() +{ + m_settings.clear(); +} + +std::shared_ptr<Setting> SettingsObject::registerOverride(std::shared_ptr<Setting> original, + std::shared_ptr<Setting> gate) +{ + if (contains(original->id())) + { + qCritical() << QString("Failed to register setting %1. ID already exists.").arg(original->id()); + return nullptr; // Fail + } + auto override = std::make_shared<OverrideSetting>(original, gate); + override->m_storage = this; + connectSignals(*override); + m_settings.insert(override->id(), override); + return override; +} + +std::shared_ptr<Setting> SettingsObject::registerPassthrough(std::shared_ptr<Setting> original, + std::shared_ptr<Setting> gate) +{ + if (contains(original->id())) + { + qCritical() << QString("Failed to register setting %1. ID already exists.").arg(original->id()); + return nullptr; // Fail + } + auto passthrough = std::make_shared<PassthroughSetting>(original, gate); + passthrough->m_storage = this; + connectSignals(*passthrough); + m_settings.insert(passthrough->id(), passthrough); + return passthrough; +} + +std::shared_ptr<Setting> SettingsObject::registerSetting(QStringList synonyms, QVariant defVal) +{ + if (synonyms.empty()) + return nullptr; + if (contains(synonyms.first())) + { + qCritical() << QString("Failed to register setting %1. ID already exists.").arg(synonyms.first()); + return nullptr; // Fail + } + auto setting = std::make_shared<Setting>(synonyms, defVal); + setting->m_storage = this; + connectSignals(*setting); + m_settings.insert(setting->id(), setting); + return setting; +} + +std::shared_ptr<Setting> SettingsObject::getSetting(const QString& id) const +{ + // Make sure there is a setting with the given ID. + if (!m_settings.contains(id)) + return NULL; + + return m_settings[id]; +} + +QVariant SettingsObject::get(const QString& id) const +{ + auto setting = getSetting(id); + return (setting ? setting->get() : QVariant()); +} + +bool SettingsObject::set(const QString& id, QVariant value) +{ + auto setting = getSetting(id); + if (!setting) + { + qCritical() << QString("Error changing setting %1. Setting doesn't exist.").arg(id); + return false; + } + else + { + setting->set(value); + return true; + } +} + +void SettingsObject::reset(const QString& id) const +{ + auto setting = getSetting(id); + if (setting) + setting->reset(); +} + +bool SettingsObject::contains(const QString& id) +{ + return m_settings.contains(id); +} + +bool SettingsObject::reload() +{ + for (auto setting : m_settings.values()) + { + setting->set(setting->get()); + } + return true; +} + +void SettingsObject::connectSignals(const Setting& setting) +{ + connect(&setting, &Setting::SettingChanged, this, &SettingsObject::changeSetting); + connect(&setting, &Setting::SettingChanged, this, &SettingsObject::SettingChanged); + + connect(&setting, &Setting::settingReset, this, &SettingsObject::resetSetting); + connect(&setting, &Setting::settingReset, this, &SettingsObject::settingReset); +} + +std::shared_ptr<Setting> SettingsObject::getOrRegisterSetting(const QString& id, QVariant defVal) +{ + return contains(id) ? getSetting(id) : registerSetting(id, defVal); +} diff --git a/archived/projt-launcher/launcher/settings/SettingsObject.h b/archived/projt-launcher/launcher/settings/SettingsObject.h new file mode 100644 index 0000000000..1845796ba8 --- /dev/null +++ b/archived/projt-launcher/launcher/settings/SettingsObject.h @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-3.0-only AND Apache-2.0 +// SPDX-FileCopyrightText: 2026 Project Tick +// SPDX-FileContributor: Project Tick Team +/* + * ProjT Launcher - Minecraft Launcher + * Copyright (C) 2026 Project Tick + * + * 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, version 3. + * + * 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, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * === Upstream License Block (Do Not Modify) ============================== + * + * Copyright 2013-2021 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + +#pragma once + +#include <QJsonArray> +#include <QJsonDocument> +#include <QMap> +#include <QObject> +#include <QStringList> +#include <QVariant> +#include <memory> + +class Setting; +class SettingsObject; + +using SettingsObjectPtr = std::shared_ptr<SettingsObject>; +using SettingsObjectWeakPtr = std::weak_ptr<SettingsObject>; + +/*! + * \brief The SettingsObject handles communicating settings between the application and a + *settings file. + * The class keeps a list of Setting objects. Each Setting object represents one + * of the application's settings. These Setting objects are registered with + * a SettingsObject and can be managed similarly to the way a list works. + * + * \author Andrew Okin + * \date 2/22/2013 + * + * \sa Setting + */ +class SettingsObject : public QObject +{ + Q_OBJECT + public: + class Lock + { + public: + Lock(SettingsObjectPtr locked) : m_locked(locked) + { + m_locked->suspendSave(); + } + ~Lock() + { + m_locked->resumeSave(); + } + + private: + SettingsObjectPtr m_locked; + }; + + public: + explicit SettingsObject(QObject* parent = 0); + virtual ~SettingsObject(); + /*! + * Registers an override setting for the given original setting in this settings object + * gate decides if the passthrough (true) or the original (false) is used for value + * + * This will fail if there is already a setting with the same ID as + * the one that is being registered. + * \return A valid Setting shared pointer if successful. + */ + std::shared_ptr<Setting> registerOverride(std::shared_ptr<Setting> original, std::shared_ptr<Setting> gate); + + /*! + * Registers a passthorugh setting for the given original setting in this settings object + * gate decides if the passthrough (true) or the original (false) is used for value + * + * This will fail if there is already a setting with the same ID as + * the one that is being registered. + * \return A valid Setting shared pointer if successful. + */ + std::shared_ptr<Setting> registerPassthrough(std::shared_ptr<Setting> original, std::shared_ptr<Setting> gate); + + /*! + * Registers the given setting with this SettingsObject and connects the necessary signals. + * + * This will fail if there is already a setting with the same ID as + * the one that is being registered. + * \return A valid Setting shared pointer if successful. + */ + std::shared_ptr<Setting> registerSetting(QStringList synonyms, QVariant defVal = QVariant()); + + /*! + * Registers the given setting with this SettingsObject and connects the necessary signals. + * + * This will fail if there is already a setting with the same ID as + * the one that is being registered. + * \return A valid Setting shared pointer if successful. + */ + std::shared_ptr<Setting> registerSetting(QString id, QVariant defVal = QVariant()) + { + return registerSetting(QStringList(id), defVal); + } + + /*! + * \brief Gets the setting with the given ID. + * \param id The ID of the setting to get. + * \return A pointer to the setting with the given ID. + * Returns null if there is no setting with the given ID. + * \sa operator []() + */ + std::shared_ptr<Setting> getSetting(const QString& id) const; + + /*! + * \brief Gets the setting with the given ID. + * \brief if is not registered yet it does that + * \param id The ID of the setting to get. + * \return A pointer to the setting with the given ID. + * Returns null if there is no setting with the given ID. + * \sa operator []() + */ + std::shared_ptr<Setting> getOrRegisterSetting(const QString& id, QVariant defVal = QVariant()); + + /*! + * \brief Gets the value of the setting with the given ID. + * \param id The ID of the setting to get. + * \return The setting's value as a QVariant. + * If no setting with the given ID exists, returns an invalid QVariant. + */ + QVariant get(const QString& id) const; + + /*! + * \brief Sets the value of the setting with the given ID. + * If no setting with the given ID exists, returns false + * \param id The ID of the setting to change. + * \param value The new value of the setting. + * \return True if successful, false if it failed. + */ + bool set(const QString& id, QVariant value); + + /*! + * \brief Reverts the setting with the given ID to default. + * \param id The ID of the setting to reset. + */ + void reset(const QString& id) const; + + /*! + * \brief Checks if this SettingsObject contains a setting with the given ID. + * \param id The ID to check for. + * \return True if the SettingsObject has a setting with the given ID. + */ + bool contains(const QString& id); + + /*! + * \brief Reloads the settings and emit signals for changed settings + * \return True if reloading was successful + */ + virtual bool reload(); + + virtual void suspendSave() = 0; + virtual void resumeSave() = 0; + signals: + /*! + * \brief Signal emitted when one of this SettingsObject object's settings changes. + * This is usually just connected directly to each Setting object's + * SettingChanged() signals. + * \param setting A reference to the Setting object that changed. + * \param value The Setting object's new value. + */ + void SettingChanged(const Setting& setting, QVariant value); + + /*! + * \brief Signal emitted when one of this SettingsObject object's settings resets. + * This is usually just connected directly to each Setting object's + * settingReset() signals. + * \param setting A reference to the Setting object that changed. + */ + void settingReset(const Setting& setting); + + protected slots: + /*! + * \brief Changes a setting. + * This slot is usually connected to each Setting object's + * SettingChanged() signal. The signal is emitted, causing this slot + * to update the setting's value in the config file. + * \param setting A reference to the Setting object that changed. + * \param value The setting's new value. + */ + virtual void changeSetting(const Setting& setting, QVariant value) = 0; + + /*! + * \brief Resets a setting. + * This slot is usually connected to each Setting object's + * settingReset() signal. The signal is emitted, causing this slot + * to update the setting's value in the config file. + * \param setting A reference to the Setting object that changed. + */ + virtual void resetSetting(const Setting& setting) = 0; + + protected: + /*! + * \brief Connects the necessary signals to the given Setting. + * \param setting The setting to connect. + */ + void connectSignals(const Setting& setting); + + /*! + * \brief Function used by Setting objects to get their values from the SettingsObject. + * \param setting The + * \return + */ + virtual QVariant retrieveValue(const Setting& setting) = 0; + + friend class Setting; + + private: + QMap<QString, std::shared_ptr<Setting>> m_settings; + + protected: + bool m_suspendSave = false; + bool m_doSave = false; +}; |
