From 45af3e2a78c7ffee952e22ab1d8677b058120359 Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Wed, 24 Apr 2013 20:50:09 +0430 Subject: [PATCH] Miscellaneous fixes --- src/Mod/Assembly/App/AppAssemblyPy.cpp | 9 +++- src/Mod/PartDesign/App/Body.cpp | 32 +++--------- src/Mod/PartDesign/Gui/Command.cpp | 55 +++++++++++---------- src/Mod/PartDesign/Gui/ViewProviderBody.cpp | 4 +- src/Mod/PartDesign/Gui/Workbench.cpp | 25 ++++++++-- src/Mod/PartDesign/Gui/Workbench.h | 7 +++ 6 files changed, 73 insertions(+), 59 deletions(-) diff --git a/src/Mod/Assembly/App/AppAssemblyPy.cpp b/src/Mod/Assembly/App/AppAssemblyPy.cpp index 812d2cdec..22473a319 100644 --- a/src/Mod/Assembly/App/AppAssemblyPy.cpp +++ b/src/Mod/Assembly/App/AppAssemblyPy.cpp @@ -45,6 +45,9 @@ Gui::Document *ActiveGuiDoc =0; App::Document *ActiveAppDoc =0; Gui::ViewProviderDocumentObject *ActiveVp =0; +// The names of the base planes. Note: The user-visible label is different from this +const char* BaseplaneNames[3] = {"BaseplaneXY", "BaseplaneYZ", "BaseplaneXZ"}; + } static PyObject * setActivePart(PyObject *self, PyObject *args) @@ -55,7 +58,9 @@ static PyObject * setActivePart(PyObject *self, PyObject *args) // Should be set! assert(Item); - if (PartDesignGui::ActivePartObject != NULL) + // Set old body inactive if we are activating another body in the same document + if ((PartDesignGui::ActivePartObject != NULL) && + (PartDesignGui::ActivePartObject->getDocument() == Item->getDocument())) PartDesignGui::ActivePartObject->IsActive.setValue(false); PartDesignGui::ActivePartObject = Item; PartDesignGui::ActiveAppDoc = Item->getDocument(); @@ -64,7 +69,7 @@ static PyObject * setActivePart(PyObject *self, PyObject *args) Item->IsActive.setValue(true); } else { // This handles the case of deactivating the workbench - PartDesignGui::ActivePartObject = 0; + PartDesignGui::ActivePartObject=0; PartDesignGui::ActiveGuiDoc =0; PartDesignGui::ActiveAppDoc =0; PartDesignGui::ActiveVp =0; diff --git a/src/Mod/PartDesign/App/Body.cpp b/src/Mod/PartDesign/App/Body.cpp index 9421be8c8..afa7f05da 100644 --- a/src/Mod/PartDesign/App/Body.cpp +++ b/src/Mod/PartDesign/App/Body.cpp @@ -113,34 +113,14 @@ const Part::TopoShape Body::getTipShape() App::DocumentObject* link = Tip.getValue(); if (!link) return Part::TopoShape(); - //Base::Console().Error("Body tip: %s\n", link->getNameInDocument()); + if (!link->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) //return new App::DocumentObjectExecReturn("Linked object is not a PartDesign object"); return Part::TopoShape(); // get the shape of the tip return static_cast(link)->Shape.getShape(); } -/* -const Part::TopoShape Body::getPreviousSolid(const PartDesign::Feature* f) -{ - std::vector features = Model.getValues(); - std::vector::const_iterator it = std::find(features.begin(), features.end(), f); - if ((it == features.end()) || (it == features.begin())) - // Wrong body or there is no previous feature - return Part::TopoShape(); - // move to previous feature - it--; - // Skip sketches and datum features - while ((*it)->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId()) || - (*it)->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) { - if (it == features.begin()) - return Part::TopoShape(); - it--; - } - return static_cast(*it)->Shape.getShape(); -} -*/ App::DocumentObject* Body::getPrevSolidFeature(App::DocumentObject *start, const bool inclusive) { std::vector features = Model.getValues(); @@ -200,8 +180,8 @@ const bool Body::isAfterTip(const App::DocumentObject *f) { const bool Body::isSolidFeature(const App::DocumentObject* f) { - return (!f->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId()) && - !f->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())); + return (f->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId()) && + !f->getTypeId().isDerivedFrom(PartDesign::Datum::getClassTypeId())); } Body* Body::findBodyOf(const App::DocumentObject* f) @@ -318,7 +298,7 @@ void Body::removeFeature(App::DocumentObject* feature) App::DocumentObjectExecReturn *Body::execute(void) { - Base::Console().Error("Checking Body '%s' for sanity\n", getNameInDocument()); + Base::Console().Error("Body '%s':\n", getNameInDocument()); App::DocumentObject* tip = Tip.getValue(); Base::Console().Error(" Tip: %s\n", (tip == NULL) ? "None" : tip->getNameInDocument()); std::vector model = Model.getValues(); @@ -326,8 +306,8 @@ App::DocumentObjectExecReturn *Body::execute(void) for (std::vector::const_iterator m = model.begin(); m != model.end(); m++) { if (*m == NULL) continue; Base::Console().Error(" %s", (*m)->getNameInDocument()); - if ((*m)->getTypeId().isDerivedFrom(PartDesign::SketchBased::getClassTypeId())) { - App::DocumentObject* baseFeature = static_cast(*m)->BaseFeature.getValue(); + if (Body::isSolidFeature(*m)) { + App::DocumentObject* baseFeature = static_cast(*m)->BaseFeature.getValue(); Base::Console().Error(", Base: %s\n", baseFeature == NULL ? "None" : baseFeature->getNameInDocument()); } else { Base::Console().Error("\n"); diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 15c8657eb..766860f16 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -77,8 +77,6 @@ using namespace std; -const char* BasePlaneNames[3] = {"Body_PlaneXY", "Body_PlaneYZ", "Body_PlaneXZ"}; - //=========================================================================== // PartDesign_Body //=========================================================================== @@ -108,7 +106,7 @@ void CmdPartDesignBody::activated(int iMsg) std::vector planes = getDocument()->getObjectsOfType(App::Plane::getClassTypeId()); for (std::vector::const_iterator p = planes.begin(); p != planes.end(); p++) { for (unsigned i = 0; i < 3; i++) { - if (strcmp(BasePlaneNames[i], (*p)->getNameInDocument()) == 0) { + if (strcmp(PartDesignGui::BaseplaneNames[i], (*p)->getNameInDocument()) == 0) { found = true; break; } @@ -118,29 +116,30 @@ void CmdPartDesignBody::activated(int iMsg) if (!found) { // Add the planes ... - doCommand(Doc,"App.activeDocument().addObject('App::Plane','%s')", BasePlaneNames[0]); - doCommand(Doc,"App.activeDocument().ActiveObject.Label = 'XY-Plane'"); - doCommand(Doc,"App.activeDocument().addObject('App::Plane','%s')", BasePlaneNames[1]); + doCommand(Doc,"App.activeDocument().addObject('App::Plane','%s')", PartDesignGui::BaseplaneNames[0]); + doCommand(Doc,"App.activeDocument().ActiveObject.Label = '%s'", QObject::tr("XY-Plane").toStdString().c_str()); + doCommand(Doc,"App.activeDocument().addObject('App::Plane','%s')", PartDesignGui::BaseplaneNames[1]); doCommand(Doc,"App.activeDocument().ActiveObject.Placement = App.Placement(App.Vector(),App.Rotation(App.Vector(0,1,0),90))"); - doCommand(Doc,"App.activeDocument().ActiveObject.Label = 'YZ-Plane'"); - doCommand(Doc,"App.activeDocument().addObject('App::Plane','%s')", BasePlaneNames[2]); + doCommand(Doc,"App.activeDocument().ActiveObject.Label = '%s'", QObject::tr("YZ-Plane").toStdString().c_str()); + doCommand(Doc,"App.activeDocument().addObject('App::Plane','%s')", PartDesignGui::BaseplaneNames[2]); doCommand(Doc,"App.activeDocument().ActiveObject.Placement = App.Placement(App.Vector(),App.Rotation(App.Vector(1,0,0),90))"); - doCommand(Doc,"App.activeDocument().ActiveObject.Label = 'XZ-Plane'"); + doCommand(Doc,"App.activeDocument().ActiveObject.Label = '%s'", QObject::tr("XZ-Plane").toStdString().c_str()); // ... and put them in the 'Origin' group - doCommand(Doc,"App.activeDocument().addObject('App::DocumentObjectGroup','Origin')"); + doCommand(Doc,"App.activeDocument().addObject('App::DocumentObjectGroup','%s')", QObject::tr("Origin").toStdString().c_str()); for (unsigned i = 0; i < 3; i++) - doCommand(Doc,"App.activeDocument().Origin.addObject(App.activeDocument().getObject('%s'))", BasePlaneNames[i]); + doCommand(Doc,"App.activeDocument().Origin.addObject(App.activeDocument().getObject('%s'))", PartDesignGui::BaseplaneNames[i]); // TODO: Fold the group (is that possible through the Python interface?) } // add the Body feature itself, and make it active doCommand(Doc,"App.activeDocument().addObject('PartDesign::Body','%s')",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Model = []",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Tip = None",FeatName.c_str()); doCommand(Doc,"import PartDesignGui"); - doCommand(Gui,"PartDesignGui.setActivePart(App.ActiveDocument.ActiveObject)"); + doCommand(Gui,"PartDesignGui.setActivePart(App.ActiveDocument.%s)", FeatName.c_str()); // Make the "Create sketch" prompt appear in the task panel doCommand(Gui,"Gui.Selection.clearSelection()"); - doCommand(Gui,"Gui.Selection.addSelection(App.ActiveDocument.ActiveObject)"); + doCommand(Gui,"Gui.Selection.addSelection(App.ActiveDocument.%s)", FeatName.c_str()); updateActive(); } @@ -281,7 +280,7 @@ const QString getReferenceString(Gui::Command* cmd) // Check whether this reference is a base plane bool base = false; for (unsigned i = 0; i < 3; i++) { - if (strcmp(BasePlaneNames[i], (*r)->getNameInDocument()) == 0) { + if (strcmp(PartDesignGui::BaseplaneNames[i], (*r)->getNameInDocument()) == 0) { status.push_back(PartDesignGui::FeaturePickDialog::basePlane); if (chosenRefs.empty()) chosenRefs.push_back(*r); @@ -325,11 +324,13 @@ const QString getReferenceString(Gui::Command* cmd) Base::Console().Warning("You have chosen more than three references for a datum feature. The extra references are being ignored"); } + // TODO: Allow user to choose front or back of the plane + referenceString = QString::fromAscii("["); for (int i = 0; i < chosenRefs.size(); i++) { referenceString += QString::fromAscii(i == 0 ? "" : ",") + QString::fromAscii("(App.activeDocument().") + QString::fromUtf8(chosenRefs[i]->getNameInDocument()) + - QString::fromAscii(",'')"); + QString::fromAscii(",'front')"); } referenceString += QString::fromAscii("]"); @@ -491,15 +492,17 @@ void CmdPartDesignNewSketch::activated(int iMsg) Gui::SelectionFilter SketchFilter("SELECT Sketcher::SketchObject COUNT 1"); Gui::SelectionFilter FaceFilter ("SELECT Part::Feature SUBELEMENT Face COUNT 1"); - Gui::SelectionFilter PlaneFilter1 ("SELECT App::Plane COUNT 1"); + Gui::SelectionFilter PlaneFilter ("SELECT App::Plane COUNT 1"); Gui::SelectionFilter PlaneFilter2 ("SELECT PartDesign::Plane COUNT 1"); + if (PlaneFilter2.match()) + PlaneFilter = PlaneFilter2; if (SketchFilter.match()) { Sketcher::SketchObject *Sketch = static_cast(SketchFilter.Result[0][0].getObject()); openCommand("Edit Sketch"); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",Sketch->getNameInDocument()); } - else if (FaceFilter.match() || PlaneFilter1.match() || PlaneFilter2.match()) { + else if (FaceFilter.match() || PlaneFilter.match()) { // get the selected object std::string supportString; @@ -534,13 +537,12 @@ void CmdPartDesignNewSketch::activated(int iMsg) supportString = FaceFilter.Result[0][0].getAsPropertyLinkSubString(); } else { - if (PlaneFilter1.match()) - supportString = PlaneFilter1.Result[0][0].getAsPropertyLinkSubString(); - else - supportString = PlaneFilter2.Result[0][0].getAsPropertyLinkSubString(); + Part::Feature *plane = static_cast(PlaneFilter.Result[0][0].getObject()); + // TODO: Find out whether the user picked front or back of this plane + supportString = std::string("(App.activeDocument().") + plane->getNameInDocument() + ", ['front'])"; } - // create Sketch on Face + // create Sketch on Face or Plane std::string FeatName = getUniqueObjectName("Sketch"); openCommand("Create a Sketch on Face"); @@ -566,7 +568,7 @@ void CmdPartDesignNewSketch::activated(int iMsg) // Check whether this plane is a base plane bool base = false; for (unsigned i = 0; i < 3; i++) { - if (strcmp(BasePlaneNames[i], (*p)->getNameInDocument()) == 0) { + if (strcmp(PartDesignGui::BaseplaneNames[i], (*p)->getNameInDocument()) == 0) { status.push_back(PartDesignGui::FeaturePickDialog::basePlane); if (firstValidPlane == planes.end()) firstValidPlane = p; @@ -609,17 +611,20 @@ void CmdPartDesignNewSketch::activated(int iMsg) firstValidPlane = planes.begin(); } + //TODO: Allow user to choose front or back of the plane + App::Plane* plane = static_cast(*firstValidPlane); Base::Vector3d p = plane->Placement.getValue().getPosition(); Base::Rotation r = plane->Placement.getValue().getRotation(); std::string FeatName = getUniqueObjectName("Sketch"); - std::string supportString = std::string("(App.activeDocument().") + plane->getNameInDocument() + ", [])"; + std::string supportString = std::string("(App.activeDocument().") + plane->getNameInDocument() + ", ['front'])"; openCommand("Create a new Sketch"); doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject','%s')",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),supportString.c_str()); - doCommand(Doc,"App.activeDocument().%s.Placement = App.Placement(App.Vector(%f,%f,%f),App.Rotation(%f,%f,%f,%f))",FeatName.c_str(),p.x,p.y,p.z,r[0],r[1],r[2],r[3]); + //doCommand(Doc,"App.activeDocument().%s.Placement = App.Placement(App.Vector(%f,%f,%f),App.Rotation(%f,%f,%f,%f))", + // FeatName.c_str(),p.x,p.y,p.z,r[0],r[1],r[2],r[3]); doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", pcActiveBody->getNameInDocument(), FeatName.c_str()); //doCommand(Gui,"Gui.activeDocument().activeView().setCamera('%s')",cam.c_str()); diff --git a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp index d92e135a3..de5729fd3 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderBody.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderBody.cpp @@ -144,11 +144,13 @@ std::vector ViewProviderBody::claimChildren3D(void)const void ViewProviderBody::updateTree() { + if (ActiveGuiDoc == NULL) return; + // Highlight active body and all its features //Base::Console().Error("ViewProviderBody::updateTree()\n"); PartDesign::Body* body = static_cast(getObject()); bool active = body->IsActive.getValue(); - //Base::Console().Error("Body is %s\n", active ? "active" : "inactive"); + //Base::Console().Error("Body is %s\n", active ? "active" : "inactive"); ActiveGuiDoc->signalHighlightObject(*this, Gui::Blue, active); std::vector features = body->Model.getValues(); bool highlight = true; diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index eb4bead40..2b7379933 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -78,10 +78,6 @@ TYPESYSTEM_SOURCE(PartDesignGui::Workbench, Gui::StdWorkbench) Workbench::Workbench() { - // Let us be notified when a document is activated, so that we can update the ActivePartObject - Gui::Application::Instance->signalActiveDocument.connect(boost::bind(&Workbench::slotActiveDocument, this, _1)); - App::GetApplication().signalNewDocument.connect(boost::bind(&Workbench::slotNewDocument, this, _1)); - App::GetApplication().signalFinishRestoreDocument.connect(boost::bind(&Workbench::slotFinishRestoreDocument, this, _1)); } Workbench::~Workbench() @@ -129,6 +125,14 @@ void Workbench::slotFinishRestoreDocument(const App::Document& Doc) switchToDocument(&Doc); } +void Workbench::slotDeleteDocument(const App::Document&) +{ + ActivePartObject = 0; + ActiveGuiDoc = 0; + ActiveAppDoc = 0; + ActiveVp = 0; +} + void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) const { if (strcmp(recipient,"Tree") == 0) @@ -297,16 +301,27 @@ void Workbench::activated() )); // make the previously used active Body active again + PartDesignGui::ActivePartObject = NULL; switchToDocument(App::GetApplication().getActiveDocument()); addTaskWatcher(Watcher); Gui::Control().showTaskView(); - + // Let us be notified when a document is activated, so that we can update the ActivePartObject + Gui::Application::Instance->signalActiveDocument.connect(boost::bind(&Workbench::slotActiveDocument, this, _1)); + App::GetApplication().signalNewDocument.connect(boost::bind(&Workbench::slotNewDocument, this, _1)); + App::GetApplication().signalFinishRestoreDocument.connect(boost::bind(&Workbench::slotFinishRestoreDocument, this, _1)); + App::GetApplication().signalDeleteDocument.connect(boost::bind(&Workbench::slotDeleteDocument, this, _1)); } void Workbench::deactivated() { + // Let us be notified when a document is activated, so that we can update the ActivePartObject + Gui::Application::Instance->signalActiveDocument.disconnect(boost::bind(&Workbench::slotActiveDocument, this, _1)); + App::GetApplication().signalNewDocument.disconnect(boost::bind(&Workbench::slotNewDocument, this, _1)); + App::GetApplication().signalFinishRestoreDocument.disconnect(boost::bind(&Workbench::slotFinishRestoreDocument, this, _1)); + App::GetApplication().signalDeleteDocument.disconnect(boost::bind(&Workbench::slotDeleteDocument, this, _1)); + removeTaskWatcher(); // reset the active Body Gui::Command::doCommand(Gui::Command::Doc,"import PartDesignGui"); diff --git a/src/Mod/PartDesign/Gui/Workbench.h b/src/Mod/PartDesign/Gui/Workbench.h index 51d1c5b3d..3c1af1f86 100644 --- a/src/Mod/PartDesign/Gui/Workbench.h +++ b/src/Mod/PartDesign/Gui/Workbench.h @@ -47,6 +47,8 @@ extern PartDesign::Body *ActivePartObject; extern Gui::Document *ActiveGuiDoc; extern App::Document *ActiveAppDoc; extern Gui::ViewProviderDocumentObject *ActiveVp; +// The names of the base planes +extern const char* BaseplaneNames[3]; /// Return active body or show a warning message PartDesign::Body *getBody(void); @@ -76,9 +78,14 @@ protected: Gui::ToolBarItem* setupCommandBars() const; private: + /// Refresh the Body's highlighting when a document becomes active void slotActiveDocument(const Gui::Document&); + /// Refresh the highlighting. Migrate legacy documents on loading void slotFinishRestoreDocument(const App::Document&); + /// Ensure that there are base planes and a body in a new document void slotNewDocument(const App::Document&); + /// Update the ActivePartObject etc. when a document is closed + void slotDeleteDocument(const App::Document&); }; } // namespace PartDesignGui