962 lines
29 KiB
C++
962 lines
29 KiB
C++
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
/***************************************************************************
|
|
* Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Library General Public License (LGPL) *
|
|
* as published by the Free Software Foundation; either version 2 of *
|
|
* the License, or (at your option) any later version. *
|
|
* for detail see the LICENCE text file. *
|
|
* *
|
|
* 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 Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with FreeCAD; if not, write to the Free Software *
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
* USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <FCConfig.h>
|
|
|
|
#ifdef FC_OS_WIN32
|
|
# include <xercesc/sax/SAXParseException.hpp>
|
|
#endif
|
|
#include <list>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#ifdef FC_OS_LINUX
|
|
# include <unistd.h>
|
|
#endif
|
|
|
|
#include "Parameter.h"
|
|
#include "Exception.h"
|
|
#include "Interpreter.h"
|
|
|
|
#include <Tools.h>
|
|
|
|
|
|
namespace Base
|
|
{
|
|
|
|
class ParameterGrpObserver: public ParameterGrp::ObserverType // NOLINT
|
|
{
|
|
public:
|
|
explicit ParameterGrpObserver(const Py::Object& obj)
|
|
: inst {obj}
|
|
{}
|
|
ParameterGrpObserver(const Py::Object& obj, const Py::Object& callable, ParameterGrp* target)
|
|
: callable(callable)
|
|
, _target(target)
|
|
, inst(obj)
|
|
{}
|
|
~ParameterGrpObserver() override
|
|
{
|
|
Base::PyGILStateLocker lock;
|
|
inst = Py::None();
|
|
callable = Py::None();
|
|
}
|
|
void OnChange(ParameterGrp::SubjectType& rCaller, ParameterGrp::MessageType Reason) override
|
|
{
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
auto& rGrp = dynamic_cast<ParameterGrp&>(rCaller);
|
|
ParameterGrp::handle hGrp(&rGrp);
|
|
Py::Callable method(this->inst.getAttr(std::string("onChange")));
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::asObject(GetPyObject(hGrp)));
|
|
// A Reason of null indicates to clear the parameter group
|
|
if (!Base::Tools::isNullOrEmpty(Reason)) {
|
|
args.setItem(1, Py::String(Reason));
|
|
}
|
|
method.apply(args);
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
bool isEqual(const Py::Object& obj) const
|
|
{
|
|
return this->inst.is(obj);
|
|
}
|
|
|
|
public:
|
|
// NOLINTBEGIN
|
|
Py::Object callable;
|
|
fastsignals::scoped_connection conn;
|
|
ParameterGrp* _target = nullptr; // no reference counted, do not access
|
|
// NOLINTEND
|
|
|
|
private:
|
|
Py::Object inst;
|
|
};
|
|
|
|
using ParameterGrpObserverList = std::list<ParameterGrpObserver*>;
|
|
|
|
class ParameterGrpPy: public Py::PythonExtension<ParameterGrpPy> // NOLINT
|
|
{
|
|
public:
|
|
static void init_type(); // announce properties and methods
|
|
|
|
explicit ParameterGrpPy(const Base::Reference<ParameterGrp>& rcParamGrp);
|
|
~ParameterGrpPy() override;
|
|
|
|
Py::Object repr() override;
|
|
|
|
// NOLINTBEGIN
|
|
Py::Object getGroup(const Py::Tuple&);
|
|
Py::Object getGroupName(const Py::Tuple&);
|
|
Py::Object getGroups(const Py::Tuple&);
|
|
Py::Object remGroup(const Py::Tuple&);
|
|
Py::Object hasGroup(const Py::Tuple&);
|
|
Py::Object renameGroup(const Py::Tuple&);
|
|
Py::Object copyTo(const Py::Tuple&);
|
|
|
|
Py::Object getManager(const Py::Tuple&);
|
|
Py::Object getParent(const Py::Tuple&);
|
|
|
|
Py::Object isEmpty(const Py::Tuple&);
|
|
Py::Object clear(const Py::Tuple&);
|
|
|
|
Py::Object attach(const Py::Tuple&);
|
|
Py::Object attachManager(const Py::Tuple& args);
|
|
Py::Object detach(const Py::Tuple&);
|
|
Py::Object notify(const Py::Tuple&);
|
|
Py::Object notifyAll(const Py::Tuple&);
|
|
|
|
Py::Object setBool(const Py::Tuple&);
|
|
Py::Object getBool(const Py::Tuple&);
|
|
Py::Object getBools(const Py::Tuple&);
|
|
Py::Object remBool(const Py::Tuple&);
|
|
|
|
Py::Object setInt(const Py::Tuple&);
|
|
Py::Object getInt(const Py::Tuple&);
|
|
Py::Object getInts(const Py::Tuple&);
|
|
Py::Object remInt(const Py::Tuple&);
|
|
|
|
Py::Object setUnsigned(const Py::Tuple&);
|
|
Py::Object getUnsigned(const Py::Tuple&);
|
|
Py::Object getUnsigneds(const Py::Tuple&);
|
|
Py::Object remUnsigned(const Py::Tuple&);
|
|
|
|
Py::Object setFloat(const Py::Tuple&);
|
|
Py::Object getFloat(const Py::Tuple&);
|
|
Py::Object getFloats(const Py::Tuple&);
|
|
Py::Object remFloat(const Py::Tuple&);
|
|
|
|
Py::Object setString(const Py::Tuple&);
|
|
Py::Object getString(const Py::Tuple&);
|
|
Py::Object getStrings(const Py::Tuple&);
|
|
Py::Object remString(const Py::Tuple&);
|
|
|
|
Py::Object importFrom(const Py::Tuple&);
|
|
Py::Object insert(const Py::Tuple&);
|
|
Py::Object exportTo(const Py::Tuple&);
|
|
|
|
Py::Object getContents(const Py::Tuple&);
|
|
// NOLINTEND
|
|
|
|
private:
|
|
void tryCall(
|
|
ParameterGrpObserver* obs,
|
|
ParameterGrp* Param,
|
|
ParameterGrp::ParamType Type,
|
|
const char* Name,
|
|
const char* Value
|
|
);
|
|
|
|
private:
|
|
ParameterGrp::handle _cParamGrp;
|
|
ParameterGrpObserverList _observers;
|
|
};
|
|
|
|
// ---------------------------------------------------------
|
|
|
|
void ParameterGrpPy::init_type()
|
|
{
|
|
behaviors().name("ParameterGrp");
|
|
behaviors().doc("Python interface class to set parameters");
|
|
// you must have overwritten the virtual functions
|
|
behaviors().supportRepr();
|
|
behaviors().supportGetattr();
|
|
behaviors().supportSetattr();
|
|
behaviors().readyType();
|
|
|
|
add_varargs_method("GetGroup", &ParameterGrpPy::getGroup, "GetGroup(str)");
|
|
add_varargs_method("GetGroupName", &ParameterGrpPy::getGroupName, "GetGroupName()");
|
|
add_varargs_method("GetGroups", &ParameterGrpPy::getGroups, "GetGroups()");
|
|
add_varargs_method("RemGroup", &ParameterGrpPy::remGroup, "RemGroup(str)");
|
|
add_varargs_method("HasGroup", &ParameterGrpPy::hasGroup, "HasGroup(str)");
|
|
add_varargs_method("RenameGroup", &ParameterGrpPy::renameGroup, "RenameGroup(str, str)");
|
|
add_varargs_method("CopyTo", &ParameterGrpPy::copyTo, "copyTo(ParameterGrp)");
|
|
|
|
add_varargs_method("Manager", &ParameterGrpPy::getManager, "Manager()");
|
|
add_varargs_method("Parent", &ParameterGrpPy::getParent, "Parent()");
|
|
|
|
add_varargs_method("IsEmpty", &ParameterGrpPy::isEmpty, "IsEmpty()");
|
|
add_varargs_method("Clear", &ParameterGrpPy::clear, "Clear()");
|
|
|
|
add_varargs_method("Attach", &ParameterGrpPy::attach, "Attach()");
|
|
add_varargs_method(
|
|
"AttachManager",
|
|
&ParameterGrpPy::attachManager,
|
|
"AttachManager(observer) -- attach parameter manager for notification\n\n"
|
|
"This method attaches a user defined observer to the manager (i.e. the root)\n"
|
|
"of the current parameter group to receive notification of all its parameters\n"
|
|
"and those from its sub-groups\n\n"
|
|
"The method expects the observer to have a callable attribute as shown below\n"
|
|
" slotParamChanged(param, tp, name, value)\n"
|
|
"where 'param' is the parameter group causing the change, 'tp' is the type of\n"
|
|
"the parameter, 'name' is the name of the parameter, and 'value' is the current\n"
|
|
"value.\n\n"
|
|
"The possible value of type are, 'FCBool', 'FCInt', 'FCUint', 'FCFloat', 'FCText',\n"
|
|
"and 'FCParamGroup'. The notification is triggered when value is changed, in which\n"
|
|
"case 'value' contains the new value in text form, or, when the parameter is removed,\n"
|
|
"in which case 'value' is empty.\n\n"
|
|
"For 'FCParamGroup' type, the observer will be notified in the following events.\n"
|
|
"* Group creation: both 'name' and 'value' contain the name of the new group\n"
|
|
"* Group removal: both 'name' and 'value' are empty\n"
|
|
"* Group rename: 'name' is the new name, and 'value' is the old name"
|
|
);
|
|
add_varargs_method("Detach", &ParameterGrpPy::detach, "Detach()");
|
|
add_varargs_method("Notify", &ParameterGrpPy::notify, "Notify()");
|
|
add_varargs_method("NotifyAll", &ParameterGrpPy::notifyAll, "NotifyAll()");
|
|
|
|
add_varargs_method("SetBool", &ParameterGrpPy::setBool, "SetBool()");
|
|
add_varargs_method("GetBool", &ParameterGrpPy::getBool, "GetBool()");
|
|
add_varargs_method("GetBools", &ParameterGrpPy::getBools, "GetBools()");
|
|
add_varargs_method("RemBool", &ParameterGrpPy::remBool, "RemBool()");
|
|
|
|
add_varargs_method("SetInt", &ParameterGrpPy::setInt, "SetInt()");
|
|
add_varargs_method("GetInt", &ParameterGrpPy::getInt, "GetInt()");
|
|
add_varargs_method("GetInts", &ParameterGrpPy::getInts, "GetInts()");
|
|
add_varargs_method("RemInt", &ParameterGrpPy::remInt, "RemInt()");
|
|
|
|
add_varargs_method("SetUnsigned", &ParameterGrpPy::setUnsigned, "SetUnsigned()");
|
|
add_varargs_method("GetUnsigned", &ParameterGrpPy::getUnsigned, "GetUnsigned()");
|
|
add_varargs_method("GetUnsigneds", &ParameterGrpPy::getUnsigneds, "GetUnsigneds()");
|
|
add_varargs_method("RemUnsigned", &ParameterGrpPy::remUnsigned, "RemUnsigned()");
|
|
|
|
add_varargs_method("SetFloat", &ParameterGrpPy::setFloat, "SetFloat()");
|
|
add_varargs_method("GetFloat", &ParameterGrpPy::getFloat, "GetFloat()");
|
|
add_varargs_method("GetFloats", &ParameterGrpPy::getFloats, "GetFloats()");
|
|
add_varargs_method("RemFloat", &ParameterGrpPy::remFloat, "RemFloat()");
|
|
|
|
add_varargs_method("SetString", &ParameterGrpPy::setString, "SetString()");
|
|
add_varargs_method("GetString", &ParameterGrpPy::getString, "GetString()");
|
|
add_varargs_method("GetStrings", &ParameterGrpPy::getStrings, "GetStrings()");
|
|
add_varargs_method("RemString", &ParameterGrpPy::remString, "RemString()");
|
|
|
|
add_varargs_method("Import", &ParameterGrpPy::importFrom, "Import()");
|
|
add_varargs_method("Insert", &ParameterGrpPy::insert, "Insert()");
|
|
add_varargs_method("Export", &ParameterGrpPy::exportTo, "Export()");
|
|
|
|
add_varargs_method("GetContents", &ParameterGrpPy::getContents, "GetContents()");
|
|
}
|
|
|
|
ParameterGrpPy::ParameterGrpPy(const Base::Reference<ParameterGrp>& rcParamGrp)
|
|
: _cParamGrp(rcParamGrp)
|
|
{}
|
|
|
|
ParameterGrpPy::~ParameterGrpPy()
|
|
{
|
|
try {
|
|
for (ParameterGrpObserver* obs : _observers) {
|
|
if (!obs->_target) {
|
|
_cParamGrp->Detach(obs);
|
|
}
|
|
delete obs;
|
|
}
|
|
}
|
|
catch (...) {
|
|
}
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::repr()
|
|
{
|
|
std::stringstream s;
|
|
s << "<ParameterGrp at " << this << ">";
|
|
return Py::String(s.str()); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::importFrom(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
try {
|
|
_cParamGrp->importFrom(pstr);
|
|
return Py::None();
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.setPyException();
|
|
throw Py::Exception();
|
|
}
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::insert(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
try {
|
|
_cParamGrp->insert(pstr);
|
|
return Py::None();
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.setPyException();
|
|
throw Py::Exception();
|
|
}
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::exportTo(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
try {
|
|
_cParamGrp->exportTo(pstr);
|
|
return Py::None();
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.setPyException();
|
|
throw Py::Exception();
|
|
}
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getGroup(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
try {
|
|
// get the Handle of the wanted group
|
|
Base::Reference<ParameterGrp> handle = _cParamGrp->GetGroup(pstr);
|
|
if (handle.isValid()) {
|
|
// create a python wrapper class
|
|
auto pcParamGrp = new ParameterGrpPy(handle);
|
|
// increment the ref count
|
|
return Py::asObject(pcParamGrp);
|
|
}
|
|
|
|
throw Py::RuntimeError("GetGroup failed");
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.setPyException();
|
|
throw Py::Exception();
|
|
}
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getManager(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
// get the Handle of the wanted group
|
|
Base::Reference<ParameterGrp> handle = _cParamGrp->Manager();
|
|
if (handle.isValid()) {
|
|
// create a python wrapper class
|
|
auto pcParamGrp = new ParameterGrpPy(handle);
|
|
// increment the ref count
|
|
return Py::asObject(pcParamGrp);
|
|
}
|
|
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getParent(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
// get the Handle of the wanted group
|
|
Base::Reference<ParameterGrp> handle = _cParamGrp->Parent();
|
|
if (handle.isValid()) {
|
|
// create a python wrapper class
|
|
auto pcParamGrp = new ParameterGrpPy(handle);
|
|
// increment the ref count
|
|
return Py::asObject(pcParamGrp);
|
|
}
|
|
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getGroupName(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
// get the Handle of the wanted group
|
|
std::string name = _cParamGrp->GetGroupName();
|
|
return Py::String(name); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getGroups(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
// get the Handle of the wanted group
|
|
std::vector<Base::Reference<ParameterGrp>> handle = _cParamGrp->GetGroups();
|
|
Py::List list;
|
|
for (const auto& it : handle) {
|
|
list.append(Py::String(it->GetGroupName()));
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::setBool(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
int Bool = 0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "si", &pstr, &Bool)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->SetBool(pstr, Bool != 0);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getBool(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
int Bool = 0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s|i", &pstr, &Bool)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
return Py::Boolean(_cParamGrp->GetBool(pstr, Bool != 0)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getBools(const Py::Tuple& args)
|
|
{
|
|
char* filter = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "|s", &filter)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
std::vector<std::pair<std::string, bool>> map = _cParamGrp->GetBoolMap(filter);
|
|
Py::List list;
|
|
for (const auto& it : map) {
|
|
list.append(Py::String(it.first));
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::setInt(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
int Int = 0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "si", &pstr, &Int)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->SetInt(pstr, Int);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getInt(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
int Int = 0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s|i", &pstr, &Int)) {
|
|
throw Py::Exception();
|
|
}
|
|
return Py::Long(_cParamGrp->GetInt(pstr, Int)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getInts(const Py::Tuple& args)
|
|
{
|
|
char* filter = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "|s", &filter)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
std::vector<std::pair<std::string, long>> map = _cParamGrp->GetIntMap(filter);
|
|
Py::List list;
|
|
for (const auto& it : map) {
|
|
list.append(Py::String(it.first));
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::setUnsigned(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
unsigned int UInt = 0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "sI", &pstr, &UInt)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->SetUnsigned(pstr, UInt);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getUnsigned(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
unsigned int UInt = 0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s|I", &pstr, &UInt)) {
|
|
throw Py::Exception();
|
|
}
|
|
return Py::Long(_cParamGrp->GetUnsigned(pstr, UInt)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getUnsigneds(const Py::Tuple& args)
|
|
{
|
|
char* filter = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "|s", &filter)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
std::vector<std::pair<std::string, unsigned long>> map = _cParamGrp->GetUnsignedMap(filter);
|
|
Py::List list;
|
|
for (const auto& it : map) {
|
|
list.append(Py::String(it.first));
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::setFloat(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
double Float {};
|
|
if (!PyArg_ParseTuple(args.ptr(), "sd", &pstr, &Float)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->SetFloat(pstr, Float);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getFloat(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
double Float = 0.0;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s|d", &pstr, &Float)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
return Py::Float(_cParamGrp->GetFloat(pstr, Float)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getFloats(const Py::Tuple& args)
|
|
{
|
|
char* filter = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "|s", &filter)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
std::vector<std::pair<std::string, double>> map = _cParamGrp->GetFloatMap(filter);
|
|
Py::List list;
|
|
for (const auto& it : map) {
|
|
list.append(Py::String(it.first));
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::setString(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
char* str = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "ss", &pstr, &str)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->SetASCII(pstr, str);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getString(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
const char* str = "";
|
|
if (!PyArg_ParseTuple(args.ptr(), "s|s", &pstr, &str)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
return Py::String(_cParamGrp->GetASCII(pstr, str)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getStrings(const Py::Tuple& args)
|
|
{
|
|
char* filter = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "|s", &filter)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
std::vector<std::pair<std::string, std::string>> map = _cParamGrp->GetASCIIMap(filter);
|
|
Py::List list;
|
|
for (const auto& it : map) {
|
|
list.append(Py::String(it.first));
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::remInt(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->RemoveInt(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::remUnsigned(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->RemoveUnsigned(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::remBool(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->RemoveBool(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::remGroup(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->RemoveGrp(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::remFloat(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->RemoveFloat(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::remString(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->RemoveASCII(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::clear(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->Clear();
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::isEmpty(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
return Py::Boolean(_cParamGrp->IsEmpty()); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::hasGroup(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
return Py::Boolean(_cParamGrp->HasGroup(pstr)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::renameGroup(const Py::Tuple& args)
|
|
{
|
|
char* oldname = nullptr;
|
|
char* newname = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "ss", &oldname, &newname)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
return Py::Boolean(_cParamGrp->RenameGrp(oldname, newname)); // NOLINT
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::copyTo(const Py::Tuple& args)
|
|
{
|
|
PyObject* pygrp {};
|
|
if (!PyArg_ParseTuple(args.ptr(), "O!", ParameterGrpPy::type_object(), &pygrp)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
auto grp = static_cast<ParameterGrpPy*>(pygrp); // NOLINT
|
|
_cParamGrp->copyTo(grp->_cParamGrp);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::attach(const Py::Tuple& args)
|
|
{
|
|
PyObject* obj = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
Py::Object o(obj);
|
|
if (!o.hasAttr(std::string("onChange"))) {
|
|
throw Py::TypeError("Object has no onChange attribute");
|
|
}
|
|
|
|
for (ParameterGrpObserver* it : _observers) {
|
|
if (it->isEqual(o)) {
|
|
throw Py::RuntimeError("Object is already attached.");
|
|
}
|
|
}
|
|
|
|
auto obs = new ParameterGrpObserver(o);
|
|
_cParamGrp->Attach(obs);
|
|
_observers.push_back(obs);
|
|
|
|
return Py::None();
|
|
}
|
|
|
|
void ParameterGrpPy::tryCall(
|
|
ParameterGrpObserver* obs,
|
|
ParameterGrp* Param,
|
|
ParameterGrp::ParamType Type,
|
|
const char* Name,
|
|
const char* Value
|
|
)
|
|
{
|
|
Base::PyGILStateLocker lock;
|
|
Py::TupleN args(
|
|
Py::asObject(new ParameterGrpPy(Param)),
|
|
Py::String(ParameterGrp::TypeName(Type)),
|
|
Py::String(Name ? Name : ""),
|
|
Py::String(Value ? Value : "")
|
|
);
|
|
try {
|
|
Py::Callable(obs->callable).apply(args);
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e;
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::attachManager(const Py::Tuple& args)
|
|
{
|
|
PyObject* obj = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
if (!_cParamGrp->Manager()) {
|
|
throw Py::RuntimeError("Parameter has no manager");
|
|
}
|
|
|
|
Py::Object o(obj);
|
|
if (!o.hasAttr(std::string("slotParamChanged"))) {
|
|
throw Py::TypeError("Object has no slotParamChanged attribute");
|
|
}
|
|
|
|
Py::Object attr(o.getAttr("slotParamChanged"));
|
|
if (!attr.isCallable()) {
|
|
throw Py::TypeError("Object has no slotParamChanged callable attribute");
|
|
}
|
|
|
|
for (ParameterGrpObserver* it : _observers) {
|
|
if (it->isEqual(o)) {
|
|
throw Py::RuntimeError("Object is already attached.");
|
|
}
|
|
}
|
|
|
|
auto obs = new ParameterGrpObserver(o, attr, _cParamGrp);
|
|
ParameterManager* man = _cParamGrp->Manager();
|
|
obs->conn = man->signalParamChanged.connect(
|
|
[obs,
|
|
this](ParameterGrp* Param, ParameterGrp::ParamType Type, const char* Name, const char* Value) {
|
|
if (!Param) {
|
|
return;
|
|
}
|
|
for (auto p = Param; p; p = p->Parent()) {
|
|
if (p == obs->_target) {
|
|
tryCall(obs, Param, Type, Name, Value);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
_observers.push_back(obs);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::detach(const Py::Tuple& args)
|
|
{
|
|
PyObject* obj = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "O", &obj)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
Py::Object o(obj);
|
|
if (!o.hasAttr(std::string("onChange"))) {
|
|
throw Py::TypeError("Object has no onChange attribute");
|
|
}
|
|
|
|
for (auto it = _observers.begin(); it != _observers.end(); ++it) {
|
|
if ((*it)->isEqual(o)) {
|
|
ParameterGrpObserver* obs = *it;
|
|
_observers.erase(it);
|
|
_cParamGrp->Detach(obs);
|
|
delete obs;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::notify(const Py::Tuple& args)
|
|
{
|
|
char* pstr = nullptr;
|
|
if (!PyArg_ParseTuple(args.ptr(), "s", &pstr)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->Notify(pstr);
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::notifyAll(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
_cParamGrp->NotifyAll();
|
|
return Py::None();
|
|
}
|
|
|
|
Py::Object ParameterGrpPy::getContents(const Py::Tuple& args)
|
|
{
|
|
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
if (_cParamGrp->IsEmpty()) {
|
|
return Py::None();
|
|
}
|
|
|
|
Py::List list;
|
|
// filling up Text nodes
|
|
std::vector<std::pair<std::string, std::string>> mcTextMap = _cParamGrp->GetASCIIMap();
|
|
for (const auto& it : mcTextMap) {
|
|
Py::Tuple t2(3);
|
|
t2.setItem(0, Py::String("String"));
|
|
t2.setItem(1, Py::String(it.first.c_str()));
|
|
t2.setItem(2, Py::String(it.second.c_str()));
|
|
list.append(t2);
|
|
}
|
|
|
|
// filling up Int nodes
|
|
std::vector<std::pair<std::string, long>> mcIntMap = _cParamGrp->GetIntMap();
|
|
for (const auto& it : mcIntMap) {
|
|
Py::Tuple t3(3);
|
|
t3.setItem(0, Py::String("Integer"));
|
|
t3.setItem(1, Py::String(it.first.c_str()));
|
|
t3.setItem(2, Py::Long(it.second));
|
|
list.append(t3);
|
|
}
|
|
|
|
// filling up Float nodes
|
|
std::vector<std::pair<std::string, double>> mcFloatMap = _cParamGrp->GetFloatMap();
|
|
for (const auto& it : mcFloatMap) {
|
|
Py::Tuple t4(3);
|
|
t4.setItem(0, Py::String("Float"));
|
|
t4.setItem(1, Py::String(it.first.c_str()));
|
|
t4.setItem(2, Py::Float(it.second));
|
|
list.append(t4);
|
|
}
|
|
|
|
// filling up bool nodes
|
|
std::vector<std::pair<std::string, bool>> mcBoolMap = _cParamGrp->GetBoolMap();
|
|
for (const auto& it : mcBoolMap) {
|
|
Py::Tuple t5(3);
|
|
t5.setItem(0, Py::String("Boolean"));
|
|
t5.setItem(1, Py::String(it.first.c_str()));
|
|
t5.setItem(2, Py::Boolean(it.second));
|
|
list.append(t5);
|
|
}
|
|
|
|
// filling up UInt nodes
|
|
std::vector<std::pair<std::string, unsigned long>> mcUIntMap = _cParamGrp->GetUnsignedMap();
|
|
for (const auto& it : mcUIntMap) {
|
|
Py::Tuple t6(3);
|
|
t6.setItem(0, Py::String("Unsigned Long"));
|
|
t6.setItem(1, Py::String(it.first.c_str()));
|
|
t6.setItem(2, Py::Long(it.second));
|
|
list.append(t6);
|
|
}
|
|
|
|
return list; // NOLINT
|
|
}
|
|
|
|
} // namespace Base
|
|
|
|
/** python wrapper function
|
|
*/
|
|
PyObject* GetPyObject(const Base::Reference<ParameterGrp>& hcParamGrp)
|
|
{
|
|
static bool init = false;
|
|
if (!init) {
|
|
init = true;
|
|
Base::ParameterGrpPy::init_type();
|
|
}
|
|
|
|
return new Base::ParameterGrpPy(hcParamGrp);
|
|
}
|