Files
create/src/Gui/PreferencePackManager.h
Chris Hennes 40171d7858 [GUI] Add PreferencePack support
Preference Packs are collections of preferences that can be applied en
mass to the user's current setup. Any preference that can be stored in
user.cfg can be stored in a preference pack, and they are designed to be
easy to distribute.

Support is also added for saving a subset of current preferences into a
new preference pack in order to facilitate easy creation of new
"themes", etc.
2021-05-13 09:08:33 -05:00

191 lines
8.0 KiB
C++

/***************************************************************************
* Copyright (c) 2021 Chris Hennes <chennes@pioneerlibrarysystem.org> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef BASE_THEMEMANAGER_H
#define BASE_THEMEMANAGER_H
#include <vector>
#include <string>
#include <mutex>
#include "App/Metadata.h"
namespace Gui {
/**
* \class PreferencePack A collection of user preferences stored in files on disk
*/
class PreferencePack {
public:
/**
* Construct a preferencePack from a directory
*
* \param path A path to a mod directory that contains a preferencePack
* \param metadata The metadata from the package.xml file describing this preferencePack
*/
PreferencePack(const boost::filesystem::path& path, const App::Metadata& metadata);
~PreferencePack() = default;
/**
* Get the name of the PreferencePack
*/
std::string name() const;
/**
* Apply the PreferencePack over the top of the current preferences set
* \returns True if the preferencePack was applied, or false if not
*/
bool apply() const;
enum class Type {
Appearance,
Behavior,
Combination
};
/**
* Get the type of PreferencePack (appearance, behavior, or a combination of the two)
*/
Type type() const;
private:
void applyConfigChanges() const;
boost::filesystem::path _path;
App::Metadata _metadata;
};
/**
* \class PreferencePackManager handles storable and loadable collections of user preferences
*
* This class provides some additional utility functions for allowing users to save their current
* preferences as a PreferencePack based on a set of template files provided either in the main
* FreeCAD distribution, or inside various installed mods.
*/
class PreferencePackManager {
public:
PreferencePackManager();
~PreferencePackManager() = default;
/**
* Rescan the preferencePack directory and update the available PreferencePacks
*/
void rescan();
/**
* Get an alphabetical list of names of all installed PreferencePacks of a given type
*/
std::vector<std::string> preferencePackNames(PreferencePack::Type type) const;
/**
* Apply the named preferencePack
* \return True if the preferencePack was applied, or false if it was not
*/
bool apply(const std::string& preferencePackName) const;
/**
* \struct TemplateFile A file containing a set of preferences that can be saved into
* a PreferencePack
*
* PreferencePacks can contain any parameters at all, but inside FreeCAD there is no
* centralized list of all of these parameters, and at any given time the user.cfg file
* usually does not store a value for all possible parameters. Instead, it simply allows
* calling code to use whatever default values that code sets. This is all completely
* hidden from the users: FreeCAD behaves as though those values exist in the config file.
*
* When a user saves their current configuration as a pack, they likely expect that saved
* configuration to include those default values, so that if they later apply their saved
* configuration those defaults are restored. To enable this a set of template files
* listing default values for various types of parameters can be used. Each file is
* presented to the user as a checkable box when saving a new preferences pack, and the
* intention is that these files will list out the various user-facing parameters that
* someone might want to save into a preferences pack.
*
* These files are themselves valid user.cfg files, that if loaded and applied will result
* in the default values of their contained variables being set. For this to work, these
* files should be kept up-to-date with the default values set in the code. They are not
* required to contain an exhaustive listing of all possible parameters: in most cases it
* is enough that they list the variables that a user would expect for a given name. For
* example, "Sketcher Colors.cfg" should list out all of the default colors used in
* Sketcher that a user can set in Preferences, but it is not necessary that it contain any
* color that is only used internally, and it should not include things like fonts, or
* behavior information.
*
* Template files are always located in a directory hierarchy that differentiates between
* templates that only affect appearance, and those that affect behavior.
*
* The base FreeCAD installation includes default templates in:
* $INSTALL_DIR/data/Gui/PreferencePackTemplates/(Appearance|Behavior)/
*
* External add-ons are also searched for any directory called PreferencePackTemplates or
* preference_pack_templates -- either of which is expected to contain appearance and/or
* behavior subdirectories. In this way external add-ons can allow a user to easily save
* their preferences to a PreferencePack, or even to add additional templates representing
* sets of core FreeCAD preferences.
*/
struct TemplateFile {
std::string group; // Generally the Add-On/Mod/Package name
std::string name;
boost::filesystem::path path;
PreferencePack::Type type;
};
/**
* Save current settings as a (possibly new) preferencePack
*
* If the named preferencePack does not exist, this creates it on disk. If it does exist, this overwrites the original.
*/
void save(const std::string& name, const std::vector<TemplateFile>& templates);
std::vector<TemplateFile> templateFiles(bool rescan = false);
private:
void FindPreferencePacksInPackage(const boost::filesystem::path& mod);
void BackupCurrentConfig() const;
void DeleteOldBackups() const;
std::vector<boost::filesystem::path> _preferencePackPaths;
std::vector<TemplateFile> _templateFiles;
std::map<std::string, PreferencePack> _preferencePacks;
mutable std::mutex _mutex;
};
}
Q_DECLARE_METATYPE(Gui::PreferencePackManager::TemplateFile) // So it can be used with QVariant
#endif