Gui: make AbstractSplitViewPy acting as sub-class of MDIViewPy

This commit is contained in:
wmayer
2021-11-21 18:59:28 +01:00
parent d64b698d05
commit 292f6dcaa7
2 changed files with 86 additions and 42 deletions

View File

@@ -38,6 +38,7 @@
#include "Application.h"
#include "NavigationStyle.h"
#include "View3DPy.h"
#include <Base/Interpreter.h>
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<AbstractSplitViewPy*>(_viewerPy)->_view = 0;
Base::PyGILStateLocker lock;
Py_DECREF(_viewerPy);
}
}
@@ -72,6 +73,12 @@ void AbstractSplitView::deleteSelf()
MDIView::deleteSelf();
}
void AbstractSplitView::viewAll()
{
for (std::vector<View3DInventorViewer*>::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<View3DInventorViewer*>::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<AbstractSplitView*>(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"

View File

@@ -25,6 +25,7 @@
#define GUI_SPLITVIEW3DINVENTOR_H
#include "MDIView.h"
#include "MDIViewPy.h"
#include <Base/Parameter.h>
#include <CXX/Extensions.hxx>
@@ -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<AbstractSplitViewPy>
{
public:
static void init_type(void); // announce properties and methods
using BaseType = Py::PythonExtension<AbstractSplitViewPy>;
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.