diff --git a/src/Gui/SplitView3DInventor.cpp b/src/Gui/SplitView3DInventor.cpp
index 7db754c7dd..78a7102da5 100644
--- a/src/Gui/SplitView3DInventor.cpp
+++ b/src/Gui/SplitView3DInventor.cpp
@@ -38,6 +38,7 @@
#include "Application.h"
#include "NavigationStyle.h"
#include "View3DPy.h"
+#include
using namespace Gui;
@@ -47,7 +48,7 @@ TYPESYSTEM_SOURCE_ABSTRACT(Gui::AbstractSplitView,Gui::MDIView)
AbstractSplitView::AbstractSplitView(Gui::Document* pcDocument, QWidget* parent, Qt::WindowFlags wflags)
: MDIView(pcDocument,parent, wflags)
{
- _viewerPy = 0;
+ _viewerPy = nullptr;
// important for highlighting
setMouseTracking(true);
}
@@ -59,7 +60,7 @@ AbstractSplitView::~AbstractSplitView()
delete *it;
}
if (_viewerPy) {
- static_cast(_viewerPy)->_view = 0;
+ Base::PyGILStateLocker lock;
Py_DECREF(_viewerPy);
}
}
@@ -72,6 +73,12 @@ void AbstractSplitView::deleteSelf()
MDIView::deleteSelf();
}
+void AbstractSplitView::viewAll()
+{
+ for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it)
+ (*it)->viewAll();
+}
+
bool AbstractSplitView::containsViewProvider(const ViewProvider* vp) const
{
for (auto it = _viewer.begin(); it != _viewer.end(); ++it) {
@@ -307,8 +314,7 @@ const char *AbstractSplitView::getName(void) const
bool AbstractSplitView::onMsg(const char* pMsg, const char**)
{
if (strcmp("ViewFit",pMsg) == 0 ) {
- for (std::vector::iterator it = _viewer.begin(); it != _viewer.end(); ++it)
- (*it)->viewAll();
+ viewAll();
return true;
}
else if (strcmp("ViewBottom",pMsg) == 0) {
@@ -439,6 +445,8 @@ void AbstractSplitViewPy::init_type()
behaviors().doc("Python binding class for the Inventor viewer class");
// you must have overwritten the virtual functions
behaviors().supportRepr();
+ behaviors().supportGetattr();
+ behaviors().supportSetattr();
behaviors().supportSequenceType();
add_varargs_method("fitAll",&AbstractSplitViewPy::fitAll,"fitAll()");
@@ -452,10 +460,12 @@ void AbstractSplitViewPy::init_type()
add_varargs_method("viewIsometric",&AbstractSplitViewPy::viewIsometric,"viewIsometric()");
add_varargs_method("getViewer",&AbstractSplitViewPy::getViewer,"getViewer(index)");
add_varargs_method("close",&AbstractSplitViewPy::close,"close()");
+ add_varargs_method("cast_to_base", &AbstractSplitViewPy::cast_to_base, "cast_to_base() cast to MDIView class");
+ behaviors().readyType();
}
AbstractSplitViewPy::AbstractSplitViewPy(AbstractSplitView *vi)
- : _view(vi)
+ : base(vi)
{
}
@@ -463,30 +473,61 @@ AbstractSplitViewPy::~AbstractSplitViewPy()
{
}
-void AbstractSplitViewPy::testExistence()
+Py::Object AbstractSplitViewPy::cast_to_base(const Py::Tuple&)
{
- if (!(_view && _view->getViewer(0)))
- throw Py::RuntimeError("Object already deleted");
+ return Gui::MDIViewPy::create(base.getMDIViewPtr());
}
Py::Object AbstractSplitViewPy::repr()
{
- std::string s;
std::ostringstream s_out;
- if (!_view)
+ if (!getSplitViewPtr())
throw Py::RuntimeError("Cannot print representation of deleted object");
s_out << "AbstractSplitView";
return Py::String(s_out.str());
}
+// Since with PyCXX it's not possible to make a sub-class of MDIViewPy
+// a trick is to use MDIViewPy as class member and override getattr() to
+// join the attributes of both classes. This way all methods of MDIViewPy
+// appear for SheetViewPy, too.
+Py::Object AbstractSplitViewPy::getattr(const char * attr)
+{
+ getSplitViewPtr();
+ std::string name( attr );
+ if (name == "__dict__" || name == "__class__") {
+ Py::Dict dict_self(BaseType::getattr("__dict__"));
+ Py::Dict dict_base(base.getattr("__dict__"));
+ for (auto it : dict_base) {
+ dict_self.setItem(it.first, it.second);
+ }
+ return dict_self;
+ }
+
+ try {
+ return BaseType::getattr(attr);
+ }
+ catch (Py::AttributeError& e) {
+ e.clear();
+ return base.getattr(attr);
+ }
+}
+
+AbstractSplitView* AbstractSplitViewPy::getSplitViewPtr()
+{
+ AbstractSplitView* view = qobject_cast(base.getMDIViewPtr());
+ if (!(view && view->getViewer(0)))
+ throw Py::RuntimeError("Object already deleted");
+ return view;
+}
+
Py::Object AbstractSplitViewPy::fitAll(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewFit", 0);
+ getSplitViewPtr()->onMsg("ViewFit", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -504,10 +545,9 @@ Py::Object AbstractSplitViewPy::viewBottom(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewBottom", 0);
+ getSplitViewPtr()->onMsg("ViewBottom", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -526,10 +566,9 @@ Py::Object AbstractSplitViewPy::viewFront(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewFront", 0);
+ getSplitViewPtr()->onMsg("ViewFront", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -548,10 +587,9 @@ Py::Object AbstractSplitViewPy::viewLeft(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewLeft", 0);
+ getSplitViewPtr()->onMsg("ViewLeft", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -570,10 +608,9 @@ Py::Object AbstractSplitViewPy::viewRear(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewRear", 0);
+ getSplitViewPtr()->onMsg("ViewRear", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -592,10 +629,9 @@ Py::Object AbstractSplitViewPy::viewRight(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewRight", 0);
+ getSplitViewPtr()->onMsg("ViewRight", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -614,10 +650,9 @@ Py::Object AbstractSplitViewPy::viewTop(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewTop", 0);
+ getSplitViewPtr()->onMsg("ViewTop", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -636,10 +671,9 @@ Py::Object AbstractSplitViewPy::viewIsometric(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
try {
- _view->onMsg("ViewAxo", 0);
+ getSplitViewPtr()->onMsg("ViewAxo", 0);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
@@ -659,10 +693,9 @@ Py::Object AbstractSplitViewPy::getViewer(const Py::Tuple& args)
int viewIndex;
if (!PyArg_ParseTuple(args.ptr(), "i", &viewIndex))
throw Py::Exception();
- testExistence();
try {
- Gui::View3DInventorViewer* view = _view->getViewer(viewIndex);
+ Gui::View3DInventorViewer* view = getSplitViewPtr()->getViewer(viewIndex);
if (!view)
throw Py::IndexError("Index out of range");
return Py::asObject(view->getPyObject());
@@ -673,6 +706,10 @@ Py::Object AbstractSplitViewPy::getViewer(const Py::Tuple& args)
catch (const std::exception& e) {
throw Py::RuntimeError(e.what());
}
+ catch (const Py::Exception&) {
+ // re-throw
+ throw;
+ }
catch(...) {
throw Py::RuntimeError("Unknown C++ exception");
}
@@ -680,29 +717,28 @@ Py::Object AbstractSplitViewPy::getViewer(const Py::Tuple& args)
Py::Object AbstractSplitViewPy::sequence_item(ssize_t viewIndex)
{
- testExistence();
- if (viewIndex >= _view->getSize() || viewIndex < 0)
+ AbstractSplitView* view = getSplitViewPtr();
+ if (viewIndex >= view->getSize() || viewIndex < 0)
throw Py::IndexError("Index out of range");
- PyObject* viewer = _view->getViewer(viewIndex)->getPyObject();
+ PyObject* viewer = view->getViewer(viewIndex)->getPyObject();
return Py::asObject(viewer);
}
int AbstractSplitViewPy::sequence_length()
{
- testExistence();
- return _view->getSize();
+ AbstractSplitView* view = getSplitViewPtr();
+ return view->getSize();
}
Py::Object AbstractSplitViewPy::close(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();
- testExistence();
- _view->close();
- if (_view->parentWidget())
- _view->parentWidget()->deleteLater();
- _view = 0;
+ AbstractSplitView* view = getSplitViewPtr();
+ view->close();
+ if (view->parentWidget())
+ view->parentWidget()->deleteLater();
return Py::None();
}
@@ -791,3 +827,5 @@ SplitView3DInventor::SplitView3DInventor(int views, Gui::Document* pcDocument, Q
SplitView3DInventor::~SplitView3DInventor()
{
}
+
+#include "moc_SplitView3DInventor.cpp"
diff --git a/src/Gui/SplitView3DInventor.h b/src/Gui/SplitView3DInventor.h
index bbbdd6d3fd..da0bfb56a6 100644
--- a/src/Gui/SplitView3DInventor.h
+++ b/src/Gui/SplitView3DInventor.h
@@ -25,6 +25,7 @@
#define GUI_SPLITVIEW3DINVENTOR_H
#include "MDIView.h"
+#include "MDIViewPy.h"
#include
#include
@@ -39,6 +40,8 @@ class AbstractSplitViewPy;
*/
class GuiExport AbstractSplitView : public MDIView, public ParameterGrp::ObserverType
{
+ Q_OBJECT
+
TYPESYSTEM_HEADER();
public:
@@ -53,6 +56,7 @@ public:
virtual void OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason);
virtual void onUpdate(void);
virtual void deleteSelf();
+ virtual void viewAll();
View3DInventorViewer *getViewer(unsigned int) const;
void setOverrideCursor(const QCursor&);
@@ -75,12 +79,16 @@ protected:
class AbstractSplitViewPy : public Py::PythonExtension
{
public:
- static void init_type(void); // announce properties and methods
+ using BaseType = Py::PythonExtension;
+ static void init_type(); // announce properties and methods
AbstractSplitViewPy(AbstractSplitView *vi);
~AbstractSplitViewPy();
+ AbstractSplitView* getSplitViewPtr();
Py::Object repr();
+ Py::Object getattr(const char *);
+ Py::Object cast_to_base(const Py::Tuple&);
Py::Object fitAll(const Py::Tuple&);
Py::Object viewBottom(const Py::Tuple&);
@@ -96,9 +104,7 @@ public:
int sequence_length();
private:
- AbstractSplitView* _view;
- friend class AbstractSplitView;
- void testExistence();
+ Gui::MDIViewPy base;
};
/** The SplitView3DInventor class allows to create a window with two or more Inventor views.