Skip to content

Commit

Permalink
[GUI] Add PreferencePack support
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
chennes committed May 12, 2021
1 parent b16a537 commit fc28ce3
Show file tree
Hide file tree
Showing 29 changed files with 1,858 additions and 32 deletions.
12 changes: 12 additions & 0 deletions src/Gui/Application.cpp
Expand Up @@ -44,6 +44,7 @@
#endif

#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/filesystem.hpp>
#include <QtOpenGL.h>
#if defined(HAVE_QT5_OPENGL)
#include <QWindow>
Expand Down Expand Up @@ -72,6 +73,7 @@
#include "WidgetFactory.h"
#include "Command.h"
#include "Macro.h"
#include "PreferencePackManager.h"
#include "ProgressBar.h"
#include "Workbench.h"
#include "WorkbenchManager.h"
Expand Down Expand Up @@ -159,6 +161,9 @@ struct ApplicationP
macroMngr = new MacroManager();
else
macroMngr = nullptr;

// Create the Theme Manager
prefPackManager = new PreferencePackManager();
}

~ApplicationP()
Expand All @@ -172,6 +177,7 @@ struct ApplicationP
Gui::Document* activeDocument;
Gui::Document* editDocument;
MacroManager* macroMngr;
PreferencePackManager* prefPackManager;
/// List of all registered views
std::list<Gui::BaseView*> passive;
bool isClosing;
Expand Down Expand Up @@ -1616,6 +1622,12 @@ CommandManager &Application::commandManager(void)
return d->commandManager;
}

Gui::PreferencePackManager* Application::prefPackManager(void)
{
return d->prefPackManager;
}


//**************************************************************************
// Init, Destruct and singleton

Expand Down
3 changes: 3 additions & 0 deletions src/Gui/Application.h
Expand Up @@ -43,6 +43,7 @@ class MacroManager;
class MDIView;
class MainWindow;
class MenuItem;
class PreferencePackManager;
class ViewProvider;
class ViewProviderDocumentObject;

Expand Down Expand Up @@ -216,6 +217,8 @@ class GuiExport Application
void createStandardOperations();
//@}

Gui::PreferencePackManager* prefPackManager(void);

/** @name Init, Destruct an Access methods */
//@{
/// some kind of singelton
Expand Down
8 changes: 8 additions & 0 deletions src/Gui/CMakeLists.txt
@@ -1,5 +1,7 @@
#add_subdirectory(Icons)
add_subdirectory(Stylesheets)
add_subdirectory(PreferencePacks)
add_subdirectory(PreferencePackTemplates)

