diff --git a/src/App/Metadata.cpp b/src/App/Metadata.cpp index ce2f5ec6df..1780c7f266 100644 --- a/src/App/Metadata.cpp +++ b/src/App/Metadata.cpp @@ -320,6 +320,14 @@ void App::Metadata::addGenericMetadata(const std::string& tag, const Meta::Gener _genericMetadata.insert(std::make_pair(tag, genericMetadata)); } +void App::Metadata::removeContentItem(const std::string& tag, const std::string& itemName) +{ + auto tagRange = _content.equal_range(tag); + auto foundItem = std::find_if(tagRange.first, tagRange.second, [itemName](auto check) -> bool { return itemName == check.second.name(); }); + if (foundItem != tagRange.second) + _content.erase(foundItem); +} + DOMElement* appendSimpleXMLNode(DOMElement* baseNode, const std::string& nodeName, const std::string& nodeContents) { diff --git a/src/App/Metadata.h b/src/App/Metadata.h index 992369bce1..3c1dcf1c73 100644 --- a/src/App/Metadata.h +++ b/src/App/Metadata.h @@ -255,6 +255,9 @@ namespace App { void setFreeCADMax(const Meta::Version& version); void addGenericMetadata(const std::string& tag, const Meta::GenericMetadata& genericMetadata); + // Deleters (work in progress...) + void removeContentItem(const std::string& tag, const std::string& itemName); + /** * Write the metadata to an XML file */ diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 0db6b3cf9e..8289d844c8 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -322,6 +322,7 @@ SET(Gui_UIC_SRCS DlgOnlineHelp.ui DlgParameter.ui DlgParameterFind.ui + DlgPreferencePackManagement.ui DlgPreferences.ui DlgProjectInformation.ui DlgProjectUtility.ui @@ -418,6 +419,7 @@ SET(Dialog_CPP_SRCS DlgMaterialPropertiesImp.cpp DlgParameterImp.cpp DlgParameterFind.cpp + DlgPreferencePackManagementImp.cpp DlgProjectInformationImp.cpp DlgProjectUtility.cpp DlgPropertyLink.cpp @@ -456,6 +458,7 @@ SET(Dialog_HPP_SRCS DlgMaterialPropertiesImp.h DlgParameterImp.h DlgParameterFind.h + DlgPreferencePackManagementImp.h DlgProjectInformationImp.h DlgProjectUtility.h DlgPropertyLink.h @@ -499,6 +502,7 @@ SET(Dialog_SRCS DlgMaterialProperties.ui DlgParameter.ui DlgParameterFind.ui + DlgPreferencePackManagement.ui DlgProjectInformation.ui DlgProjectUtility.ui DlgPropertyLink.ui diff --git a/src/Gui/DlgGeneralImp.cpp b/src/Gui/DlgGeneralImp.cpp index 0e50826e55..ce11676143 100644 --- a/src/Gui/DlgGeneralImp.cpp +++ b/src/Gui/DlgGeneralImp.cpp @@ -44,10 +44,7 @@ #include "DlgPreferencesImp.h" #include "DlgCreateNewPreferencePackImp.h" - -// Only needed until PreferencePacks can be managed from the AddonManager: -#include -namespace fs = boost::filesystem; +#include "DlgPreferencePackManagementImp.h" using namespace Gui::Dialog; @@ -97,19 +94,8 @@ DlgGeneralImp::DlgGeneralImp( QWidget* parent ) recreatePreferencePackMenu(); connect(ui->SaveNewPreferencePack, &QPushButton::clicked, this, &DlgGeneralImp::saveAsNewPreferencePack); - // Future work: the Add-On Manager will be modified to include a section for Preference Packs, at which point this - // button will be modified to open the Add-On Manager to that tab. - auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; - - // If that directory hasn't been created yet, just send the user to the preferences directory - if (!(fs::exists(savedPreferencePacksDirectory) && fs::is_directory(savedPreferencePacksDirectory))) { - savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()); - ui->ManagePreferencePacks->hide(); - } - - QString pathToSavedPacks(QString::fromStdString(savedPreferencePacksDirectory.string())); - ui->ManagePreferencePacks->setToolTip(tr("Open the directory of saved user preference packs")); - connect(ui->ManagePreferencePacks, &QPushButton::clicked, this, [pathToSavedPacks]() { QDesktopServices::openUrl(QUrl::fromLocalFile(pathToSavedPacks)); }); + ui->ManagePreferencePacks->setToolTip(tr("Manage preference packs")); + connect(ui->ManagePreferencePacks, &QPushButton::clicked, this, &DlgGeneralImp::onManagePreferencePacksClicked); } /** @@ -353,6 +339,7 @@ void DlgGeneralImp::recreatePreferencePackMenu() ui->PreferencePacks->setHorizontalHeaderLabels(columnHeaders); // Populate the Preference Packs list + Application::Instance->prefPackManager()->rescan(); auto packs = Application::Instance->prefPackManager()->preferencePacks(); ui->PreferencePacks->setRowCount(packs.size()); @@ -405,10 +392,19 @@ void DlgGeneralImp::newPreferencePackDialogAccepted() }); auto preferencePackName = newPreferencePackDialog->preferencePackName(); Application::Instance->prefPackManager()->save(preferencePackName, selectedTemplates); - Application::Instance->prefPackManager()->rescan(); recreatePreferencePackMenu(); } +void DlgGeneralImp::onManagePreferencePacksClicked() +{ + if (!this->preferencePackManagementDialog) { + this->preferencePackManagementDialog = std::make_unique(this); + connect(this->preferencePackManagementDialog.get(), &DlgPreferencePackManagementImp::packVisibilityChanged, + this, &DlgGeneralImp::recreatePreferencePackMenu); + } + this->preferencePackManagementDialog->show(); +} + void DlgGeneralImp::onLoadPreferencePackClicked(const std::string& packName) { if (Application::Instance->prefPackManager()->apply(packName)) { diff --git a/src/Gui/DlgGeneralImp.h b/src/Gui/DlgGeneralImp.h index 1e08282669..73447cb421 100644 --- a/src/Gui/DlgGeneralImp.h +++ b/src/Gui/DlgGeneralImp.h @@ -33,6 +33,7 @@ namespace Gui { namespace Dialog { class Ui_DlgGeneral; class DlgCreateNewPreferencePackImp; +class DlgPreferencePackManagementImp; /** This class implements the settings for the application. * You can change window style, size of pixmaps, size of recent file list and so on @@ -56,6 +57,7 @@ protected Q_SLOTS: void onLoadPreferencePackClicked(const std::string &packName); void recreatePreferencePackMenu(); void newPreferencePackDialogAccepted(); + void onManagePreferencePacksClicked(); private: void setRecentFileSize(); @@ -64,6 +66,7 @@ private: private: std::unique_ptr ui; std::unique_ptr newPreferencePackDialog; + std::unique_ptr preferencePackManagementDialog; }; } // namespace Dialog diff --git a/src/Gui/DlgPreferencePackManagement.ui b/src/Gui/DlgPreferencePackManagement.ui new file mode 100644 index 0000000000..04ef287480 --- /dev/null +++ b/src/Gui/DlgPreferencePackManagement.ui @@ -0,0 +1,105 @@ + + + Gui::Dialog::DlgPreferencePackManagement + + + + 0 + 0 + 392 + 255 + + + + Manage Preference Packs + + + true + + + false + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + QAbstractItemView::NoSelection + + + true + + + true + + + 2 + + + false + + + + 1 + + + + + 2 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Open Addon Manager... + + + + + + + + + + + diff --git a/src/Gui/DlgPreferencePackManagementImp.cpp b/src/Gui/DlgPreferencePackManagementImp.cpp new file mode 100644 index 0000000000..4be6d35c97 --- /dev/null +++ b/src/Gui/DlgPreferencePackManagementImp.cpp @@ -0,0 +1,225 @@ +/*************************************************************************** + * Copyright (c) 2022 Chris Hennes * + * * + * 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 * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +#endif + +#include "DlgPreferencePackManagementImp.h" +#include "ui_DlgPreferencePackManagement.h" + +#include +#include +#include "Application.h" +#include "Command.h" + +using namespace Gui::Dialog; +namespace fs = boost::filesystem; + +const auto TemplateRole = Qt::UserRole; + +/* TRANSLATOR Gui::Dialog::DlgPreferencePackManagementImp */ + +/** + * Constructs a Gui::Dialog::DlgPreferencePackManagementImp as a child of 'parent' + */ +DlgPreferencePackManagementImp::DlgPreferencePackManagementImp(QWidget* parent) + : QDialog(parent) + , ui(new Ui_DlgPreferencePackManagement) +{ + ui->setupUi(this); + connect(ui->pushButtonOpenAddonManager, &QPushButton::clicked, this, &DlgPreferencePackManagementImp::showAddonManager); +} + +void DlgPreferencePackManagementImp::showEvent(QShowEvent* event) +{ + // Separate out user-saved packs from installed packs: we can remove individual user-saved packs, + // but can only disable individual installed packs (though we can completely uninstall the pack's + // containing Addon by redirecting to the Addon Manager). + auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + auto modDirectory = fs::path(App::Application::getUserAppDataDir()) / "Mod"; + auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui" / "PreferencePacks"; + + // The displayed tree has two levels: at the toplevel is either "User-Saved Packs" or the name + // of the addon containing the pack. Beneath those are the individual packs themselves. The tree view shows + // "Hide"/"Show" for packs installed as a Mod, and "Delete" for packs in the user-saved pack + // section. + auto userPacks = getPacksFromDirectory(savedPreferencePacksDirectory); + + auto builtinPacks = getPacksFromDirectory(resourcePath); + + std::map> installedPacks; + if (fs::exists(modDirectory) && fs::is_directory(modDirectory)) { + for (const auto& mod : fs::directory_iterator(modDirectory)) { + auto packs = getPacksFromDirectory(mod); + if (!packs.empty()) { + auto modName = mod.path().leaf().string(); + installedPacks.emplace(modName, packs); + } + } + } + + ui->treeWidget->clear(); // Begin by clearing whatever is there + ui->treeWidget->header()->setDefaultAlignment(Qt::AlignLeft); + ui->treeWidget->setColumnCount(2); + ui->treeWidget->setSelectionMode(QAbstractItemView::SelectionMode::NoSelection); + ui->treeWidget->header()->setStretchLastSection(false); + ui->treeWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); + ui->treeWidget->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents); + + if (!userPacks.empty()) { + addTreeNode(tr("User-Saved Preference Packs").toStdString(), userPacks, TreeWidgetType::USER); + } + + if (!builtinPacks.empty()) { + addTreeNode(tr("Built-In Preference Packs").toStdString(), builtinPacks, TreeWidgetType::BUILTIN); + } + + for (const auto& installedPack : installedPacks) { + addTreeNode(installedPack.first, installedPack.second, TreeWidgetType::ADDON); + } + + if (event) + QDialog::showEvent(event); +} + +void DlgPreferencePackManagementImp::addTreeNode(const std::string &name, const std::vector &contents, TreeWidgetType twt) +{ + static const auto iconIsVisible = QIcon(QLatin1String(":/icons/dagViewVisible.svg")); + static const auto iconIsInvisible = QIcon(QLatin1String(":/icons/Invisible.svg")); + auto packRoot = new QTreeWidgetItem(); + packRoot->setText(0, QString::fromStdString(name)); + std::vector items; + for (const auto& packName : contents) { + auto pack = new QTreeWidgetItem(packRoot); + pack->setText(0, QString::fromStdString(packName)); + items.push_back(pack); + } + ui->treeWidget->addTopLevelItem(packRoot); + packRoot->setExpanded(true); + for (const auto item : items) { + auto button = new QPushButton(); + button->setFlat(true); + switch (twt) { + break; case TreeWidgetType::BUILTIN: + // The button is a "hide" button + if (Application::Instance->prefPackManager()->isVisible("##BUILT_IN##", item->text(0).toStdString())) + button->setIcon(iconIsVisible); + else + button->setIcon(iconIsInvisible); + button->setToolTip(tr("Toggle visibility of built-in preference pack '%1'").arg(item->text(0))); + connect(button, &QPushButton::clicked, [this, name, item]() { + this->hideBuiltInPack(item->text(0).toStdString()); + }); + break; case TreeWidgetType::USER: + // The button is a "delete" button + button->setIcon(QIcon(QLatin1String(":/icons/delete.svg"))); + button->setToolTip(tr("Delete user-saved preference pack '%1'").arg(item->text(0))); + connect(button, &QPushButton::clicked, [this, item]() { + this->deleteUserPack(item->text(0).toStdString()); + }); + break; case TreeWidgetType::ADDON: + // The button is a "hide" button + if (Application::Instance->prefPackManager()->isVisible(name, item->text(0).toStdString())) + button->setIcon(iconIsVisible); + else + button->setIcon(iconIsInvisible); + button->setToolTip(tr("Toggle visibility of Addon preference pack '%1' (use Addon Manager to permanently remove)").arg(item->text(0))); + connect(button, &QPushButton::clicked, [this, name, item]() { + this->hideInstalledPack(name, item->text(0).toStdString()); + }); + } + ui->treeWidget->setItemWidget(item, 1, button); + } +} + +std::vector DlgPreferencePackManagementImp::getPacksFromDirectory(const fs::path& path) const +{ + std::vector results; + auto packageMetadataFile = path / "package.xml"; + if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) { + try { + App::Metadata metadata(packageMetadataFile); + auto content = metadata.content(); + for (const auto& item : content) { + if (item.first == "preferencepack") { + results.push_back(item.second.name()); + } + } + } + catch (...) { + // Failed to read the metadata, or to create the preferencePack based on it... + Base::Console().Error(("Failed to read " + packageMetadataFile.string()).c_str()); + } + } + return results; +} + + +void DlgPreferencePackManagementImp::deleteUserPack(const std::string& name) +{ + // Do the deletion here... + auto result = QMessageBox::warning(this, tr("Delete saved preference pack?"), + tr("Are you sure you want to delete the preference pack named '%1'? This cannot be undone.").arg(QString::fromStdString(name)), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); + if (result == QMessageBox::Yes) { + Application::Instance->prefPackManager()->deleteUserPack(name); + showEvent(nullptr); + packVisibilityChanged(); + } +} + +void DlgPreferencePackManagementImp::hideBuiltInPack(const std::string& prefPackName) +{ + Application::Instance->prefPackManager()->toggleVisibility("##BUILT_IN##", prefPackName); + showEvent(nullptr); + packVisibilityChanged(); +} + +void DlgPreferencePackManagementImp::hideInstalledPack(const std::string& addonName, const std::string& prefPackName) +{ + Application::Instance->prefPackManager()->toggleVisibility(addonName, prefPackName); + showEvent(nullptr); + packVisibilityChanged(); +} + +void DlgPreferencePackManagementImp::showAddonManager() +{ + // Configure the view to show all preference packs (installed and uninstalled) + auto pref = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Addons"); + pref->SetInt("PackageTypeSelection", 3); + pref->SetInt("StatusSelection", 0); + + CommandManager& rMgr = Application::Instance->commandManager(); + rMgr.runCommandByName("Std_AddonMgr"); + close(); +} + +DlgPreferencePackManagementImp::~DlgPreferencePackManagementImp() +{ +} + + + +#include "moc_DlgPreferencePackManagementImp.cpp" diff --git a/src/Gui/DlgPreferencePackManagementImp.h b/src/Gui/DlgPreferencePackManagementImp.h new file mode 100644 index 0000000000..fce25e4b3f --- /dev/null +++ b/src/Gui/DlgPreferencePackManagementImp.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (c) 2022 Chris Hennes * + * * + * 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 GUI_DIALOG_DLGPREFERENCEPACKMANAGEMENTIMP_H +#define GUI_DIALOG_DLGPREFERENCEPACKMANAGEMENTIMP_H + +#include +#include +#include + + +class QTreeWidgetItem; + +namespace Gui { + +namespace Dialog { + +class Ui_DlgPreferencePackManagement; + +/** + * \class DlgCreateNewPreferencePackImp + * + * A dialog to request a preferencePack name and a set of preferencePack templates. + * + * \author Chris Hennes + */ +class GuiExport DlgPreferencePackManagementImp : public QDialog +{ + Q_OBJECT + +public: + + DlgPreferencePackManagementImp(QWidget* parent = nullptr); + ~DlgPreferencePackManagementImp(); + +Q_SIGNALS: + void packVisibilityChanged(); + +protected Q_SLOTS: + + void deleteUserPack(const std::string & prefPackName); + void hideBuiltInPack(const std::string& prefPackName); + void hideInstalledPack(const std::string& addonName, const std::string& prefPackName); + + void showEvent(QShowEvent* event) override; + void showAddonManager(); + +private: + + enum class TreeWidgetType { + BUILTIN, + USER, + ADDON + }; + + std::unique_ptr ui; + + std::vector getPacksFromDirectory(const boost::filesystem::path& path) const; + void addTreeNode(const std::string& name, const std::vector& contents, TreeWidgetType twt); + +}; + +} // namespace Dialog +} // namespace Gui + +#endif // GUI_DIALOG_DLGPREFERENCEPACKMANAGEMENTIMP_H diff --git a/src/Gui/PreferencePackManager.cpp b/src/Gui/PreferencePackManager.cpp index 3bb79c2c5e..af38742d66 100644 --- a/src/Gui/PreferencePackManager.cpp +++ b/src/Gui/PreferencePackManager.cpp @@ -149,6 +149,7 @@ PreferencePackManager::PreferencePackManager() void PreferencePackManager::rescan() { std::lock_guard lock(_mutex); + _preferencePacks.clear(); for (const auto& path : _preferencePackPaths) { if (fs::exists(path) && fs::is_directory(path)) { FindPreferencePacksInPackage(path); @@ -164,14 +165,24 @@ void PreferencePackManager::rescan() void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path& mod) { auto packageMetadataFile = mod / "package.xml"; + static const auto modDirectory = fs::path(App::Application::getUserAppDataDir()) / "Mod" / "SavedPreferencePacks"; + static const auto resourcePath = fs::path(App::Application::getResourceDir()) / "Gui" / "PreferencePacks"; + if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) { try { App::Metadata metadata(packageMetadataFile); auto content = metadata.content(); + auto basename = mod.leaf().string(); + if (mod == modDirectory) + basename = "##USER_SAVED##"; + else if (mod == resourcePath) + basename = "##BUILT_IN##"; for (const auto& item : content) { if (item.first == "preferencepack") { - PreferencePack newPreferencePack(mod / item.second.name(), item.second); - _preferencePacks.insert(std::make_pair(newPreferencePack.name(), newPreferencePack)); + if (isVisible(basename, item.second.name())) { + PreferencePack newPreferencePack(mod / item.second.name(), item.second); + _preferencePacks.insert(std::make_pair(newPreferencePack.name(), newPreferencePack)); + } } } } @@ -220,6 +231,77 @@ bool PreferencePackManager::apply(const std::string& preferencePackName) const } } +std::string findUnusedName(const std::string &basename, ParameterGrp::handle parent) +{ + int i = 1; + while (true) { + std::ostringstream nameToTest; + nameToTest << basename << "_" << i; + if (!parent->HasGroup(nameToTest.str().c_str())) + return nameToTest.str(); + ++i; + } +} + +bool PreferencePackManager::isVisible(const std::string& addonName, const std::string& preferencePackName) const +{ + if (addonName == "" || preferencePackName == "") + return true; + + auto pref = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General/HiddenPreferencePacks"); + auto hiddenPacks = pref->GetGroups(); + auto hiddenPack = std::find_if(hiddenPacks.begin(), hiddenPacks.end(), [addonName, preferencePackName](ParameterGrp::handle handle) { + return (handle->GetASCII("addonName", "") == addonName) && (handle->GetASCII("preferencePackName", "") == preferencePackName); + }); + if (hiddenPack == hiddenPacks.end()) + return true; + else + return false; +} + +void PreferencePackManager::toggleVisibility(const std::string& addonName, const std::string& preferencePackName) +{ + if (preferencePackName == "") + return; + auto pref = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General/HiddenPreferencePacks"); + auto hiddenPacks = pref->GetGroups(); + auto hiddenPack = std::find_if(hiddenPacks.begin(), hiddenPacks.end(), [addonName,preferencePackName](ParameterGrp::handle handle) { + return (handle->GetASCII("addonName", "") == addonName) && (handle->GetASCII("preferencePackName", "") == preferencePackName); + }); + if (hiddenPack == hiddenPacks.end()) { + auto name = findUnusedName("PreferencePack", pref); + auto group = pref->GetGroup(name.c_str()); + group->SetASCII("addonName", addonName.c_str()); + group->SetASCII("preferencePackName", preferencePackName.c_str()); + } + else { + auto groupName = (*hiddenPack)->GetGroupName(); + hiddenPacks.clear(); // To decrement the reference count of the group we are about the remove... + pref->RemoveGrp(groupName); + } + rescan(); +} + +void Gui::PreferencePackManager::deleteUserPack(const std::string& name) +{ + if (name == "") + return; + auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + auto savedPath = savedPreferencePacksDirectory / name; + std::unique_ptr metadata; + if (fs::exists(savedPreferencePacksDirectory / "package.xml")) { + metadata = std::make_unique(savedPreferencePacksDirectory / "package.xml"); + } + else { + throw std::runtime_error("Lost the user-saved preference packs metadata file!"); + } + metadata->removeContentItem("preferencepack", name); + metadata->write(savedPreferencePacksDirectory / "package.xml"); + if (fs::exists(savedPath)) + fs::remove_all(savedPath); + rescan(); +} + void copyTemplateParameters(Base::Reference templateGroup, const std::string& path, Base::Reference outputGroup) { auto userParameterHandle = App::GetApplication().GetParameterGroupByPath(path.c_str()); diff --git a/src/Gui/PreferencePackManager.h b/src/Gui/PreferencePackManager.h index 78fd80c236..11251c9809 100644 --- a/src/Gui/PreferencePackManager.h +++ b/src/Gui/PreferencePackManager.h @@ -94,12 +94,12 @@ namespace Gui { void rescan(); /** - * Get an alphabetical list of names of all installed PreferencePacks + * Get an alphabetical list of names of all visible PreferencePacks */ std::vector preferencePackNames() const; /** - * Get a map of all installed PreferencePack names and their associated packs + * Get a map of all visible PreferencePack names and their associated packs */ std::map preferencePacks() const; @@ -109,6 +109,25 @@ namespace Gui { */ bool apply(const std::string& preferencePackName) const; + /** + * Check the visibility of the specified pack + * \return True if the preferencePack is visible, or false if not. All packs are visible by default, + * but can be marked as "invisible" (i.e. not returned by the manager in lists of packs) by using the + * toggleVisibility function. + */ + bool isVisible(const std::string& addonName, const std::string& preferencePackName) const; + + /** + * Toggle the visibility of the named preference pack in a named addon + */ + void toggleVisibility(const std::string& addonName, const std::string& preferencePackName); + + /** + * Deletes the user-saved pack specified by name + */ + void deleteUserPack(const std::string& name); + + /** * \struct TemplateFile A file containing a set of preferences that can be saved into * a PreferencePack