Skip to content

Commit

Permalink
fixes #4125: MDIViews not accessible correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
wwmayer committed Sep 15, 2019
1 parent 4631b26 commit 1bfe0f3
Show file tree
Hide file tree
Showing 14 changed files with 276 additions and 8 deletions.
4 changes: 4 additions & 0 deletions src/Gui/Application.cpp
Expand Up @@ -85,6 +85,7 @@
#include "SoFCDB.h"
#include "PythonConsolePy.h"
#include "PythonDebugger.h"
#include "MDIViewPy.h"
#include "View3DPy.h"
#include "DlgOnlineHelpImp.h"
#include "SpaceballEvent.h"
Expand All @@ -93,6 +94,7 @@
#include "TransactionObject.h"
#include "FileDialog.h"

#include "TextDocumentEditorView.h"
#include "SplitView3DInventor.h"
#include "View3DInventor.h"
#include "ViewProvider.h"
Expand Down Expand Up @@ -430,6 +432,7 @@ Application::Application(bool GUIenabled)
OutputStdout ::init_type();
OutputStderr ::init_type();
PythonStdin ::init_type();
MDIViewPy ::init_type();
View3DInventorPy ::init_type();
View3DInventorViewerPy ::init_type();
AbstractSplitViewPy ::init_type();
Expand Down Expand Up @@ -1654,6 +1657,7 @@ void Application::initTypes(void)
Gui::View3DInventor ::init();
Gui::AbstractSplitView ::init();
Gui::SplitView3DInventor ::init();
Gui::TextDocumentEditorView ::init();
// View Provider
Gui::ViewProvider ::init();
Gui::ViewProviderExtension ::init();
Expand Down
2 changes: 2 additions & 0 deletions src/Gui/CMakeLists.txt
Expand Up @@ -1133,11 +1133,13 @@ SOURCE_GROUP("Widget" FILES ${Widget_SRCS})
# The view sources
SET(View_CPP_SRCS
MDIView.cpp
MDIViewPy.cpp
GraphvizView.cpp
ActiveObjectList.cpp
)
SET(View_HPP_SRCS
MDIView.h
MDIViewPy.h
GraphvizView.h
ActiveObjectList.h
)
Expand Down
24 changes: 22 additions & 2 deletions src/Gui/MDIView.cpp
Expand Up @@ -36,6 +36,7 @@


#include "MDIView.h"
#include "MDIViewPy.h"
#include "Command.h"
#include "Document.h"
#include "Application.h"
Expand All @@ -44,11 +45,15 @@

using namespace Gui;

TYPESYSTEM_SOURCE_ABSTRACT(Gui::MDIView,Gui::BaseView);
TYPESYSTEM_SOURCE_ABSTRACT(Gui::MDIView,Gui::BaseView)


MDIView::MDIView(Gui::Document* pcDocument,QWidget* parent, Qt::WindowFlags wflags)
: QMainWindow(parent, wflags), BaseView(pcDocument),currentMode(Child), wstate(Qt::WindowNoState)
: QMainWindow(parent, wflags)
, BaseView(pcDocument)
, pythonObject(nullptr)
, currentMode(Child)
, wstate(Qt::WindowNoState)
, ActiveObjects(pcDocument)
{
setAttribute(Qt::WA_DeleteOnClose);
Expand Down Expand Up @@ -83,6 +88,12 @@ MDIView::~MDIView()
}
if (connectDelObject.connected())
connectDelObject.disconnect();

if (pythonObject) {
Base::PyGILStateLocker lock;
Py_DECREF(pythonObject);
pythonObject = nullptr;
}
}

void MDIView::deleteSelf()
Expand Down Expand Up @@ -111,6 +122,15 @@ void MDIView::deleteSelf()
_pcDocument = 0;
}

PyObject* MDIView::getPyObject()
{
if (!pythonObject)
pythonObject = new MDIViewPy(this);

Py_INCREF(pythonObject);
return pythonObject;
}

