add (variadic) templates to replace (non-strict ISO C++11 compliant) macros
This commit is contained in:
@@ -499,6 +499,7 @@ SET(Command_SRCS
|
||||
Action.h
|
||||
ActionFunction.h
|
||||
Command.h
|
||||
CommandT.h
|
||||
)
|
||||
SOURCE_GROUP("Command" FILES ${Command_SRCS})
|
||||
|
||||
|
||||
335
src/Gui/CommandT.h
Normal file
335
src/Gui/CommandT.h
Normal file
@@ -0,0 +1,335 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2019 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* 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_COMMAND_T_H
|
||||
#define GUI_COMMAND_T_H
|
||||
|
||||
#include <Base/Exception.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class FormatString
|
||||
{
|
||||
public:
|
||||
static std::string str(const std::string& s) {
|
||||
return s;
|
||||
}
|
||||
static std::string str(const std::stringstream& s) {
|
||||
return s.str();
|
||||
}
|
||||
static std::string str(const std::ostream& s) {
|
||||
return dynamic_cast<const std::ostringstream&>(s).str();
|
||||
}
|
||||
static std::string toStr(boost::format& f) {
|
||||
return f.str();
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static std::string toStr(boost::format& f, T&& t, Args&&... args) {
|
||||
return toStr(f % std::forward<T>(t), std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
/** @defgroup CommandFuncs Helper functions for running commands through Python interpreter */
|
||||
//@{
|
||||
|
||||
/** Runs a command for accessing document attribute or method
|
||||
* @param doc: pointer to a document
|
||||
* @param mod: module name, "Gui" or "App"
|
||||
* @param cmd: command string, streamable
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* _cmdDocument(Gui::Command::Gui, doc, "Gui", std::stringstream() << "getObject('" << objName << "')");
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming doc's name is 'DocName', and
|
||||
* and objName contains value 'ObjName'):
|
||||
* @code{.py}
|
||||
* Gui.getDocument('DocName').getObject('ObjName')
|
||||
* @endcode
|
||||
*/
|
||||
template<typename T>
|
||||
void _cmdDocument(Gui::Command::DoCmd_Type cmdType, App::Document* doc, const std::string& mod, T&& cmd) {
|
||||
if (doc && doc->getName()) {
|
||||
std::stringstream str;
|
||||
str << mod << ".getDocument('" << doc->getName() << "')."
|
||||
<< FormatString::str(cmd);
|
||||
Gui::Command::runCommand(cmdType, str.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a command for accessing App.Document attribute or method
|
||||
*
|
||||
* @param doc: pointer to a document
|
||||
* @param cmd: command string, streamable
|
||||
* @sa _cmdDocument()
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* cmdAppDocument(doc, std::stringstream() << "getObject('" << objName << "')");
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming doc's name is 'DocName', and
|
||||
* and objName contains value 'ObjName'):
|
||||
* @code{.py}
|
||||
* App.getDocument('DocName').getObject('ObjName')
|
||||
* @endcode
|
||||
*/
|
||||
template<typename T>
|
||||
inline void cmdAppDocument(App::Document* doc, T&& cmd) {
|
||||
_cmdDocument(Gui::Command::Doc, doc, "App", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing App.Document attribute or method
|
||||
*
|
||||
* @param doc: pointer to a document
|
||||
* @param cmd: command string, streamable
|
||||
* @sa _cmdDocument()
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* cmdGuiDocument(doc, std::stringstream() << "getObject('" << objName << "')");
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming doc's name is 'DocName', and
|
||||
* and objName contains value 'ObjName'):
|
||||
* @code{.py}
|
||||
* Gui.getDocument('DocName').getObject('ObjName')
|
||||
* @endcode
|
||||
*/
|
||||
template<typename T>
|
||||
inline void cmdGuiDocument(App::Document* doc, T&& cmd) {
|
||||
_cmdDocument(Gui::Command::Gui, doc, "Gui", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing an object's document attribute or method
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @param mod: module name, "Gui" or "App"
|
||||
* @param cmd: command string, streamable
|
||||
*/
|
||||
template<typename T>
|
||||
inline void _cmdDocument(Gui::Command::DoCmd_Type cmdType, App::DocumentObject* obj, const std::string& mod, T&& cmd) {
|
||||
if (obj) _cmdDocument(cmdType, obj->getDocument(), mod, std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing an object's App::Document attribute or method
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @param cmd: command string, streamable
|
||||
*/
|
||||
template<typename T>
|
||||
inline void cmdAppDocument(App::DocumentObject* obj, T&& cmd) {
|
||||
_cmdDocument(Gui::Command::Doc, obj, "App", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing an object's Gui::Document attribute or method
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @param cmd: command string, streamable
|
||||
*/
|
||||
template<typename T>
|
||||
inline void cmdGuiDocument(App::DocumentObject* obj, T&& cmd) {
|
||||
_cmdDocument(Gui::Command::Gui, obj, "Gui", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing a document/view object's attribute or method
|
||||
* @param cmdType: Command type
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @param mod: module name, "Gui" or "App"
|
||||
* @param cmd: command string, streamable
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* _cmdObject(Command::Gui,obj,"Gui", "Visibility = " << (visible?"True":"False"));
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming obj's document name is 'DocName', obj's name
|
||||
* is 'ObjName', and visible is true):
|
||||
* @code{.py}
|
||||
* Gui.getDocument('DocName').getObject('ObjName').Visibility = True
|
||||
* @endcode
|
||||
*/
|
||||
template<typename T>
|
||||
void _cmdObject(Gui::Command::DoCmd_Type cmdType, App::DocumentObject* obj, const std::string& mod, T&& cmd) {
|
||||
if (obj && obj->getNameInDocument()) {
|
||||
std::ostringstream str;
|
||||
str << mod << ".getDocument('" << obj->getDocument()->getName() << "')"
|
||||
".getObject('" << obj->getNameInDocument() << "')."
|
||||
<< FormatString::str(cmd);
|
||||
Gui::Command::runCommand(cmdType, str.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a command for accessing an document object's attribute or method
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @param cmd: command string, streamable
|
||||
* @sa _cmdObject()
|
||||
*/
|
||||
template<typename T>
|
||||
inline void cmdAppObject(App::DocumentObject* obj, T&& cmd) {
|
||||
_cmdObject(Gui::Command::Doc, obj, "App", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/** Runs a command for accessing an view object's attribute or method
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @param cmd: command string, streamable
|
||||
* @sa _cmdObject()
|
||||
*/
|
||||
template<typename T>
|
||||
inline void cmdGuiObject(App::DocumentObject* obj, T&& cmd) {
|
||||
_cmdObject(Gui::Command::Gui, obj, "Gui", std::forward<T>(cmd));
|
||||
}
|
||||
|
||||
/// Hides an object
|
||||
inline void cmdAppObjectHide(App::DocumentObject* obj) {
|
||||
cmdAppObject(obj, "Visibility = False");
|
||||
}
|
||||
|
||||
/// Shows an object
|
||||
inline void cmdAppObjectShow(App::DocumentObject* obj) {
|
||||
cmdAppObject(obj, "Visibility = True");
|
||||
}
|
||||
|
||||
/** Runs a command to start editing a give object
|
||||
* @param obj: pointer to a DocumentObject
|
||||
*
|
||||
* Unlike other helper functions, this one editing the object using the current
|
||||
* active document, instead of the object's owner document. This allows
|
||||
* in-place editing an object, which may be brought in through linking to an
|
||||
* external group.
|
||||
*/
|
||||
inline void cmdSetEdit(App::DocumentObject* obj) {
|
||||
if (obj && obj->getNameInDocument()) {
|
||||
Gui::Command::doCommand(Gui::Command::Gui,
|
||||
"Gui.ActiveDocument.setEdit(App.getDocument('%s').getObject('%s'))",
|
||||
obj->getDocument()->getName(), obj->getNameInDocument());
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a command for accessing a document object's attribute or method
|
||||
* @param cmd: command string, supporting printf like formatter
|
||||
* @param obj: pointer to a DocumentObject
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* cmdAppObjectArgs(obj, "Visibility = %s", visible ? "True" : "False");
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming obj's document name is 'DocName', obj's name
|
||||
* is 'ObjName', and visible is true):
|
||||
* @code{.py}
|
||||
* App.getDocument('DocName').getObject('ObjName').Visibility = True
|
||||
* @endcode
|
||||
*/
|
||||
template<typename...Args>
|
||||
void cmdAppObjectArgs(App::DocumentObject* obj, const std::string& cmd, Args&&... args) {
|
||||
std::string _cmd;
|
||||
try {
|
||||
boost::format fmt(cmd);
|
||||
_cmd = FormatString::toStr(fmt, std::forward<Args>(args)...);
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.getDocument('%s').getObject('%s').%s",
|
||||
obj->getDocument()->getName(), obj->getNameInDocument(), _cmd.c_str());
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
Base::Console().Error("%s: %s\n", e.what(), cmd.c_str());
|
||||
}
|
||||
catch (const Base::Exception&) {
|
||||
Base::Console().Error("App.getDocument('%s').getObject('%s').%s\n",
|
||||
obj->getDocument()->getName(), obj->getNameInDocument(), _cmd.c_str());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a command for accessing a view object's attribute or method
|
||||
* @param cmd: command string, supporting printf like formatter
|
||||
* @param obj: pointer to a DocumentObject
|
||||
* @sa cmdObject()
|
||||
*/
|
||||
template<typename...Args>
|
||||
void cmdGuiObjectArgs(App::DocumentObject* obj, const std::string& cmd, Args&&... args) {
|
||||
std::string _cmd;
|
||||
try {
|
||||
boost::format fmt(cmd);
|
||||
_cmd = FormatString::toStr(fmt, std::forward<Args>(args)...);
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"Gui.getDocument('%s').getObject('%s').%s",
|
||||
obj->getDocument()->getName(), obj->getNameInDocument(), _cmd.c_str());
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
Base::Console().Error("%s: %s\n", e.what(), cmd.c_str());
|
||||
}
|
||||
catch (const Base::Exception&) {
|
||||
Base::Console().Error("Gui.getDocument('%s').getObject('%s').%s\n",
|
||||
obj->getDocument()->getName(), obj->getNameInDocument(), _cmd.c_str());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs a command
|
||||
* @param cmdType: command type
|
||||
* @param cmd: command string, supporting printf like formatter
|
||||
*
|
||||
* Example:
|
||||
* @code{.cpp}
|
||||
* doCommandT(Gui::Command::Gui, "Gui.getDocument(%s).getObject(%s).Visibility = %s", "DocName", "ObjName", visible?"True":"False");
|
||||
* @endcode
|
||||
*
|
||||
* Translates to command (assuming obj's document name is 'DocName', obj's name
|
||||
* is 'ObjName', and visible is true):
|
||||
* @code{.py}
|
||||
* Gui.getDocument('DocName').getObject('ObjName').Visibility = True
|
||||
* @endcode
|
||||
*/
|
||||
template<typename...Args>
|
||||
void doCommandT(Gui::Command::DoCmd_Type cmdType, const std::string& cmd, Args&&... args) {
|
||||
std::string _cmd;
|
||||
try {
|
||||
boost::format fmt(cmd);
|
||||
_cmd = FormatString::toStr(fmt, std::forward<Args>(args)...);
|
||||
Gui::Command::doCommand(cmdType,"%s", _cmd.c_str());
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
Base::Console().Error("%s: %s\n", e.what(), cmd.c_str());
|
||||
}
|
||||
catch (const Base::Exception&) {
|
||||
Base::Console().Error("%s\n", _cmd.c_str());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy visual attributes from a source to a target object
|
||||
*/
|
||||
template<typename...Args>
|
||||
void copyVisualT(Args&&... args) {
|
||||
// file and line number is useless here. Check C++'s source location function once available
|
||||
Gui::Command::_copyVisual(__FILE__, __LINE__, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
};
|
||||
|
||||
#endif // GUI_COMMAND_T_H
|
||||
|
||||
Reference in New Issue
Block a user