// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2002 Jürgen Riegel * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "BoxSelection.h" #include "CrossSections.h" #include "DlgBooleanOperation.h" #include "DlgExtrusion.h" #include "DlgScale.h" #include "DlgFilletEdges.h" #include "DlgPrimitives.h" #include "DlgProjectionOnSurface.h" #include "DlgRevolution.h" #include "Mirroring.h" #include "SectionCutting.h" #include "TaskCheckGeometry.h" #include "TaskLoft.h" #include "TaskShapeBuilder.h" #include "TaskSweep.h" #include "ViewProvider.h" //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //=========================================================================== // Part_PickCurveNet //=========================================================================== DEF_STD_CMD(CmdPartPickCurveNet) CmdPartPickCurveNet::CmdPartPickCurveNet() : Command("Part_PickCurveNet") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Pick Curve Network"); sToolTipText = QT_TR_NOOP("Picks a curve network"); sWhatsThis = "Part_PickCurveNet"; sStatusTip = sToolTipText; sPixmap = "Test1"; } void CmdPartPickCurveNet::activated(int iMsg) { Q_UNUSED(iMsg); } //=========================================================================== // Part_NewDoc //=========================================================================== DEF_STD_CMD(CmdPartNewDoc) CmdPartNewDoc::CmdPartNewDoc() : Command("Part_NewDoc") { sAppModule = "Part"; sGroup = "Part"; sMenuText = "New Document"; sToolTipText = "Creates an Empty Part Document"; sWhatsThis = "Part_NewDoc"; sStatusTip = sToolTipText; sPixmap = "New"; } void CmdPartNewDoc::activated(int iMsg) { Q_UNUSED(iMsg); doCommand(Doc, "d = App.New()"); updateActive(); } //=========================================================================== // Part_Box2 //=========================================================================== DEF_STD_CMD_A(CmdPartBox2) CmdPartBox2::CmdPartBox2() : Command("Part_Box2") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Box Fix 1"); sToolTipText = QT_TR_NOOP("Creates a solid box"); sWhatsThis = "Part_Box2"; sStatusTip = sToolTipText; sPixmap = "Part_Box_Parametric"; } void CmdPartBox2::activated(int iMsg) { Q_UNUSED(iMsg); openCommand(QT_TRANSLATE_NOOP("Command", "Part Box Create")); doCommand(Doc, "from FreeCAD import Base"); doCommand(Doc, "import Part"); doCommand(Doc, "__fb__ = App.ActiveDocument.addObject(\"Part::Box\",\"PartBox\")"); doCommand(Doc, "__fb__.Location = Base.Vector(0.0,0.0,0.0)"); doCommand(Doc, "__fb__.Length = 100.0"); doCommand(Doc, "__fb__.Width = 100.0"); doCommand(Doc, "__fb__.Height = 100.0"); doCommand(Doc, "del __fb__"); commitCommand(); updateActive(); } bool CmdPartBox2::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // Part_Box3 //=========================================================================== DEF_STD_CMD_A(CmdPartBox3) CmdPartBox3::CmdPartBox3() : Command("Part_Box3") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Box Fix 2"); sToolTipText = QT_TR_NOOP("Creates a solid box"); sWhatsThis = "Part_Box3"; sStatusTip = sToolTipText; sPixmap = "Part_Box_Parametric"; } void CmdPartBox3::activated(int iMsg) { Q_UNUSED(iMsg); openCommand(QT_TRANSLATE_NOOP("Command", "Part Box Create")); doCommand(Doc, "from FreeCAD import Base"); doCommand(Doc, "import Part"); doCommand(Doc, "__fb__ = App.ActiveDocument.addObject(\"Part::Box\",\"PartBox\")"); doCommand(Doc, "__fb__.Location = Base.Vector(50.0,50.0,50.0)"); doCommand(Doc, "__fb__.Length = 100.0"); doCommand(Doc, "__fb__.Width = 100.0"); doCommand(Doc, "__fb__.Height = 100.0"); doCommand(Doc, "del __fb__"); commitCommand(); updateActive(); } bool CmdPartBox3::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // Part_Primitives //=========================================================================== DEF_STD_CMD_A(CmdPartPrimitives) CmdPartPrimitives::CmdPartPrimitives() : Command("Part_Primitives") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Primitive"); sToolTipText = QT_TR_NOOP("Creates solid geometric primitives parametrically"); sWhatsThis = "Part_Primitives"; sStatusTip = sToolTipText; sPixmap = "Part_Primitives"; } void CmdPartPrimitives::activated(int iMsg) { Q_UNUSED(iMsg); PartGui::TaskPrimitives* dlg = new PartGui::TaskPrimitives(); Gui::Control().showDialog(dlg); } bool CmdPartPrimitives::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } namespace PartGui { bool checkForSolids(const TopoDS_Shape& shape) { TopExp_Explorer xp; xp.Init(shape, TopAbs_FACE, TopAbs_SHELL); if (xp.More()) { return false; } xp.Init(shape, TopAbs_WIRE, TopAbs_FACE); if (xp.More()) { return false; } xp.Init(shape, TopAbs_EDGE, TopAbs_WIRE); if (xp.More()) { return false; } xp.Init(shape, TopAbs_VERTEX, TopAbs_EDGE); if (xp.More()) { return false; } return true; } /* * returns vector of Part::TopoShapes from selected Part::Feature derived objects, * App::Links linked to Part::Features, or App::Part containers with visible Part::Features */ std::vector getShapesFromSelection() { std::vector objs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); std::vector shapes; for (auto it : objs) { Part::TopoShape shp = Part::Feature::getTopoShape( it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!shp.isNull()) { shapes.push_back(shp); } } return shapes; } /* * returns true if selected objects contain valid Part::TopoShapes. * Objects can be Part::Features, App::Links, or App::Parts */ bool hasShapesInSelection() { bool hasShapes = false; std::vector docobjs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); for (auto it : docobjs) { if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink).isNull()) { hasShapes = true; break; } } return hasShapes; } } // namespace PartGui //=========================================================================== // Part_Cut //=========================================================================== DEF_STD_CMD_A(CmdPartCut) CmdPartCut::CmdPartCut() : Command("Part_Cut") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Cut"); sToolTipText = QT_TR_NOOP("Cuts 2 selected shapes"); sWhatsThis = "Part_Cut"; sStatusTip = sToolTipText; sPixmap = "Part_Cut"; } void CmdPartCut::activated(int iMsg) { Q_UNUSED(iMsg); std::vector Sel = getSelection().getSelectionEx( nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::FollowLink ); if (Sel.size() != 2) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select 2 shapes") ); return; } bool askUser = false; std::vector names; for (const auto& it : Sel) { const App::DocumentObject* obj = it.getObject(); const TopoDS_Shape& shape = Part::Feature::getShape( obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!PartGui::checkForSolids(shape) && !askUser) { int ret = QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Non-solids selected"), QObject::tr( "The use of non-solids for boolean operations may lead to unexpected results.\n" "Continue?" ), QMessageBox::Yes, QMessageBox::No ); if (ret == QMessageBox::No) { return; } askUser = true; } names.push_back(Base::Tools::quoted(it.getFeatName())); } openCommand(QT_TRANSLATE_NOOP("Command", "Part Cut")); doCommand(Doc, "from BOPTools import BOPFeatures"); doCommand(Doc, "bp = BOPFeatures.BOPFeatures(App.activeDocument())"); doCommand(Doc, "bp.make_cut([%s])", Base::Tools::joinList(names).c_str()); updateActive(); commitCommand(); } bool CmdPartCut::isActive() { return getSelection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) == 2; } //=========================================================================== // Part_Common //=========================================================================== DEF_STD_CMD_A(CmdPartCommon) CmdPartCommon::CmdPartCommon() : Command("Part_Common") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Intersection"); sToolTipText = QT_TR_NOOP("Intersects the selected shapes"); sWhatsThis = "Part_Common"; sStatusTip = sToolTipText; sPixmap = "Part_Common"; } void CmdPartCommon::activated(int iMsg) { Q_UNUSED(iMsg); std::vector Sel = getSelection().getSelectionEx( nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::FollowLink ); if (Sel.empty()) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select at least 2 shapes. Alternatively, select 1 compound containing 2 or more shapes to compute the intersection between.") ); return; } bool askUser = false; std::vector names; for (const auto& it : Sel) { const App::DocumentObject* obj = it.getObject(); const TopoDS_Shape& shape = Part::Feature::getShape( obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!PartGui::checkForSolids(shape) && !askUser) { int ret = QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Non-solids selected"), QObject::tr( "The use of non-solids for boolean operations may lead to unexpected results.\n" "Continue?" ), QMessageBox::Yes, QMessageBox::No ); if (ret == QMessageBox::No) { return; } askUser = true; } names.push_back(Base::Tools::quoted(it.getFeatName())); } openCommand(QT_TRANSLATE_NOOP("Command", "Common")); doCommand(Doc, "from BOPTools import BOPFeatures"); doCommand(Doc, "bp = BOPFeatures.BOPFeatures(App.activeDocument())"); doCommand(Doc, "bp.make_multi_common([%s])", Base::Tools::joinList(names).c_str()); updateActive(); commitCommand(); } bool CmdPartCommon::isActive() { return getSelection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) >= 1; } //=========================================================================== // Part_Fuse //=========================================================================== DEF_STD_CMD_A(CmdPartFuse) CmdPartFuse::CmdPartFuse() : Command("Part_Fuse") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Union"); sToolTipText = QT_TR_NOOP("Unites the selected shapes"); sWhatsThis = "Part_Fuse"; sStatusTip = sToolTipText; sPixmap = "Part_Fuse"; } void CmdPartFuse::activated(int iMsg) { Q_UNUSED(iMsg); std::vector Sel = getSelection().getSelectionEx( nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::FollowLink ); // test if selected object is a compound, and if it is, look how many children it has... std::size_t numShapes = 0; if (Sel.size() == 1) { numShapes = 1; // to be updated later in code Gui::SelectionObject selobj = Sel[0]; TopoDS_Shape sh = Part::Feature::getShape( selobj.getObject(), Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); while (numShapes == 1 && sh.ShapeType() == TopAbs_COMPOUND) { numShapes = 0; TopoDS_Iterator it(sh); TopoDS_Shape last; for (; it.More(); it.Next()) { ++numShapes; last = it.Value(); } sh = last; } } else { numShapes = Sel.size(); } if (numShapes < 2) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select at least 2 shapes. Alternatively, select 1 compound containing 2 or more shapes to be fused.") ); return; } bool askUser = false; std::vector names; for (const auto& it : Sel) { const App::DocumentObject* obj = it.getObject(); const TopoDS_Shape& shape = Part::Feature::getShape( obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!PartGui::checkForSolids(shape) && !askUser) { int ret = QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Non-solids selected"), QObject::tr( "The use of non-solids for boolean operations may lead to unexpected results.\n" "Continue?" ), QMessageBox::Yes, QMessageBox::No ); if (ret == QMessageBox::No) { return; } askUser = true; } names.push_back(Base::Tools::quoted(it.getFeatName())); } openCommand(QT_TRANSLATE_NOOP("Command", "Fusion")); doCommand(Doc, "from BOPTools import BOPFeatures"); doCommand(Doc, "bp = BOPFeatures.BOPFeatures(App.activeDocument())"); doCommand(Doc, "bp.make_multi_fuse([%s])", Base::Tools::joinList(names).c_str()); updateActive(); commitCommand(); } bool CmdPartFuse::isActive() { return getSelection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) >= 1; } //=========================================================================== // Part_CompJoinFeatures (dropdown toolbar button for Connect, Embed and Cutout) //=========================================================================== DEF_STD_CMD_ACL(CmdPartCompJoinFeatures) CmdPartCompJoinFeatures::CmdPartCompJoinFeatures() : Command("Part_CompJoinFeatures") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Join Shapes"); sToolTipText = QT_TR_NOOP("Joins the selected walled shapes"); sWhatsThis = "Part_CompJoinFeatures"; sStatusTip = sToolTipText; } void CmdPartCompJoinFeatures::activated(int iMsg) { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); if (iMsg == 0) { rcCmdMgr.runCommandByName("Part_JoinConnect"); } else if (iMsg == 1) { rcCmdMgr.runCommandByName("Part_JoinEmbed"); } else if (iMsg == 2) { rcCmdMgr.runCommandByName("Part_JoinCutout"); } else { return; } // Since the default icon is reset when enabling/disabling the command we have // to explicitly set the icon of the used command. Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); assert(iMsg < a.size()); pcAction->setIcon(a[iMsg]->icon()); } Gui::Action* CmdPartCompJoinFeatures::createAction() { Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); pcAction->setDropDownMenu(true); applyCommandData(this->className(), pcAction); QAction* cmd0 = pcAction->addAction(QString()); cmd0->setIcon(Gui::BitmapFactory().iconFromTheme("Part_JoinConnect")); QAction* cmd1 = pcAction->addAction(QString()); cmd1->setIcon(Gui::BitmapFactory().iconFromTheme("Part_JoinEmbed")); QAction* cmd2 = pcAction->addAction(QString()); cmd2->setIcon(Gui::BitmapFactory().iconFromTheme("Part_JoinCutout")); _pcAction = pcAction; languageChange(); pcAction->setIcon(cmd0->icon()); int defaultId = 0; pcAction->setProperty("defaultAction", QVariant(defaultId)); return pcAction; } void CmdPartCompJoinFeatures::languageChange() { Command::languageChange(); if (!_pcAction) { return; } Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); Gui::Command* joinConnect = rcCmdMgr.getCommandByName("Part_JoinConnect"); if (joinConnect) { QAction* cmd0 = a[0]; cmd0->setText(QApplication::translate("Part_JoinFeatures", joinConnect->getMenuText())); cmd0->setToolTip(QApplication::translate("Part_JoinFeatures", joinConnect->getToolTipText())); cmd0->setStatusTip(QApplication::translate("Part_JoinFeatures", joinConnect->getStatusTip())); } Gui::Command* joinEmbed = rcCmdMgr.getCommandByName("Part_JoinEmbed"); if (joinEmbed) { QAction* cmd1 = a[1]; cmd1->setText(QApplication::translate("Part_JoinFeatures", joinEmbed->getMenuText())); cmd1->setToolTip(QApplication::translate("Part_JoinFeatures", joinEmbed->getToolTipText())); cmd1->setStatusTip(QApplication::translate("Part_JoinFeatures", joinEmbed->getStatusTip())); } Gui::Command* joinCutout = rcCmdMgr.getCommandByName("Part_JoinCutout"); if (joinCutout) { QAction* cmd2 = a[2]; cmd2->setText(QApplication::translate("Part_JoinFeatures", joinCutout->getMenuText())); cmd2->setToolTip(QApplication::translate("Part_JoinFeatures", joinCutout->getToolTipText())); cmd2->setStatusTip(QApplication::translate("Part_JoinFeatures", joinCutout->getStatusTip())); } } bool CmdPartCompJoinFeatures::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // Part_CompSplitFeatures (dropdown toolbar button for BooleanFragments, Slice) //=========================================================================== DEF_STD_CMD_ACL(CmdPartCompSplitFeatures) CmdPartCompSplitFeatures::CmdPartCompSplitFeatures() : Command("Part_CompSplitFeatures") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Split Shapes"); sToolTipText = QT_TR_NOOP("Shape splitting and compsolid creation tools"); sWhatsThis = "Part_CompSplitFeatures"; sStatusTip = sToolTipText; } void CmdPartCompSplitFeatures::activated(int iMsg) { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); if (iMsg == 0) { rcCmdMgr.runCommandByName("Part_BooleanFragments"); } else if (iMsg == 1) { rcCmdMgr.runCommandByName("Part_SliceApart"); } else if (iMsg == 2) { rcCmdMgr.runCommandByName("Part_Slice"); } else if (iMsg == 3) { rcCmdMgr.runCommandByName("Part_XOR"); } else { return; } // Since the default icon is reset when enabling/disabling the command we have // to explicitly set the icon of the used command. Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); assert(iMsg < a.size()); pcAction->setIcon(a[iMsg]->icon()); } Gui::Action* CmdPartCompSplitFeatures::createAction() { Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); pcAction->setDropDownMenu(true); applyCommandData(this->className(), pcAction); QAction* cmd0 = pcAction->addAction(QString()); cmd0->setIcon(Gui::BitmapFactory().iconFromTheme("Part_BooleanFragments")); QAction* cmd1 = pcAction->addAction(QString()); cmd1->setIcon(Gui::BitmapFactory().iconFromTheme("Part_SliceApart")); QAction* cmd2 = pcAction->addAction(QString()); cmd2->setIcon(Gui::BitmapFactory().iconFromTheme("Part_Slice")); QAction* cmd3 = pcAction->addAction(QString()); cmd3->setIcon(Gui::BitmapFactory().iconFromTheme("Part_XOR")); _pcAction = pcAction; languageChange(); pcAction->setIcon(cmd0->icon()); int defaultId = 0; pcAction->setProperty("defaultAction", QVariant(defaultId)); return pcAction; } void CmdPartCompSplitFeatures::languageChange() { Command::languageChange(); if (!_pcAction) { return; } Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); Gui::Command* splitBoolFragments = rcCmdMgr.getCommandByName("Part_BooleanFragments"); if (splitBoolFragments) { QAction* cmd0 = a[0]; cmd0->setText(QApplication::translate("Part_SplitFeatures", splitBoolFragments->getMenuText())); cmd0->setToolTip( QApplication::translate("Part_SplitFeatures", splitBoolFragments->getToolTipText()) ); cmd0->setStatusTip( QApplication::translate("Part_SplitFeatures", splitBoolFragments->getStatusTip()) ); } Gui::Command* splitSliceApart = rcCmdMgr.getCommandByName("Part_SliceApart"); if (splitSliceApart) { QAction* cmd1 = a[1]; cmd1->setText(QApplication::translate("Part_SplitFeatures", splitSliceApart->getMenuText())); cmd1->setToolTip( QApplication::translate("Part_SplitFeatures", splitSliceApart->getToolTipText()) ); cmd1->setStatusTip( QApplication::translate("Part_SplitFeatures", splitSliceApart->getStatusTip()) ); } Gui::Command* splitSlice = rcCmdMgr.getCommandByName("Part_Slice"); if (splitSlice) { QAction* cmd1 = a[2]; cmd1->setText(QApplication::translate("Part_SplitFeatures", splitSlice->getMenuText())); cmd1->setToolTip(QApplication::translate("Part_SplitFeatures", splitSlice->getToolTipText())); cmd1->setStatusTip(QApplication::translate("Part_SplitFeatures", splitSlice->getStatusTip())); } Gui::Command* splitXOR = rcCmdMgr.getCommandByName("Part_XOR"); if (splitXOR) { QAction* cmd2 = a[3]; cmd2->setText(QApplication::translate("Part_SplitFeatures", splitXOR->getMenuText())); cmd2->setToolTip(QApplication::translate("Part_SplitFeatures", splitXOR->getToolTipText())); cmd2->setStatusTip(QApplication::translate("Part_SplitFeatures", splitXOR->getStatusTip())); } } bool CmdPartCompSplitFeatures::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // Part_CompCompoundTools (dropdown toolbar button for BooleanFragments, Slice) //=========================================================================== DEF_STD_CMD_ACL(CmdPartCompCompoundTools) CmdPartCompCompoundTools::CmdPartCompCompoundTools() : Command("Part_CompCompoundTools") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Compound Tools"); sToolTipText = QT_TR_NOOP("Compound tools for working with multiple shapes"); sWhatsThis = "Part_CompCompoundTools"; sStatusTip = sToolTipText; } void CmdPartCompCompoundTools::activated(int iMsg) { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); if (iMsg == 0) { rcCmdMgr.runCommandByName("Part_Compound"); } else if (iMsg == 1) { rcCmdMgr.runCommandByName("Part_ExplodeCompound"); } else if (iMsg == 2) { rcCmdMgr.runCommandByName("Part_CompoundFilter"); } else { return; } // Since the default icon is reset when enabling/disabling the command we have // to explicitly set the icon of the used command. Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); assert(iMsg < a.size()); pcAction->setIcon(a[iMsg]->icon()); } Gui::Action* CmdPartCompCompoundTools::createAction() { Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); pcAction->setDropDownMenu(true); applyCommandData(this->className(), pcAction); QAction* cmd0 = pcAction->addAction(QString()); cmd0->setIcon(Gui::BitmapFactory().iconFromTheme("Part_Compound")); QAction* cmd1 = pcAction->addAction(QString()); cmd1->setIcon(Gui::BitmapFactory().iconFromTheme("Part_ExplodeCompound")); QAction* cmd2 = pcAction->addAction(QString()); cmd2->setIcon(Gui::BitmapFactory().iconFromTheme("Part_CompoundFilter")); _pcAction = pcAction; languageChange(); pcAction->setIcon(cmd0->icon()); int defaultId = 0; pcAction->setProperty("defaultAction", QVariant(defaultId)); return pcAction; } void CmdPartCompCompoundTools::languageChange() { Command::languageChange(); if (!_pcAction) { return; } Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); Gui::Command* cmdCompound = rcCmdMgr.getCommandByName("Part_Compound"); if (cmdCompound) { QAction* cmd0 = a[0]; cmd0->setText(QApplication::translate("CmdPartCompound", cmdCompound->getMenuText())); cmd0->setToolTip(QApplication::translate("CmdPartCompound", cmdCompound->getToolTipText())); cmd0->setStatusTip(QApplication::translate("CmdPartCompound", cmdCompound->getStatusTip())); } Gui::Command* cmdExplode = rcCmdMgr.getCommandByName("Part_ExplodeCompound"); if (cmdExplode) { QAction* cmd1 = a[1]; cmd1->setText(QApplication::translate("Part_CompoundTools", cmdExplode->getMenuText())); cmd1->setToolTip(QApplication::translate("Part_CompoundTools", cmdExplode->getToolTipText())); cmd1->setStatusTip(QApplication::translate("Part_CompoundTools", cmdExplode->getStatusTip())); } Gui::Command* cmdCompoundFilter = rcCmdMgr.getCommandByName("Part_CompoundFilter"); if (cmdCompoundFilter) { QAction* cmd2 = a[2]; cmd2->setText(QApplication::translate("Part_CompoundTools", cmdCompoundFilter->getMenuText())); cmd2->setToolTip( QApplication::translate("Part_CompoundTools", cmdCompoundFilter->getToolTipText()) ); cmd2->setStatusTip( QApplication::translate("Part_CompoundTools", cmdCompoundFilter->getStatusTip()) ); } } bool CmdPartCompCompoundTools::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // Part_Compound //=========================================================================== DEF_STD_CMD_A(CmdPartCompound) CmdPartCompound::CmdPartCompound() : Command("Part_Compound") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Compound"); sToolTipText = QT_TR_NOOP("Compounds the selected shapes"); sWhatsThis = "Part_Compound"; sStatusTip = sToolTipText; sPixmap = "Part_Compound"; } void CmdPartCompound::activated(int iMsg) { Q_UNUSED(iMsg); unsigned int n = getSelection().countObjectsOfType( nullptr, Gui::ResolveMode::FollowLink ); if (n < 1) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select at least one shape") ); return; } std::string FeatName = getUniqueObjectName("Compound"); std::vector Sel = getSelection().getSelection(); std::stringstream str; // avoid duplicates without changing the order std::set tempSelNames; str << "App.activeDocument()." << FeatName << ".Links = ["; for (const auto& it : Sel) { auto pos = tempSelNames.insert(it.FeatName); if (pos.second) { str << "App.activeDocument()." << it.FeatName << ","; } } str << "]"; openCommand(QT_TRANSLATE_NOOP("Command", "Compound")); doCommand(Doc, "App.activeDocument().addObject(\"Part::Compound\",\"%s\")", FeatName.c_str()); runCommand(Doc, str.str().c_str()); updateActive(); commitCommand(); } bool CmdPartCompound::isActive() { return getSelection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) >= 1; } //=========================================================================== // Part_Section //=========================================================================== DEF_STD_CMD_A(CmdPartSection) CmdPartSection::CmdPartSection() : Command("Part_Section") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Section"); sToolTipText = QT_TR_NOOP("Sections 2 selected shapes"); sWhatsThis = "Part_Section"; sStatusTip = sToolTipText; sPixmap = "Part_Section"; } void CmdPartSection::activated(int iMsg) { Q_UNUSED(iMsg); std::vector Sel = getSelection().getSelectionEx( nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::FollowLink ); if (Sel.size() != 2) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select 2 shapes") ); return; } std::string FeatName = getUniqueObjectName("Section"); std::string BaseName = Sel[0].getFeatName(); std::string ToolName = Sel[1].getFeatName(); openCommand(QT_TRANSLATE_NOOP("Command", "Section")); doCommand(Doc, "App.activeDocument().addObject(\"Part::Section\",\"%s\")", FeatName.c_str()); doCommand( Doc, "App.activeDocument().%s.Base = App.activeDocument().%s", FeatName.c_str(), BaseName.c_str() ); doCommand( Doc, "App.activeDocument().%s.Tool = App.activeDocument().%s", FeatName.c_str(), ToolName.c_str() ); doCommand(Gui, "Gui.activeDocument().hide('%s')", BaseName.c_str()); doCommand(Gui, "Gui.activeDocument().hide('%s')", ToolName.c_str()); doCommand( Gui, "Gui.activeDocument().%s.LineMaterial = Gui.activeDocument().%s.ShapeAppearance[0]", FeatName.c_str(), BaseName.c_str() ); updateActive(); commitCommand(); } bool CmdPartSection::isActive() { return getSelection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) == 2; } //=========================================================================== // CmdPartImport //=========================================================================== DEF_STD_CMD_A(CmdPartImport) CmdPartImport::CmdPartImport() : Command("Part_Import") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Import CAD File"); sToolTipText = QT_TR_NOOP("Imports a CAD file"); sWhatsThis = "Part_Import"; sStatusTip = sToolTipText; sPixmap = "Part_Import"; } void CmdPartImport::activated(int iMsg) { Q_UNUSED(iMsg); QStringList filter; filter << QStringLiteral("STEP (*.stp *.step)"); filter << QStringLiteral("STEP with colors (*.stp *.step)"); filter << QStringLiteral("IGES (*.igs *.iges)"); filter << QStringLiteral("IGES with colors (*.igs *.iges)"); filter << QStringLiteral("BREP (*.brp *.brep)"); QString select; QString fn = Gui::FileDialog::getOpenFileName( Gui::getMainWindow(), QString(), QString(), filter.join(QLatin1String(";;")), &select ); if (!fn.isEmpty()) { Gui::WaitCursor wc; App::Document* pDoc = getDocument(); if (!pDoc) { // no document return; } fn = Base::Tools::escapeEncodeFilename(fn); openCommand(QT_TRANSLATE_NOOP("Command", "Import Part")); if (select == filter[1] || select == filter[3]) { doCommand(Doc, "import ImportGui"); doCommand(Doc, "ImportGui.insert(\"%s\",\"%s\")", (const char*)fn.toUtf8(), pDoc->getName()); } else { doCommand(Doc, "import Part"); doCommand(Doc, "Part.insert(\"%s\",\"%s\")", (const char*)fn.toUtf8(), pDoc->getName()); } commitCommand(); std::list views = getActiveGuiDocument()->getMDIViewsOfType( Gui::View3DInventor::getClassTypeId() ); for (auto view : views) { view->viewAll(); } } } bool CmdPartImport::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // CmdPartExport //=========================================================================== DEF_STD_CMD_A(CmdPartExport) CmdPartExport::CmdPartExport() : Command("Part_Export") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Export CAD File"); sToolTipText = QT_TR_NOOP("Exports to a CAD file"); sWhatsThis = "Part_Export"; sStatusTip = sToolTipText; sPixmap = "Part_Export"; } void CmdPartExport::activated(int iMsg) { Q_UNUSED(iMsg); QStringList filter; filter << QStringLiteral("STEP (*.stp *.step)"); filter << QStringLiteral("STEP with colors (*.stp *.step)"); filter << QStringLiteral("IGES (*.igs *.iges)"); filter << QStringLiteral("IGES with colors (*.igs *.iges)"); filter << QStringLiteral("BREP (*.brp *.brep)"); QString select; QString fn = Gui::FileDialog::getSaveFileName( Gui::getMainWindow(), QString(), QString(), filter.join(QLatin1String(";;")), &select ); if (!fn.isEmpty()) { App::Document* pDoc = getDocument(); if (!pDoc) { // no document return; } if (select == filter[1] || select == filter[3]) { Gui::Application::Instance->exportTo((const char*)fn.toUtf8(), pDoc->getName(), "ImportGui"); } else { Gui::Application::Instance->exportTo((const char*)fn.toUtf8(), pDoc->getName(), "Part"); } } } bool CmdPartExport::isActive() { return Gui::Selection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) > 0; } //=========================================================================== // PartImportCurveNet //=========================================================================== DEF_STD_CMD_A(CmdPartImportCurveNet) CmdPartImportCurveNet::CmdPartImportCurveNet() : Command("Part_ImportCurveNet") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Import Curve Network"); sToolTipText = QT_TR_NOOP("Imports a curve network"); sWhatsThis = "Part_ImportCurveNet"; sStatusTip = sToolTipText; sPixmap = "Part_Box_Parametric"; } void CmdPartImportCurveNet::activated(int iMsg) { Q_UNUSED(iMsg); QStringList filter; filter << QStringLiteral("%1 (*.stp *.step *.igs *.iges *.brp *.brep)") .arg(QObject::tr("All CAD Files")); filter << QStringLiteral("STEP (*.stp *.step)"); filter << QStringLiteral("IGES (*.igs *.iges)"); filter << QStringLiteral("BREP (*.brp *.brep)"); filter << QStringLiteral("%1 (*.*)").arg(QObject::tr("All Files")); QString fn = Gui::FileDialog::getOpenFileName( Gui::getMainWindow(), QString(), QString(), filter.join(QLatin1String(";;")) ); if (!fn.isEmpty()) { QFileInfo fi; fi.setFile(fn); openCommand(QT_TRANSLATE_NOOP("Command", "Import Curve Net")); doCommand( Doc, "f = App.activeDocument().addObject(\"Part::CurveNet\",\"%s\")", (const char*)fi.baseName().toLatin1() ); doCommand(Doc, "f.FileName = \"%s\"", (const char*)fn.toLatin1()); commitCommand(); updateActive(); } } bool CmdPartImportCurveNet::isActive() { if (getActiveGuiDocument()) { return true; } else { return false; } } //=========================================================================== // Part_MakeSolid //=========================================================================== DEF_STD_CMD_A(CmdPartMakeSolid) CmdPartMakeSolid::CmdPartMakeSolid() : Command("Part_MakeSolid") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Convert to Solid"); sToolTipText = QT_TR_NOOP("Converts the selected shell or compound to a solid"); sWhatsThis = "Part_MakeSolid"; sStatusTip = sToolTipText; sPixmap = "Part_MakeSolid"; } void CmdPartMakeSolid::activated(int iMsg) { Q_UNUSED(iMsg); std::vector objs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId(), nullptr, Gui::ResolveMode::FollowLink ); runCommand(Doc, "import Part"); for (auto it : objs) { const TopoDS_Shape& shape = Part::Feature::getShape( it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!shape.IsNull()) { TopAbs_ShapeEnum type = shape.ShapeType(); QString str; if (type == TopAbs_SOLID) { Base::Console().message( "%s is ignored because it is already a solid.\n", it->Label.getValue() ); } else if (type == TopAbs_COMPOUND || type == TopAbs_COMPSOLID) { str = QStringLiteral( "__s__=App.ActiveDocument.%1.Shape.Faces\n" "__s__=Part.Solid(Part.Shell(__s__))\n" "__o__=App.ActiveDocument.addObject(\"Part::Feature\",\"%1_solid\")\n" "__o__.Label=\"%2 (Solid)\"\n" "__o__.Shape=__s__\n" "del __s__, __o__" ) .arg( QLatin1String(it->getNameInDocument()), QLatin1String(it->Label.getValue()) ); } else if (type == TopAbs_SHELL) { str = QStringLiteral( "__s__=App.ActiveDocument.%1.Shape\n" "__s__=Part.Solid(__s__)\n" "__o__=App.ActiveDocument.addObject(\"Part::Feature\",\"%1_solid\")\n" "__o__.Label=\"%2 (Solid)\"\n" "__o__.Shape=__s__\n" "del __s__, __o__" ) .arg( QLatin1String(it->getNameInDocument()), QLatin1String(it->Label.getValue()) ); } else { Base::Console().message( "%s is ignored because it is neither a shell nor a compound.\n", it->Label.getValue() ); } try { if (!str.isEmpty()) { runCommand(Doc, str.toLatin1()); } } catch (const Base::Exception& e) { Base::Console().error("Cannot convert %s because %s.\n", it->Label.getValue(), e.what()); } } } } bool CmdPartMakeSolid::isActive() { return Gui::Selection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) > 0; } //=========================================================================== // Part_ReverseShape //=========================================================================== DEF_STD_CMD_A(CmdPartReverseShape) CmdPartReverseShape::CmdPartReverseShape() : Command("Part_ReverseShape") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Reverse Shapes"); sToolTipText = QT_TR_NOOP("Reverses the orientation of the selected shapes"); sWhatsThis = "Part_ReverseShape"; sStatusTip = sToolTipText; sPixmap = "Part_Reverse_Shape"; } void CmdPartReverseShape::activated(int iMsg) { Q_UNUSED(iMsg); std::vector objs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); openCommand(QT_TRANSLATE_NOOP("Command", "Reverse")); for (auto it : objs) { const TopoDS_Shape& shape = Part::Feature::getShape( it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!shape.IsNull()) { std::string name = it->getNameInDocument(); name += "_rev"; name = getUniqueObjectName(name.c_str()); QString str = QStringLiteral( "__o__=App.ActiveDocument.addObject(\"Part::Reverse\",\"%1\")\n" "__o__.Source=App.ActiveDocument.%2\n" "__o__.Label=\"%3 (Rev)\"\n" "del __o__" ) .arg( QString::fromLatin1(name.c_str()), QString::fromLatin1(it->getNameInDocument()), QString::fromLatin1(it->Label.getValue()) ); try { runCommand(Doc, str.toLatin1()); copyVisual(name.c_str(), "ShapeAppearance", it->getNameInDocument()); copyVisual(name.c_str(), "LineColor", it->getNameInDocument()); copyVisual(name.c_str(), "PointColor", it->getNameInDocument()); } catch (const Base::Exception& e) { Base::Console().error("Cannot convert %s because %s.\n", it->Label.getValue(), e.what()); } } } commitCommand(); updateActive(); } bool CmdPartReverseShape::isActive() { return PartGui::hasShapesInSelection(); } //=========================================================================== // Part_Boolean //=========================================================================== DEF_STD_CMD_A(CmdPartBoolean) CmdPartBoolean::CmdPartBoolean() : Command("Part_Boolean") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Boolean Operation"); sToolTipText = QT_TR_NOOP("Applies a boolean operations with the selected shapes"); sWhatsThis = "Part_Boolean"; sStatusTip = sToolTipText; sPixmap = "Part_Booleans"; } void CmdPartBoolean::activated(int iMsg) { Q_UNUSED(iMsg); Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); if (!dlg) { dlg = new PartGui::TaskBooleanOperation(); } Gui::Control().showDialog(dlg); } bool CmdPartBoolean::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Extrude //=========================================================================== DEF_STD_CMD_A(CmdPartExtrude) CmdPartExtrude::CmdPartExtrude() : Command("Part_Extrude") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Extrude"); sToolTipText = QT_TR_NOOP("Extrudes the selected sketch or profile"); sWhatsThis = "Part_Extrude"; sStatusTip = sToolTipText; sPixmap = "Part_Extrude"; } void CmdPartExtrude::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskExtrusion()); } bool CmdPartExtrude::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Scale //=========================================================================== DEF_STD_CMD_A(CmdPartScale) CmdPartScale::CmdPartScale() : Command("Part_Scale") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Scale"); sToolTipText = QT_TR_NOOP("Scales the selected shape"); sWhatsThis = "Part_Scale"; sStatusTip = sToolTipText; sPixmap = "Part_Scale"; } void CmdPartScale::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskScale()); } bool CmdPartScale::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_MakeFace //=========================================================================== DEF_STD_CMD_A(CmdPartMakeFace) CmdPartMakeFace::CmdPartMakeFace() : Command("Part_MakeFace") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Face From Wires"); sToolTipText = QT_TR_NOOP("Creates a face from the selected wires (e.g. from a sketch)"); sWhatsThis = "Part_MakeFace"; sStatusTip = sToolTipText; sPixmap = "Part_MakeFace"; } void CmdPartMakeFace::activated(int iMsg) { Q_UNUSED(iMsg); auto sketches = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId(), nullptr, Gui::ResolveMode::FollowLink ); if (sketches.empty()) { return; } openCommand(QT_TRANSLATE_NOOP("Command", "Make face")); try { App::DocumentT doc(sketches.front()->getDocument()); std::stringstream str; str << doc.getDocumentPython() << R"(.addObject("Part::Face", "Face").Sources = ()"; for (auto& obj : sketches) { str << App::DocumentObjectT(obj).getObjectPython() << ", "; } str << ")"; runCommand(Doc, str.str().c_str()); commitCommand(); updateActive(); } catch (...) { abortCommand(); throw; } } bool CmdPartMakeFace::isActive() { return ( Gui::Selection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) > 0 && !Gui::Control().activeDialog() ); } //=========================================================================== // Part_Revolve //=========================================================================== DEF_STD_CMD_A(CmdPartRevolve) CmdPartRevolve::CmdPartRevolve() : Command("Part_Revolve") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Revolve"); sToolTipText = QT_TR_NOOP("Revolves the selected shape"); sWhatsThis = "Part_Revolve"; sStatusTip = sToolTipText; sPixmap = "Part_Revolve"; } void CmdPartRevolve::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskRevolution()); } bool CmdPartRevolve::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Fillet //=========================================================================== DEF_STD_CMD_A(CmdPartFillet) CmdPartFillet::CmdPartFillet() : Command("Part_Fillet") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Fillet"); sToolTipText = QT_TR_NOOP("Fillets the selected edges of a shape"); sWhatsThis = "Part_Fillet"; sStatusTip = sToolTipText; sPixmap = "Part_Fillet"; } void CmdPartFillet::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskFilletEdges(nullptr)); } bool CmdPartFillet::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Chamfer //=========================================================================== DEF_STD_CMD_A(CmdPartChamfer) CmdPartChamfer::CmdPartChamfer() : Command("Part_Chamfer") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Chamfer"); sToolTipText = QT_TR_NOOP("Chamfers the selected edges of a shape"); sWhatsThis = "Part_Chamfer"; sStatusTip = sToolTipText; sPixmap = "Part_Chamfer"; } void CmdPartChamfer::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskChamferEdges(nullptr)); } bool CmdPartChamfer::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Mirror //=========================================================================== DEF_STD_CMD_A(CmdPartMirror) CmdPartMirror::CmdPartMirror() : Command("Part_Mirror") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Mirror"); sToolTipText = QT_TR_NOOP("Mirrors the selected shape"); sWhatsThis = "Part_Mirror"; sStatusTip = sToolTipText; sPixmap = "Part_Mirror"; } void CmdPartMirror::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskMirroring()); } bool CmdPartMirror::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_CrossSections //=========================================================================== DEF_STD_CMD_A(CmdPartCrossSections) CmdPartCrossSections::CmdPartCrossSections() : Command("Part_CrossSections") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Cross-Sections"); sToolTipText = QT_TR_NOOP("Creates cross-sections"); sWhatsThis = "Part_CrossSections"; sStatusTip = sToolTipText; sPixmap = "Part_CrossSections"; } void CmdPartCrossSections::activated(int iMsg) { Q_UNUSED(iMsg); Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); if (!dlg) { std::vector shapes = PartGui::getShapesFromSelection(); Base::BoundBox3d bbox; for (const auto& it : shapes) { bbox.Add(it.getBoundBox()); } dlg = new PartGui::TaskCrossSections(bbox); } Gui::Control().showDialog(dlg); } bool CmdPartCrossSections::isActive() { bool hasShapes = PartGui::hasShapesInSelection(); return (hasShapes && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Builder //=========================================================================== DEF_STD_CMD_A(CmdPartBuilder) CmdPartBuilder::CmdPartBuilder() : Command("Part_Builder") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Shape Builder"); sToolTipText = QT_TR_NOOP("Advanced utility to create shapes"); sWhatsThis = "Part_Builder"; sStatusTip = sToolTipText; sPixmap = "Part_Shapebuilder"; } void CmdPartBuilder::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskShapeBuilder()); } bool CmdPartBuilder::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Loft //=========================================================================== DEF_STD_CMD_A(CmdPartLoft) CmdPartLoft::CmdPartLoft() : Command("Part_Loft") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Loft"); sToolTipText = QT_TR_NOOP("Lofts the selected profiles"); sWhatsThis = "Part_Loft"; sStatusTip = sToolTipText; sPixmap = "Part_Loft"; } void CmdPartLoft::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskLoft()); } bool CmdPartLoft::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Sweep //=========================================================================== DEF_STD_CMD_A(CmdPartSweep) CmdPartSweep::CmdPartSweep() : Command("Part_Sweep") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Sweep"); sToolTipText = QT_TR_NOOP("Sweeps profiles along a wire"); sWhatsThis = "Part_Sweep"; sStatusTip = sToolTipText; sPixmap = "Part_Sweep"; } void CmdPartSweep::activated(int iMsg) { Q_UNUSED(iMsg); Gui::Control().showDialog(new PartGui::TaskSweep()); } bool CmdPartSweep::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_Offset //=========================================================================== DEF_STD_CMD_A(CmdPartOffset) CmdPartOffset::CmdPartOffset() : Command("Part_Offset") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("3D Offset"); sToolTipText = QT_TR_NOOP("Offsets shapes in 3D"); sWhatsThis = "Part_Offset"; sStatusTip = sToolTipText; sPixmap = "Part_Offset"; } void CmdPartOffset::activated(int iMsg) { Q_UNUSED(iMsg); std::vector docobjs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); std::vector shapes; for (auto it : docobjs) { if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform) .isNull()) { shapes.push_back(it); } } if (shapes.size() != 1) { return; } App::DocumentObject* shape = shapes.front(); std::string offset = getUniqueObjectName("Offset"); openCommand(QT_TRANSLATE_NOOP("Command", "Make Offset")); doCommand(Doc, "App.ActiveDocument.addObject(\"Part::Offset\",\"%s\")", offset.c_str()); doCommand( Doc, "App.ActiveDocument.%s.Source = App.ActiveDocument.%s", offset.c_str(), shape->getNameInDocument() ); doCommand(Doc, "App.ActiveDocument.%s.Value = 1.0", offset.c_str()); updateActive(); doCommand(Gui, "Gui.ActiveDocument.setEdit('%s')", offset.c_str()); if (!shape->isDerivedFrom()) { copyVisual(offset.c_str(), "ShapeAppearance", shape->getNameInDocument()); copyVisual(offset.c_str(), "LineColor", shape->getNameInDocument()); copyVisual(offset.c_str(), "PointColor", shape->getNameInDocument()); } } bool CmdPartOffset::isActive() { bool hasShapes = PartGui::hasShapesInSelection(); std::vector docobjs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); return (hasShapes && !Gui::Control().activeDialog() && docobjs.size() == 1); } //=========================================================================== // Part_Offset2D //=========================================================================== DEF_STD_CMD_A(CmdPartOffset2D) CmdPartOffset2D::CmdPartOffset2D() : Command("Part_Offset2D") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("2D Offset"); sToolTipText = QT_TR_NOOP("Offsets planar shapes in 2D"); sWhatsThis = "Part_Offset2D"; sStatusTip = sToolTipText; sPixmap = "Part_Offset2D"; } void CmdPartOffset2D::activated(int iMsg) { Q_UNUSED(iMsg); std::vector docobjs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); std::vector shapes; for (auto it : docobjs) { if (!Part::Feature::getTopoShape(it, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform) .isNull()) { shapes.push_back(it); } } if (shapes.size() != 1) { return; } App::DocumentObject* shape = shapes.front(); std::string offset = getUniqueObjectName("Offset2D"); openCommand(QT_TRANSLATE_NOOP("Command", "Make 2D Offset")); doCommand(Doc, "App.ActiveDocument.addObject(\"Part::Offset2D\",\"%s\")", offset.c_str()); doCommand( Doc, "App.ActiveDocument.%s.Source = App.ActiveDocument.%s", offset.c_str(), shape->getNameInDocument() ); doCommand(Doc, "App.ActiveDocument.%s.Value = 1.0", offset.c_str()); updateActive(); doCommand(Gui, "Gui.ActiveDocument.setEdit('%s')", offset.c_str()); if (!shape->isDerivedFrom()) { copyVisual(offset.c_str(), "ShapeAppearance", shape->getNameInDocument()); copyVisual(offset.c_str(), "LineColor", shape->getNameInDocument()); copyVisual(offset.c_str(), "PointColor", shape->getNameInDocument()); } } bool CmdPartOffset2D::isActive() { bool hasShapes = PartGui::hasShapesInSelection(); std::vector docobjs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); return (hasShapes && !Gui::Control().activeDialog() && docobjs.size() == 1); } //=========================================================================== // Part_CompOffset (dropdown toolbar button for Offset features) //=========================================================================== DEF_STD_CMD_ACL(CmdPartCompOffset) CmdPartCompOffset::CmdPartCompOffset() : Command("Part_CompOffset") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Offset"); sToolTipText = QT_TR_NOOP("Tools to offset shapes (construct parallel shapes)"); sWhatsThis = "Part_CompOffset"; sStatusTip = sToolTipText; } void CmdPartCompOffset::activated(int iMsg) { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); if (iMsg == 0) { rcCmdMgr.runCommandByName("Part_Offset"); } else if (iMsg == 1) { rcCmdMgr.runCommandByName("Part_Offset2D"); } else { return; } // Since the default icon is reset when enabling/disabling the command we have // to explicitly set the icon of the used command. Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); assert(iMsg < a.size()); pcAction->setIcon(a[iMsg]->icon()); } Gui::Action* CmdPartCompOffset::createAction() { Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); pcAction->setDropDownMenu(true); applyCommandData(this->className(), pcAction); QAction* cmd0 = pcAction->addAction(QString()); cmd0->setIcon(Gui::BitmapFactory().iconFromTheme("Part_Offset")); QAction* cmd1 = pcAction->addAction(QString()); cmd1->setIcon(Gui::BitmapFactory().iconFromTheme("Part_Offset2D")); _pcAction = pcAction; languageChange(); pcAction->setIcon(cmd0->icon()); int defaultId = 0; pcAction->setProperty("defaultAction", QVariant(defaultId)); return pcAction; } void CmdPartCompOffset::languageChange() { Command::languageChange(); if (!_pcAction) { return; } Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); Gui::Command* cmdOffset = rcCmdMgr.getCommandByName("Part_Offset"); if (cmdOffset) { QAction* cmd0 = a[0]; cmd0->setText(QApplication::translate(cmdOffset->className(), cmdOffset->getMenuText())); cmd0->setToolTip(QApplication::translate(cmdOffset->className(), cmdOffset->getToolTipText())); cmd0->setStatusTip(QApplication::translate(cmdOffset->className(), cmdOffset->getStatusTip())); } Gui::Command* cmdOffset2D = rcCmdMgr.getCommandByName("Part_Offset2D"); if (cmdOffset2D) { QAction* cmd1 = a[1]; cmd1->setText(QApplication::translate(cmdOffset2D->className(), cmdOffset2D->getMenuText())); cmd1->setToolTip( QApplication::translate(cmdOffset2D->className(), cmdOffset2D->getToolTipText()) ); cmd1->setStatusTip( QApplication::translate(cmdOffset2D->className(), cmdOffset2D->getStatusTip()) ); } } bool CmdPartCompOffset::isActive() { bool hasShapes = PartGui::hasShapesInSelection(); std::vector docobjs = Gui::Selection().getObjectsOfType( App::DocumentObject::getClassTypeId() ); return (hasShapes && !Gui::Control().activeDialog() && docobjs.size() == 1); } //=========================================================================== // Part_Thickness //=========================================================================== DEF_STD_CMD_A(CmdPartThickness) CmdPartThickness::CmdPartThickness() : Command("Part_Thickness") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Thickness"); sToolTipText = QT_TR_NOOP( "Removes the selected faces and offsets the remaining shape outward to add thickness" ); sWhatsThis = "Part_Thickness"; sStatusTip = sToolTipText; sPixmap = "Part_Thickness"; } void CmdPartThickness::activated(int iMsg) { Q_UNUSED(iMsg); const App::DocumentObject* obj = nullptr; std::string selection; const std::vector selobjs = Gui::Selection().getSelectionEx(); std::vector subShapes; Part::TopoShape topoShape = Part::TopoShape(); bool ok = true; if (selobjs.size() == 1) { selection = selobjs[0].getAsPropertyLinkSubString(); const std::vector& subnames = selobjs[0].getSubNames(); obj = selobjs[0].getObject(); topoShape = Part::Feature::getTopoShape( obj, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (!topoShape.isNull()) { for (std::vector::const_iterator it = subnames.begin(); it != subnames.end(); ++it) { subShapes.emplace_back(topoShape.getSubShape(subnames[0].c_str())); } for (const auto& it : subShapes) { TopoDS_Shape dsShape = it.getShape(); if (dsShape.IsNull() || dsShape.ShapeType() != TopAbs_FACE) { // only face selection allowed ok = false; } } } else { // could be not a part::feature or app:link to non-part::feature or app::part // without a visible part::feature ok = false; } } else { // not just one object selected ok = false; } int countSolids = 0; TopExp_Explorer xp; if (!topoShape.isNull()) { xp.Init(topoShape.getShape(), TopAbs_SOLID); for (; xp.More(); xp.Next()) { countSolids++; } } if (countSolids != 1 || !ok) { QMessageBox::warning( Gui::getMainWindow(), QApplication::translate("CmdPartThickness", "Wrong selection"), QApplication::translate("CmdPartThickness", "Selected shape is not a solid") ); return; } std::string thick = getUniqueObjectName("Thickness"); openCommand(QT_TRANSLATE_NOOP("Command", "Make Thickness")); doCommand(Doc, "App.ActiveDocument.addObject(\"Part::Thickness\",\"%s\")", thick.c_str()); doCommand(Doc, "App.ActiveDocument.%s.Faces = %s", thick.c_str(), selection.c_str()); doCommand(Doc, "App.ActiveDocument.%s.Value = 1.0", thick.c_str()); updateActive(); if (isActiveObjectValid()) { doCommand( App, "App.getDocument(\"%s\").getObject(\"%s\").ViewObject.Visibility = False", obj->getDocument()->getName(), obj->getNameInDocument() ); } doCommand(Gui, "Gui.ActiveDocument.setEdit('%s')", thick.c_str()); copyVisual(thick.c_str(), "ShapeAppearance", obj->getNameInDocument()); copyVisual(thick.c_str(), "LineColor", obj->getNameInDocument()); copyVisual(thick.c_str(), "PointColor", obj->getNameInDocument()); } bool CmdPartThickness::isActive() { bool objectsSelected = Gui::Selection().countObjectsOfType(nullptr, Gui::ResolveMode::FollowLink) > 0; return (objectsSelected && !Gui::Control().activeDialog()); } //=========================================================================== // Part_ShapeInfo //=========================================================================== DEF_STD_CMD_A(CmdShapeInfo) CmdShapeInfo::CmdShapeInfo() : Command("Part_ShapeInfo") { sAppModule = "Part"; sGroup = "Part"; sMenuText = "Shape Info"; sToolTipText = "Displays information about the selected shape"; sWhatsThis = "Part_ShapeInfo"; sStatusTip = sToolTipText; sPixmap = "Part_ShapeInfo"; } void CmdShapeInfo::activated(int iMsg) { Q_UNUSED(iMsg); } bool CmdShapeInfo::isActive() { App::Document* doc = App::GetApplication().getActiveDocument(); if (!doc || doc->countObjectsOfType() == 0) { return false; } Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); if (view && view->isDerivedFrom()) { Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); return !viewer->isEditing(); } return false; } //=========================================================================== // Part_RuledSurface //=========================================================================== DEF_STD_CMD_A(CmdPartRuledSurface) CmdPartRuledSurface::CmdPartRuledSurface() : Command("Part_RuledSurface") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Ruled Surface"); sToolTipText = QT_TR_NOOP("Creates a ruled surface between 2 selected wires"); sWhatsThis = "Part_RuledSurface"; sStatusTip = sToolTipText; sPixmap = "Part_RuledSurface"; } void CmdPartRuledSurface::activated(int iMsg) { Q_UNUSED(iMsg); bool ok = true; TopoDS_Shape curve1, curve2; std::string link1, link2, obj1, obj2; const std::vector selobjs = Gui::Selection().getSelectionEx(); const App::DocumentObject* docobj1 = nullptr; const App::DocumentObject* docobj2 = nullptr; if (selobjs.size() != 1 && selobjs.size() != 2) { ok = false; } if (ok && selobjs.size() <= 2) { if (!selobjs.empty()) { const std::vector& subnames1 = selobjs[0].getSubNames(); docobj1 = selobjs[0].getObject(); obj1 = docobj1->getNameInDocument(); obj2 = obj1; // changed later if 2 objects were selected const Part::TopoShape& shape1 = Part::Feature::getTopoShape( docobj1, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (shape1.isNull()) { ok = false; } if (ok && subnames1.size() <= 2) { if (!subnames1.empty()) { curve2 = Part::Feature::getTopoShape( docobj1, Part::ShapeOption::NeedSubElement | Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform, subnames1[0].c_str() ) .getShape(); link1 = subnames1[0]; } if (subnames1.size() == 2) { curve2 = Part::Feature::getTopoShape( docobj1, Part::ShapeOption::NeedSubElement | Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform, subnames1[1].c_str() ) .getShape(); link2 = subnames1[1]; } if (subnames1.empty()) { curve1 = shape1.getShape(); } } else { ok = false; } } if (selobjs.size() == 2) { const std::vector& subnames2 = selobjs[1].getSubNames(); docobj2 = selobjs[1].getObject(); obj2 = docobj2->getNameInDocument(); const Part::TopoShape& shape2 = Part::Feature::getTopoShape( docobj2, Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform ); if (shape2.isNull()) { ok = false; } if (ok && subnames2.size() == 1) { curve2 = Part::Feature::getTopoShape( docobj2, Part::ShapeOption::NeedSubElement | Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform, subnames2[0].c_str() ) .getShape(); link2 = subnames2[0]; } else { if (subnames2.empty()) { curve2 = shape2.getShape(); } } } if (!curve1.IsNull() && !curve2.IsNull()) { if ((curve1.ShapeType() == TopAbs_EDGE || curve1.ShapeType() == TopAbs_WIRE) && (curve2.ShapeType() == TopAbs_EDGE || curve2.ShapeType() == TopAbs_WIRE)) { ok = true; } } } if (!ok) { QMessageBox::warning( Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select either 2 edges or 2 wires.") ); return; } openCommand(QT_TRANSLATE_NOOP("Command", "Create ruled surface")); doCommand(Doc, "FreeCAD.ActiveDocument.addObject('Part::RuledSurface', 'Ruled Surface')"); doCommand( Doc, "FreeCAD.ActiveDocument.ActiveObject.Curve1=(FreeCAD.ActiveDocument.%s,['%s'])", obj1.c_str(), link1.c_str() ); doCommand( Doc, "FreeCAD.ActiveDocument.ActiveObject.Curve2=(FreeCAD.ActiveDocument.%s,['%s'])", obj2.c_str(), link2.c_str() ); commitCommand(); updateActive(); } bool CmdPartRuledSurface::isActive() { return getActiveGuiDocument(); } //=========================================================================== // Part_CheckGeometry //=========================================================================== DEF_STD_CMD_A(CmdCheckGeometry) CmdCheckGeometry::CmdCheckGeometry() : Command("Part_CheckGeometry") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Check Geometry"); sToolTipText = QT_TR_NOOP("Analyzes the selected shapes for errors"); sWhatsThis = "Part_CheckGeometry"; sStatusTip = sToolTipText; sPixmap = "Part_CheckGeometry"; } void CmdCheckGeometry::activated(int iMsg) { Q_UNUSED(iMsg); Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); if (!dlg) { dlg = new PartGui::TaskCheckGeometryDialog(); } Gui::Control().showDialog(dlg); } bool CmdCheckGeometry::isActive() { bool hasShapes = PartGui::hasShapesInSelection(); return (hasShapes && !Gui::Control().activeDialog()); } //=========================================================================== // Part_ColorPerFace //=========================================================================== DEF_STD_CMD_A(CmdColorPerFace) CmdColorPerFace::CmdColorPerFace() : Command("Part_ColorPerFace") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Appearance per &Face"); sToolTipText = QT_TR_NOOP("Sets the appearance of individual faces of the selected object"); sStatusTip = sToolTipText; sWhatsThis = "Part_ColorPerFace"; sPixmap = "Part_ColorFace"; } void CmdColorPerFace::activated(int iMsg) { Q_UNUSED(iMsg); if (getActiveGuiDocument()->getInEdit()) { getActiveGuiDocument()->resetEdit(); } std::vector sel = Gui::Selection().getObjectsOfType( Part::Feature::getClassTypeId() ); if (sel.empty()) { return; } PartGui::ViewProviderPartExt* vp = dynamic_cast( Gui::Application::Instance->getViewProvider(sel.front()) ); if (vp) { vp->changeFaceAppearances(); } } bool CmdColorPerFace::isActive() { bool objectSelected = Gui::Selection().countObjectsOfType() == 1; return (hasActiveDocument() && !Gui::Control().activeDialog() && objectSelected); } //=========================================================================== // Part_BoxSelection //=========================================================================== DEF_STD_CMD_A(CmdBoxSelection) CmdBoxSelection::CmdBoxSelection() : Command("Part_BoxSelection") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Box Selection"); sToolTipText = QT_TR_NOOP("Selects elements in the 3D view using a box selection"); sWhatsThis = "Part_BoxSelection"; sStatusTip = QT_TR_NOOP("Box selection"); sPixmap = "Part_BoxSelection"; } void CmdBoxSelection::activated(int iMsg) { Q_UNUSED(iMsg); PartGui::BoxSelection* sel = new PartGui::BoxSelection(); sel->setAutoDelete(true); sel->start(TopAbs_FACE); } bool CmdBoxSelection::isActive() { return hasActiveDocument(); } //=========================================================================== // Part_ProjectionOnSurface //=========================================================================== DEF_STD_CMD_A(CmdPartProjectionOnSurface) CmdPartProjectionOnSurface::CmdPartProjectionOnSurface() : Command("Part_ProjectionOnSurface") { sAppModule = "Part"; sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Project on Surface"); sToolTipText = QT_TR_NOOP( "Projects edges, wires, or faces of one shape\n" "onto a face of another shape.\n" "The camera view determines the direction\n" "of the projection." ); sWhatsThis = "Part_ProjectionOnSurface"; sStatusTip = sToolTipText; sPixmap = "Part_ProjectionOnSurface"; } void CmdPartProjectionOnSurface::activated(int iMsg) { Q_UNUSED(iMsg); auto dlg = new PartGui::TaskProjectOnSurface(getDocument(nullptr)); Gui::Control().showDialog(dlg); } bool CmdPartProjectionOnSurface::isActive() { return (hasActiveDocument() && !Gui::Control().activeDialog()); } //=========================================================================== // Part_SectionCut //=========================================================================== DEF_STD_CMD_AC(CmdPartSectionCut) CmdPartSectionCut::CmdPartSectionCut() : Command("Part_SectionCut") { sAppModule = "Part"; sGroup = "View"; sMenuText = QT_TR_NOOP("Persiste&nt Section Cut"); sToolTipText = QT_TR_NOOP( "Creates a new object as a boolean intersection of all visible " "shapes and the selected axis planes" ); sWhatsThis = "Part_SectionCut"; sStatusTip = sToolTipText; sPixmap = "Part_SectionCut"; eType = AlterDoc | Alter3DView; } Gui::Action* CmdPartSectionCut::createAction() { Gui::Action* pcAction = Gui::Command::createAction(); return pcAction; } void CmdPartSectionCut::activated(int iMsg) { Q_UNUSED(iMsg); static QPointer sectionCut = nullptr; if (!sectionCut) { sectionCut = PartGui::SectionCut::makeDockWidget(Gui::getMainWindow()); } } bool CmdPartSectionCut::isActive() { return hasActiveDocument(); } //=========================================================================== // Part_CoordinateSystem //=========================================================================== namespace { QString getAutoGroupCommandStr() // Helper function to get the python code to add the newly created object to the active Part/Body // object if present { App::GeoFeature* activeObj = Gui::Application::Instance->activeView()->getActiveObject(PDBODYKEY); if (!activeObj) { activeObj = Gui::Application::Instance->activeView()->getActiveObject( PARTKEY ); } if (activeObj) { QString activeName = QString::fromLatin1(activeObj->getNameInDocument()); return QStringLiteral("App.ActiveDocument.getObject('%1\').addObject(obj)\n").arg(activeName); } return QStringLiteral("# Object created at document root."); } } // namespace DEF_STD_CMD_A(CmdPartCoordinateSystem) CmdPartCoordinateSystem::CmdPartCoordinateSystem() : Command("Part_CoordinateSystem") { sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Coordinate System"); sToolTipText = QT_TR_NOOP("Creates a coordinate system that can be attached to other objects"); sWhatsThis = "Part_CoordinateSystem"; sStatusTip = sToolTipText; sPixmap = "Std_CoordinateSystem"; } void CmdPartCoordinateSystem::activated(int iMsg) { Q_UNUSED(iMsg); openCommand(QT_TRANSLATE_NOOP("Command", "Add coordinate system")); std::string name = getUniqueObjectName("LCS"); doCommand( Doc, "obj = App.activeDocument().addObject('Part::LocalCoordinateSystem','%s')", name.c_str() ); doCommand(Doc, getAutoGroupCommandStr().toUtf8()); doCommand(Doc, "obj.Visibility = True"); doCommand(Doc, "obj.ViewObject.doubleClicked()"); } bool CmdPartCoordinateSystem::isActive() { return hasActiveDocument(); } //=========================================================================== // Part_DatumPlane //=========================================================================== DEF_STD_CMD_A(CmdPartDatumPlane) CmdPartDatumPlane::CmdPartDatumPlane() : Command("Part_DatumPlane") { sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Datum Plane"); sToolTipText = QT_TR_NOOP("Creates a datum plane that can be attached to other objects"); sWhatsThis = "Part_DatumPlane"; sStatusTip = sToolTipText; sPixmap = "Std_Plane"; } void CmdPartDatumPlane::activated(int iMsg) { Q_UNUSED(iMsg); openCommand(QT_TRANSLATE_NOOP("Command", "Add datum plane")); std::string name = getUniqueObjectName("DatumPlane"); doCommand(Doc, "obj = App.activeDocument().addObject('Part::DatumPlane','%s')", name.c_str()); doCommand(Doc, getAutoGroupCommandStr().toUtf8()); doCommand(Doc, "obj.ViewObject.doubleClicked()"); } bool CmdPartDatumPlane::isActive() { return hasActiveDocument(); } //=========================================================================== // Part_DatumLine //=========================================================================== DEF_STD_CMD_A(CmdPartDatumLine) CmdPartDatumLine::CmdPartDatumLine() : Command("Part_DatumLine") { sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Datum Line"); sToolTipText = QT_TR_NOOP("Creates a datum line that can be attached to other objects"); sWhatsThis = "Part_DatumLine"; sStatusTip = sToolTipText; sPixmap = "Std_Axis"; } void CmdPartDatumLine::activated(int iMsg) { Q_UNUSED(iMsg); openCommand(QT_TRANSLATE_NOOP("Command", "Add datum line")); std::string name = getUniqueObjectName("DatumLine"); doCommand(Doc, "obj = App.activeDocument().addObject('Part::DatumLine','%s')", name.c_str()); doCommand(Doc, getAutoGroupCommandStr().toUtf8()); doCommand(Doc, "obj.ViewObject.doubleClicked()"); } bool CmdPartDatumLine::isActive() { return hasActiveDocument(); } //=========================================================================== // Part_DatumPoint //=========================================================================== DEF_STD_CMD_A(CmdPartDatumPoint) CmdPartDatumPoint::CmdPartDatumPoint() : Command("Part_DatumPoint") { sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Datum Point"); sToolTipText = QT_TR_NOOP("Creates a datum point that can be attached to other objects"); sWhatsThis = "Part_DatumPoint"; sStatusTip = sToolTipText; sPixmap = "Std_Point"; } void CmdPartDatumPoint::activated(int iMsg) { Q_UNUSED(iMsg); openCommand(QT_TRANSLATE_NOOP("Command", "Add datum point")); std::string name = getUniqueObjectName("DatumPoint"); doCommand(Doc, "obj = App.activeDocument().addObject('Part::DatumPoint','%s')", name.c_str()); doCommand(Doc, getAutoGroupCommandStr().toUtf8()); doCommand(Doc, "obj.ViewObject.doubleClicked()"); } bool CmdPartDatumPoint::isActive() { return hasActiveDocument(); } //=========================================================================== // Part_Datums //=========================================================================== class CmdPartDatums: public Gui::GroupCommand { public: CmdPartDatums() : GroupCommand("Part_Datums") { sGroup = QT_TR_NOOP("Part"); sMenuText = QT_TR_NOOP("Datums"); sToolTipText = QT_TR_NOOP("Creates a datum object (coordinate system, plane, line, or point) that can be attached to other objects"); sWhatsThis = "Part_Datums"; sStatusTip = sToolTipText; setCheckable(false); addCommand("Part_CoordinateSystem"); addCommand("Part_DatumPlane"); addCommand("Part_DatumLine"); addCommand("Part_DatumPoint"); } const char* className() const override { return "CmdPartDatums"; } bool isActive() override { return hasActiveDocument(); } }; //--------------------------------------------------------------- void CreatePartCommands() { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); rcCmdMgr.addCommand(new CmdPartMakeSolid()); rcCmdMgr.addCommand(new CmdPartReverseShape()); rcCmdMgr.addCommand(new CmdPartBoolean()); rcCmdMgr.addCommand(new CmdPartExtrude()); rcCmdMgr.addCommand(new CmdPartScale()); rcCmdMgr.addCommand(new CmdPartMakeFace()); rcCmdMgr.addCommand(new CmdPartMirror()); rcCmdMgr.addCommand(new CmdPartRevolve()); rcCmdMgr.addCommand(new CmdPartCrossSections()); rcCmdMgr.addCommand(new CmdPartFillet()); rcCmdMgr.addCommand(new CmdPartChamfer()); rcCmdMgr.addCommand(new CmdPartCommon()); rcCmdMgr.addCommand(new CmdPartCut()); rcCmdMgr.addCommand(new CmdPartFuse()); rcCmdMgr.addCommand(new CmdPartCompJoinFeatures()); rcCmdMgr.addCommand(new CmdPartCompSplitFeatures()); rcCmdMgr.addCommand(new CmdPartCompCompoundTools()); rcCmdMgr.addCommand(new CmdPartCompound()); rcCmdMgr.addCommand(new CmdPartSection()); rcCmdMgr.addCommand(new CmdPartPrimitives()); rcCmdMgr.addCommand(new CmdPartImport()); rcCmdMgr.addCommand(new CmdPartExport()); rcCmdMgr.addCommand(new CmdPartImportCurveNet()); rcCmdMgr.addCommand(new CmdPartPickCurveNet()); rcCmdMgr.addCommand(new CmdShapeInfo()); rcCmdMgr.addCommand(new CmdPartRuledSurface()); rcCmdMgr.addCommand(new CmdPartBuilder()); rcCmdMgr.addCommand(new CmdPartLoft()); rcCmdMgr.addCommand(new CmdPartSweep()); rcCmdMgr.addCommand(new CmdPartOffset()); rcCmdMgr.addCommand(new CmdPartOffset2D()); rcCmdMgr.addCommand(new CmdPartCompOffset()); rcCmdMgr.addCommand(new CmdPartThickness()); rcCmdMgr.addCommand(new CmdCheckGeometry()); rcCmdMgr.addCommand(new CmdColorPerFace()); rcCmdMgr.addCommand(new CmdBoxSelection()); rcCmdMgr.addCommand(new CmdPartProjectionOnSurface()); rcCmdMgr.addCommand(new CmdPartSectionCut()); rcCmdMgr.addCommand(new CmdPartCoordinateSystem()); rcCmdMgr.addCommand(new CmdPartDatumPlane()); rcCmdMgr.addCommand(new CmdPartDatumLine()); rcCmdMgr.addCommand(new CmdPartDatumPoint()); rcCmdMgr.addCommand(new CmdPartDatums()); }