diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index b36273d0b9..c15445d6c9 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -96,6 +96,7 @@ #include "SplitView3DInventor.h" #include "View3DInventor.h" #include "ViewProvider.h" +#include "ViewProviderDocumentObject.h" #include "ViewProviderExtension.h" #include "ViewProviderExtern.h" #include "ViewProviderFeature.h" @@ -678,8 +679,9 @@ void Application::slotNewDocument(const App::Document& Doc) pDoc->signalChangedObject.connect(boost::bind(&Gui::Application::slotChangedObject, this, _1, _2)); pDoc->signalRelabelObject.connect(boost::bind(&Gui::Application::slotRelabelObject, this, _1)); pDoc->signalActivatedObject.connect(boost::bind(&Gui::Application::slotActivatedObject, this, _1)); - - + pDoc->signalInEdit.connect(boost::bind(&Gui::Application::slotInEdit, this, _1)); + pDoc->signalResetEdit.connect(boost::bind(&Gui::Application::slotResetEdit, this, _1)); + signalNewDocument(*pDoc); pDoc->createView(View3DInventor::getClassTypeId()); // FIXME: Do we really need this further? Calling processEvents() mixes up order of execution in an @@ -781,6 +783,16 @@ void Application::slotActivatedObject(const ViewProvider& vp) this->signalActivatedObject(vp); } +void Application::slotInEdit(const Gui::ViewProviderDocumentObject& vp) +{ + this->signalInEdit(vp); +} + +void Application::slotResetEdit(const Gui::ViewProviderDocumentObject& vp) +{ + this->signalResetEdit(vp); +} + void Application::onLastWindowClosed(Gui::Document* pcDoc) { if (!d->isClosing && pcDoc) { diff --git a/src/Gui/Application.h b/src/Gui/Application.h index eda3a1962f..73ca82a56d 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -43,6 +43,7 @@ class MDIView; class MainWindow; class MenuItem; class ViewProvider; +class ViewProviderDocumentObject; /** The Application main class * This is the central class of the GUI @@ -115,6 +116,10 @@ public: boost::signal signalRemoveWorkbench; /// signal on activating view boost::signal signalActivateView; + /// signal on entering in edit mode + boost::signal signalInEdit; + /// signal on leaving edit mode + boost::signal signalResetEdit; //@} /** @name methods for Document handling */ @@ -131,6 +136,8 @@ protected: void slotChangedObject(const ViewProvider&, const App::Property& Prop); void slotRelabelObject(const ViewProvider&); void slotActivatedObject(const ViewProvider&); + void slotInEdit(const Gui::ViewProviderDocumentObject&); + void slotResetEdit(const Gui::ViewProviderDocumentObject&); public: /// message when a GuiDocument is about to vanish diff --git a/src/Gui/DocumentObserverPython.cpp b/src/Gui/DocumentObserverPython.cpp index 9177126c2f..ddcb8ae0b7 100644 --- a/src/Gui/DocumentObserverPython.cpp +++ b/src/Gui/DocumentObserverPython.cpp @@ -29,6 +29,7 @@ #include "Application.h" #include "Document.h" #include "ViewProvider.h" +#include "ViewProviderDocumentObject.h" #include "DocumentObserverPython.h" #include #include @@ -77,6 +78,11 @@ DocumentObserverPython::DocumentObserverPython(const Py::Object& obj) : inst(obj this->connectDocumentChangedObject = Gui::Application::Instance->signalChangedObject.connect(boost::bind (&DocumentObserverPython::slotChangedObject, this, _1, _2)); + this->connectDocumentObjectInEdit = Gui::Application::Instance->signalInEdit.connect(boost::bind + (&DocumentObserverPython::slotInEdit, this, _1)); + this->connectDocumentObjectResetEdit = Gui::Application::Instance->signalResetEdit.connect(boost::bind + (&DocumentObserverPython::slotResetEdit, this, _1)); + } DocumentObserverPython::~DocumentObserverPython() @@ -90,6 +96,9 @@ DocumentObserverPython::~DocumentObserverPython() this->connectDocumentCreatedObject.disconnect(); this->connectDocumentDeletedObject.disconnect(); this->connectDocumentChangedObject.disconnect(); + + this->connectDocumentObjectInEdit.disconnect(); + this->connectDocumentObjectResetEdit.disconnect(); } void DocumentObserverPython::slotCreatedDocument(const Gui::Document& Doc) @@ -234,3 +243,37 @@ void DocumentObserverPython::slotChangedObject(const Gui::ViewProvider& Obj, e.ReportException(); } } + +void DocumentObserverPython::slotInEdit(const Gui::ViewProviderDocumentObject& Obj) +{ + Base::PyGILStateLocker lock; + try { + if (this->inst.hasAttr(std::string("slotInEdit"))) { + Py::Callable method(this->inst.getAttr(std::string("slotInEdit"))); + Py::Tuple args(1); + args.setItem(0, Py::Object(const_cast(Obj).getPyObject(), true)); + method.apply(args); + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} + +void DocumentObserverPython::slotResetEdit(const Gui::ViewProviderDocumentObject& Obj) +{ + Base::PyGILStateLocker lock; + try { + if (this->inst.hasAttr(std::string("slotResetEdit"))) { + Py::Callable method(this->inst.getAttr(std::string("slotResetEdit"))); + Py::Tuple args(1); + args.setItem(0, Py::Object(const_cast(Obj).getPyObject(), true)); + method.apply(args); + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } +} diff --git a/src/Gui/DocumentObserverPython.h b/src/Gui/DocumentObserverPython.h index 0087b97b7f..280e26887c 100644 --- a/src/Gui/DocumentObserverPython.h +++ b/src/Gui/DocumentObserverPython.h @@ -66,6 +66,10 @@ private: void slotDeletedObject(const Gui::ViewProvider& Obj); /** The property of an observed object has changed */ void slotChangedObject(const Gui::ViewProvider& Obj, const App::Property& Prop); + /** The object was set into edit mode */ + void slotInEdit(const Gui::ViewProviderDocumentObject& Obj); + /** The has left edit mode */ + void slotResetEdit(const Gui::ViewProviderDocumentObject& Obj); private: Py::Object inst; @@ -80,6 +84,8 @@ private: Connection connectDocumentCreatedObject; Connection connectDocumentDeletedObject; Connection connectDocumentChangedObject; + Connection connectDocumentObjectInEdit; + Connection connectDocumentObjectResetEdit; }; } //namespace Gui diff --git a/src/Mod/Test/Document.py b/src/Mod/Test/Document.py index 87e0ba5af6..b1e6224a08 100644 --- a/src/Mod/Test/Document.py +++ b/src/Mod/Test/Document.py @@ -1446,6 +1446,13 @@ class DocumentObserverCases(unittest.TestCase): self.parameter.append(obj) self.parameter2.append(prop) + def slotInEdit(self, obj): + self.signal.append('ObjInEdit'); + self.parameter.append(obj) + + def slotResetEdit(self, obj): + self.signal.append('ObjResetEdit'); + self.parameter.append(obj) def setUp(self): self.Obs = self.Observer(); @@ -1631,7 +1638,10 @@ class DocumentObserverCases(unittest.TestCase): self.Obs.parameter2 = [] def testGuiObserver(self): - + + if not FreeCAD.GuiUp: + return + self.GuiObs = self.GuiObserver() FreeCAD.Gui.addDocumentObserver(self.GuiObs) self.Doc1 = FreeCAD.newDocument("Observer1"); @@ -1682,7 +1692,7 @@ class DocumentObserverCases(unittest.TestCase): self.failUnless(self.GuiObs.signal.pop(0) == 'ObjChanged') self.failUnless(self.GuiObs.parameter.pop(0) is obj.ViewObject) self.failUnless(self.GuiObs.parameter2.pop(0) == "Visibility") - self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2) + self.failUnless(not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2) obj.ViewObject.addProperty("App::PropertyLength","Prop","Group","test property") self.failUnless(self.Obs.signal.pop() == 'ObjAddDynProp') @@ -1705,6 +1715,18 @@ class DocumentObserverCases(unittest.TestCase): self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2) self.failUnless(not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2) + self.GuiDoc1.setEdit('obj', 0) + self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2) + self.failUnless(self.GuiObs.signal.pop(0) == 'ObjInEdit') + self.failUnless(self.GuiObs.parameter.pop(0) is obj.ViewObject) + self.failUnless(not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2) + + self.GuiDoc1.resetEdit() + self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2) + self.failUnless(self.GuiObs.signal.pop(0) == 'ObjResetEdit') + self.failUnless(self.GuiObs.parameter.pop(0) is obj.ViewObject) + self.failUnless(not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2) + vo = obj.ViewObject FreeCAD.ActiveDocument.removeObject(obj.Name) self.failUnless(self.Obs.signal.pop() == 'ObjDeleted') @@ -1722,6 +1744,8 @@ class DocumentObserverCases(unittest.TestCase): self.failUnless(self.GuiObs.parameter.pop() is self.GuiDoc1) self.failUnless(not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2) + FreeCAD.Gui.removeDocumentObserver(self.GuiObs) + def tearDown(self): #closing doc FreeCAD.removeDocumentObserver(self.Obs)