Gui: Add interface for managing preference packs

This commit is contained in:
Chris Hennes
2022-02-13 17:31:56 -06:00
parent 38327fa71c
commit 7a566ea4d8
10 changed files with 553 additions and 22 deletions

View File

@@ -320,6 +320,14 @@ void App::Metadata::addGenericMetadata(const std::string& tag, const Meta::Gener
_genericMetadata.insert(std::make_pair(tag, genericMetadata)); _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) DOMElement* appendSimpleXMLNode(DOMElement* baseNode, const std::string& nodeName, const std::string& nodeContents)
{ {

View File

@@ -255,6 +255,9 @@ namespace App {
void setFreeCADMax(const Meta::Version& version); void setFreeCADMax(const Meta::Version& version);
void addGenericMetadata(const std::string& tag, const Meta::GenericMetadata& genericMetadata); 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 * Write the metadata to an XML file
*/ */

View File

@@ -322,6 +322,7 @@ SET(Gui_UIC_SRCS
DlgOnlineHelp.ui DlgOnlineHelp.ui
DlgParameter.ui DlgParameter.ui
DlgParameterFind.ui DlgParameterFind.ui
DlgPreferencePackManagement.ui
DlgPreferences.ui DlgPreferences.ui
DlgProjectInformation.ui DlgProjectInformation.ui
DlgProjectUtility.ui DlgProjectUtility.ui
@@ -418,6 +419,7 @@ SET(Dialog_CPP_SRCS
DlgMaterialPropertiesImp.cpp DlgMaterialPropertiesImp.cpp
DlgParameterImp.cpp DlgParameterImp.cpp
DlgParameterFind.cpp DlgParameterFind.cpp
DlgPreferencePackManagementImp.cpp
DlgProjectInformationImp.cpp DlgProjectInformationImp.cpp
DlgProjectUtility.cpp DlgProjectUtility.cpp
DlgPropertyLink.cpp DlgPropertyLink.cpp
@@ -456,6 +458,7 @@ SET(Dialog_HPP_SRCS
DlgMaterialPropertiesImp.h DlgMaterialPropertiesImp.h
DlgParameterImp.h DlgParameterImp.h
DlgParameterFind.h DlgParameterFind.h
DlgPreferencePackManagementImp.h
DlgProjectInformationImp.h DlgProjectInformationImp.h
DlgProjectUtility.h DlgProjectUtility.h
DlgPropertyLink.h DlgPropertyLink.h
@@ -499,6 +502,7 @@ SET(Dialog_SRCS
DlgMaterialProperties.ui DlgMaterialProperties.ui
DlgParameter.ui DlgParameter.ui
DlgParameterFind.ui DlgParameterFind.ui
DlgPreferencePackManagement.ui
DlgProjectInformation.ui DlgProjectInformation.ui
DlgProjectUtility.ui DlgProjectUtility.ui
DlgPropertyLink.ui DlgPropertyLink.ui

View File

@@ -44,10 +44,7 @@
#include "DlgPreferencesImp.h" #include "DlgPreferencesImp.h"
#include "DlgCreateNewPreferencePackImp.h" #include "DlgCreateNewPreferencePackImp.h"
#include "DlgPreferencePackManagementImp.h"
// Only needed until PreferencePacks can be managed from the AddonManager:
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
using namespace Gui::Dialog; using namespace Gui::Dialog;
@@ -97,19 +94,8 @@ DlgGeneralImp::DlgGeneralImp( QWidget* parent )
recreatePreferencePackMenu(); recreatePreferencePackMenu();
connect(ui->SaveNewPreferencePack, &QPushButton::clicked, this, &DlgGeneralImp::saveAsNewPreferencePack); 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 ui->ManagePreferencePacks->setToolTip(tr("Manage preference packs"));
// button will be modified to open the Add-On Manager to that tab. connect(ui->ManagePreferencePacks, &QPushButton::clicked, this, &DlgGeneralImp::onManagePreferencePacksClicked);
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)); });
} }
/** /**
@@ -353,6 +339,7 @@ void DlgGeneralImp::recreatePreferencePackMenu()
ui->PreferencePacks->setHorizontalHeaderLabels(columnHeaders); ui->PreferencePacks->setHorizontalHeaderLabels(columnHeaders);
// Populate the Preference Packs list // Populate the Preference Packs list
Application::Instance->prefPackManager()->rescan();
auto packs = Application::Instance->prefPackManager()->preferencePacks(); auto packs = Application::Instance->prefPackManager()->preferencePacks();
ui->PreferencePacks->setRowCount(packs.size()); ui->PreferencePacks->setRowCount(packs.size());
@@ -405,10 +392,19 @@ void DlgGeneralImp::newPreferencePackDialogAccepted()
}); });
auto preferencePackName = newPreferencePackDialog->preferencePackName(); auto preferencePackName = newPreferencePackDialog->preferencePackName();
Application::Instance->prefPackManager()->save(preferencePackName, selectedTemplates); Application::Instance->prefPackManager()->save(preferencePackName, selectedTemplates);
Application::Instance->prefPackManager()->rescan();
recreatePreferencePackMenu(); recreatePreferencePackMenu();
} }
void DlgGeneralImp::onManagePreferencePacksClicked()
{
if (!this->preferencePackManagementDialog) {
this->preferencePackManagementDialog = std::make_unique<DlgPreferencePackManagementImp>(this);
connect(this->preferencePackManagementDialog.get(), &DlgPreferencePackManagementImp::packVisibilityChanged,
this, &DlgGeneralImp::recreatePreferencePackMenu);
}
this->preferencePackManagementDialog->show();
}
void DlgGeneralImp::onLoadPreferencePackClicked(const std::string& packName) void DlgGeneralImp::onLoadPreferencePackClicked(const std::string& packName)
{ {
if (Application::Instance->prefPackManager()->apply(packName)) { if (Application::Instance->prefPackManager()->apply(packName)) {

View File

@@ -33,6 +33,7 @@ namespace Gui {
namespace Dialog { namespace Dialog {
class Ui_DlgGeneral; class Ui_DlgGeneral;
class DlgCreateNewPreferencePackImp; class DlgCreateNewPreferencePackImp;
class DlgPreferencePackManagementImp;
/** This class implements the settings for the application. /** This class implements the settings for the application.
* You can change window style, size of pixmaps, size of recent file list and so on * 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 onLoadPreferencePackClicked(const std::string &packName);
void recreatePreferencePackMenu(); void recreatePreferencePackMenu();
void newPreferencePackDialogAccepted(); void newPreferencePackDialogAccepted();
void onManagePreferencePacksClicked();
private: private:
void setRecentFileSize(); void setRecentFileSize();
@@ -64,6 +66,7 @@ private:
private: private:
std::unique_ptr<Ui_DlgGeneral> ui; std::unique_ptr<Ui_DlgGeneral> ui;
std::unique_ptr<DlgCreateNewPreferencePackImp> newPreferencePackDialog; std::unique_ptr<DlgCreateNewPreferencePackImp> newPreferencePackDialog;
std::unique_ptr<DlgPreferencePackManagementImp> preferencePackManagementDialog;
}; };
} // namespace Dialog } // namespace Dialog

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Gui::Dialog::DlgPreferencePackManagement</class>
<widget class="QDialog" name="Gui::Dialog::DlgPreferencePackManagement">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>392</width>
<height>255</height>
</rect>
</property>
<property name="windowTitle">
<string>Manage Preference Packs</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<property name="modal">
<bool>false</bool>
</property>
<layout class="QGridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="1" column="0">
<widget class="QTreeWidget" name="treeWidget">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<property name="columnCount">
<number>2</number>
</property>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButtonOpenAddonManager">
<property name="text">
<string>Open Addon Manager...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,225 @@
/***************************************************************************
* Copyright (c) 2022 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 *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QMessageBox>
#endif
#include "DlgPreferencePackManagementImp.h"
#include "ui_DlgPreferencePackManagement.h"
#include <PreferencePackManager.h>
#include <App/Application.h>
#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<std::string, std::vector<std::string>> 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<std::string> &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<QTreeWidgetItem*> 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<std::string> DlgPreferencePackManagementImp::getPacksFromDirectory(const fs::path& path) const
{
std::vector<std::string> 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"

View File

@@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (c) 2022 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 GUI_DIALOG_DLGPREFERENCEPACKMANAGEMENTIMP_H
#define GUI_DIALOG_DLGPREFERENCEPACKMANAGEMENTIMP_H
#include <memory>
#include <QDialog>
#include <boost/filesystem.hpp>
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_DlgPreferencePackManagement> ui;
std::vector<std::string> getPacksFromDirectory(const boost::filesystem::path& path) const;
void addTreeNode(const std::string& name, const std::vector<std::string>& contents, TreeWidgetType twt);
};
} // namespace Dialog
} // namespace Gui
#endif // GUI_DIALOG_DLGPREFERENCEPACKMANAGEMENTIMP_H

View File

@@ -149,6 +149,7 @@ PreferencePackManager::PreferencePackManager()
void PreferencePackManager::rescan() void PreferencePackManager::rescan()
{ {
std::lock_guard<std::mutex> lock(_mutex); std::lock_guard<std::mutex> lock(_mutex);
_preferencePacks.clear();
for (const auto& path : _preferencePackPaths) { for (const auto& path : _preferencePackPaths) {
if (fs::exists(path) && fs::is_directory(path)) { if (fs::exists(path) && fs::is_directory(path)) {
FindPreferencePacksInPackage(path); FindPreferencePacksInPackage(path);
@@ -164,14 +165,24 @@ void PreferencePackManager::rescan()
void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path& mod) void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path& mod)
{ {
auto packageMetadataFile = mod / "package.xml"; 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)) { if (fs::exists(packageMetadataFile) && fs::is_regular_file(packageMetadataFile)) {
try { try {
App::Metadata metadata(packageMetadataFile); App::Metadata metadata(packageMetadataFile);
auto content = metadata.content(); 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) { for (const auto& item : content) {
if (item.first == "preferencepack") { if (item.first == "preferencepack") {
PreferencePack newPreferencePack(mod / item.second.name(), item.second); if (isVisible(basename, item.second.name())) {
_preferencePacks.insert(std::make_pair(newPreferencePack.name(), newPreferencePack)); 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<App::Metadata> metadata;
if (fs::exists(savedPreferencePacksDirectory / "package.xml")) {
metadata = std::make_unique<App::Metadata>(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<ParameterGrp> templateGroup, const std::string& path, Base::Reference<ParameterGrp> outputGroup) void copyTemplateParameters(Base::Reference<ParameterGrp> templateGroup, const std::string& path, Base::Reference<ParameterGrp> outputGroup)
{ {
auto userParameterHandle = App::GetApplication().GetParameterGroupByPath(path.c_str()); auto userParameterHandle = App::GetApplication().GetParameterGroupByPath(path.c_str());

View File

@@ -94,12 +94,12 @@ namespace Gui {
void rescan(); void rescan();
/** /**
* Get an alphabetical list of names of all installed PreferencePacks * Get an alphabetical list of names of all visible PreferencePacks
*/ */
std::vector<std::string> preferencePackNames() const; std::vector<std::string> 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<std::string, PreferencePack> preferencePacks() const; std::map<std::string, PreferencePack> preferencePacks() const;
@@ -109,6 +109,25 @@ namespace Gui {
*/ */
bool apply(const std::string& preferencePackName) const; 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 * \struct TemplateFile A file containing a set of preferences that can be saved into
* a PreferencePack * a PreferencePack