Download src/Mod/TechDraw/Gui/Command.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 80 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/TechDraw/Gui/Command.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/TechDraw/Gui/Command.cpp
-
curl -L -o Command.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/TechDraw/Gui/Command.cpp
80 kB
| /*************************************************************************** | |
| * Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de> * | |
| * Copyright (c) 2014 Luke Parry <l.parry@warwick.ac.uk> * | |
| * * | |
| * 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 * | |
| * * | |
| ***************************************************************************/ | |
| void execSimpleSection(Gui::Command* cmd); | |
| void execComplexSection(Gui::Command* cmd); | |
| void getSelectedShapes(Gui::Command* cmd, | |
| std::vector<App::DocumentObject*>& shapes, | |
| std::vector<App::DocumentObject*>& xShapes, | |
| App::DocumentObject* faceObj, | |
| std::string& faceName); | |
| std::pair<App::DocumentObject*, std::string> faceFromSelection(); | |
| std::pair<Base::Vector3d, Base::Vector3d> viewDirection(); | |
| class Vertex; | |
| using namespace TechDrawGui; | |
| using namespace TechDraw; | |
| using DU = DrawUtil; | |
| //=========================================================================== | |
| // TechDraw_PageDefault | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawPageDefault) | |
| CmdTechDrawPageDefault::CmdTechDrawPageDefault() : Command("TechDraw_PageDefault") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("New Page"); | |
| sToolTipText = QT_TR_NOOP("Creates a new page with the default template"); | |
| sWhatsThis = "TechDraw_PageDefault"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_PageDefault"; | |
| } | |
| void CmdTechDrawPageDefault::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| QString templateFileName = Preferences::defaultTemplate(); | |
| QFileInfo tfi(templateFileName); | |
| if (tfi.isReadable()) { | |
| Gui::WaitCursor wc; | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Drawing create page")); | |
| auto page = getDocument()->addObject<TechDraw::DrawPage>("Page"); | |
| if (!page) { | |
| throw Base::TypeError("CmdTechDrawPageDefault - page not created"); | |
| } | |
| page->translateLabel("DrawPage", "Page", page->getNameInDocument()); | |
| auto svgTemplate = getDocument()->addObject<TechDraw::DrawSVGTemplate>("Template"); | |
| if (!svgTemplate) { | |
| throw Base::TypeError("CmdTechDrawPageDefault - template not created"); | |
| } | |
| svgTemplate->translateLabel("DrawSVGTemplate", "Template", svgTemplate->getNameInDocument()); | |
| page->Template.setValue(svgTemplate); | |
| auto filespec = DU::cleanFilespecBackslash(templateFileName.toStdString()); | |
| svgTemplate->Template.setValue(filespec); | |
| updateActive(); | |
| commitCommand(); | |
| TechDrawGui::ViewProviderPage *dvp = dynamic_cast<TechDrawGui::ViewProviderPage *> | |
| (Gui::Application::Instance->getViewProvider(page)); | |
| if (dvp) { | |
| dvp->show(); | |
| } | |
| } | |
| else { | |
| QMessageBox::critical(Gui::getMainWindow(), QLatin1String("No template"), | |
| QLatin1String("No default template found")); | |
| } | |
| } | |
| bool CmdTechDrawPageDefault::isActive() { return hasActiveDocument(); } | |
| //=========================================================================== | |
| // TechDraw_PageTemplate | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawPageTemplate) | |
| CmdTechDrawPageTemplate::CmdTechDrawPageTemplate() : Command("TechDraw_PageTemplate") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("New Page From Template"); | |
| sToolTipText = QT_TR_NOOP("Creates a new page from a custom template"); | |
| sWhatsThis = "TechDraw_PageTemplate"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_PageTemplate"; | |
| } | |
| void CmdTechDrawPageTemplate::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| QString work_dir = Gui::FileDialog::getWorkingDirectory(); | |
| QString templateDir = Preferences::defaultTemplateDir(); | |
| QString templateFileName = Gui::FileDialog::getOpenFileName( | |
| Gui::getMainWindow(), QString::fromUtf8(QT_TR_NOOP("Select a template file")), templateDir, | |
| QString::fromUtf8(QT_TR_NOOP("Template (*.svg)"))); | |
| Gui::FileDialog::setWorkingDirectory(work_dir);// Don't overwrite WD with templateDir | |
| if (templateFileName.isEmpty()) { | |
| return; | |
| } | |
| QFileInfo tfi(templateFileName); | |
| if (tfi.isReadable()) { | |
| Gui::WaitCursor wc; | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Drawing create page")); | |
| auto page = getDocument()->addObject<TechDraw::DrawPage>("Page"); | |
| if (!page) { | |
| throw Base::TypeError("CmdTechDrawPageTemplate - page not created"); | |
| } | |
| page->translateLabel("DrawPage", "Page", page->getNameInDocument()); | |
| auto svgTemplate = getDocument()->addObject<TechDraw::DrawSVGTemplate>("Template"); | |
| if (!svgTemplate) { | |
| throw Base::TypeError("CmdTechDrawPageTemplate - template not created"); | |
| } | |
| svgTemplate->translateLabel("DrawSVGTemplate", "Template", svgTemplate->getNameInDocument()); | |
| page->Template.setValue(svgTemplate); | |
| auto filespec = DU::cleanFilespecBackslash(templateFileName.toStdString()); | |
| svgTemplate->Template.setValue(filespec); | |
| updateActive(); | |
| commitCommand(); | |
| TechDrawGui::ViewProviderPage *dvp = dynamic_cast<TechDrawGui::ViewProviderPage *> | |
| (Gui::Application::Instance->getViewProvider(page)); | |
| if (dvp) { | |
| dvp->show(); | |
| } | |
| } | |
| else { | |
| QMessageBox::critical(Gui::getMainWindow(), QLatin1String("No template"), | |
| QLatin1String("Template file is invalid")); | |
| } | |
| } | |
| bool CmdTechDrawPageTemplate::isActive() { return hasActiveDocument(); } | |
| //=========================================================================== | |
| // TechDraw_RedrawPage | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawRedrawPage) | |
| CmdTechDrawRedrawPage::CmdTechDrawRedrawPage() : Command("TechDraw_RedrawPage") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Redraw Page"); | |
| sToolTipText = QT_TR_NOOP("Redraws the current page"); | |
| sWhatsThis = "TechDraw_RedrawPage"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_RedrawPage"; | |
| } | |
| void CmdTechDrawRedrawPage::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| Gui::WaitCursor wc; | |
| page->redrawCommand(); | |
| } | |
| bool CmdTechDrawRedrawPage::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveView = DrawGuiUtil::needView(this, false); | |
| return (havePage && haveView); | |
| } | |
| //=========================================================================== | |
| // TechDraw_PrintAll | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawPrintAll) | |
| CmdTechDrawPrintAll::CmdTechDrawPrintAll() : Command("TechDraw_PrintAll") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Print All Pages"); | |
| sToolTipText = QT_TR_NOOP("Prints all pages with the print dialog"); | |
| sWhatsThis = "TechDraw_PrintAll"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_PrintAll"; | |
| } | |
| void CmdTechDrawPrintAll::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| MDIViewPage::printAllPages(); | |
| } | |
| bool CmdTechDrawPrintAll::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_View | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawView) | |
| CmdTechDrawView::CmdTechDrawView() : Command("TechDraw_View") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("New View"); | |
| sToolTipText = QT_TR_NOOP( | |
| "Inserts a new view into the current page based on the selected object in the tree view " | |
| "or 3D view.\n" | |
| "If no object is selected, a file browser opens to select an SVG or image file."); | |
| sWhatsThis = "TechDraw_View"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_View"; | |
| } | |
| void CmdTechDrawView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| bool viewCreated = false; | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| // switch to the page if it's not current active window | |
| auto* vpp = freecad_cast<ViewProviderPage*> | |
| (Gui::Application::Instance->getViewProvider(page)); | |
| if (vpp) { | |
| vpp->show(); | |
| } | |
| //set projection direction from selected Face | |
| //use first object with a face selected | |
| std::vector<App::DocumentObject*> shapes, xShapes; | |
| App::DocumentObject* partObj = nullptr; | |
| std::string faceName; | |
| auto selection = getSelection().getSelectionEx(nullptr, App::DocumentObject::getClassTypeId()); | |
| for (auto& sel : selection) { | |
| bool is_linked = false; | |
| auto obj = sel.getObject(); | |
| if (obj->isDerivedFrom<TechDraw::DrawPage>() || obj->isDerivedFrom<TechDraw::DrawView>()) { | |
| continue; | |
| } | |
| if (obj->isDerivedFrom<Spreadsheet::Sheet>()) { | |
| std::string SpreadName = obj->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create spreadsheet view")); | |
| std::string FeatName = getUniqueObjectName("Sheet"); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewSpreadsheet', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewSpreadsheet', 'Sheet', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Source = App.activeDocument().%s", FeatName.c_str(), | |
| SpreadName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| viewCreated = true; | |
| continue; | |
| } | |
| else if (DrawGuiUtil::isArchSection(obj)) { | |
| std::string FeatName = getUniqueObjectName("BIM view"); | |
| std::string SourceName = obj->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create BIM view")); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewArch', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewArch', 'BIM view', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Source = App.activeDocument().%s", FeatName.c_str(), | |
| SourceName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| viewCreated = true; | |
| continue; | |
| } | |
| if (obj->isDerivedFrom<App::LinkElement>() | |
| || obj->isDerivedFrom<App::LinkGroup>() | |
| || obj->isDerivedFrom<App::Link>()) { | |
| is_linked = true; | |
| } | |
| // If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too | |
| // 1st, is obj in another document? | |
| if (obj->getDocument() != this->getDocument()) { | |
| std::set<App::DocumentObject*> parents = obj->getInListEx(true); | |
| for (auto& parent : parents) { | |
| // Only consider parents in the current document, i.e. possible links in this View's document | |
| if (parent->getDocument() != this->getDocument()) { | |
| continue; | |
| } | |
| // 2nd, do we really have a link to obj? | |
| if (parent->isDerivedFrom<App::LinkElement>() | |
| || parent->isDerivedFrom<App::LinkGroup>() | |
| || parent->isDerivedFrom<App::Link>()) { | |
| // We have a link chain from this document to obj, and obj is in another document -> it is an XLink target | |
| is_linked = true; | |
| } | |
| } | |
| } | |
| if (is_linked) { | |
| xShapes.push_back(obj); | |
| continue; | |
| } | |
| //not a Link and not null. assume to be drawable. Undrawables will be | |
| // skipped later. | |
| shapes.push_back(obj); | |
| if (partObj) { | |
| continue; | |
| } | |
| //don't know if this works for an XLink | |
| for (auto& sub : sel.getSubNames()) { | |
| if (TechDraw::DrawUtil::getGeomTypeFromName(sub) == "Face") { | |
| faceName = sub; | |
| // | |
| partObj = obj; | |
| break; | |
| } | |
| } | |
| } | |
| ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/TechDraw"); | |
| if (shapes.empty() && xShapes.empty()) { | |
| if (!viewCreated) { | |
| // If nothing was selected, then we offer to insert SVG or Images files. | |
| bool dontShowAgain = hGrp->GetBool("DontShowInsertFileMessage", false); | |
| if (!dontShowAgain) { | |
| auto msgText = QObject::tr("To insert a view from existing objects, " | |
| "select them before invoking this tool. Without a selection, a " | |
| "file browser will open to insert an SVG or image file."); | |
| QMessageBox msgBox(Gui::getMainWindow()); | |
| msgBox.setText(msgText); | |
| auto dontShowMsg = QObject::tr("Do not show this message again"); | |
| QCheckBox dontShowCheckBox(dontShowMsg, &msgBox); | |
| msgBox.setCheckBox(&dontShowCheckBox); | |
| QPushButton* okButton = msgBox.addButton(QMessageBox::Ok); | |
| msgBox.exec(); | |
| if (msgBox.clickedButton() == okButton && dontShowCheckBox.isChecked()) { | |
| // Save the preference to not show the message again | |
| hGrp->SetBool("DontShowInsertFileMessage", true); | |
| } | |
| } | |
| QString filename = Gui::FileDialog::getOpenFileName(Gui::getMainWindow(), | |
| QObject::tr("Select a SVG or Image file to open"), | |
| Preferences::defaultSymbolDir(), | |
| QStringLiteral("%1 (*.svg *.svgz *.jpg *.jpeg *.png *.bmp);;%2 (*.*)") | |
| .arg(QObject::tr("SVG or Image files"), QObject::tr("All Files"))); | |
| if (!filename.isEmpty()) { | |
| if (filename.endsWith(QStringLiteral(".svg"), Qt::CaseInsensitive) | |
| || filename.endsWith(QStringLiteral(".svgz"), Qt::CaseInsensitive)) { | |
| std::string FeatName = getUniqueObjectName("Symbol"); | |
| filename = Base::Tools::escapeEncodeFilename(filename); | |
| auto filespec = DU::cleanFilespecBackslash(filename.toStdString()); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create Symbol")); | |
| doCommand(Doc, "import codecs"); | |
| doCommand(Doc, | |
| "f = codecs.open(\"%s\", 'r', encoding=\"utf-8\")", | |
| filespec.c_str()); | |
| doCommand(Doc, "svg = f.read()"); | |
| doCommand(Doc, "f.close()"); | |
| doCommand(Doc, | |
| "App.activeDocument().addObject('TechDraw::DrawViewSymbol', '%s')", | |
| FeatName.c_str()); | |
| doCommand( | |
| Doc, | |
| "App.activeDocument().%s.translateLabel('DrawViewSymbol', 'Symbol', '%s')", | |
| FeatName.c_str(), | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Symbol = svg", FeatName.c_str()); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.addView(App.activeDocument().%s)", | |
| PageName.c_str(), | |
| FeatName.c_str()); | |
| } | |
| else { | |
| std::string FeatName = getUniqueObjectName("Image"); | |
| filename = Base::Tools::escapeEncodeFilename(filename); | |
| auto filespec = DU::cleanFilespecBackslash(filename.toStdString()); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create image")); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewImage', '%s')", FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewImage', 'Image', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.ImageFile = '%s'", FeatName.c_str(), filespec.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), FeatName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| } | |
| return; | |
| } | |
| Gui::WaitCursor wc; | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create view")); | |
| std::string FeatName = getUniqueObjectName("View"); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawProjGroupItem', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawProjGroupItem', 'View', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| App::DocumentObject* docObj = getDocument()->getObject(FeatName.c_str()); | |
| auto* dvp = dynamic_cast<TechDraw::DrawViewPart*>(docObj); | |
| if (!dvp) { | |
| throw Base::TypeError("CmdTechDrawView DVP not found\n"); | |
| } | |
| dvp->Source.setValues(shapes); | |
| dvp->XSource.setValues(xShapes); | |
| getDocument()->setStatus(App::Document::Status::SkipRecompute, true); | |
| auto dirs = viewDirection(); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.Direction = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| FeatName.c_str(), dirs.first.x, dirs.first.y, dirs.first.z); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.RotationVector = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| FeatName.c_str(), dirs.second.x, dirs.second.y, dirs.second.z); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.XDirection = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| FeatName.c_str(), dirs.second.x, dirs.second.y, dirs.second.z); | |
| getDocument()->setStatus(App::Document::Status::SkipRecompute, false); | |
| doCommand(Doc, "App.activeDocument().%s.recompute()", FeatName.c_str()); | |
| commitCommand(); | |
| // create the rest of the desired views | |
| Gui::Control().showDialog(new TaskDlgProjGroup(dvp, true)); | |
| } | |
| bool CmdTechDrawView::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_BrokenView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawBrokenView) | |
| CmdTechDrawBrokenView::CmdTechDrawBrokenView() | |
| : Command("TechDraw_BrokenView") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Broken View"); | |
| sToolTipText = QT_TR_NOOP("Inserts a new broken view for the selected objects or base view and break definition objects"); | |
| sWhatsThis = "TechDraw_BrokenView"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_BrokenView"; | |
| } | |
| void CmdTechDrawBrokenView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| // get shape objects from a base view | |
| std::vector<App::DocumentObject*> shapesFromBase; | |
| std::vector<App::DocumentObject*> xShapesFromBase; | |
| std::vector<App::DocumentObject*> baseViews = | |
| getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); | |
| TechDraw::DrawViewPart* dvp{nullptr}; | |
| if (!baseViews.empty()) { | |
| dvp = static_cast<TechDraw::DrawViewPart*>(*baseViews.begin()); | |
| shapesFromBase = dvp->Source.getValues(); | |
| xShapesFromBase = dvp->XSource.getValues(); | |
| } | |
| auto doc = getDocument(); | |
| if (dvp) { | |
| doc = dvp->getDocument(); | |
| } | |
| // get the shape objects from the selection | |
| std::vector<App::DocumentObject*> shapes; | |
| std::vector<App::DocumentObject*> xShapes; | |
| App::DocumentObject* faceObj = nullptr; | |
| std::string faceName; | |
| getSelectedShapes(this, shapes, xShapes, faceObj, faceName); | |
| // we need either a base view (dvp) or some shape objects in the selection | |
| if (!dvp && (shapes.empty() && xShapes.empty())) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Empty selection"), | |
| QObject::tr("Select objects to break or a base view and break definition objects")); | |
| return; | |
| } | |
| shapes.insert(shapes.end(), shapesFromBase.begin(), shapesFromBase.end()); | |
| shapes.insert(xShapes.end(), xShapesFromBase.begin(), xShapesFromBase.end()); | |
| // pick the Break objects out of the selected pile | |
| std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx( | |
| nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::NoResolve); | |
| std::vector<App::DocumentObject*> breakObjects; | |
| for (auto& selObj : selection) { | |
| auto temp = selObj.getObject(); | |
| // a sketch outside a body is returned as an independent object in the selection | |
| if (selObj.getSubNames().empty()) { | |
| if (DrawBrokenView::isBreakObject(*temp)) { | |
| breakObjects.push_back(selObj.getObject()); | |
| } | |
| continue; | |
| } | |
| // a sketch inside a body is returned as body + subelement, so we have to search through | |
| // subnames to find it. This may(?) apply to App::Part and Group also? | |
| auto subname = selObj.getSubNames().front(); | |
| if (subname.back() == '.') { | |
| subname = subname.substr(0, subname.length() - 1); | |
| auto objects = doc->getObjects(); | |
| for (auto& obj : objects) { | |
| std::string objname{obj->getNameInDocument()}; | |
| if (subname == objname && | |
| DrawBrokenView::isBreakObject(*obj)) { | |
| breakObjects.push_back(obj); | |
| } | |
| } | |
| } | |
| } | |
| if (breakObjects.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No break objects found in this selection")); | |
| return; | |
| } | |
| // remove Break objects from shape pile | |
| shapes = DrawBrokenView::removeBreakObjects(breakObjects, shapes); | |
| xShapes = DrawBrokenView::removeBreakObjects(breakObjects, xShapes); | |
| if (shapes.empty() && | |
| xShapes.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No shapes, groups, or links in this selection")); | |
| return; | |
| } | |
| Gui::WaitCursor wc; | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create broken view")); | |
| getDocument()->setStatus(App::Document::Status::SkipRecompute, true); | |
| std::string FeatName = getUniqueObjectName("BrokenView"); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawBrokenView','%s')", FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), FeatName.c_str()); | |
| App::DocumentObject* docObj = getDocument()->getObject(FeatName.c_str()); | |
| TechDraw::DrawBrokenView* dbv = dynamic_cast<TechDraw::DrawBrokenView*>(docObj); | |
| if (!dbv) { | |
| throw Base::TypeError("CmdTechDrawBrokenView DBV not found\n"); | |
| } | |
| dbv->Source.setValues(shapes); | |
| dbv->XSource.setValues(xShapes); | |
| dbv->Breaks.setValues(breakObjects); | |
| //set projection direction from selected Face | |
| std::pair<Base::Vector3d, Base::Vector3d> dirs; | |
| if (faceName.size()) { | |
| dirs = DrawGuiUtil::getProjDirFromFace(faceObj, faceName); | |
| } | |
| else { | |
| dirs = DrawGuiUtil::get3DDirAndRot(); | |
| } | |
| Base::Vector3d projDir = dirs.first; | |
| doCommand(Doc, "App.activeDocument().%s.Direction = FreeCAD.Vector(%.6f,%.6f,%.6f)", | |
| FeatName.c_str(), projDir.x, projDir.y, projDir.z); | |
| doCommand(Doc, "App.activeDocument().%s.XDirection = FreeCAD.Vector(%.6f,%.6f,%.6f)", | |
| FeatName.c_str(), dirs.second.x, dirs.second.y, dirs.second.z); | |
| getDocument()->setStatus(App::Document::Status::SkipRecompute, true); | |
| commitCommand(); | |
| dbv->recomputeFeature(); | |
| } | |
| bool CmdTechDrawBrokenView::isActive(void) | |
| { | |
| return DrawGuiUtil::needPage(this); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ActiveView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawActiveView) | |
| CmdTechDrawActiveView::CmdTechDrawActiveView() : Command("TechDraw_ActiveView") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Active View"); | |
| sToolTipText = "Inserts an image of the open 3D view in the current page.\n" | |
| "If multiple 3D views are open, a selection dialog will be shown."; | |
| sWhatsThis = "TechDraw_ActiveView"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ActiveView"; | |
| } | |
| void CmdTechDrawActiveView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this, true); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| Gui::Control().showDialog(new TaskDlgActiveView(page)); | |
| } | |
| bool CmdTechDrawActiveView::isActive() { return DrawGuiUtil::needPage(this, true); } | |
| //=========================================================================== | |
| // TechDraw_SectionGroup | |
| //=========================================================================== | |
| DEF_STD_CMD_ACL(CmdTechDrawSectionGroup) | |
| CmdTechDrawSectionGroup::CmdTechDrawSectionGroup() : Command("TechDraw_SectionGroup") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Section View (Simple or Complex)"); | |
| sToolTipText = QT_TR_NOOP("Inserts a simple or complex section view in the current page"); | |
| sWhatsThis = "TechDraw_SectionGroup"; | |
| sStatusTip = sToolTipText; | |
| } | |
| void CmdTechDrawSectionGroup::activated(int iMsg) | |
| { | |
| // Base::Console().message("CMD::SectionGrp - activated(%d)\n", iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task in progress"), | |
| QObject::tr("Close active task dialog and try again")); | |
| return; | |
| } | |
| Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction); | |
| pcAction->setIcon(pcAction->actions().at(iMsg)->icon()); | |
| switch (iMsg) { | |
| case 0: | |
| execSimpleSection(this); | |
| break; | |
| case 1: | |
| execComplexSection(this); | |
| break; | |
| default: | |
| Base::Console().message("CMD::SectionGrp - invalid iMsg: %d\n", iMsg); | |
| }; | |
| } | |
| Gui::Action* CmdTechDrawSectionGroup::createAction() | |
| { | |
| Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); | |
| pcAction->setDropDownMenu(true); | |
| applyCommandData(this->className(), pcAction); | |
| QAction* p1 = pcAction->addAction(QString()); | |
| p1->setIcon(Gui::BitmapFactory().iconFromTheme("actions/TechDraw_SectionView")); | |
| p1->setObjectName(QStringLiteral("TechDraw_SectionView")); | |
| p1->setWhatsThis(QStringLiteral("TechDraw_SectionView")); | |
| QAction* p2 = pcAction->addAction(QString()); | |
| p2->setIcon(Gui::BitmapFactory().iconFromTheme("actions/TechDraw_ComplexSection")); | |
| p2->setObjectName(QStringLiteral("TechDraw_ComplexSection")); | |
| p2->setWhatsThis(QStringLiteral("TechDraw_ComplexSection")); | |
| _pcAction = pcAction; | |
| languageChange(); | |
| pcAction->setIcon(p1->icon()); | |
| int defaultId = 0; | |
| pcAction->setProperty("defaultAction", QVariant(defaultId)); | |
| return pcAction; | |
| } | |
| void CmdTechDrawSectionGroup::languageChange() | |
| { | |
| Command::languageChange(); | |
| if (!_pcAction) | |
| return; | |
| Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction); | |
| QList<QAction*> a = pcAction->actions(); | |
| QAction* arc1 = a[0]; | |
| arc1->setText(QApplication::translate("CmdTechDrawSectionGroup", "Section View")); | |
| arc1->setToolTip(QApplication::translate("TechDraw_SectionView", "Inserts a simple section view")); | |
| arc1->setStatusTip(arc1->toolTip()); | |
| QAction* arc2 = a[1]; | |
| arc2->setText(QApplication::translate("CmdTechDrawSectionGroup", "Complex Section View")); | |
| arc2->setToolTip( | |
| QApplication::translate("TechDraw_ComplexSection", "Inserts a complex section view")); | |
| arc2->setStatusTip(arc2->toolTip()); | |
| } | |
| bool CmdTechDrawSectionGroup::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveView = DrawGuiUtil::needView(this, false); | |
| return (havePage && haveView); | |
| } | |
| //=========================================================================== | |
| // TechDraw_SectionView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawSectionView) | |
| CmdTechDrawSectionView::CmdTechDrawSectionView() : Command("TechDraw_SectionView") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Section View"); | |
| sToolTipText = QT_TR_NOOP("Inserts a new section view based on the selected view in the current page"); | |
| sWhatsThis = "TechDraw_SectionView"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_SectionView"; | |
| } | |
| void CmdTechDrawSectionView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task in progress"), | |
| QObject::tr("Close active task dialog and try again")); | |
| return; | |
| } | |
| execSimpleSection(this); | |
| } | |
| bool CmdTechDrawSectionView::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveView = DrawGuiUtil::needView(this); | |
| bool taskInProgress = false; | |
| if (havePage) { | |
| taskInProgress = Gui::Control().activeDialog(); | |
| } | |
| return (havePage && haveView && !taskInProgress); | |
| } | |
| void execSimpleSection(Gui::Command* cmd) | |
| { | |
| std::vector<App::DocumentObject*> baseObj = | |
| cmd->getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); | |
| if (baseObj.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select at least 1 DrawViewPart object as base")); | |
| return; | |
| } | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(cmd); | |
| if (!page) { | |
| return; | |
| } | |
| TechDraw::DrawViewPart* dvp = static_cast<TechDraw::DrawViewPart*>(*baseObj.begin()); | |
| Gui::Control().showDialog(new TaskDlgSectionView(dvp)); | |
| cmd->updateActive();//ok here since dialog doesn't call doc.recompute() | |
| cmd->commitCommand(); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ComplexSection | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawComplexSection) | |
| CmdTechDrawComplexSection::CmdTechDrawComplexSection() : Command("TechDraw_ComplexSection") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Complex Section View"); | |
| sToolTipText = QT_TR_NOOP("Inserts a complex section view based on the selected view in the current page"); | |
| sWhatsThis = "TechDraw_ComplexSection"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ComplexSection"; | |
| } | |
| void CmdTechDrawComplexSection::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (dlg) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task in progress"), | |
| QObject::tr("Close active task dialog and try again")); | |
| return; | |
| } | |
| execComplexSection(this); | |
| } | |
| bool CmdTechDrawComplexSection::isActive() { return DrawGuiUtil::needPage(this); } | |
| //Complex Sections can be created without a baseView, so the gathering of input | |
| //for the dialog is more involved that simple section | |
| void execComplexSection(Gui::Command* cmd) | |
| { | |
| TechDraw::DrawViewPart* baseView(nullptr); | |
| std::vector<App::DocumentObject*> shapes; | |
| std::vector<App::DocumentObject*> xShapes; | |
| App::DocumentObject* profileObject(nullptr); | |
| std::vector<std::string> profileSubs; | |
| Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement; | |
| bool single = false; | |
| auto selection = cmd->getSelection().getSelectionEx( | |
| nullptr, App::DocumentObject::getClassTypeId(), resolve, single); | |
| for (auto& sel : selection) { | |
| bool is_linked = false; | |
| auto obj = sel.getObject(); | |
| if (obj->isDerivedFrom<TechDraw::DrawPage>()) { | |
| continue; | |
| } | |
| if (obj->isDerivedFrom<TechDraw::DrawViewPart>()) { | |
| //use the dvp's Sources as sources for this ComplexSection & | |
| //check the subelement(s) to see if they can be used as a profile | |
| baseView = static_cast<TechDraw::DrawViewPart*>(obj); | |
| if (!sel.getSubNames().empty()) { | |
| //need to add profile subs as parameter | |
| profileObject = baseView; | |
| profileSubs = sel.getSubNames(); | |
| } | |
| continue; | |
| } | |
| if (obj->isDerivedFrom<App::LinkElement>() | |
| || obj->isDerivedFrom<App::LinkGroup>() | |
| || obj->isDerivedFrom<App::Link>()) { | |
| is_linked = true; | |
| } | |
| // If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too | |
| // 1st, is obj in another document? | |
| if (obj->getDocument() != cmd->getDocument()) { | |
| std::set<App::DocumentObject*> parents = obj->getInListEx(true); | |
| for (auto& parent : parents) { | |
| // Only consider parents in the current document, i.e. possible links in this View's document | |
| if (parent->getDocument() != cmd->getDocument()) { | |
| continue; | |
| } | |
| // 2nd, do we really have a link to obj? | |
| if (parent->isDerivedFrom<App::LinkElement>() | |
| || parent->isDerivedFrom<App::LinkGroup>() | |
| || parent->isDerivedFrom<App::Link>()) { | |
| // We have a link chain from this document to obj, and obj is in another document -> it is an XLink target | |
| is_linked = true; | |
| } | |
| } | |
| } | |
| if (is_linked) { | |
| xShapes.push_back(obj); | |
| continue; | |
| } | |
| //not a Link and not null. assume to be drawable. Undrawables will be | |
| // skipped later. | |
| if (TechDraw::DrawComplexSection::isProfileObject(obj)) { | |
| profileObject = obj; | |
| } | |
| else { | |
| shapes.push_back(obj); | |
| } | |
| } | |
| if (!baseView) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No base view selected")); | |
| return; | |
| } | |
| if (shapes.empty() && xShapes.empty() && !baseView) { | |
| QMessageBox::warning( | |
| Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No base view, shapes, groups, or links in this selection")); | |
| return; | |
| } | |
| if (!profileObject) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No profile object found in selection")); | |
| return; | |
| } | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(cmd); | |
| if (!page) { | |
| return; | |
| } | |
| Gui::Control().showDialog( | |
| new TaskDlgComplexSection(page, baseView, shapes, xShapes, profileObject, profileSubs)); | |
| } | |
| //=========================================================================== | |
| // TechDraw_DetailView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawDetailView) | |
| CmdTechDrawDetailView::CmdTechDrawDetailView() : Command("TechDraw_DetailView") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Detail View"); | |
| sToolTipText = QT_TR_NOOP("Inserts a new detail view based on the selected view in the current page"); | |
| sWhatsThis = "TechDraw_DetailView"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_DetailView"; | |
| } | |
| void CmdTechDrawDetailView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| std::vector<App::DocumentObject*> baseObj = | |
| getSelection().getObjectsOfType(TechDraw::DrawViewPart::getClassTypeId()); | |
| if (baseObj.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select at least 1 DrawViewPart object as base")); | |
| return; | |
| } | |
| TechDraw::DrawViewPart* dvp = static_cast<TechDraw::DrawViewPart*>(*(baseObj.begin())); | |
| Gui::Control().showDialog(new TaskDlgDetail(dvp)); | |
| } | |
| bool CmdTechDrawDetailView::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveView = DrawGuiUtil::needView(this); | |
| bool taskInProgress = false; | |
| if (havePage) { | |
| taskInProgress = Gui::Control().activeDialog(); | |
| } | |
| return (havePage && haveView && !taskInProgress); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ProjectionGroup | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawProjectionGroup) | |
| CmdTechDrawProjectionGroup::CmdTechDrawProjectionGroup() : Command("TechDraw_ProjectionGroup") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Projection Group"); | |
| sToolTipText = QT_TR_NOOP("Inserts multiple new linked views of the selected objects in the current page"); | |
| sWhatsThis = "TechDraw_ProjectionGroup"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ProjectionGroup"; | |
| } | |
| void CmdTechDrawProjectionGroup::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| //set projection direction from selected Face | |
| //use first object with a face selected | |
| std::vector<App::DocumentObject*> shapes; | |
| std::vector<App::DocumentObject*> xShapes; | |
| App::DocumentObject* partObj = nullptr; | |
| std::string faceName; | |
| Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement; | |
| bool single = false; | |
| auto selection = getSelection().getSelectionEx(nullptr, App::DocumentObject::getClassTypeId(), | |
| resolve, single); | |
| for (auto& sel : selection) { | |
| bool is_linked = false; | |
| auto obj = sel.getObject(); | |
| if (obj->isDerivedFrom<TechDraw::DrawPage>()) { | |
| continue; | |
| } | |
| if (obj->isDerivedFrom<App::LinkElement>() | |
| || obj->isDerivedFrom<App::LinkGroup>() | |
| || obj->isDerivedFrom<App::Link>()) { | |
| is_linked = true; | |
| } | |
| // If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too | |
| // 1st, is obj in another document? | |
| if (obj->getDocument() != this->getDocument()) { | |
| std::set<App::DocumentObject*> parents = obj->getInListEx(true); | |
| for (auto& parent : parents) { | |
| // Only consider parents in the current document, i.e. possible links in this View's document | |
| if (parent->getDocument() != this->getDocument()) { | |
| continue; | |
| } | |
| // 2nd, do we really have a link to obj? | |
| if (parent->isDerivedFrom<App::LinkElement>() | |
| || parent->isDerivedFrom<App::LinkGroup>() | |
| || parent->isDerivedFrom<App::Link>()) { | |
| // We have a link chain from this document to obj, and obj is in another document -> it is an XLink target | |
| is_linked = true; | |
| } | |
| } | |
| } | |
| if (is_linked) { | |
| xShapes.push_back(obj); | |
| continue; | |
| } | |
| //not a Link and not null. assume to be drawable. Undrawables will be | |
| // skipped later. | |
| shapes.push_back(obj); | |
| if (partObj) { | |
| continue; | |
| } | |
| for (auto& sub : sel.getSubNames()) { | |
| if (TechDraw::DrawUtil::getGeomTypeFromName(sub) == "Face") { | |
| faceName = sub; | |
| partObj = obj; | |
| break; | |
| } | |
| } | |
| } | |
| if (shapes.empty() && xShapes.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No shapes, groups, or links in this selection")); | |
| return; | |
| } | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| Base::Vector3d projDir; | |
| Gui::WaitCursor wc; | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create projection group")); | |
| std::string multiViewName = getUniqueObjectName("ProjGroup"); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawProjGroup', '%s')", | |
| multiViewName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| multiViewName.c_str()); | |
| App::DocumentObject* docObj = getDocument()->getObject(multiViewName.c_str()); | |
| auto multiView(static_cast<TechDraw::DrawProjGroup*>(docObj)); | |
| multiView->Source.setValues(shapes); | |
| multiView->XSource.setValues(xShapes); | |
| doCommand(Doc, "App.activeDocument().%s.addProjection('Front')", multiViewName.c_str()); | |
| std::pair<Base::Vector3d, Base::Vector3d> dirs = !faceName.empty() ? | |
| DrawGuiUtil::getProjDirFromFace(partObj, faceName) | |
| : DrawGuiUtil::get3DDirAndRot(); | |
| getDocument()->setStatus(App::Document::Status::SkipRecompute, true); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.Anchor.Direction = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| multiViewName.c_str(), dirs.first.x, dirs.first.y, dirs.first.z); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.Anchor.RotationVector = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| multiViewName.c_str(), dirs.second.x, dirs.second.y, dirs.second.z); | |
| doCommand(Doc, | |
| "App.activeDocument().%s.Anchor.XDirection = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| multiViewName.c_str(), dirs.second.x, dirs.second.y, dirs.second.z); | |
| getDocument()->setStatus(App::Document::Status::SkipRecompute, false); | |
| doCommand(Doc, "App.activeDocument().%s.Anchor.recompute()", multiViewName.c_str()); | |
| commitCommand(); | |
| updateActive(); | |
| // create the rest of the desired views | |
| Gui::Control().showDialog(new TaskDlgProjGroup(multiView, true)); | |
| } | |
| bool CmdTechDrawProjectionGroup::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool taskInProgress = false; | |
| if (havePage) { | |
| taskInProgress = Gui::Control().activeDialog(); | |
| } | |
| return (havePage && !taskInProgress); | |
| } | |
| //! common checks of Selection for Dimension commands | |
| //non-empty selection, no more than maxObjs selected and at least 1 DrawingPage exists | |
| bool _checkSelectionBalloon(Gui::Command* cmd, unsigned maxObjs) | |
| { | |
| std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx(); | |
| if (selection.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"), | |
| QObject::tr("Select an object first")); | |
| return false; | |
| } | |
| const std::vector<std::string> SubNames = selection[0].getSubNames(); | |
| if (SubNames.size() > maxObjs) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"), | |
| QObject::tr("Too many objects selected")); | |
| return false; | |
| } | |
| std::vector<App::DocumentObject*> pages = | |
| cmd->getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId()); | |
| if (pages.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"), | |
| QObject::tr("Create a page first")); | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool _checkDrawViewPartBalloon(Gui::Command* cmd) | |
| { | |
| std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx(); | |
| auto objFeat(dynamic_cast<TechDraw::DrawViewPart*>(selection[0].getObject())); | |
| if (!objFeat) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"), | |
| QObject::tr("No view of a part in selection")); | |
| return false; | |
| } | |
| return true; | |
| } | |
| bool _checkDirectPlacement(const QGIView* view, const std::vector<std::string>& subNames, | |
| QPointF& placement) | |
| { | |
| // Let's see, if we can help speed up the placement of the balloon: | |
| // As of now we support: | |
| // Single selected vertex: place the balloon tip end here | |
| // Single selected edge: place the balloon tip at its midpoint (suggested placement for e.g. chamfer dimensions) | |
| // | |
| // Single selected faces are currently not supported, but maybe we could in this case use the center of mass? | |
| if (subNames.size() != 1) { | |
| // If nothing or more than one subjects are selected, let the user decide, where to place the balloon | |
| return false; | |
| } | |
| const QGIViewPart* viewPart = dynamic_cast<const QGIViewPart*>(view); | |
| if (!viewPart) { | |
| //not a view of a part, so no geometry to attach to | |
| return false; | |
| } | |
| std::string geoType = TechDraw::DrawUtil::getGeomTypeFromName(subNames[0]); | |
| if (geoType == "Vertex") { | |
| int index = TechDraw::DrawUtil::getIndexFromName(subNames[0]); | |
| TechDraw::VertexPtr vertex = | |
| static_cast<DrawViewPart*>(viewPart->getViewObject())->getProjVertexByIndex(index); | |
| if (vertex) { | |
| placement = viewPart->mapToScene(Rez::guiX(vertex->x()), Rez::guiX(vertex->y())); | |
| return true; | |
| } | |
| } | |
| else if (geoType == "Edge") { | |
| int index = TechDraw::DrawUtil::getIndexFromName(subNames[0]); | |
| TechDraw::BaseGeomPtr geo = | |
| static_cast<DrawViewPart*>(viewPart->getViewObject())->getGeomByIndex(index); | |
| if (geo) { | |
| Base::Vector3d midPoint(Rez::guiX(geo->getMidPoint())); | |
| placement = viewPart->mapToScene(midPoint.x, midPoint.y); | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| DEF_STD_CMD_A(CmdTechDrawBalloon) | |
| CmdTechDrawBalloon::CmdTechDrawBalloon() : Command("TechDraw_Balloon") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Balloon Annotation"); | |
| sToolTipText = QT_TR_NOOP("Inserts a new balloon annotation in the selected view"); | |
| sWhatsThis = "TechDraw_Balloon"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "TechDraw_Balloon"; | |
| } | |
| void CmdTechDrawBalloon::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| bool result = _checkSelectionBalloon(this, 1); | |
| if (!result) { | |
| return; | |
| } | |
| std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(); | |
| auto objFeat(dynamic_cast<TechDraw::DrawView*>(selection[0].getObject())); | |
| if (!objFeat) { | |
| return; | |
| } | |
| TechDraw::DrawPage* page = objFeat->findParentPage(); | |
| std::string PageName = page->getNameInDocument(); | |
| Gui::Document* guiDoc = Gui::Application::Instance->getDocument(page->getDocument()); | |
| ViewProviderPage* pageVP = freecad_cast<ViewProviderPage*>(guiDoc->getViewProvider(page)); | |
| ViewProviderDrawingView* viewVP = | |
| freecad_cast<ViewProviderDrawingView*>(guiDoc->getViewProvider(objFeat)); | |
| if (pageVP && viewVP) { | |
| QGVPage* viewPage = pageVP->getQGVPage(); | |
| QGSPage* scenePage = pageVP->getQGSPage(); | |
| if (viewPage) { | |
| auto* view = dynamic_cast<QGIView*>(viewVP->getQView()); | |
| QPointF placement; | |
| if (view && _checkDirectPlacement(view, selection[0].getSubNames(), placement)) { | |
| //this creates the balloon if something is already selected | |
| scenePage->createBalloon(placement, objFeat); | |
| return; | |
| } | |
| viewPage->startBalloonPlacing(objFeat); | |
| } | |
| } | |
| } | |
| bool CmdTechDrawBalloon::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveView = DrawGuiUtil::needView(this, false); | |
| bool taskInProgress = Gui::Control().activeDialog(); | |
| return (havePage && haveView && !taskInProgress); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ClipGroup | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawClipGroup) | |
| CmdTechDrawClipGroup::CmdTechDrawClipGroup() : Command("TechDraw_ClipGroup") | |
| { | |
| // setting the | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Clip Group"); | |
| sToolTipText = QT_TR_NOOP("Inserts a new clip group for the selected view"); | |
| sWhatsThis = "TechDraw_ClipGroup"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ClipGroup"; | |
| } | |
| void CmdTechDrawClipGroup::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| std::string FeatName = getUniqueObjectName("Clip"); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create clip")); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewClip', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| bool CmdTechDrawClipGroup::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_ClipGroupAdd | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawClipGroupAdd) | |
| CmdTechDrawClipGroupAdd::CmdTechDrawClipGroupAdd() : Command("TechDraw_ClipGroupAdd") | |
| { | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Add View To Clip Group"); | |
| sToolTipText = QT_TR_NOOP("Adds the selected view to a clip group"); | |
| sWhatsThis = "TechDraw_ClipGroupAdd"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ClipGroupAdd"; | |
| } | |
| void CmdTechDrawClipGroupAdd::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(); | |
| if (selection.size() != 2) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select one clip group and one view")); | |
| return; | |
| } | |
| TechDraw::DrawViewClip* clip = nullptr; | |
| TechDraw::DrawView* view = nullptr; | |
| std::vector<Gui::SelectionObject>::iterator itSel = selection.begin(); | |
| for (; itSel != selection.end(); itSel++) { | |
| if ((*itSel).getObject()->isDerivedFrom<TechDraw::DrawViewClip>()) { | |
| clip = static_cast<TechDraw::DrawViewClip*>((*itSel).getObject()); | |
| } | |
| else if ((*itSel).getObject()->isDerivedFrom<TechDraw::DrawView>()) { | |
| view = static_cast<TechDraw::DrawView*>((*itSel).getObject()); | |
| } | |
| } | |
| if (!view) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select exactly one view to add to clip group")); | |
| return; | |
| } | |
| if (!clip) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select exactly one clip group")); | |
| return; | |
| } | |
| TechDraw::DrawPage* pageClip = clip->findParentPage(); | |
| TechDraw::DrawPage* pageView = view->findParentPage(); | |
| if (pageClip != pageView) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Clip and view must be from same page")); | |
| return; | |
| } | |
| std::string PageName = pageClip->getNameInDocument(); | |
| std::string ClipName = clip->getNameInDocument(); | |
| std::string ViewName = view->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Add clip group")); | |
| doCommand(Doc, "App.activeDocument().%s.ViewObject.Visibility = False", ViewName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", ClipName.c_str(), | |
| ViewName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.ViewObject.Visibility = True", ViewName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| bool CmdTechDrawClipGroupAdd::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveClip = false; | |
| if (havePage) { | |
| auto drawClipType(TechDraw::DrawViewClip::getClassTypeId()); | |
| auto selClips = getDocument()->getObjectsOfType(drawClipType); | |
| if (!selClips.empty()) { | |
| haveClip = true; | |
| } | |
| } | |
| return (havePage && haveClip); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ClipGroupRemove | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawClipGroupRemove) | |
| CmdTechDrawClipGroupRemove::CmdTechDrawClipGroupRemove() : Command("TechDraw_ClipGroupRemove") | |
| { | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Remove From Clip Group"); | |
| sToolTipText = QT_TR_NOOP("Removes a view based on the selected clip group"); | |
| sWhatsThis = "TechDraw_ClipGroupRemove"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ClipGroupRemove"; | |
| } | |
| void CmdTechDrawClipGroupRemove::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| auto dObj(getSelection().getObjectsOfType(TechDraw::DrawView::getClassTypeId())); | |
| if (dObj.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select exactly one view to remove from clip group")); | |
| return; | |
| } | |
| auto view(static_cast<TechDraw::DrawView*>(dObj.front())); | |
| TechDraw::DrawPage* page = view->findParentPage(); | |
| const std::vector<App::DocumentObject*> pViews = page->getViews(); | |
| TechDraw::DrawViewClip* clip(nullptr); | |
| for (auto& v : pViews) { | |
| clip = dynamic_cast<TechDraw::DrawViewClip*>(v); | |
| if (clip && clip->isViewInClip(view)) { | |
| break; | |
| } | |
| clip = nullptr; | |
| } | |
| if (!clip) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("View does not belong to a clip")); | |
| return; | |
| } | |
| std::string ClipName = clip->getNameInDocument(); | |
| std::string ViewName = view->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Remove clip group")); | |
| doCommand(Doc, "App.activeDocument().%s.ViewObject.Visibility = False", ViewName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.removeView(App.activeDocument().%s)", ClipName.c_str(), | |
| ViewName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.ViewObject.Visibility = True", ViewName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| bool CmdTechDrawClipGroupRemove::isActive() | |
| { | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveClip = false; | |
| if (havePage) { | |
| auto drawClipType(TechDraw::DrawViewClip::getClassTypeId()); | |
| auto selClips = getDocument()->getObjectsOfType(drawClipType); | |
| if (!selClips.empty()) { | |
| haveClip = true; | |
| } | |
| } | |
| return (havePage && haveClip); | |
| } | |
| //=========================================================================== | |
| // TechDraw_Symbol | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawSymbol) | |
| CmdTechDrawSymbol::CmdTechDrawSymbol() : Command("TechDraw_Symbol") | |
| { | |
| // setting the Gui eye-candy | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Insert SVG"); | |
| sToolTipText = QT_TR_NOOP("Inserts a symbol from an SVG file"); | |
| sWhatsThis = "TechDraw_Symbol"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_Symbol"; | |
| } | |
| void CmdTechDrawSymbol::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| // Reading an image | |
| QString filename = Gui::FileDialog::getOpenFileName( | |
| Gui::getMainWindow(), QObject::tr("Choose an SVG file to open"), | |
| Preferences::defaultSymbolDir(), | |
| QStringLiteral("%1 (*.svg *.svgz);;%2 (*.*)") | |
| .arg(QObject::tr("Scalable vector graphic"), QObject::tr("All files"))); | |
| if (!filename.isEmpty()) { | |
| std::string FeatName = getUniqueObjectName("Symbol"); | |
| filename = Base::Tools::escapeEncodeFilename(filename); | |
| auto filespec = DU::cleanFilespecBackslash(filename.toStdString()); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create Symbol")); | |
| doCommand(Doc, "import codecs"); | |
| doCommand(Doc, "f = codecs.open(\"%s\", 'r', encoding=\"utf-8\")", filespec.c_str()); | |
| doCommand(Doc, "svg = f.read()"); | |
| doCommand(Doc, "f.close()"); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewSymbol', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewSymbol', 'Symbol', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Symbol = svg", FeatName.c_str()); | |
| auto baseView = CommandHelpers::firstViewInSelection(this); | |
| if (baseView) { | |
| auto baseName = baseView->getNameInDocument(); | |
| doCommand(Doc, "App.activeDocument().%s.Owner = App.activeDocument().%s", | |
| FeatName.c_str(), baseName); | |
| } | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| } | |
| bool CmdTechDrawSymbol::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_DraftView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawDraftView) | |
| CmdTechDrawDraftView::CmdTechDrawDraftView() : Command("TechDraw_DraftView") | |
| { | |
| // setting the Gui eye-candy | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Draft View"); | |
| //: "Draft" is a workbench and should not be translated | |
| sToolTipText = QT_TR_NOOP("Inserts a view of a Draft object"); | |
| sWhatsThis = "TechDraw_NewDraft"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_DraftView"; | |
| } | |
| void CmdTechDrawDraftView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| std::vector<App::DocumentObject*> objects = | |
| getSelection().getObjectsOfType(App::DocumentObject::getClassTypeId()); | |
| if (objects.empty()) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select at least one object")); | |
| return; | |
| } | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| std::pair<Base::Vector3d, Base::Vector3d> dirs = DrawGuiUtil::get3DDirAndRot(); | |
| for (auto* obj : objects) { | |
| if (obj->isDerivedFrom<TechDraw::DrawPage>() || | |
| obj->isDerivedFrom<TechDraw::DrawView>()) { | |
| // skip over TechDraw objects as they are not valid subjects for a DraftView | |
| continue; | |
| } | |
| std::string FeatName = getUniqueObjectName("DraftView"); | |
| std::string SourceName = obj->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create DraftView")); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewDraft', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewDraft', 'DraftView', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Source = App.activeDocument().%s", FeatName.c_str(), | |
| SourceName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Direction = FreeCAD.Vector(%.12f, %.12f, %.12f)", | |
| FeatName.c_str(), dirs.first.x, dirs.first.y, dirs.first.z); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| } | |
| bool CmdTechDrawDraftView::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_ArchView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawArchView) | |
| CmdTechDrawArchView::CmdTechDrawArchView() : Command("TechDraw_ArchView") | |
| { | |
| // setting the Gui eye-candy | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("BIM View"); | |
| sToolTipText = QT_TR_NOOP("Inserts a view of a BIM section plane"); | |
| sWhatsThis = "TechDraw_NewArch"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ArchView"; | |
| } | |
| void CmdTechDrawArchView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| const std::vector<App::DocumentObject*> objects = | |
| getSelection().getObjectsOfType(App::DocumentObject::getClassTypeId()); | |
| App::DocumentObject* archObject = nullptr; | |
| int archCount = 0; | |
| for (auto& obj : objects) { | |
| if (obj->isDerivedFrom<TechDraw::DrawPage>() || | |
| obj->isDerivedFrom<TechDraw::DrawView>()) { | |
| // skip over TechDraw objects as they are not valid subjects for a ArchView | |
| continue; | |
| } | |
| if (DrawGuiUtil::isArchSection(obj)) { | |
| archCount++; | |
| archObject = obj; | |
| } | |
| } | |
| if (archCount > 1) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select only 1 BIM section plane")); | |
| return; | |
| } | |
| if (!archObject) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("No BIM section plane in selection")); | |
| return; | |
| } | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| std::string FeatName = getUniqueObjectName("BIM view"); | |
| std::string SourceName = archObject->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create BIM view")); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewArch', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewArch', 'BIM view', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Source = App.activeDocument().%s", FeatName.c_str(), | |
| SourceName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| doCommand(Doc, "if App.activeDocument().%s.Scale: App.activeDocument().%s.Scale = App.activeDocument().%s.Scale", | |
| PageName.c_str(), FeatName.c_str(), PageName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| bool CmdTechDrawArchView::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_SpreadsheetView | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawSpreadsheetView) | |
| CmdTechDrawSpreadsheetView::CmdTechDrawSpreadsheetView() : Command("TechDraw_SpreadsheetView") | |
| { | |
| // setting the | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Spreadsheet View"); | |
| sToolTipText = QT_TR_NOOP("Inserts a view of a spreadsheet in the current page"); | |
| sWhatsThis = "TechDraw_SpreadsheetView"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_SpreadsheetView"; | |
| } | |
| void CmdTechDrawSpreadsheetView::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| const std::vector<App::DocumentObject*> spreads = | |
| getSelection().getObjectsOfType(Spreadsheet::Sheet::getClassTypeId()); | |
| if (spreads.size() != 1) { | |
| QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), | |
| QObject::tr("Select exactly one spreadsheet object")); | |
| return; | |
| } | |
| std::string SpreadName = spreads.front()->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Create spreadsheet view")); | |
| std::string FeatName = getUniqueObjectName("Sheet"); | |
| doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewSpreadsheet', '%s')", | |
| FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewSpreadsheet', 'Sheet', '%s')", | |
| FeatName.c_str(), FeatName.c_str()); | |
| doCommand(Doc, "App.activeDocument().%s.Source = App.activeDocument().%s", FeatName.c_str(), | |
| SpreadName.c_str()); | |
| // look for an owner view in the selection | |
| auto baseView = CommandHelpers::firstViewInSelection(this); | |
| if (baseView) { | |
| auto baseName = baseView->getNameInDocument(); | |
| doCommand(Doc, "App.activeDocument().%s.Owner = App.activeDocument().%s", | |
| FeatName.c_str(), baseName); | |
| } | |
| doCommand(Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", PageName.c_str(), | |
| FeatName.c_str()); | |
| updateActive(); | |
| commitCommand(); | |
| } | |
| bool CmdTechDrawSpreadsheetView::isActive() | |
| { | |
| //need a Page and a SpreadSheet::Sheet | |
| bool havePage = DrawGuiUtil::needPage(this); | |
| bool haveSheet = false; | |
| if (havePage) { | |
| auto spreadSheetType(Spreadsheet::Sheet::getClassTypeId()); | |
| auto selSheets = getDocument()->getObjectsOfType(spreadSheetType); | |
| if (!selSheets.empty()) { | |
| haveSheet = true; | |
| } | |
| } | |
| return (havePage && haveSheet); | |
| } | |
| //=========================================================================== | |
| // TechDraw_ExportPageSVG | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawExportPageSVG) | |
| CmdTechDrawExportPageSVG::CmdTechDrawExportPageSVG() : Command("TechDraw_ExportPageSVG") | |
| { | |
| sGroup = QT_TR_NOOP("File"); | |
| sMenuText = QT_TR_NOOP("Export Page as SVG"); | |
| sToolTipText = QT_TR_NOOP("Exports the current page as an SVG"); | |
| sWhatsThis = "TechDraw_ExportPageSVG"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ExportPageSVG"; | |
| } | |
| void CmdTechDrawExportPageSVG::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| Gui::Document* activeGui = Gui::Application::Instance->getDocument(page->getDocument()); | |
| Gui::ViewProvider* vp = activeGui->getViewProvider(page); | |
| ViewProviderPage* vpPage = freecad_cast<ViewProviderPage*>(vp); | |
| if (vpPage) { | |
| vpPage->show(); // make sure a mdi will be available | |
| vpPage->getMDIViewPage()->saveSVG(); | |
| } | |
| else { | |
| QMessageBox::warning(Gui::getMainWindow(), | |
| QObject::tr("No drawing page"), | |
| QObject::tr("FreeCAD could not find a page to export")); | |
| return; | |
| } | |
| } | |
| bool CmdTechDrawExportPageSVG::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_ExportPageDXF | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawExportPageDXF) | |
| CmdTechDrawExportPageDXF::CmdTechDrawExportPageDXF() : Command("TechDraw_ExportPageDXF") | |
| { | |
| sGroup = QT_TR_NOOP("File"); | |
| sMenuText = QT_TR_NOOP("Export Page as DXF"); | |
| sToolTipText = QT_TR_NOOP("Exports the current page as a DXF"); | |
| sWhatsThis = "TechDraw_ExportPageDXF"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ExportPageDXF"; | |
| } | |
| void CmdTechDrawExportPageDXF::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); | |
| if (!page) { | |
| return; | |
| } | |
| std::vector<App::DocumentObject*> views = page->getViews(); | |
| for (auto& v : views) { | |
| if (v->isDerivedFrom<TechDraw::DrawViewArch>()) { | |
| QMessageBox::StandardButton rc = QMessageBox::question( | |
| Gui::getMainWindow(), QObject::tr("Cannot export selection"), | |
| QObject::tr("Page contains a BIM view which will not be exported. Continue?"), | |
| QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No)); | |
| if (rc == QMessageBox::No) { | |
| return; | |
| } | |
| else { | |
| break; | |
| } | |
| } | |
| } | |
| //WF? allow more than one TD Page per Dxf file?? 1 TD page = 1 DXF file = 1 drawing? | |
| QString defaultDir; | |
| QString fileName = Gui::FileDialog::getSaveFileName( | |
| Gui::getMainWindow(), QString::fromUtf8(QT_TR_NOOP("Save DXF file")), defaultDir, | |
| QStringLiteral("DXF (*.dxf)")); | |
| if (fileName.isEmpty()) { | |
| return; | |
| } | |
| std::string PageName = page->getNameInDocument(); | |
| openCommand(QT_TRANSLATE_NOOP("Command", "Save page to DXF")); | |
| doCommand(Doc, "import TechDraw"); | |
| fileName = Base::Tools::escapeEncodeFilename(fileName); | |
| auto filespec = DU::cleanFilespecBackslash(fileName.toStdString()); | |
| doCommand(Doc, "TechDraw.writeDXFPage(App.activeDocument().%s, u\"%s\")", PageName.c_str(), | |
| filespec.c_str()); | |
| commitCommand(); | |
| } | |
| bool CmdTechDrawExportPageDXF::isActive() { return DrawGuiUtil::needPage(this); } | |
| //=========================================================================== | |
| // TechDraw_ProjectShape | |
| //=========================================================================== | |
| DEF_STD_CMD_A(CmdTechDrawProjectShape) | |
| CmdTechDrawProjectShape::CmdTechDrawProjectShape() : Command("TechDraw_ProjectShape") | |
| { | |
| sAppModule = "TechDraw"; | |
| sGroup = QT_TR_NOOP("TechDraw"); | |
| sMenuText = QT_TR_NOOP("Project Shape"); | |
| sToolTipText = QT_TR_NOOP("Creates a projected geometry of the selected object in the 3D view from the current camera angle"); | |
| sWhatsThis = "TechDraw_ProjectShape"; | |
| sStatusTip = sToolTipText; | |
| sPixmap = "actions/TechDraw_ProjectShape"; | |
| } | |
| void CmdTechDrawProjectShape::activated(int iMsg) | |
| { | |
| Q_UNUSED(iMsg); | |
| Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); | |
| if (!dlg) { | |
| Gui::Control().showDialog(new TaskDlgProjection()); | |
| } | |
| } | |
| bool CmdTechDrawProjectShape::isActive() { return true; } | |
| void CreateTechDrawCommands() | |
| { | |
| Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); | |
| rcCmdMgr.addCommand(new CmdTechDrawPageDefault()); | |
| rcCmdMgr.addCommand(new CmdTechDrawPageTemplate()); | |
| rcCmdMgr.addCommand(new CmdTechDrawRedrawPage()); | |
| rcCmdMgr.addCommand(new CmdTechDrawPrintAll()); | |
| rcCmdMgr.addCommand(new CmdTechDrawView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawActiveView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawSectionGroup()); | |
| rcCmdMgr.addCommand(new CmdTechDrawSectionView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawComplexSection()); | |
| rcCmdMgr.addCommand(new CmdTechDrawDetailView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawProjectionGroup()); | |
| rcCmdMgr.addCommand(new CmdTechDrawClipGroup()); | |
| rcCmdMgr.addCommand(new CmdTechDrawClipGroupAdd()); | |
| rcCmdMgr.addCommand(new CmdTechDrawClipGroupRemove()); | |
| rcCmdMgr.addCommand(new CmdTechDrawSymbol()); | |
| rcCmdMgr.addCommand(new CmdTechDrawExportPageSVG()); | |
| rcCmdMgr.addCommand(new CmdTechDrawExportPageDXF()); | |
| rcCmdMgr.addCommand(new CmdTechDrawDraftView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawArchView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawSpreadsheetView()); | |
| rcCmdMgr.addCommand(new CmdTechDrawBalloon()); | |
| rcCmdMgr.addCommand(new CmdTechDrawProjectShape()); | |
| rcCmdMgr.addCommand(new CmdTechDrawBrokenView()); | |
| } | |
| //**************************************** | |
| //! extract the selected shapes and xShapes and determine if a face has been | |
| //! selected to define the projection direction | |
| void getSelectedShapes(Gui::Command* cmd, | |
| std::vector<App::DocumentObject*>& shapes, | |
| std::vector<App::DocumentObject*>& xShapes, | |
| App::DocumentObject* faceObj, | |
| std::string& faceName) | |
| { | |
| Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement; | |
| bool single = false; | |
| auto selection = cmd->getSelection().getSelectionEx(nullptr, App::DocumentObject::getClassTypeId(), | |
| resolve, single); | |
| for (auto& sel : selection) { | |
| bool is_linked = false; | |
| auto obj = sel.getObject(); | |
| if (obj->isDerivedFrom<TechDraw::DrawPage>()) { | |
| continue; | |
| } | |
| if (obj->isDerivedFrom<App::LinkElement>() | |
| || obj->isDerivedFrom<App::LinkGroup>() | |
| || obj->isDerivedFrom<App::Link>()) { | |
| is_linked = true; | |
| } | |
| // If parent of the obj is a link to another document, we possibly need to treat non-link obj as linked, too | |
| // 1st, is obj in another document? | |
| if (obj->getDocument() != cmd->getDocument()) { | |
| std::set<App::DocumentObject*> parents = obj->getInListEx(true); | |
| for (auto& parent : parents) { | |
| // Only consider parents in the current document, i.e. possible links in this View's document | |
| if (parent->getDocument() != cmd->getDocument()) { | |
| continue; | |
| } | |
| // 2nd, do we really have a link to obj? | |
| if (parent->isDerivedFrom<App::LinkElement>() | |
| || parent->isDerivedFrom<App::LinkGroup>() | |
| || parent->isDerivedFrom<App::Link>()) { | |
| // We have a link chain from this document to obj, and obj is in another document -> it is an XLink target | |
| is_linked = true; | |
| } | |
| } | |
| } | |
| if (is_linked) { | |
| xShapes.push_back(obj); | |
| continue; | |
| } | |
| //not a Link and not null. assume to be drawable. Undrawables will be | |
| // skipped later. | |
| shapes.push_back(obj); | |
| if (faceObj) { | |
| continue; | |
| } | |
| //don't know if this works for an XLink | |
| for (auto& sub : sel.getSubNames()) { | |
| if (TechDraw::DrawUtil::getGeomTypeFromName(sub) == "Face") { | |
| faceName = sub; | |
| // | |
| faceObj = obj; | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| std::pair<Base::Vector3d, Base::Vector3d> viewDirection() | |
| { | |
| if (!Preferences::useCameraDirection()) { | |
| return { Base::Vector3d(0, -1, 0), Base::Vector3d(1, 0, 0) }; | |
| } | |
| auto faceInfo = faceFromSelection(); | |
| if (faceInfo.first) { | |
| return DrawGuiUtil::getProjDirFromFace(faceInfo.first, faceInfo.second); | |
| } | |
| return DrawGuiUtil::get3DDirAndRot(); | |
| } | |
| std::pair<App::DocumentObject*, std::string> faceFromSelection() | |
| { | |
| auto selection = Gui::Selection().getSelectionEx( | |
| nullptr, App::DocumentObject::getClassTypeId(), Gui::ResolveMode::NoResolve); | |
| if (selection.empty()) { | |
| return { nullptr, "" }; | |
| } | |
| for (auto& sel : selection) { | |
| for (auto& sub : sel.getSubNames()) { | |
| if (TechDraw::DrawUtil::getGeomTypeFromName(sub) == "Face") { | |
| return { sel.getObject(), sub }; | |
| } | |
| } | |
| } | |
| return { nullptr, "" }; | |
| } | |