Skip to content

Commit

Permalink
Gui: expose various overlay UI options to preference pages
Browse files Browse the repository at this point in the history
  • Loading branch information
realthunder committed Oct 2, 2023
1 parent 2745e26 commit 2c6acc0
Show file tree
Hide file tree
Showing 12 changed files with 1,418 additions and 78 deletions.
8 changes: 6 additions & 2 deletions src/Gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ SET(Dialog_Settings_CPP_SRCS
PreferencePages/DlgSettingsTheme.cpp
PreferencePages/DlgSettingsViewColor.cpp
PreferencePages/DlgSettingsWorkbenchesImp.cpp
PreferencePages/DlgSettingsUI.cpp
)
SET(Dialog_Settings_HPP_SRCS
DlgOnlineHelpImp.h
Expand All @@ -594,6 +595,7 @@ SET(Dialog_Settings_HPP_SRCS
PreferencePages/DlgSettingsTheme.h
PreferencePages/DlgSettingsViewColor.h
PreferencePages/DlgSettingsWorkbenchesImp.h
PreferencePages/DlgSettingsUI.h
)
SET(Dialog_Settings_SRCS
${Dialog_Settings_CPP_SRCS}
Expand Down Expand Up @@ -1035,7 +1037,6 @@ SET(Widget_CPP_SRCS
WidgetFactory.cpp
Widgets.cpp
Window.cpp
ViewParams.cpp
)
SET(Widget_HPP_SRCS
FileDialog.h
Expand All @@ -1056,7 +1057,6 @@ SET(Widget_HPP_SRCS
WidgetFactory.h
Widgets.h
Window.h
ViewParams.h
)
SET(Widget_SRCS
${Widget_CPP_SRCS}
Expand All @@ -1067,11 +1067,15 @@ SOURCE_GROUP("Widget" FILES ${Widget_SRCS})
SET(Params_CPP_SRCS
TreeParams.cpp
OverlayParams.cpp
ParamHandler.cpp
ViewParams.cpp
)

SET(Params_HPP_SRCS
TreeParams.h
OverlayParams.h
ParamHandler.cpp
ViewParams.h
)

SET(Params_SRCS
Expand Down
61 changes: 61 additions & 0 deletions src/Gui/ParamHandler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/****************************************************************************
* Copyright (c) 2023 Zheng Lei (realthunder) <[email protected]> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/

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

#include "ParamHandler.h"

using namespace Gui;

ParamHandlers::ParamHandlers()
{
}

ParamHandlers::~ParamHandlers()
{
}

void ParamHandlers::addHandler(const ParamKey &key, const std::shared_ptr<ParamHandler> &handler)
{
if (handlers.empty()) {
conn = App::GetApplication().GetUserParameter().signalParamChanged.connect(
[this](ParameterGrp *Param, ParameterGrp::ParamType, const char *Name, const char *) {
if (!Param || !Name)
return;
auto it = handlers.find(ParamKey(Param, Name));
if (it != handlers.end() && it->second->onChange(&it->first)) {
pendings.insert(it->second);
timer.start(100);
}
});

timer.setSingleShot(true);
QObject::connect(&timer, &QTimer::timeout, [this]() {
for (const auto &v : pendings) {
v->onTimer();
}
pendings.clear();
});
}
handlers[key] = handler;
}
231 changes: 231 additions & 0 deletions src/Gui/ParamHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/****************************************************************************
* Copyright (c) 2023 Zheng Lei (realthunder) <[email protected]> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/

#ifndef GUI_PARAM_HANDLER_H
#define GUI_PARAM_HANDLER_H

#include <map>
#include <memory>
#include <boost_signals2.hpp>
#include <QTimer>

#include <FCGlobal.h>
#include <App/Application.h>
#include <Base/Parameter.h>

namespace Gui {

/// Structure for storing a parameter key and its path to be used in std::map
struct GuiExport ParamKey {
ParameterGrp::handle hGrp;
const char *key;

ParamKey(const char *path, const char *key)
:hGrp(App::GetApplication().GetUserParameter().GetGroup(path))
,key(key)
{}

ParamKey(ParameterGrp *h, const char *key)
:hGrp(h), key(key)
{}

bool operator < (const ParamKey &other) const {
if (hGrp < other.hGrp)
return true;
if (hGrp > other.hGrp)
return false;
return strcmp(key, other.key) < 0;
}
};

/// Helper class to handle parameter change
class GuiExport ParamHandler {
public:
virtual ~ParamHandler() {}

/** Called when the corresponding parameter key changes
* @param key: the parameter key
* @return Returns true if the handler needs to be delay triggered by a timer
*/
virtual bool onChange(const ParamKey *key) = 0;
/// Called in delay triggered
virtual void onTimer() {}
};

/// Template class for a non-delayed parameter handler
template<class Func>
class ParamHandlerT : public ParamHandler
{
public:
ParamHandlerT(Func f)
:func(f)
{}

bool onChange(const ParamKey *key) override {
func(key);
return false;
}

private:
Func func;
};

/// Template class for a delayed parameter handler
template<class Func>
class ParamDelayedHandlerT : public ParamHandler
{
public:
ParamDelayedHandlerT(Func f)
:func(f)
{}

bool onChange(const ParamKey *) override {
return true;
}

void onTimer() override {
func();
}

private:
Func func;
};

// Helper class to manage handlers of a list of parameters.
//
// The handlers are stored in a map from ParamKey to shared pointer to a
// ParamHandler. The same handler can be registered with multiple keys. When
// the registered parameter key is changed, the manager will call the
// registered handler function ParamHandler::onChange(). If it returns True,
// then the handler will be appended to a queue to be invoked later by a timer
// to avoid repeatitive processing on change of multiple keys.
//
// The handler manager is meant to be initiated by some static function, e.g.
// DlgSettingsGeneral::attachObserver(). It is intended to be one and only
// place of handling changes of the given set of parameters, regardless of
// whether the changes are coming from direct editing through parameter editor,
// user code changing of parameters, changing preference dialog, or loading a
// preference pack.
//
class GuiExport ParamHandlers {
public:
ParamHandlers();
virtual ~ParamHandlers();

void addHandler(const ParamKey &key, const std::shared_ptr<ParamHandler> &handler);

void addHandler(const char *path, const char *key, const std::shared_ptr<ParamHandler> &handler) {
addHandler(ParamKey(path, key), handler);
}

void addHandler(ParameterGrp *hGrp, const char *key, const std::shared_ptr<ParamHandler> &handler) {
addHandler(ParamKey(hGrp, key), handler);
}

void addHandler(const std::vector<ParamKey> &keys, const std::shared_ptr<ParamHandler> &handler) {
for (const auto &key : keys)
addHandler(key, handler);
}

void addHandler(const char *path, const std::vector<const char*> &keys, const std::shared_ptr<ParamHandler> &handler) {
for (const auto &key : keys)
addHandler(path, key, handler);
}

void addHandler(ParameterGrp *hGrp, const std::vector<const char*> &keys, const std::shared_ptr<ParamHandler> &handler) {
for (const auto &key : keys)
addHandler(hGrp, key, handler);
}

template<class Func>
std::shared_ptr<ParamHandler> addHandler(const char *path, const char *key, Func func) {
std::shared_ptr<ParamHandler> handler(new ParamHandlerT<Func>(func));
addHandler(path, key, handler);
return handler;
}

template<class Func>
std::shared_ptr<ParamHandler> addHandler(ParameterGrp *hGrp, const char *key, Func func) {
std::shared_ptr<ParamHandler> handler(new ParamHandlerT<Func>(func));
addHandler(hGrp, key, handler);
return handler;
}

template<class Func>
std::shared_ptr<ParamHandler> addDelayedHandler(const char *path, const char *key, Func func) {
auto hGrp = App::GetApplication().GetUserParameter().GetGroup(path);
auto wrap = [hGrp, func]() {
func(hGrp);
};
std::shared_ptr<ParamHandler> handler(new ParamDelayedHandlerT<decltype(wrap)>(wrap));
addHandler(hGrp, key, handler);
return handler;
}

template<class Func>
std::shared_ptr<ParamHandler> addDelayedHandler(ParameterGrp *hGrp, const char *key, Func func) {
auto wrap = [hGrp, func]() {
func(hGrp);
};
std::shared_ptr<ParamHandler> handler(new ParamDelayedHandlerT<decltype(wrap)>(wrap));
addHandler(hGrp, key, handler);
return handler;
}

template<class Func>
std::shared_ptr<ParamHandler> addDelayedHandler(const char *path,
const std::vector<const char *> &keys,
Func func)
{
auto hGrp = App::GetApplication().GetUserParameter().GetGroup(path);
auto wrap = [hGrp, func]() {
func(hGrp);
};
std::shared_ptr<ParamHandler> handler(new ParamDelayedHandlerT<decltype(wrap)>(wrap));
for (const auto &key : keys)
addHandler(ParamKey(hGrp, key), handler);
return handler;
}

template<class Func>
std::shared_ptr<ParamHandler> addDelayedHandler(ParameterGrp::handle hGrp,
const std::vector<const char *> &keys,
Func func)
{
auto wrap = [hGrp, func]() {
func(hGrp);
};
std::shared_ptr<ParamHandler> handler(new ParamDelayedHandlerT<decltype(wrap)>(wrap));
for (const auto &key : keys)
addHandler(ParamKey(hGrp, key), handler);
return handler;
}

protected:
std::map<ParamKey, std::shared_ptr<ParamHandler>> handlers;
std::set<std::shared_ptr<ParamHandler>> pendings;
boost::signals2::scoped_connection conn;
QTimer timer;
};

} // namespace Gui

#endif // GUI_PARAM_HANDLER_H
33 changes: 33 additions & 0 deletions src/Gui/PreferencePages/DlgSettingsGeneral.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,15 @@
#include <Gui/DlgPreferencePackManagementImp.h>
#include <Gui/DlgRevertToBackupConfigImp.h>
#include <Gui/MainWindow.h>
#include <Gui/OverlayManager.h>
#include <Gui/ParamHandler.h>
#include <Gui/PreferencePackManager.h>
#include <Gui/Language/Translator.h>

#include "DlgSettingsGeneral.h"
#include "ui_DlgSettingsGeneral.h"

using namespace Gui;
using namespace Gui::Dialog;
namespace fs = boost::filesystem;
using namespace Base;
Expand Down Expand Up @@ -605,4 +608,34 @@ void DlgSettingsGeneral::onThemeChanged(int index) {
themeChanged = true;
}

///////////////////////////////////////////////////////////
namespace {

class ApplyDockWidget: public ParamHandler {
public:
bool onChange(const ParamKey *) override {
OverlayManager::instance()->reload(OverlayManager::ReloadMode::ReloadPause);
return true;
}

void onTimer() override {
getMainWindow()->initDockWindows(true);
OverlayManager::instance()->reload(OverlayManager::ReloadMode::ReloadResume);
}
};

} // anonymous namespace

void DlgSettingsGeneral::attachObserver()
{
static ParamHandlers handlers;

auto hDockWindows = App::GetApplication().GetUserParameter().GetGroup("BaseApp/Preferences/DockWindows");
auto applyDockWidget = std::shared_ptr<ParamHandler>(new ApplyDockWidget);
handlers.addHandler(ParamKey(hDockWindows->GetGroup("ComboView"), "Enabled"), applyDockWidget);
handlers.addHandler(ParamKey(hDockWindows->GetGroup("TreeView"), "Enabled"), applyDockWidget);
handlers.addHandler(ParamKey(hDockWindows->GetGroup("PropertyView"), "Enabled"), applyDockWidget);
handlers.addHandler(ParamKey(hDockWindows->GetGroup("DAGView"), "Enabled"), applyDockWidget);
}

#include "moc_DlgSettingsGeneral.cpp"
Loading

0 comments on commit 2c6acc0

Please sign in to comment.