1429 lines
44 KiB
C++
1429 lines
44 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2006 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 *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include <sstream>
|
|
#include <QApplication>
|
|
#include <QEvent>
|
|
#include <QFileInfo>
|
|
#include <QMenu>
|
|
#include <QPixmap>
|
|
#include <Inventor/SoPickedPoint.h>
|
|
#include <Inventor/details/SoDetail.h>
|
|
|
|
|
|
#include <App/DocumentObjectPy.h>
|
|
#include <Base/Interpreter.h>
|
|
#include <Base/Tools.h>
|
|
#include <CXX/Python3/Objects.hxx>
|
|
|
|
#include "ViewProviderFeaturePython.h"
|
|
#include "Application.h"
|
|
#include "BitmapFactory.h"
|
|
#include "Document.h"
|
|
#include "PythonWrapper.h"
|
|
#include "View3DInventorViewer.h"
|
|
#include "ViewProviderDocumentObjectPy.h"
|
|
#include "Selection.h"
|
|
|
|
|
|
FC_LOG_LEVEL_INIT("ViewProviderFeaturePython", true, true)
|
|
|
|
|
|
using namespace Gui;
|
|
namespace sp = std::placeholders;
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
ViewProviderFeaturePythonImp::ViewProviderFeaturePythonImp(
|
|
ViewProviderDocumentObject* vp,
|
|
App::PropertyPythonObject& proxy
|
|
)
|
|
: object(vp)
|
|
, Proxy(proxy)
|
|
{}
|
|
|
|
ViewProviderFeaturePythonImp::~ViewProviderFeaturePythonImp()
|
|
{
|
|
Base::PyGILStateLocker lock;
|
|
#undef FC_PY_ELEMENT
|
|
#define FC_PY_ELEMENT(_name) py_##_name = Py::None();
|
|
|
|
try {
|
|
FC_PY_VIEW_OBJECT
|
|
}
|
|
catch (Py::Exception& e) {
|
|
e.clear();
|
|
}
|
|
|
|
this->selectionObserver.~SelectionObserverPythonHandler();
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::init(PyObject* pyobj)
|
|
{
|
|
Base::PyGILStateLocker lock;
|
|
has__object__ = !!PyObject_HasAttrString(pyobj, "__object__");
|
|
|
|
#undef FC_PY_ELEMENT
|
|
#define FC_PY_ELEMENT(_name) FC_PY_ELEMENT_INIT(_name)
|
|
|
|
FC_PY_VIEW_OBJECT
|
|
|
|
this->selectionObserver.init(pyobj);
|
|
}
|
|
|
|
#define FC_PY_CALL_CHECK(_name) _FC_PY_CALL_CHECK(_name, return (NotImplemented))
|
|
|
|
QIcon ViewProviderFeaturePythonImp::getIcon() const
|
|
{
|
|
_FC_PY_CALL_CHECK(getIcon, return (QIcon()));
|
|
|
|
// Run the getIcon method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Object ret(Base::pyCall(py_getIcon.ptr()));
|
|
if (ret.isNone()) {
|
|
return {};
|
|
}
|
|
|
|
if (ret.isString()) {
|
|
std::string content = Py::String(ret).as_std_string("utf-8");
|
|
QPixmap icon;
|
|
if (BitmapFactory().findPixmapInCache(content.c_str(), icon)) {
|
|
return icon;
|
|
}
|
|
|
|
// Check if the passed string is a filename, otherwise treat as xpm data
|
|
QFileInfo fi(QString::fromUtf8(content.c_str()));
|
|
if (fi.isFile() && fi.exists()) {
|
|
icon.load(fi.absoluteFilePath());
|
|
}
|
|
else {
|
|
QByteArray ary;
|
|
int strlen = (int)content.size();
|
|
ary.resize(strlen);
|
|
for (int j = 0; j < strlen; j++) {
|
|
ary[j] = content[j];
|
|
}
|
|
// Make sure to remove crap around the XPM data
|
|
QList<QByteArray> lines = ary.split('\n');
|
|
QByteArray buffer;
|
|
buffer.reserve(ary.size() + lines.size());
|
|
for (const auto& line : lines) {
|
|
QByteArray trim = line.trimmed();
|
|
if (!trim.isEmpty()) {
|
|
buffer.append(trim);
|
|
buffer.append('\n');
|
|
}
|
|
}
|
|
icon.loadFromData(buffer, "XPM");
|
|
}
|
|
if (!icon.isNull()) {
|
|
return icon;
|
|
}
|
|
}
|
|
else {
|
|
PythonWrapper wrap;
|
|
wrap.loadGuiModule();
|
|
wrap.loadWidgetsModule();
|
|
QIcon* picon = wrap.toQIcon(ret.ptr());
|
|
if (picon) {
|
|
return *picon;
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
}
|
|
else {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::map<BitmapFactoryInst::Position, std::string> ViewProviderFeaturePythonImp::getOverlayIcons() const
|
|
{
|
|
std::map<BitmapFactoryInst::Position, std::string> overlays;
|
|
_FC_PY_CALL_CHECK(getOverlayIcons, return overlays);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Object ret(Base::pyCall(py_getOverlayIcons.ptr()));
|
|
if (ret.isNone()) {
|
|
return overlays;
|
|
}
|
|
|
|
// Expect a dictionary (dict) from Python
|
|
if (!PyDict_Check(ret.ptr())) {
|
|
return overlays;
|
|
}
|
|
|
|
Py::Dict dict(ret);
|
|
PyObject *key, *value;
|
|
Py_ssize_t pos = 0;
|
|
|
|
// Iterate over the dictionary items
|
|
while (PyDict_Next(dict.ptr(), &pos, &key, &value)) {
|
|
// Key should be an integer (from the enum)
|
|
if (!PyLong_Check(key)) {
|
|
continue;
|
|
}
|
|
// Value should be a string
|
|
if (!PyUnicode_Check(value)) {
|
|
continue;
|
|
}
|
|
|
|
long position_val = PyLong_AsLong(key);
|
|
// Basic validation for the enum range
|
|
if (position_val >= BitmapFactoryInst::TopLeft
|
|
&& position_val <= BitmapFactoryInst::BottomRight) {
|
|
auto position = static_cast<BitmapFactoryInst::Position>(position_val);
|
|
std::string iconName = Py::String(value).as_std_string("utf-8");
|
|
if (!iconName.empty()) {
|
|
overlays[position] = iconName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
}
|
|
else {
|
|
Base::PyException e;
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
return overlays;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::claimChildren(std::vector<App::DocumentObject*>& children) const
|
|
{
|
|
_FC_PY_CALL_CHECK(claimChildren, return (false));
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Sequence list(Base::pyCall(py_claimChildren.ptr()));
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
PyObject* item = (*it).ptr();
|
|
if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
|
|
App::DocumentObject* obj
|
|
= static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
|
|
children.push_back(obj);
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::useNewSelectionModel() const
|
|
{
|
|
FC_PY_CALL_CHECK(useNewSelectionModel);
|
|
|
|
// Run the useNewSelectionModel method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Boolean ok(Py::Callable(py_useNewSelectionModel).apply(Py::Tuple()));
|
|
return ok ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Accepted;
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::onSelectionChanged(const SelectionChanges& changes)
|
|
{
|
|
this->selectionObserver.handleSelectionChanged(changes);
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::getElement(const SoDetail* det, std::string& res) const
|
|
{
|
|
_FC_PY_CALL_CHECK(getElement, return (false));
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
PyObject* pivy = nullptr;
|
|
// Note: As there is no ref'counting mechanism for the SoDetail class we must
|
|
// pass '0' as the last parameter so that the Python object does not 'own'
|
|
// the detail object.
|
|
pivy = Base::Interpreter().createSWIGPointerObj(
|
|
"pivy.coin",
|
|
"SoDetail *",
|
|
const_cast<void*>(static_cast<const void*>(det)),
|
|
0
|
|
);
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(pivy, true));
|
|
Py::String name(Base::pyCall(py_getElement.ptr(), args.ptr()));
|
|
res = name;
|
|
return true;
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.reportException();
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::getElementPicked(
|
|
const SoPickedPoint* pp,
|
|
std::string& subname
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(getElementPicked);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
PyObject* pivy = nullptr;
|
|
pivy = Base::Interpreter().createSWIGPointerObj(
|
|
"pivy.coin",
|
|
"SoPickedPoint *",
|
|
const_cast<void*>(static_cast<const void*>(pp)),
|
|
0
|
|
);
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(pivy, true));
|
|
Py::Object ret(Base::pyCall(py_getElementPicked.ptr(), args.ptr()));
|
|
if (!ret.isString()) {
|
|
return Rejected;
|
|
}
|
|
subname = ret.as_string();
|
|
return Accepted;
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.reportException();
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::getDetail(const char* name, SoDetail*& det) const
|
|
{
|
|
_FC_PY_CALL_CHECK(getDetail, return (false));
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::String(name));
|
|
Py::Object pydet(Base::pyCall(py_getDetail.ptr(), args.ptr()));
|
|
void* ptr = nullptr;
|
|
Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoDetail *", pydet.ptr(), &ptr, 0);
|
|
auto detail = static_cast<SoDetail*>(ptr);
|
|
det = detail ? detail->copy() : nullptr;
|
|
return true;
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.reportException();
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::getDetailPath(
|
|
const char* name,
|
|
SoFullPath* path,
|
|
bool append,
|
|
SoDetail*& det
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(getDetailPath);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
auto length = path->getLength();
|
|
try {
|
|
PyObject* pivy = nullptr;
|
|
pivy = Base::Interpreter()
|
|
.createSWIGPointerObj("pivy.coin", "SoFullPath *", static_cast<void*>(path), 1);
|
|
path->ref();
|
|
Py::Tuple args(3);
|
|
args.setItem(0, Py::String(name));
|
|
args.setItem(1, Py::Object(pivy, true));
|
|
args.setItem(2, Py::Boolean(append));
|
|
Py::Object pyDet(Base::pyCall(py_getDetailPath.ptr(), args.ptr()));
|
|
if (!pyDet.isTrue()) {
|
|
return Rejected;
|
|
}
|
|
if (pyDet.isBoolean()) {
|
|
return Accepted;
|
|
}
|
|
void* ptr = nullptr;
|
|
Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoDetail *", pyDet.ptr(), &ptr, 0);
|
|
auto detail = static_cast<SoDetail*>(ptr);
|
|
det = detail ? detail->copy() : nullptr;
|
|
if (det) {
|
|
return Accepted;
|
|
}
|
|
delete det;
|
|
}
|
|
catch (const Base::Exception& e) {
|
|
e.reportException();
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
path->truncate(length);
|
|
return Rejected;
|
|
}
|
|
|
|
|
|
std::vector<Base::Vector3d> ViewProviderFeaturePythonImp::getSelectionShape(const char* /*Element*/) const
|
|
{
|
|
return {};
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::setEdit(int ModNum)
|
|
{
|
|
FC_PY_CALL_CHECK(setEdit)
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Long(ModNum));
|
|
Py::Object ret(Base::pyCall(py_setEdit.ptr(), args.ptr()));
|
|
if (ret.isNone()) {
|
|
return NotImplemented;
|
|
}
|
|
Py::Boolean ok(ret);
|
|
bool value = static_cast<bool>(ok);
|
|
return value ? Accepted : Rejected;
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, Py::Long(ModNum));
|
|
Py::Object ret(Base::pyCall(py_setEdit.ptr(), args.ptr()));
|
|
if (ret.isNone()) {
|
|
return NotImplemented;
|
|
}
|
|
Py::Boolean ok(ret);
|
|
bool value = static_cast<bool>(ok);
|
|
return value ? Accepted : Rejected;
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::unsetEdit(int ModNum)
|
|
{
|
|
FC_PY_CALL_CHECK(unsetEdit)
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Long(ModNum));
|
|
Py::Object ret(Base::pyCall(py_unsetEdit.ptr(), args.ptr()));
|
|
if (ret.isNone()) {
|
|
return NotImplemented;
|
|
}
|
|
Py::Boolean ok(ret);
|
|
bool value = static_cast<bool>(ok);
|
|
return value ? Accepted : Rejected;
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, Py::Long(ModNum));
|
|
Py::Object ret(Base::pyCall(py_unsetEdit.ptr(), args.ptr()));
|
|
if (ret.isNone()) {
|
|
return NotImplemented;
|
|
}
|
|
Py::Boolean ok(ret);
|
|
bool value = static_cast<bool>(ok);
|
|
return value ? Accepted : Rejected;
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::setEditViewer(
|
|
View3DInventorViewer* viewer,
|
|
int ModNum
|
|
)
|
|
{
|
|
FC_PY_CALL_CHECK(setEditViewer)
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(3);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, Py::Object(viewer->getPyObject(), true));
|
|
args.setItem(2, Py::Long(ModNum));
|
|
Py::Object ret(Base::pyCall(py_setEditViewer.ptr(), args.ptr()));
|
|
return ret.isTrue() ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::unsetEditViewer(
|
|
View3DInventorViewer* viewer
|
|
)
|
|
{
|
|
FC_PY_CALL_CHECK(unsetEditViewer)
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, Py::Object(viewer->getPyObject(), true));
|
|
Py::Object ret(Base::pyCall(py_unsetEditViewer.ptr(), args.ptr()));
|
|
return ret.isTrue() ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::doubleClicked()
|
|
{
|
|
FC_PY_CALL_CHECK(doubleClicked)
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Boolean ok(Base::pyCall(py_doubleClicked.ptr()));
|
|
bool value = (bool)ok;
|
|
return value ? Accepted : Rejected;
|
|
}
|
|
else {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
Py::Boolean ok(Base::pyCall(py_doubleClicked.ptr(), args.ptr()));
|
|
bool value = (bool)ok;
|
|
return value ? Accepted : Rejected;
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::setupContextMenu(QMenu* menu)
|
|
{
|
|
_FC_PY_CALL_CHECK(setupContextMenu, return (false));
|
|
|
|
// Run the attach method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
PythonWrapper wrap;
|
|
wrap.loadGuiModule();
|
|
wrap.loadWidgetsModule();
|
|
Py::Tuple args(1);
|
|
args.setItem(0, wrap.fromQWidget(menu, "QMenu"));
|
|
return Base::pyCall(py_setupContextMenu.ptr(), args.ptr()).isTrue();
|
|
}
|
|
else {
|
|
PythonWrapper wrap;
|
|
wrap.loadGuiModule();
|
|
wrap.loadWidgetsModule();
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, wrap.fromQWidget(menu, "QMenu"));
|
|
return Base::pyCall(py_setupContextMenu.ptr(), args.ptr()).isTrue();
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::attach(App::DocumentObject* pcObject)
|
|
{
|
|
_FC_PY_CALL_CHECK(attach, return);
|
|
|
|
// Run the attach method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Base::pyCall(py_attach.ptr());
|
|
}
|
|
else {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
Base::pyCall(py_attach.ptr(), args.ptr());
|
|
}
|
|
|
|
// #0000415: Now simulate a property change event to call
|
|
// claimChildren if implemented.
|
|
pcObject->Label.touch();
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::updateData(const App::Property* prop)
|
|
{
|
|
if (py_updateData.isNone()) {
|
|
return;
|
|
}
|
|
|
|
// Run the updateData method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
const char* prop_name = object->getObject()->getPropertyName(prop);
|
|
if (prop_name) {
|
|
args.setItem(0, Py::String(prop_name));
|
|
Base::pyCall(py_updateData.ptr(), args.ptr());
|
|
}
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getObject()->getPyObject(), true));
|
|
const char* prop_name = object->getObject()->getPropertyName(prop);
|
|
if (prop_name) {
|
|
args.setItem(1, Py::String(prop_name));
|
|
Base::pyCall(py_updateData.ptr(), args.ptr());
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::onChanged(const App::Property* prop)
|
|
{
|
|
if (py_onChanged.isNone()) {
|
|
return;
|
|
}
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
const char* prop_name = object->getPropertyName(prop);
|
|
if (prop_name) {
|
|
args.setItem(0, Py::String(prop_name));
|
|
Base::pyCall(py_onChanged.ptr(), args.ptr());
|
|
}
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
const char* prop_name = object->getPropertyName(prop);
|
|
if (prop_name) {
|
|
args.setItem(1, Py::String(prop_name));
|
|
Base::pyCall(py_onChanged.ptr(), args.ptr());
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::onBeforeChange(const App::Property* prop)
|
|
{
|
|
if (py_onBeforeChange.isNone()) {
|
|
return;
|
|
}
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
const char* prop_name = object->getPropertyName(prop);
|
|
if (prop_name) {
|
|
args.setItem(0, Py::String(prop_name));
|
|
Base::pyCall(py_onBeforeChange.ptr(), args.ptr());
|
|
}
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
const char* prop_name = object->getPropertyName(prop);
|
|
if (prop_name) {
|
|
args.setItem(1, Py::String(prop_name));
|
|
Base::pyCall(py_onBeforeChange.ptr(), args.ptr());
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::startRestoring()
|
|
{}
|
|
|
|
void ViewProviderFeaturePythonImp::finishRestoring()
|
|
{
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Object vp = Proxy.getValue();
|
|
if (vp.isNone()) {
|
|
object->show();
|
|
Proxy.setValue(Py::Long(1));
|
|
}
|
|
else {
|
|
_FC_PY_CALL_CHECK(finishRestoring, return);
|
|
Base::pyCall(py_finishRestoring.ptr());
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
void ViewProviderFeaturePythonImp::beforeDelete()
|
|
{
|
|
_FC_PY_CALL_CHECK(beforeDelete, return);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Base::pyCall(py_beforeDelete.ptr());
|
|
}
|
|
else {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
Base::pyCall(py_beforeDelete.ptr(), args.ptr());
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
}
|
|
else {
|
|
Base::PyException e;
|
|
e.reportException();
|
|
}
|
|
}
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::onDelete(
|
|
const std::vector<std::string>& sub
|
|
)
|
|
{
|
|
FC_PY_CALL_CHECK(onDelete);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple seq(sub.size());
|
|
int index = 0;
|
|
for (const auto& it : sub) {
|
|
seq.setItem(index++, Py::String(it));
|
|
}
|
|
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, seq);
|
|
Py::Boolean ok(Base::pyCall(py_onDelete.ptr(), args.ptr()));
|
|
return ok ? Accepted : Rejected;
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, seq);
|
|
Py::Boolean ok(Base::pyCall(py_onDelete.ptr(), args.ptr()));
|
|
return ok ? Accepted : Rejected;
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
return Rejected;
|
|
}
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDelete(
|
|
App::DocumentObject* obj
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(canDelete);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, obj ? Py::Object(obj->getPyObject(), true) : Py::Object());
|
|
return Py::Boolean(Base::pyCall(py_canDelete.ptr(), args.ptr())) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
return Rejected;
|
|
}
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canAddToSceneGraph() const
|
|
{
|
|
FC_PY_CALL_CHECK(canAddToSceneGraph);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
return Py::Boolean(Py::Callable(py_canAddToSceneGraph).apply(Py::Tuple())) ? Accepted
|
|
: Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return Accepted;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::getDefaultDisplayMode(std::string& mode) const
|
|
{
|
|
_FC_PY_CALL_CHECK(getDefaultDisplayMode, return (0));
|
|
|
|
// Run the getDefaultDisplayMode method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::String str(Base::pyCall(py_getDefaultDisplayMode.ptr()));
|
|
mode = str.as_std_string("ascii");
|
|
return true;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
std::vector<std::string> ViewProviderFeaturePythonImp::getDisplayModes() const
|
|
{
|
|
std::vector<std::string> modes;
|
|
_FC_PY_CALL_CHECK(getDisplayModes, return (modes));
|
|
|
|
// Run the getDisplayModes method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Sequence list(Base::pyCall(py_getDisplayModes.ptr()));
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
Py::String str(*it);
|
|
modes.push_back(str.as_std_string("ascii"));
|
|
}
|
|
}
|
|
else {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
Py::Sequence list(Base::pyCall(py_getDisplayModes.ptr(), args.ptr()));
|
|
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
|
Py::String str(*it);
|
|
modes.push_back(str.as_std_string("ascii"));
|
|
}
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
}
|
|
else {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
}
|
|
|
|
return modes;
|
|
}
|
|
|
|
std::string ViewProviderFeaturePythonImp::setDisplayMode(const char* ModeName)
|
|
{
|
|
_FC_PY_CALL_CHECK(setDisplayMode, return (ModeName));
|
|
|
|
// Run the setDisplayMode method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::String(ModeName));
|
|
Py::String str(Base::pyCall(py_setDisplayMode.ptr(), args.ptr()));
|
|
return str.as_std_string("ascii");
|
|
}
|
|
catch (Py::Exception&) {
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return ModeName;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDragObjects() const
|
|
{
|
|
FC_PY_CALL_CHECK(canDragObjects);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Boolean ok(Base::pyCall(py_canDragObjects.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDragObject(
|
|
App::DocumentObject* obj
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(canDragObject);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(obj->getPyObject(), true));
|
|
Py::Boolean ok(Base::pyCall(py_canDragObject.ptr(), args.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::dragObject(App::DocumentObject* obj)
|
|
{
|
|
FC_PY_CALL_CHECK(dragObject);
|
|
|
|
// Run the onChanged method of the proxy object.
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(obj->getPyObject(), true));
|
|
Base::pyCall(py_dragObject.ptr(), args.ptr());
|
|
return Accepted;
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, Py::Object(obj->getPyObject(), true));
|
|
Base::pyCall(py_dragObject.ptr(), args.ptr());
|
|
return Accepted;
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDropObjects() const
|
|
{
|
|
FC_PY_CALL_CHECK(canDropObjects);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Boolean ok(Base::pyCall(py_canDropObjects.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDropObject(
|
|
App::DocumentObject* obj
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(canDropObject);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(obj->getPyObject(), true));
|
|
Py::Boolean ok(Base::pyCall(py_canDropObject.ptr(), args.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::dropObject(App::DocumentObject* obj)
|
|
{
|
|
FC_PY_CALL_CHECK(dropObject);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
if (has__object__) {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Object(obj->getPyObject(), true));
|
|
Base::pyCall(py_dropObject.ptr(), args.ptr());
|
|
return Accepted;
|
|
}
|
|
else {
|
|
Py::Tuple args(2);
|
|
args.setItem(0, Py::Object(object->getPyObject(), true));
|
|
args.setItem(1, Py::Object(obj->getPyObject(), true));
|
|
Base::pyCall(py_dropObject.ptr(), args.ptr());
|
|
return Accepted;
|
|
}
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException::throwException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDragAndDropObject(
|
|
App::DocumentObject* obj
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(canDragAndDropObject);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::TupleN args(Py::Object(obj->getPyObject(), true));
|
|
Py::Boolean ok(Base::pyCall(py_canDragAndDropObject.ptr(), args.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canDropObjectEx(
|
|
App::DocumentObject* obj,
|
|
App::DocumentObject* owner,
|
|
const char* subname,
|
|
const std::vector<std::string>& elements
|
|
) const
|
|
{
|
|
FC_PY_CALL_CHECK(canDropObjectEx);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(4);
|
|
args.setItem(0, Py::Object(obj->getPyObject(), true));
|
|
args.setItem(1, owner ? Py::Object(owner->getPyObject(), true) : Py::None());
|
|
args.setItem(2, Py::String(subname ? subname : ""));
|
|
Py::Tuple tuple(elements.size());
|
|
int i = 0;
|
|
for (auto& element : elements) {
|
|
tuple.setItem(i++, Py::String(element));
|
|
}
|
|
args.setItem(3, tuple);
|
|
Py::Boolean ok(Base::pyCall(py_canDropObjectEx.ptr(), args.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::dropObjectEx(
|
|
App::DocumentObject* obj,
|
|
App::DocumentObject* owner,
|
|
const char* subname,
|
|
const std::vector<std::string>& elements,
|
|
std::string& ret
|
|
)
|
|
{
|
|
_FC_PY_CALL_CHECK(dropObjectEx, return (false));
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple tuple(elements.size());
|
|
int i = 0;
|
|
for (auto& element : elements) {
|
|
tuple.setItem(i++, Py::String(element));
|
|
}
|
|
Py::Object res;
|
|
Py::TupleN args(
|
|
Py::Object(object->getPyObject(), true),
|
|
Py::Object(obj->getPyObject(), true),
|
|
owner ? Py::Object(owner->getPyObject(), true) : Py::Object(),
|
|
Py::String(subname ? subname : ""),
|
|
tuple
|
|
);
|
|
res = Base::pyCall(py_dropObjectEx.ptr(), args.ptr());
|
|
if (!res.isNone()) {
|
|
ret = res.as_string();
|
|
}
|
|
return true;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException::throwException();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::isShow() const
|
|
{
|
|
FC_PY_CALL_CHECK(isShow);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Boolean ok(Base::pyCall(py_isShow.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
|
|
return Rejected;
|
|
}
|
|
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::canRemoveChildrenFromRoot() const
|
|
{
|
|
|
|
FC_PY_CALL_CHECK(canRemoveChildrenFromRoot);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Boolean ok(Base::pyCall(py_canRemoveChildrenFromRoot.ptr()));
|
|
return static_cast<bool>(ok) ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return Rejected;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::getDropPrefix(std::string& prefix) const
|
|
{
|
|
|
|
_FC_PY_CALL_CHECK(getDropPrefix, return (false));
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Object ret(Base::pyCall(py_getDropPrefix.ptr()));
|
|
if (ret.isNone()) {
|
|
return false;
|
|
}
|
|
prefix = ret.as_string();
|
|
return true;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
ViewProviderFeaturePythonImp::ValueT ViewProviderFeaturePythonImp::replaceObject(
|
|
App::DocumentObject* oldObj,
|
|
App::DocumentObject* newObj
|
|
)
|
|
{
|
|
if (!oldObj || !oldObj->isAttachedToDocument() || !newObj || !newObj->isAttachedToDocument()) {
|
|
return NotImplemented;
|
|
}
|
|
|
|
FC_PY_CALL_CHECK(replaceObject);
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::TupleN args(Py::asObject(oldObj->getPyObject()), Py::asObject(newObj->getPyObject()));
|
|
Py::Boolean ok(Base::pyCall(py_replaceObject.ptr(), args.ptr()));
|
|
return ok ? Accepted : Rejected;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return NotImplemented;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return Rejected;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::getLinkedViewProvider(
|
|
ViewProviderDocumentObject*& vp,
|
|
std::string* subname,
|
|
bool recursive
|
|
) const
|
|
{
|
|
_FC_PY_CALL_CHECK(getLinkedViewProvider, return (false));
|
|
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::Boolean(recursive));
|
|
Py::Object res(Base::pyCall(py_getLinkedViewProvider.ptr(), args.ptr()));
|
|
if (res.isNone()) {
|
|
return true;
|
|
}
|
|
if (PyObject_TypeCheck(res.ptr(), &ViewProviderDocumentObjectPy::Type)) {
|
|
vp = static_cast<ViewProviderDocumentObjectPy*>(res.ptr())
|
|
->getViewProviderDocumentObjectPtr();
|
|
return true;
|
|
}
|
|
else if (PySequence_Check(res.ptr()) && PySequence_Length(res.ptr()) == 2) {
|
|
Py::Sequence seq(res);
|
|
Py::Object item0(seq[0].ptr());
|
|
Py::Object item1(seq[1].ptr());
|
|
if (PyObject_TypeCheck(item0.ptr(), &ViewProviderDocumentObjectPy::Type)
|
|
&& item1.isString()) {
|
|
if (subname) {
|
|
*subname = Py::String(item1).as_std_string("utf-8");
|
|
}
|
|
vp = static_cast<ViewProviderDocumentObjectPy*>(item0.ptr())
|
|
->getViewProviderDocumentObjectPtr();
|
|
return true;
|
|
}
|
|
}
|
|
FC_ERR("getLinkedViewProvider(): invalid return type, expects ViewObject or (ViewObject, subname)");
|
|
return true;
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ViewProviderFeaturePythonImp::editProperty(const char* name)
|
|
{
|
|
_FC_PY_CALL_CHECK(editProperty, return false);
|
|
Base::PyGILStateLocker lock;
|
|
try {
|
|
Py::Tuple args(1);
|
|
args.setItem(0, Py::String(name));
|
|
Py::Object ret(Base::pyCall(py_editProperty.ptr(), args.ptr()));
|
|
return ret.isTrue();
|
|
}
|
|
catch (Py::Exception&) {
|
|
if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
|
|
PyErr_Clear();
|
|
return false;
|
|
}
|
|
|
|
Base::PyException e; // extract the Python error text
|
|
e.reportException();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
|
|
namespace Gui
|
|
{
|
|
PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderFeaturePython, Gui::ViewProviderDocumentObject)
|
|
// explicit template instantiation
|
|
template class GuiExport ViewProviderFeaturePythonT<ViewProviderDocumentObject>;
|
|
} // namespace Gui
|
|
|
|
// ---------------------------------------------------------
|
|
|
|
namespace Gui
|
|
{
|
|
PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderGeometryPython, Gui::ViewProviderGeometryObject)
|
|
// explicit template instantiation
|
|
template class GuiExport ViewProviderFeaturePythonT<ViewProviderGeometryObject>;
|
|
} // namespace Gui
|