From ffc09ec50c2ef63067831eda0c8898495eb99aa7 Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Thu, 16 May 2013 14:46:33 +0430 Subject: [PATCH] Duplicate Selection: Add duplicated features to active Body --- src/Mod/PartDesign/App/Body.cpp | 7 +++ src/Mod/PartDesign/Gui/Command.cpp | 79 ++++++++++++++++++++++++++++ src/Mod/PartDesign/Gui/Workbench.cpp | 23 ++++++++ src/Mod/PartDesign/Gui/Workbench.h | 2 + 4 files changed, 111 insertions(+) diff --git a/src/Mod/PartDesign/App/Body.cpp b/src/Mod/PartDesign/App/Body.cpp index de1014f9b..c95718381 100644 --- a/src/Mod/PartDesign/App/Body.cpp +++ b/src/Mod/PartDesign/App/Body.cpp @@ -196,6 +196,13 @@ const bool Body::isAllowed(const App::DocumentObject* f) void Body::addFeature(App::DocumentObject *feature) { + /* + // Remove this test if Workbench::slotNewObject() has been tested sufficiently in respect to Undo() and + // the addFeature() calls have been removed in Command.cpp + if (hasFeature(feature)) + return; + */ + // Set the BaseFeature property if (feature->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId())) { App::DocumentObject* prevSolidFeature = getPrevSolidFeature(NULL, true); diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index e3b0fb541..d15448cb1 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -210,6 +210,78 @@ bool CmdPartDesignMoveTip::isActive(void) return hasActiveDocument(); } +//=========================================================================== +// PartDesign_DuplicateSelection +//=========================================================================== + +DEF_STD_CMD_A(CmdPartDesignDuplicateSelection); + +CmdPartDesignDuplicateSelection::CmdPartDesignDuplicateSelection() + :Command("PartDesign_DuplicateSelection") +{ + sAppModule = "PartDesign"; + sGroup = QT_TR_NOOP("PartDesign"); + sMenuText = QT_TR_NOOP("Duplicate selected object"); + sToolTipText = QT_TR_NOOP("Duplicates the selected object and adds it to the active body"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; + sPixmap = ""; +} + +void CmdPartDesignDuplicateSelection::activated(int iMsg) +{ + PartDesign::Body *pcActiveBody = PartDesignGui::getBody(); + if(!pcActiveBody) return; + + std::vector features = getSelection().getObjectsOfType(Part::Feature::getClassTypeId()); + if (features.empty()) return; + App::DocumentObject* selFeature = features.front(); + + if (!pcActiveBody->hasFeature(selFeature)) { + // NOTE: We assume all selected features will be in the same document + // Switch to other body + pcActiveBody = static_cast(Part::BodyBase::findBodyOf(selFeature)); + if (pcActiveBody != NULL) + Gui::Command::doCommand(Gui::Command::Gui,"PartDesignGui.setActivePart(App.activeDocument().%s)", + pcActiveBody->getNameInDocument()); + else + return; + } + + std::vector beforeFeatures = PartDesignGui::ActiveAppDoc->getObjects(); + + openCommand("Duplicate a PartDesign object"); + doCommand(Doc,"FreeCADGui.runCommand('Std_DuplicateSelection')"); + + // Find the features that were added + std::vector afterFeatures = PartDesignGui::ActiveAppDoc->getObjects(); + std::vector newFeatures; + std::set_difference(afterFeatures.begin(), afterFeatures.end(), beforeFeatures.begin(), beforeFeatures.end(), + std::back_inserter(newFeatures)); + + for (std::vector::const_iterator f = newFeatures.begin(); f != newFeatures.end(); f++) { + if (PartDesign::Body::isAllowed(*f)) { + doCommand(Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", + pcActiveBody->getNameInDocument(), (*f)->getNameInDocument()); + doCommand(Gui,"Gui.activeDocument().hide(\"%s\")", (*f)->getNameInDocument()); + } + } + + // Adjust visibility of features + doCommand(Gui,"Gui.activeDocument().show(\"%s\")", newFeatures.back()->getNameInDocument()); + App::DocumentObject* prevSolidFeature = pcActiveBody->getPrevSolidFeature(); + if ((prevSolidFeature != NULL) && !PartDesign::Body::isSolidFeature(selFeature)) + doCommand(Gui,"Gui.activeDocument().show(\"%s\")", prevSolidFeature->getNameInDocument()); +} + +bool CmdPartDesignDuplicateSelection::isActive(void) +{ + if (getActiveGuiDocument()) + return true; + else + return false; +} + //=========================================================================== // PartDesign_Datum //=========================================================================== @@ -1524,17 +1596,24 @@ void CreatePartDesignCommands(void) rcCmdMgr.addCommand(new CmdPartDesignBody()); rcCmdMgr.addCommand(new CmdPartDesignMoveTip()); + + rcCmdMgr.addCommand(new CmdPartDesignDuplicateSelection()); + rcCmdMgr.addCommand(new CmdPartDesignPlane()); rcCmdMgr.addCommand(new CmdPartDesignLine()); rcCmdMgr.addCommand(new CmdPartDesignPoint()); + rcCmdMgr.addCommand(new CmdPartDesignNewSketch()); + rcCmdMgr.addCommand(new CmdPartDesignPad()); rcCmdMgr.addCommand(new CmdPartDesignPocket()); rcCmdMgr.addCommand(new CmdPartDesignRevolution()); rcCmdMgr.addCommand(new CmdPartDesignGroove()); + rcCmdMgr.addCommand(new CmdPartDesignFillet()); rcCmdMgr.addCommand(new CmdPartDesignDraft()); rcCmdMgr.addCommand(new CmdPartDesignChamfer()); + rcCmdMgr.addCommand(new CmdPartDesignMirrored()); rcCmdMgr.addCommand(new CmdPartDesignLinearPattern()); rcCmdMgr.addCommand(new CmdPartDesignPolarPattern()); diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index d0daf7219..b85029593 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -256,6 +256,21 @@ void Workbench::slotDeleteDocument(const App::Document&) ActiveAppDoc = 0; ActiveVp = 0; } +/* + This does not work for Std_DuplicateSelection: + Tree.cpp gives: "Cannot reparent unknown object", probably because the signalNewObject is emitted + before the duplication of the object has been completely finished + +void Workbench::slotNewObject(const App::DocumentObject& obj) +{ + if ((obj.getDocument() == ActiveAppDoc) && (ActivePartObject != NULL)) { + // Add the new object to the active Body + // Note: Will this break Undo? But how else can we catch Edit->Duplicate selection? + Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)", + ActivePartObject->getNameInDocument(), obj.getNameInDocument()); + } +} +*/ void Workbench::setupContextMenu(const char* recipient, Gui::MenuItem* item) const { @@ -437,6 +452,8 @@ void Workbench::activated() 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)); + // Watch out for objects being added to the active document, so that we can add them to the body + //App::GetApplication().signalNewObject.connect(boost::bind(&Workbench::slotNewObject, this, _1)); } void Workbench::deactivated() @@ -446,6 +463,7 @@ void Workbench::deactivated() 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)); + //App::GetApplication().signalNewObject.disconnect(boost::bind(&Workbench::slotNewObject, this, _1)); removeTaskWatcher(); // reset the active Body @@ -513,6 +531,11 @@ Gui::MenuItem* Workbench::setupMenuBar() const *part << "Separator" << "PartDesign_WizardShaft"; } + // Replace the "Duplicate selection" menu item with a replacement that is compatible with Body + item = root->findItem("&Edit"); + Gui::MenuItem* dup = item->findItem("Std_DuplicateSelection"); + dup->setCommand("PartDesign_DuplicateSelection"); + return root; } diff --git a/src/Mod/PartDesign/Gui/Workbench.h b/src/Mod/PartDesign/Gui/Workbench.h index 3c1af1f86..bfaf79011 100644 --- a/src/Mod/PartDesign/Gui/Workbench.h +++ b/src/Mod/PartDesign/Gui/Workbench.h @@ -86,6 +86,8 @@ private: void slotNewDocument(const App::Document&); /// Update the ActivePartObject etc. when a document is closed void slotDeleteDocument(const App::Document&); + // Add new objects to the body, if appropriate + //void slotNewObject(const App::DocumentObject& obj); }; } // namespace PartDesignGui