Gui: Add interface for managing preference packs
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -44,10 +44,7 @@
|
||||
#include "DlgPreferencesImp.h"
|
||||
|
||||
#include "DlgCreateNewPreferencePackImp.h"
|
||||
|
||||
// Only needed until PreferencePacks can be managed from the AddonManager:
|
||||
#include <boost/filesystem.hpp>
|
||||
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<DlgPreferencePackManagementImp>(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)) {
|
||||
|
||||
@@ -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_DlgGeneral> ui;
|
||||
std::unique_ptr<DlgCreateNewPreferencePackImp> newPreferencePackDialog;
|
||||
std::unique_ptr<DlgPreferencePackManagementImp> preferencePackManagementDialog;
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
|
||||
105
src/Gui/DlgPreferencePackManagement.ui
Normal file
105
src/Gui/DlgPreferencePackManagement.ui
Normal 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>
|
||||
225
src/Gui/DlgPreferencePackManagementImp.cpp
Normal file
225
src/Gui/DlgPreferencePackManagementImp.cpp
Normal 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"
|
||||
86
src/Gui/DlgPreferencePackManagementImp.h
Normal file
86
src/Gui/DlgPreferencePackManagementImp.h
Normal 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
|
||||
@@ -149,6 +149,7 @@ PreferencePackManager::PreferencePackManager()
|
||||
void PreferencePackManager::rescan()
|
||||
{
|
||||
std::lock_guard<std::mutex> 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<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)
|
||||
{
|
||||
auto userParameterHandle = App::GetApplication().GetParameterGroupByPath(path.c_str());
|
||||
|
||||
@@ -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<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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user