This enables sandboxed apps to maintain access to user-selected items. In addition, for both sandboxed and nonsandboxed apps it can keep track of directories even if they are moved or renamed, and can remember access to directories in "sensitive" locations (such as the Documents folder or external drives). Signed-off-by: Kenneth Chew <79120643+kthchew@users.noreply.github.com>
242 lines
8.8 KiB
C++
242 lines
8.8 KiB
C++
/* 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>
|
|
|
|
#ifdef Q_OS_MACOS
|
|
#include "macsandbox/SecurityBookmarkFileAccess.h"
|
|
#endif
|
|
|
|
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);
|
|
|
|
#ifdef Q_OS_MACOS
|
|
/*!
|
|
* \brief Get the path to the file or directory represented by the bookmark stored in the associated setting.
|
|
* \param id The setting ID of the relevant directory - this should not include "Bookmark" at the end.
|
|
* \return A path to the file or directory represented by the bookmark.
|
|
* If a bookmark is not valid or stored, use default logic (directly return the stored path).
|
|
* This can attempt to create a bookmark if the path is accessible and the bookmark is not valid.
|
|
*/
|
|
QString getPathFromBookmark(const QString& id);
|
|
/*!
|
|
* \brief Set a security-scoped bookmark to the provided path for the associated setting.
|
|
* \param id The setting ID of the relevant directory - this should not include "Bookmark" at the end.
|
|
* \param path The new desired path.
|
|
* \return A boolean indicating whether a bookmark was successfully set.
|
|
* The path needs to be accessible to the launcher before calling this function. For example,
|
|
* it could come from a user selection in an open panel.
|
|
*/
|
|
bool setPathWithBookmark(const QString& id, const QString& path);
|
|
#endif
|
|
|
|
/*!
|
|
* \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;
|
|
#ifdef Q_OS_MACOS
|
|
SecurityBookmarkFileAccess m_sandboxedFileAccess;
|
|
#endif
|
|
|
|
protected:
|
|
bool m_suspendSave = false;
|
|
bool m_doSave = false;
|
|
};
|