void MDIView::setOverrideCursor(const QCursor& c)
{
Q_UNUSED(c);
Expand Down
6 changes: 5 additions & 1 deletion src/Gui/MDIView.h
Expand Up @@ -55,7 +55,6 @@ class GuiExport MDIView : public QMainWindow, public BaseView

TYPESYSTEM_HEADER();


public:
/** View constructor
* Attach the view to the given document. If the document is zero
Expand All @@ -80,10 +79,12 @@ class GuiExport MDIView : public QMainWindow, public BaseView
virtual bool canClose(void);
/// delete itself
virtual void deleteSelf();
virtual PyObject *getPyObject();
/** @name Printing */
//@{
public Q_SLOTS:
virtual void print(QPrinter* printer);

public:
/** Print content of view */
virtual void print();
Expand Down Expand Up @@ -149,6 +150,9 @@ protected Q_SLOTS:
/** \internal */
void changeEvent(QEvent *e);

protected:
PyObject* pythonObject;

private:
ViewMode currentMode;
Qt::WindowStates wstate;
Expand Down
172 changes: 172 additions & 0 deletions src/Gui/MDIViewPy.cpp
@@ -0,0 +1,172 @@
/***************************************************************************
* 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 *
* *
***************************************************************************/


#include "PreCompiled.h"

#include "MDIViewPy.h"
#include "Application.h"
#include "Document.h"

#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Interpreter.h>
#include <Base/PlacementPy.h>
#include <Base/Rotation.h>
#include <Base/RotationPy.h>
#include <Base/VectorPy.h>
#include <Base/GeometryPyCXX.h>

#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/DocumentObjectPy.h>
#include <App/GeoFeature.h>
#include <CXX/Objects.hxx>

using namespace Gui;


void MDIViewPy::init_type()
{
behaviors().name("MDIViewPy");
behaviors().doc("Python binding class for the MDI view class");
// you must have overwritten the virtual functions
behaviors().supportRepr();
behaviors().supportGetattr();
behaviors().supportSetattr();

add_varargs_method("message",&MDIViewPy::message,"message()");
add_varargs_method("fitAll",&MDIViewPy::fitAll,"fitAll()");
add_varargs_method("setActiveObject", &MDIViewPy::setActiveObject, "setActiveObject(name,object,subname=None)\nadd or set a new active object");
add_varargs_method("getActiveObject", &MDIViewPy::getActiveObject, "getActiveObject(name,resolve=True)\nreturns the active object for the given type");
}

MDIViewPy::MDIViewPy(MDIView *mdi)
: _view(mdi)
{
}

MDIViewPy::~MDIViewPy()
{
}

Py::Object MDIViewPy::repr()
{
std::string s;
std::ostringstream s_out;
if (!_view)
throw Py::RuntimeError("Cannot print representation of deleted object");
s_out << "MDIView";
return Py::String(s_out.str());
}

Py::Object MDIViewPy::message(const Py::Tuple& args)
{
const char **ppReturn = 0;
char *psMsgStr;
if (!PyArg_ParseTuple(args.ptr(), "s;Message string needed (string)",&psMsgStr)) // convert args: Python->C
throw Py::Exception();

try {
if (_view)
_view->onMsg(psMsgStr,ppReturn);
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
}
catch (const std::exception& e) {
throw Py::RuntimeError(e.what());
}
catch (...) {
throw Py::RuntimeError("Unknown C++ exception");
}
return Py::None();
}

Py::Object MDIViewPy::fitAll(const Py::Tuple& args)
{
if (!PyArg_ParseTuple(args.ptr(), ""))
throw Py::Exception();

try {
if (_view)
_view->viewAll();
}
catch (const Base::Exception& e) {
throw Py::RuntimeError(e.what());
}
catch (const std::exception& e) {
throw Py::RuntimeError(e.what());
}
catch (...) {
throw Py::RuntimeError("Unknown C++ exception");
}
return Py::None();
}

Py::Object MDIViewPy::setActiveObject(const Py::Tuple& args)
{
PyObject* docObject = Py_None;
char* name;
char *subname = 0;
if (!PyArg_ParseTuple(args.ptr(), "s|Os", &name, &docObject, &subname))
throw Py::Exception();

if (_view) {
if (docObject == Py_None) {
_view->setActiveObject(0, name);
}
else {
if (!PyObject_TypeCheck(docObject, &App::DocumentObjectPy::Type))
throw Py::TypeError("Expect the second argument to be a document object or None");

App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(docObject)->getDocumentObjectPtr();
_view->setActiveObject(obj, name, subname);
}
}

return Py::None();
}

Py::Object MDIViewPy::getActiveObject(const Py::Tuple& args)
{
const char* name;
PyObject *resolve = Py_True;
if (!PyArg_ParseTuple(args.ptr(), "s|O", &name,&resolve))
throw Py::Exception();

App::DocumentObject *parent = nullptr;
std::string subname;
App::DocumentObject* obj = nullptr;
if (_view)
obj = _view->getActiveObject<App::DocumentObject*>(name,&parent,&subname);
if (!obj)
return Py::None();

if (PyObject_IsTrue(resolve))
return Py::asObject(obj->getPyObject());

return Py::TupleN(
Py::asObject(obj->getPyObject()),
Py::asObject(parent->getPyObject()),
Py::String(subname.c_str()));
}
57 changes: 57 additions & 0 deletions src/Gui/MDIViewPy.h
@@ -0,0 +1,57 @@
/***************************************************************************
* 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_MDIVIEWPY_H
#define GUI_MDIVIEWPY_H

#include <Base/PyObjectBase.h>
#include <CXX/Extensions.hxx>
#include <QPointer>

namespace Gui {
class MDIView;

class MDIViewPy : public Py::PythonExtension<MDIViewPy>
{
public:
static void init_type(void); // announce properties and methods

MDIViewPy(MDIView *mdi);
~MDIViewPy();

Py::Object repr();

Py::Object message(const Py::Tuple&);
Py::Object fitAll(const Py::Tuple&);
Py::Object setActiveObject(const Py::Tuple&);
Py::Object getActiveObject(const Py::Tuple&);

MDIView* getMDIViewPtr() {return _view.data();}

private:
QPointer<MDIView> _view;
};

} // namespace Gui

#endif //GUI_MDIVIEWPY_H
2 changes: 2 additions & 0 deletions src/Gui/TextDocumentEditorView.cpp
Expand Up @@ -40,6 +40,8 @@

using namespace Gui;

TYPESYSTEM_SOURCE_ABSTRACT(Gui::TextDocumentEditorView, Gui::MDIView)

TextDocumentEditorView::TextDocumentEditorView(
App::TextDocument* txtDoc, QPlainTextEdit* e,
QWidget* parent)
Expand Down
2 changes: 2 additions & 0 deletions src/Gui/TextDocumentEditorView.h
Expand Up @@ -39,6 +39,8 @@ namespace Gui {

class GuiExport TextDocumentEditorView : public MDIView {
Q_OBJECT
TYPESYSTEM_HEADER();

public:
TextDocumentEditorView(
App::TextDocument* textDocument,
Expand Down
2 changes: 1 addition & 1 deletion src/Gui/View3DInventor.cpp
Expand Up @@ -105,7 +105,7 @@ void GLOverlayWidget::paintEvent(QPaintEvent*)

/* TRANSLATOR Gui::View3DInventor */

TYPESYSTEM_SOURCE_ABSTRACT(Gui::View3DInventor,Gui::MDIView);
TYPESYSTEM_SOURCE_ABSTRACT(Gui::View3DInventor,Gui::MDIView)

View3DInventor::View3DInventor(Gui::Document* pcDocument, QWidget* parent,
const QtGLWidget* sharewidget, Qt::WindowFlags wflags)
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp
Expand Up @@ -117,7 +117,7 @@ PyMOD_INIT_FUNC(SpreadsheetGui)

SpreadsheetGui::ViewProviderSheet::init();
SpreadsheetGui::Workbench::init();
// SpreadsheetGui::SheetView::init();
SpreadsheetGui::SheetView::init();

// add resources and reloads the translators
loadSpreadsheetResource();
Expand Down

0 comments on commit 1bfe0f3

Please sign in to comment.