forked from FreeCAD/FreeCAD
-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Gui: expose various overlay UI options to preference pages
- Loading branch information
1 parent
2745e26
commit 2c6acc0
Showing
12 changed files
with
1,418 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.