if(WIN32)
add_definitions(-DFCGui -DQIIS_MAKEDLL -DQSINT_MAKEDLL -DOVR_OS_WIN32 -DQUARTER_INTERNAL -DQUARTER_MAKE_DLL -DCOIN_DLL)
Expand Down Expand Up @@ -306,6 +308,7 @@ SET(Gui_UIC_SRCS
DlgAuthorization.ui
DlgChooseIcon.ui
DlgCommands.ui
DlgCreateNewPreferencePack.ui
DlgCustomizeSpNavSettings.ui
DlgDisplayProperties.ui
DlgEditor.ui
Expand Down Expand Up @@ -403,6 +406,7 @@ SET(Dialog_CPP_SRCS
Clipping.cpp
DemoMode.cpp
DlgActivateWindowImp.cpp
DlgCreateNewPreferencePackImp.cpp
DlgUnitsCalculatorImp.cpp
DlgDisplayPropertiesImp.cpp
DlgInputDialogImp.cpp
Expand Down Expand Up @@ -440,6 +444,7 @@ SET(Dialog_HPP_SRCS
Clipping.h
DemoMode.h
DlgActivateWindowImp.h
DlgCreateNewPreferencePackImp.h
DlgUnitsCalculatorImp.h
DlgDisplayPropertiesImp.h
DlgInputDialogImp.h
Expand Down Expand Up @@ -499,6 +504,7 @@ SET(Dialog_SRCS
DlgCheckableMessageBox.ui
DlgTreeWidget.ui
DlgExpressionInput.ui
DlgCreateNewPreferencePack.ui
DownloadManager.ui
DownloadItem.ui
DocumentRecovery.ui
Expand Down Expand Up @@ -1139,6 +1145,7 @@ SET(FreeCADGui_CPP_SRCS
resource.cpp
Control.cpp
SpaceballEvent.cpp
PreferencePackManager.cpp
Thumbnail.cpp
Utilities.cpp
WaitCursor.cpp
Expand Down Expand Up @@ -1171,6 +1178,7 @@ SET(FreeCADGui_SRCS
Qt4All.h
Control.h
SpaceballEvent.h
PreferencePackManager.h
Thumbnail.h
Utilities.h
WaitCursor.h
Expand Down
107 changes: 107 additions & 0 deletions src/Gui/DlgCreateNewPreferencePack.ui
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Gui::Dialog::DlgCreateNewPreferencePack</class>
<widget class="QDialog" name="Gui::Dialog::DlgCreateNewPreferencePack">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>580</width>
<height>520</height>
</rect>
</property>
<property name="windowTitle">
<string>Create New Preference Pack</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
</layout>
</item>
<item>
<widget class="QTreeWidget" name="treeWidget">
<attribute name="headerMinimumSectionSize">
<number>50</number>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>250</number>
</attribute>
<attribute name="headerShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string>Property group templates</string>
</property>
</column>
<column>
<property name="text">
<string>Template Type</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Gui::Dialog::DlgCreateNewPreferencePack</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Gui::Dialog::DlgCreateNewPreferencePack</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
156 changes: 156 additions & 0 deletions src/Gui/DlgCreateNewPreferencePackImp.cpp
@@ -0,0 +1,156 @@
/***************************************************************************
* 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 *
* *
***************************************************************************/


#include "PreCompiled.h"
#ifndef _PreComp_
#endif

#include "DlgCreateNewPreferencePackImp.h"
#include "ui_DlgCreateNewPreferencePack.h"

#include <QPushButton>

using namespace Gui::Dialog;

const auto TemplateRole = Qt::UserRole;

/* TRANSLATOR Gui::Dialog::DlgCreateNewPreferencePackImp */

/**
* Constructs a Gui::Dialog::DlgCreateNewPreferencePackImp as a child of 'parent'
*/
DlgCreateNewPreferencePackImp::DlgCreateNewPreferencePackImp(QWidget* parent)
: QDialog(parent)
, ui(new Ui_DlgCreateNewPreferencePack)
{
ui->setupUi(this);

QRegExp validNames(QString::fromUtf8("[^/\\\\?%*:|\"<>]+"));
_nameValidator.setRegExp(validNames);
ui->lineEdit->setValidator(&_nameValidator);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &DlgCreateNewPreferencePackImp::onItemChanged);
}


DlgCreateNewPreferencePackImp::~DlgCreateNewPreferencePackImp()
{
}

void DlgCreateNewPreferencePackImp::setPreferencePackTemplates(const std::vector<Gui::PreferencePackManager::TemplateFile>& availableTemplates)
{
ui->treeWidget->clear();
_groups.clear();

ui->treeWidget->header()->setDefaultSectionSize(250);

_templates = availableTemplates;
for (const auto &t : _templates) {

QTreeWidgetItem* group;
if (auto foundGroup = _groups.find(t.group); foundGroup != _groups.end()) {
group = foundGroup->second;
}
else {
group = new QTreeWidgetItem(ui->treeWidget, QStringList(QString::fromStdString(t.group)));
group->setCheckState(0, Qt::Checked);
group->setExpanded(true);
_groups.insert(std::make_pair(t.group, group));
}

QStringList itemColumns;
itemColumns.push_back(QString::fromStdString(t.name));
switch (t.type) {
case Gui::PreferencePack::Type::Appearance: itemColumns.push_back(tr("Appearance")); break;
case Gui::PreferencePack::Type::Behavior: itemColumns.push_back(tr("Behavior")); break;
case Gui::PreferencePack::Type::Combination: itemColumns.push_back(tr("Combination")); break;
}
auto newItem = new QTreeWidgetItem(group, itemColumns);
newItem->setCheckState(0, Qt::Checked);
if (group->checkState(0) != newItem->checkState(0))
group->setCheckState(0, Qt::PartiallyChecked);
newItem->setData(0, TemplateRole, QVariant::fromValue(t));
group->addChild(newItem);
}
}

std::vector<Gui::PreferencePackManager::TemplateFile> DlgCreateNewPreferencePackImp::selectedTemplates() const
{
std::vector<Gui::PreferencePackManager::TemplateFile> results;

for (const auto& group : _groups)
for (int childIndex = 0; childIndex < group.second->childCount(); ++childIndex)
if (auto child = group.second->child(childIndex); child->checkState(0) == Qt::Checked)
if (child->data(0, TemplateRole).canConvert<Gui::PreferencePackManager::TemplateFile>())
results.push_back(child->data(0, TemplateRole).value<Gui::PreferencePackManager::TemplateFile>());

return results;
}

std::string DlgCreateNewPreferencePackImp::preferencePackName() const
{
return ui->lineEdit->text().toStdString();
}

void DlgCreateNewPreferencePackImp::onItemChanged(QTreeWidgetItem* item, int column)
{
Q_UNUSED(column);
const QSignalBlocker blocker(ui->treeWidget);
if (auto group = item->parent(); group) {
// Child clicked
bool firstItemChecked = false;
for (int childIndex = 0; childIndex < group->childCount(); ++childIndex) {
auto child = group->child(childIndex);
if (childIndex == 0) {
firstItemChecked = child->checkState(0) == Qt::Checked;
}
else {
bool thisItemChecked = child->checkState(0) == Qt::Checked;
if (firstItemChecked != thisItemChecked) {
group->setCheckState(0, Qt::PartiallyChecked);
return;
}
}
}
group->setCheckState(0, firstItemChecked ? Qt::Checked : Qt::Unchecked);
}
else {
// Group clicked:
auto groupCheckState = item->checkState(0);
for (int childIndex = 0; childIndex < item->childCount(); ++childIndex) {
auto child = item->child(childIndex);
child->setCheckState(0, groupCheckState);
}
}
}

void DlgCreateNewPreferencePackImp::on_lineEdit_textEdited(const QString& text)
{
if (!text.isEmpty())
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
else
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}


#include "moc_DlgCreateNewPreferencePackImp.cpp"

0 comments on commit fc28ce3

Please sign in to comment.