From 91d7c875a55161b84d4c8f1fee85b8d74dd6f974 Mon Sep 17 00:00:00 2001 From: WandererFan Date: Mon, 6 Jan 2025 12:11:25 -0500 Subject: [PATCH] [TD]Fix RichText parent in scene (fix #18283) (#18768) * [TD]allow DrawViewAnno to be attached to another view * [TD]allow image and spreadsheet attach to view * [TD]ensure correct parent in scene * [TD]refactor command helpers to separate file - gathering the helpers in one place - helper redundancy to be address in another change * [TD]create symbol, spreadsheet, image with parent * [TD]fix claimChildren for some views - also includes many lint fixes --- src/Mod/TechDraw/App/DrawViewAnnotation.cpp | 19 +- src/Mod/TechDraw/App/DrawViewAnnotation.h | 6 + src/Mod/TechDraw/App/DrawViewImage.cpp | 2 + src/Mod/TechDraw/App/DrawViewImage.h | 4 + src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp | 3 + src/Mod/TechDraw/App/DrawViewSpreadsheet.h | 4 + src/Mod/TechDraw/Gui/CMakeLists.txt | 2 + src/Mod/TechDraw/Gui/Command.cpp | 31 ++- src/Mod/TechDraw/Gui/CommandAnnotate.cpp | 64 +---- src/Mod/TechDraw/Gui/CommandDecorate.cpp | 10 + src/Mod/TechDraw/Gui/CommandHelpers.cpp | 228 +++++++++++++++++ src/Mod/TechDraw/Gui/CommandHelpers.h | 71 ++++++ src/Mod/TechDraw/Gui/QGIViewBalloon.cpp | 2 +- src/Mod/TechDraw/Gui/QGSPage.cpp | 232 ++++++++++-------- src/Mod/TechDraw/Gui/QGSPage.h | 11 +- src/Mod/TechDraw/Gui/ViewProviderBalloon.cpp | 50 ++-- src/Mod/TechDraw/Gui/ViewProviderBalloon.h | 10 +- .../TechDraw/Gui/ViewProviderDimension.cpp | 62 +++-- src/Mod/TechDraw/Gui/ViewProviderDimension.h | 5 +- src/Mod/TechDraw/Gui/ViewProviderLeader.cpp | 14 +- .../TechDraw/Gui/ViewProviderProjGroup.cpp | 71 +++--- src/Mod/TechDraw/Gui/ViewProviderProjGroup.h | 11 +- src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp | 45 +++- src/Mod/TechDraw/Gui/ViewProviderRichAnno.h | 10 +- src/Mod/TechDraw/Gui/ZVALUE.h | 3 +- 25 files changed, 698 insertions(+), 272 deletions(-) create mode 100644 src/Mod/TechDraw/Gui/CommandHelpers.cpp create mode 100644 src/Mod/TechDraw/Gui/CommandHelpers.h diff --git a/src/Mod/TechDraw/App/DrawViewAnnotation.cpp b/src/Mod/TechDraw/App/DrawViewAnnotation.cpp index 5d8f6ab94e..9964bf09e1 100644 --- a/src/Mod/TechDraw/App/DrawViewAnnotation.cpp +++ b/src/Mod/TechDraw/App/DrawViewAnnotation.cpp @@ -24,8 +24,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include -# include #endif #include "DrawViewAnnotation.h" @@ -62,6 +60,9 @@ DrawViewAnnotation::DrawViewAnnotation() TextStyle.setEnums(TextStyleEnums); ADD_PROPERTY_TYPE(TextStyle, ((long)0), vgroup, App::Prop_None, "Text style"); + ADD_PROPERTY_TYPE(Owner, (nullptr), vgroup, (App::PropertyType)(App::Prop_None), + "Feature to which this annotation is attached, if any"); + Scale.setStatus(App::Property::Hidden, true); ScaleType.setStatus(App::Property::Hidden, true); } @@ -82,6 +83,20 @@ void DrawViewAnnotation::onChanged(const App::Property* prop) TechDraw::DrawView::onChanged(prop); } + +short DrawViewAnnotation::mustExecute() const +{ + if (!isRestoring()) { + if (Text.isTouched() || + Owner.isTouched()) { + return 1; + } + } + + return DrawView::mustExecute(); +} + + void DrawViewAnnotation::handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property *prop) // transforms properties that had been changed { diff --git a/src/Mod/TechDraw/App/DrawViewAnnotation.h b/src/Mod/TechDraw/App/DrawViewAnnotation.h index bec639f85d..8cf2711a6d 100644 --- a/src/Mod/TechDraw/App/DrawViewAnnotation.h +++ b/src/Mod/TechDraw/App/DrawViewAnnotation.h @@ -51,6 +51,7 @@ public: App::PropertyInteger LineSpace; App::PropertyEnumeration TextStyle; // Plain, Bold, Italic, Bold-Italic App::PropertyFloat MaxWidth; + App::PropertyLink Owner; QRectF getRect() const override; @@ -65,6 +66,11 @@ public: return "TechDrawGui::ViewProviderAnnotation"; } + short mustExecute() const override; + + bool checkFit() const override {return true;} + App::PropertyLink *getOwnerProperty() override { return &Owner; } + protected: void onChanged(const App::Property* prop) override; void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override; diff --git a/src/Mod/TechDraw/App/DrawViewImage.cpp b/src/Mod/TechDraw/App/DrawViewImage.cpp index 619d484e20..8a3da9d447 100644 --- a/src/Mod/TechDraw/App/DrawViewImage.cpp +++ b/src/Mod/TechDraw/App/DrawViewImage.cpp @@ -52,6 +52,8 @@ DrawViewImage::DrawViewImage() "Embedded image file. System use only.");// n/a to end users ADD_PROPERTY_TYPE(Width, (100), vgroup, App::Prop_None, "The width of cropped image"); ADD_PROPERTY_TYPE(Height, (100), vgroup, App::Prop_None, "The height of cropped image"); + ADD_PROPERTY_TYPE(Owner, (nullptr), vgroup, (App::PropertyType)(App::Prop_None), + "Feature to which this symbol is attached"); ScaleType.setValue("Custom"); Scale.setStatus(App::Property::Hidden, false); diff --git a/src/Mod/TechDraw/App/DrawViewImage.h b/src/Mod/TechDraw/App/DrawViewImage.h index c1274bba52..54225ecee9 100644 --- a/src/Mod/TechDraw/App/DrawViewImage.h +++ b/src/Mod/TechDraw/App/DrawViewImage.h @@ -47,6 +47,7 @@ public: App::PropertyFileIncluded ImageIncluded; App::PropertyFloat Width; App::PropertyFloat Height; + App::PropertyLink Owner; /** @name methods override Feature */ //@{ @@ -58,6 +59,9 @@ public: const char* getViewProviderName() const override { return "TechDrawGui::ViewProviderImage"; } + + App::PropertyLink *getOwnerProperty() override { return &Owner; } + QRectF getRect() const override; void setupObject() override; diff --git a/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp b/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp index 2e722514af..98566c2893 100644 --- a/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp +++ b/src/Mod/TechDraw/App/DrawViewSpreadsheet.cpp @@ -63,6 +63,9 @@ DrawViewSpreadsheet::DrawViewSpreadsheet() ADD_PROPERTY_TYPE(TextSize, (12.0), vgroup, App::Prop_None, "The size of the text"); ADD_PROPERTY_TYPE(LineWidth, (0.35), vgroup, App::Prop_None, "The thickness of the cell lines"); + ADD_PROPERTY_TYPE(Owner, (nullptr), vgroup, (App::PropertyType)(App::Prop_None), + "Feature to which this sheet is attached"); + EditableTexts.setStatus(App::Property::Hidden, true); } diff --git a/src/Mod/TechDraw/App/DrawViewSpreadsheet.h b/src/Mod/TechDraw/App/DrawViewSpreadsheet.h index 4f1f6f0c94..6ca008f43e 100644 --- a/src/Mod/TechDraw/App/DrawViewSpreadsheet.h +++ b/src/Mod/TechDraw/App/DrawViewSpreadsheet.h @@ -49,9 +49,13 @@ public: App::PropertyFloat LineWidth; App::PropertyFloat TextSize; + App::PropertyLink Owner; App::DocumentObjectExecReturn *execute() override; short mustExecute() const override; + + App::PropertyLink *getOwnerProperty() override { return &Owner; } + std::string getSheetImage(); const char* getViewProviderName() const override { diff --git a/src/Mod/TechDraw/Gui/CMakeLists.txt b/src/Mod/TechDraw/Gui/CMakeLists.txt index f9ab485b59..9339c5828c 100644 --- a/src/Mod/TechDraw/Gui/CMakeLists.txt +++ b/src/Mod/TechDraw/Gui/CMakeLists.txt @@ -105,6 +105,8 @@ SET(TechDrawGui_SRCS CommandExtensionDims.h CommandExtensionPack.cpp CommandStack.cpp + CommandHelpers.cpp + CommandHelpers.h DimensionValidators.cpp DimensionValidators.h Resources/TechDraw.qrc diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index e931c7e896..87f33de1ef 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -79,6 +79,7 @@ #include "TaskSectionView.h" #include "ViewProviderPage.h" #include "ViewProviderDrawingView.h" +#include "CommandHelpers.h" void execSimpleSection(Gui::Command* cmd); void execComplexSection(Gui::Command* cmd); @@ -1558,8 +1559,17 @@ void CmdTechDrawSymbol::activated(int iMsg) 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(); } @@ -1721,6 +1731,12 @@ CmdTechDrawSpreadsheetView::CmdTechDrawSpreadsheetView() : Command("TechDraw_Spr 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 spreads = getSelection().getObjectsOfType(Spreadsheet::Sheet::getClassTypeId()); if (spreads.size() != 1) { @@ -1730,12 +1746,6 @@ void CmdTechDrawSpreadsheetView::activated(int iMsg) } std::string SpreadName = spreads.front()->getNameInDocument(); - TechDraw::DrawPage* page = DrawGuiUtil::findPage(this); - if (!page) { - return; - } - std::string PageName = page->getNameInDocument(); - openCommand(QT_TRANSLATE_NOOP("Command", "Create spreadsheet view")); std::string FeatName = getUniqueObjectName("Sheet"); doCommand(Doc, "App.activeDocument().addObject('TechDraw::DrawViewSpreadsheet', '%s')", @@ -1744,6 +1754,15 @@ void CmdTechDrawSpreadsheetView::activated(int iMsg) 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(); diff --git a/src/Mod/TechDraw/Gui/CommandAnnotate.cpp b/src/Mod/TechDraw/Gui/CommandAnnotate.cpp index bfbc3fa873..52d5f29461 100644 --- a/src/Mod/TechDraw/Gui/CommandAnnotate.cpp +++ b/src/Mod/TechDraw/Gui/CommandAnnotate.cpp @@ -24,7 +24,6 @@ #ifndef _PreComp_ # include # include -# include #endif #include @@ -60,13 +59,15 @@ #include "TaskWeldingSymbol.h" #include "TaskCosmeticCircle.h" #include "ViewProviderViewPart.h" +#include "CommandHelpers.h" using namespace TechDrawGui; using namespace TechDraw; +using namespace CommandHelpers; +//using CH = CommandHelpers; //internal functions -bool _checkSelectionHatch(Gui::Command* cmd); void execCosmeticVertex(Gui::Command* cmd); void execMidpoints(Gui::Command* cmd); @@ -76,9 +77,6 @@ void exec2LineCenterLine(Gui::Command* cmd); void exec2PointCenterLine(Gui::Command* cmd); void execLine2Points(Gui::Command* cmd); void execCosmeticCircle(Gui::Command* cmd); -std::vector getSelectedSubElements(Gui::Command* cmd, - TechDraw::DrawViewPart* &dvp, - std::string subType = "Edge"); //=========================================================================== // TechDraw_Leader @@ -333,7 +331,7 @@ void execMidpoints(Gui::Command* cmd) { // Base::Console().Message("execMidpoints()\n"); TechDraw::DrawViewPart * dvp = nullptr; - std::vector selectedEdges = getSelectedSubElements(cmd, dvp, "Edge"); + std::vector selectedEdges = CommandHelpers::getSelectedSubElements(cmd, dvp, "Edge"); if (!dvp || selectedEdges.empty()) return; @@ -360,7 +358,7 @@ void execQuadrants(Gui::Command* cmd) { // Base::Console().Message("execQuadrants()\n"); TechDraw::DrawViewPart* dvp = nullptr; - std::vector selectedEdges = getSelectedSubElements(cmd, dvp, "Edge"); + std::vector selectedEdges = CommandHelpers::getSelectedSubElements(cmd, dvp, "Edge"); if (!dvp || selectedEdges.empty()) return; @@ -553,6 +551,13 @@ void CmdTechDrawAnnotation::activated(int iMsg) doCommand(Doc, "App.activeDocument().%s.translateLabel('DrawViewAnnotation', 'Annotation', '%s')", FeatName.c_str(), 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(); @@ -823,7 +828,7 @@ void exec2LineCenterLine(Gui::Command* cmd) return; } TechDraw::DrawViewPart* dvp = nullptr; - std::vector selectedEdges = getSelectedSubElements(cmd, dvp, "Edge"); + std::vector selectedEdges = CommandHelpers::getSelectedSubElements(cmd, dvp, "Edge"); if (!dvp || selectedEdges.empty()) { return; @@ -1687,46 +1692,3 @@ void CreateTechDrawCommandsAnnotate() rcCmdMgr.addCommand(new CmdTechDrawSurfaceFinishSymbols()); } -//=========================================================================== -// Selection Validation Helpers -//=========================================================================== - -std::vector getSelectedSubElements(Gui::Command* cmd, - TechDraw::DrawViewPart* &dvp, - std::string subType) -{ -// Base::Console().Message("getSelectedSubElements() - dvp: %X\n", dvp); - std::vector selectedSubs; - std::vector subNames; - dvp = nullptr; - std::vector selection = cmd->getSelection().getSelectionEx(); - std::vector::iterator itSel = selection.begin(); - for (; itSel != selection.end(); itSel++) { - if ((*itSel).getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { - dvp = static_cast ((*itSel).getObject()); - subNames = (*itSel).getSubNames(); - break; - } - } - if (!dvp) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong Selection"), - QObject::tr("No Part View in Selection")); - return selectedSubs; - } - - for (auto& s: subNames) { - if (TechDraw::DrawUtil::getGeomTypeFromName(s) == subType) { - selectedSubs.push_back(s); - } - } - - if (selectedSubs.empty()) { - QMessageBox::warning(Gui::getMainWindow(), - QObject::tr("Wrong Selection"), - QObject::tr("No %1 in Selection") - .arg(QString::fromStdString(subType))); - return selectedSubs; - } - - return selectedSubs; -} diff --git a/src/Mod/TechDraw/Gui/CommandDecorate.cpp b/src/Mod/TechDraw/Gui/CommandDecorate.cpp index 9a05d64ea1..e57a1dbd3e 100644 --- a/src/Mod/TechDraw/Gui/CommandDecorate.cpp +++ b/src/Mod/TechDraw/Gui/CommandDecorate.cpp @@ -53,6 +53,7 @@ #include "ViewProviderGeomHatch.h" #include "ViewProviderPage.h" #include "MDIViewPage.h" +#include "CommandHelpers.h" using namespace TechDrawGui; @@ -268,11 +269,20 @@ void CmdTechDrawImage::activated(int iMsg) 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()); + + 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(); diff --git a/src/Mod/TechDraw/Gui/CommandHelpers.cpp b/src/Mod/TechDraw/Gui/CommandHelpers.cpp new file mode 100644 index 0000000000..b7a78c9dbc --- /dev/null +++ b/src/Mod/TechDraw/Gui/CommandHelpers.cpp @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: LGPL-2.0-or-later + +/*************************************************************************** + * Copyright (c) 2024 WandererFan * + * * + * 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 * + * * + ***************************************************************************/ + +//! CommandHelpers is a collection of methods for common actions in commands +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + +#include "CommandHelpers.h" + +using namespace TechDraw; +using namespace TechDrawGui; + +//! find the first DrawView in the current selection for use as a base view (owner) +TechDraw::DrawView* CommandHelpers::firstViewInSelection(Gui::Command* cmd) +{ + std::vector selection = cmd->getSelection().getSelectionEx(); + TechDraw::DrawView* baseView{nullptr}; + if (!selection.empty()) { + for (auto& selobj : selection) { + if (selobj.getObject()->isDerivedFrom()) { + auto docobj = selobj.getObject(); + baseView = dynamic_cast(docobj); + break; + } + } + } + return baseView; +} + +//! find the first DrawView in the current selection for use as a base view (owner) +TechDraw::DrawView* CommandHelpers::firstNonSpreadsheetInSelection(Gui::Command* cmd) +{ + std::vector selection = cmd->getSelection().getSelectionEx(); + TechDraw::DrawView* baseView{nullptr}; + if (!selection.empty()) { + for (auto& selobj : selection) { + if (selobj.getObject()->isDerivedFrom()) { + continue; + } else { + auto docobj = selobj.getObject(); + baseView = dynamic_cast(docobj); + break; + } + } + } + return baseView; +} + + +std::vector CommandHelpers::getSelectedSubElements(Gui::Command* cmd, + TechDraw::DrawViewPart* &dvp, + std::string subType) +{ + std::vector selectedSubs; + std::vector subNames; + dvp = nullptr; + std::vector selection = cmd->getSelection().getSelectionEx(); + std::vector::iterator itSel = selection.begin(); + for (; itSel != selection.end(); itSel++) { + if ((*itSel).getObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { + dvp = static_cast ((*itSel).getObject()); + subNames = (*itSel).getSubNames(); + break; + } + } + if (!dvp) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong Selection"), + QObject::tr("No Part View in Selection")); + return selectedSubs; + } + + for (auto& s: subNames) { + if (TechDraw::DrawUtil::getGeomTypeFromName(s) == subType) { + selectedSubs.push_back(s); + } + } + + if (selectedSubs.empty()) { + QMessageBox::warning(Gui::getMainWindow(), + QObject::tr("Wrong Selection"), + QObject::tr("No %1 in Selection") + .arg(QString::fromStdString(subType))); + return selectedSubs; + } + + return selectedSubs; +} + +//! extract the selected shapes and xShapes and determine if a face has been +//! selected to define the projection direction +void CommandHelpers::getSelectedShapes(Gui::Command* cmd, + std::vector& shapes, + std::vector& xShapes, + App::DocumentObject* faceObj, + std::string& faceName) +{ + Gui::ResolveMode resolve = Gui::ResolveMode::OldStyleElement;//mystery + bool single = false; //mystery + 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::getClassTypeId())) { + continue; + } + if (obj->isDerivedFrom(App::LinkElement::getClassTypeId()) + || obj->isDerivedFrom(App::LinkGroup::getClassTypeId()) + || obj->isDerivedFrom(App::Link::getClassTypeId())) { + 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 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::getClassTypeId()) + || parent->isDerivedFrom(App::LinkGroup::getClassTypeId()) + || parent->isDerivedFrom(App::Link::getClassTypeId())) { + // 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 CommandHelpers::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 CommandHelpers::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, "" }; +} diff --git a/src/Mod/TechDraw/Gui/CommandHelpers.h b/src/Mod/TechDraw/Gui/CommandHelpers.h new file mode 100644 index 0000000000..ed86dbefae --- /dev/null +++ b/src/Mod/TechDraw/Gui/CommandHelpers.h @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: LGPL-2.0-or-later + +/*************************************************************************** + * Copyright (c) 2024 WandererFan * + * * + * 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 * + * * + ***************************************************************************/ + +//! CommandHelpers is a collection of methods for common actions in commands + + +#ifndef COMMANDHELPERS_H +#define COMMANDHELPERS_H + +#include +#include + +#include +#include + +namespace App { +class DocumentObject; +} + +namespace Gui { +class Command; +} + +namespace TechDraw { +class DrawView; +class DrawViewPart; + +namespace CommandHelpers { + +TechDraw::DrawView* firstViewInSelection(Gui::Command* cmd); +TechDraw::DrawView* firstNonSpreadsheetInSelection(Gui::Command* cmd); + +std::vector getSelectedSubElements(Gui::Command* cmd, + TechDraw::DrawViewPart* &dvp, + std::string subType = "Edge"); + +void getSelectedShapes(Gui::Command* cmd, + std::vector& shapes, + std::vector& xShapes, + App::DocumentObject* faceObj, + std::string& faceName); + +std::pair faceFromSelection(); +std::pair viewDirection(); + + +} // end namespace CommandHelpers +} // end namespace TechDraw + +#endif diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp index f137ebd864..1502c02151 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp @@ -277,7 +277,7 @@ QGIViewBalloon::QGIViewBalloon() arrow->setPrettyNormal(); arrow->setStyle(prefDefaultArrow()); - balloonLabel->setZValue(ZVALUE::LABEL); + balloonLabel->setZValue(ZVALUE::BALLOON); arrow->setZValue(ZVALUE::DIMENSION); balloonLines->setZValue(ZVALUE::DIMENSION); diff --git a/src/Mod/TechDraw/Gui/QGSPage.cpp b/src/Mod/TechDraw/Gui/QGSPage.cpp index af6cf78d0a..c8cc68ea8e 100644 --- a/src/Mod/TechDraw/Gui/QGSPage.cpp +++ b/src/Mod/TechDraw/Gui/QGSPage.cpp @@ -175,7 +175,6 @@ Qt::KeyboardModifiers QGSPage::cleanModifierList(Qt::KeyboardModifiers mods) void QGSPage::addChildrenToPage() { - // Base::Console().Message("QGSP::addChildrenToPage()\n"); // A fresh page is added and we iterate through its collected children and add these to Canvas View -MLP // if docobj is a featureviewcollection (ex orthogroup), add its child views. if there are ever children that have children, // we'll have to make this recursive. -WF @@ -188,11 +187,11 @@ void QGSPage::addChildrenToPage() } } } - //when restoring, it is possible for a Dimension to be loaded before the ViewPart it applies to - //therefore we need to make sure parentage of the graphics representation is set properly. bit of a kludge. - setDimensionGroups(); - setBalloonGroups(); - setLeaderParentage(); + // when restoring, it is possible for an item (ex a Dimension) to be loaded before the ViewPart + // it applies to therefore we need to make sure parentage of the graphics representation is set + // properly. bit of a kludge. + // + setViewParents(); App::DocumentObject* obj = m_vpPage->getDrawPage()->Template.getValue(); auto pageTemplate(dynamic_cast(obj)); @@ -329,6 +328,8 @@ int QGSPage::addQView(QGIView* view) } view->updateView(true); + } else { + Base::Console().Message("QGSP::addQView - qview already exists\n"); } return 0; } @@ -416,7 +417,7 @@ bool QGSPage::attachView(App::DocumentObject* obj) qview = addViewBalloon(static_cast(obj)); } else if (typeId.isDerivedFrom(TechDraw::DrawViewAnnotation::getClassTypeId())) { - qview = addDrawViewAnnotation(static_cast(obj)); + qview = addAnnotation(static_cast(obj)); } else if (typeId.isDerivedFrom(TechDraw::DrawViewSymbol::getClassTypeId())) { qview = addDrawViewSymbol(static_cast(obj)); @@ -447,37 +448,85 @@ bool QGSPage::attachView(App::DocumentObject* obj) return (qview != nullptr); } + +void QGSPage::addItemToScene(QGIView* item) +{ + addItem(item); + + // Does item belong to a parent? + QGIView* parent = nullptr; + parent = findParent(item); + + if (parent) { + addItemToParent(item, parent); + } +} + +//! adds item to parent's group with position adjustments if required. +void QGSPage::addItemToParent(QGIView* item, QGIView* parent) +{ + // not every view uses the same remapping?? spreadsheets, image, RTA, anno? + // anything that was originally designed to have its position + // defined relative to the Page should not use the dimension/balloon mapping. + assert(item); + assert(parent); + // TODO: make custom user types retrievable by name (see QGIUserTypes.h) + constexpr int QGIVDimensionType {QGraphicsItem::UserType + 106}; + constexpr int QGIVBalloonType {QGraphicsItem::UserType + 140}; + constexpr int QGIWeldSymbolType {QGraphicsItem::UserType + 340}; + // constexpr int QGIViewAnnotationType {QGraphicsItem::UserType + 120}; + + if (item->type() == QGIWeldSymbolType) { + // don't touch these + return; + } + + // original parenting logic here + QPointF posRef(0., 0.); + if (item->type() == QGIVDimensionType || item->type() == QGIVBalloonType) { + QPointF mapPos = item->mapToItem(parent, posRef); + item->moveBy(-mapPos.x(), -mapPos.y()); + parent->addToGroup(item); + return; + } + + // positioning logic for objects (leader/rta/etc) that normally draw relative to the page goes + // here + // + QPointF itemPosition {item->getViewObject()->X.getValue(), // millimetres on page + -item->getViewObject()->Y.getValue()}; + parent->addToGroup(item); + item->setPos(Rez::guiX(itemPosition)); + + item->setZValue(ZVALUE::DIMENSION); +} + QGIView* QGSPage::addViewPart(TechDraw::DrawViewPart* partFeat) { - // Base::Console().Message("QGSP::addViewPart(%s)\n", partFeat->Label.getValue()); auto viewPart(new QGIViewPart); - + addItem(viewPart); viewPart->setViewPartFeature(partFeat); - - addQView(viewPart); // we need to install an event filter for any views derived from DrawViewPart viewPart->installSceneEventFilter(viewPart); + return viewPart; } QGIView* QGSPage::addViewSection(DrawViewSection* sectionFeat) { auto viewSection(new QGIViewSection); - + addItem(viewSection); viewSection->setViewPartFeature(sectionFeat); - - addQView(viewSection); viewSection->installSceneEventFilter(viewSection); + return viewSection; } QGIView* QGSPage::addProjectionGroup(TechDraw::DrawProjGroup* projGroupFeat) { - // Base::Console().Message("QGSP::addprojectionGroup(%s)\n", projGroupFeat->Label.getValue()); auto qview(new QGIProjGroup); - + addItem(qview); qview->setViewFeature(projGroupFeat); - addQView(qview); qview->installSceneEventFilter(qview); return qview; @@ -486,85 +535,72 @@ QGIView* QGSPage::addProjectionGroup(TechDraw::DrawProjGroup* projGroupFeat) QGIView* QGSPage::addDrawView(TechDraw::DrawView* view) { auto qview(new QGIView); - + addItem(qview); qview->setViewFeature(view); - addQView(qview); return qview; } QGIView* QGSPage::addDrawViewCollection(TechDraw::DrawViewCollection* collectionFeat) { auto qview(new QGIViewCollection); - + addItem(qview); qview->setViewFeature(collectionFeat); - addQView(qview); + return qview; } -QGIView* QGSPage::addDrawViewAnnotation(TechDraw::DrawViewAnnotation* annoFeat) +QGIView* QGSPage::addAnnotation(TechDraw::DrawViewAnnotation* annoFeat) { - auto qview(new QGIViewAnnotation); + auto annoView{new QGIViewAnnotation}; + annoView->setViewFeature(annoFeat); + annoView->setZValue(ZVALUE::ANNOTATION); + addItemToScene(annoView); - qview->setViewAnnoFeature(annoFeat); - - addQView(qview); - return qview; + return annoView; } QGIView* QGSPage::addDrawViewSymbol(TechDraw::DrawViewSymbol* symbolFeat) { QGIViewSymbol *symbolView = new QGIViewSymbol; symbolView->setViewFeature(symbolFeat); + addItemToScene(symbolView); - addQView(symbolView); return symbolView; } QGIView* QGSPage::addDrawViewClip(TechDraw::DrawViewClip* view) { auto qview(new QGIViewClip); - - qview->setPosition(Rez::guiX(view->X.getValue()), Rez::guiX(view->Y.getValue())); qview->setViewFeature(view); + addItemToScene(qview); + qview->setPosition(Rez::guiX(view->X.getValue()), Rez::guiX(view->Y.getValue())); - addQView(qview); return qview; } QGIView* QGSPage::addDrawViewSpreadsheet(TechDraw::DrawViewSpreadsheet* sheetFeat) { auto qview(new QGIViewSpreadsheet); - qview->setViewFeature(sheetFeat); + addItemToScene(qview); - addQView(qview); return qview; } QGIView* QGSPage::addDrawViewImage(TechDraw::DrawViewImage* imageFeat) { auto qview(new QGIViewImage); - qview->setViewFeature(imageFeat); + addItemToScene(qview); - addQView(qview); return qview; } QGIView* QGSPage::addViewBalloon(TechDraw::DrawViewBalloon* balloonFeat) { auto vBalloon(new QGIViewBalloon); - - addItem(vBalloon); - vBalloon->setViewPartFeature(balloonFeat); - - QGIView* parent = nullptr; - parent = findParent(vBalloon); - - if (parent) { - addBalloonToParent(vBalloon, parent); - } + addItemToScene(vBalloon); return vBalloon; } @@ -631,18 +667,8 @@ void QGSPage::createBalloon(QPointF origin, DrawView* parent) QGIView* QGSPage::addViewDimension(TechDraw::DrawViewDimension* dimFeat) { auto dimGroup(new QGIViewDimension); - - addItem(dimGroup); - dimGroup->setViewPartFeature(dimFeat); - - // Find if it belongs to a parent - QGIView* parent = nullptr; - parent = findParent(dimGroup); - - if (parent) { - addDimToParent(dimGroup, parent); - } + addItemToScene(dimGroup); return dimGroup; } @@ -662,16 +688,9 @@ void QGSPage::addDimToParent(QGIViewDimension* dim, QGIView* parent) QGIView* QGSPage::addViewLeader(TechDraw::DrawLeaderLine* leaderFeat) { QGILeaderLine *leaderItem = new QGILeaderLine; - addItem(leaderItem); leaderItem->setViewFeature(leaderFeat); + addItemToScene(leaderItem); - // Find if it belongs to a parent - QGIView* parent = nullptr; - parent = findParent(leaderItem); - - if (parent) { - addLeaderToParent(leaderItem, parent); - } return leaderItem; } @@ -693,67 +712,67 @@ void QGSPage::addLeaderToParent(QGILeaderLine* leader, QGIView* parent) QGIView* QGSPage::addRichAnno(TechDraw::DrawRichAnno* richFeat) { - QGIRichAnno *richView = new QGIRichAnno; + auto richView = new QGIRichAnno; richView->setViewFeature(richFeat); + addItemToScene(richView); + + // Find if it belongs to a parent + QGIView* parent = nullptr; + parent = findParent(richView); + + if (parent) { + addRichAnnoToParent(richView, parent); + } - addQView(richView); return richView; } + +void QGSPage::addRichAnnoToParent(QGIRichAnno* anno, QGIView* parent) +{ + assert(anno); + assert(parent);//blow up if we don't have Anno or Parent + QPointF posRef(0., 0.); + QPointF parentOrigin = anno->mapToItem(parent, posRef); + // this is not right for a DPGI? Needs the usual calculation?? + QPointF annoPositionInParent{ anno->getViewObject()->X.getValue(), + anno->getViewObject()->Y.getValue()}; + QPointF moveToPosition = parentOrigin + annoPositionInParent; + anno->moveBy(-moveToPosition.x(), -moveToPosition.y()); + parent->addToGroup(anno); + anno->setZValue(ZVALUE::DIMENSION); +} + +// ?? why does this not get parented to its leader here?? +// the taskdialog sets the Leader property in the weld feature. +// the weld symbol draws itself based on the leader's geometry, but is not added to the leader's +// group(?why?) QGIView* QGSPage::addWeldSymbol(TechDraw::DrawWeldSymbol* weldFeat) { QGIWeldSymbol *weldView = new QGIWeldSymbol; weldView->setViewFeature(weldFeat); + addItem(weldView); - addQView(weldView); return weldView; } -void QGSPage::setDimensionGroups() + +//! ensure that all QGIViews are parented correctly in the scene +void QGSPage::setViewParents() { const std::vector& allItems = getViews(); - int dimItemType = QGraphicsItem::UserType + 106; for (auto& item : allItems) { - if (item->type() == dimItemType && !item->group()) { - QGIView* parent = findParent(item); - if (parent) { - QGIViewDimension* dim = dynamic_cast(item); - addDimToParent(dim, parent); - } + if (item->group()) { + // this item already has a parent in the scene. probably should check if it is the + // correct parent + continue; } - } -} -void QGSPage::setBalloonGroups() -{ - const std::vector& allItems = getViews(); - int balloonItemType = QGraphicsItem::UserType + 140; - - for (auto& item : allItems) { - if (item->type() == balloonItemType && !item->group()) { - QGIView* parent = findParent(item); - if (parent) { - QGIViewBalloon* balloon = dynamic_cast(item); - addBalloonToParent(balloon, parent); - } - } - } -} - -//! ensure that all Leader QGItems are parented correctly -void QGSPage::setLeaderParentage() -{ - const std::vector& allItems = getViews(); - int LeaderItemType = QGraphicsItem::UserType + 232; - - for (auto& item : allItems) { - if (item->type() == LeaderItemType && !item->group()) { - QGIView* parent = findParent(item); - if (parent) { - QGILeaderLine* leader = dynamic_cast(item); - addLeaderToParent(leader, parent); - } + QGIView* parent = findParent(item); + if (parent) { + // item has a parent, so make sure it belongs to parent's group + addItemToParent(item, parent); } } } @@ -792,7 +811,6 @@ QGIView* QGSPage::getQGIVByName(std::string name) const //find the parent of a QGIV based on the corresponding feature's parentage QGIView* QGSPage::findParent(QGIView* view) const { - // Base::Console().Message("QGSP::findParent(%s)\n", view->getViewName()); const std::vector qviews = getViews(); TechDraw::DrawView* myFeat = view->getViewObject(); diff --git a/src/Mod/TechDraw/Gui/QGSPage.h b/src/Mod/TechDraw/Gui/QGSPage.h index b811e6ff17..294fd8431d 100644 --- a/src/Mod/TechDraw/Gui/QGSPage.h +++ b/src/Mod/TechDraw/Gui/QGSPage.h @@ -67,6 +67,7 @@ class ViewProviderPage; class QGIViewBalloon; class QGITile; class QGILeaderLine; +class QGIRichAnno; class TechDrawGuiExport QGSPage: public QGraphicsScene { @@ -85,7 +86,7 @@ public: QGIView* addViewSection(TechDraw::DrawViewSection* sectionFeat); QGIView* addDrawView(TechDraw::DrawView* viewFeat); QGIView* addDrawViewCollection(TechDraw::DrawViewCollection* collectionFeat); - QGIView* addDrawViewAnnotation(TechDraw::DrawViewAnnotation* annoFeat); + QGIView* addAnnotation(TechDraw::DrawViewAnnotation* annoFeat); QGIView* addDrawViewSymbol(TechDraw::DrawViewSymbol* symbolFeat); QGIView* addDrawViewClip(TechDraw::DrawViewClip* clipFeat); QGIView* addDrawViewSpreadsheet(TechDraw::DrawViewSpreadsheet* sheetFeat); @@ -112,6 +113,10 @@ public: void addDimToParent(QGIViewDimension* dim, QGIView* parent); void addLeaderToParent(QGILeaderLine* leader, QGIView* parent); + void addRichAnnoToParent(QGIRichAnno* anno, QGIView* parent); + + void addItemToScene(QGIView* item); + void addItemToParent(QGIView* item, QGIView* parent); std::vector getViews() const; @@ -143,9 +148,7 @@ public: void postProcessXml(QTemporaryFile& temporaryFile, QString filename, QString pagename); // scene parentage fixups - void setDimensionGroups(); - void setBalloonGroups(); - void setLeaderParentage(); + void setViewParents(); static bool itemClearsSelection(int itemTypeIn); static Qt::KeyboardModifiers cleanModifierList(Qt::KeyboardModifiers mods); diff --git a/src/Mod/TechDraw/Gui/ViewProviderBalloon.cpp b/src/Mod/TechDraw/Gui/ViewProviderBalloon.cpp index bcd22e5650..0471fed01b 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderBalloon.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderBalloon.cpp @@ -40,6 +40,8 @@ #include #include +#include +#include #include "PreferencesGui.h" #include "ZVALUE.h" @@ -72,9 +74,6 @@ ViewProviderBalloon::ViewProviderBalloon() StackOrder.setValue(ZVALUE::DIMENSION); } -ViewProviderBalloon::~ViewProviderBalloon() -{ -} bool ViewProviderBalloon::doubleClicked() { @@ -84,7 +83,7 @@ bool ViewProviderBalloon::doubleClicked() void ViewProviderBalloon::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) { - Gui::ActionFunction* func = new Gui::ActionFunction(menu); + auto* func = new Gui::ActionFunction(menu); QAction* act = menu->addAction(QObject::tr("Edit %1").arg(QString::fromUtf8(getObject()->Label.getValue()))); act->setData(QVariant((int)ViewProvider::Default)); func->trigger(act, [this]() { @@ -111,12 +110,12 @@ bool ViewProviderBalloon::setEdit(int ModNum) return true; } -void ViewProviderBalloon::updateData(const App::Property* p) +void ViewProviderBalloon::updateData(const App::Property* prop) { //Balloon handles X, Y updates differently that other QGIView //call QGIViewBalloon::updateView - if (p == &(getViewObject()->X) || - p == &(getViewObject()->Y) ){ + if (prop == &(getViewObject()->X) || + prop == &(getViewObject()->Y) ){ QGIView* qgiv = getQView(); if (qgiv) { qgiv->updateView(true); @@ -124,22 +123,22 @@ void ViewProviderBalloon::updateData(const App::Property* p) } //Skip QGIView X, Y processing - do not call ViewProviderDrawingView - Gui::ViewProviderDocumentObject::updateData(p); + Gui::ViewProviderDocumentObject::updateData(prop); } -void ViewProviderBalloon::onChanged(const App::Property* p) +void ViewProviderBalloon::onChanged(const App::Property* prop) { - if ((p == &Font) || - (p == &Fontsize) || - (p == &Color) || - (p == &LineWidth) || - (p == &LineVisible)) { + if ((prop == &Font) || + (prop == &Fontsize) || + (prop == &Color) || + (prop == &LineWidth) || + (prop == &LineVisible)) { QGIView* qgiv = getQView(); if (qgiv) { qgiv->updateView(true); } } - Gui::ViewProviderDocumentObject::onChanged(p); + Gui::ViewProviderDocumentObject::onChanged(prop); } TechDraw::DrawViewBalloon* ViewProviderBalloon::getViewObject() const @@ -189,3 +188,24 @@ bool ViewProviderBalloon::onDelete(const std::vector & parms) } return true; } + +std::vector ViewProviderBalloon::claimChildren() const +{ + // What can reasonably have a Balloon as a parent? A leader? a bit unconventional, but not forbidden. + // A RichAnno? Maybe? Another Balloon? Maybe? + + std::vector temp; + const std::vector& candidates = getViewObject()->getInList(); + for (auto& obj : candidates) { + if (obj->isDerivedFrom() || + obj->isDerivedFrom() || + obj->isDerivedFrom() ) { + temp.push_back(obj); + } + } + return temp; +} + + + + diff --git a/src/Mod/TechDraw/Gui/ViewProviderBalloon.h b/src/Mod/TechDraw/Gui/ViewProviderBalloon.h index 5499cedb62..d0d8e86d84 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderBalloon.h +++ b/src/Mod/TechDraw/Gui/ViewProviderBalloon.h @@ -44,7 +44,7 @@ public: /// constructor ViewProviderBalloon(); /// destructor - ~ViewProviderBalloon() override; + ~ViewProviderBalloon() override = default; App::PropertyFont Font; App::PropertyLength Fontsize; @@ -53,9 +53,9 @@ public: App::PropertyColor Color; bool useNewSelectionModel() const override {return false;} - void updateData(const App::Property*) override; - void onChanged(const App::Property* p) override; - void setupContextMenu(QMenu*, QObject*, const char*) override; + void updateData(const App::Property* prop) override; + void onChanged(const App::Property* prop) override; + void setupContextMenu(QMenu* menu, QObject* receiver, const char* member) override; bool setEdit(int ModNum) override; bool doubleClicked() override; bool canDelete(App::DocumentObject* obj) const override; @@ -63,6 +63,8 @@ public: TechDraw::DrawViewBalloon* getViewObject() const override; + std::vector claimChildren() const override; + protected: void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override; }; diff --git a/src/Mod/TechDraw/Gui/ViewProviderDimension.cpp b/src/Mod/TechDraw/Gui/ViewProviderDimension.cpp index 2f4562640d..eb6b0f2a52 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderDimension.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderDimension.cpp @@ -41,6 +41,10 @@ #include #include +#include +#include +#include + #include "PreferencesGui.h" #include "ZVALUE.h" @@ -98,9 +102,6 @@ ViewProviderDimension::ViewProviderDimension() StackOrder.setValue(ZVALUE::DIMENSION); } -ViewProviderDimension::~ViewProviderDimension() -{ -} void ViewProviderDimension::attach(App::DocumentObject *pcFeat) { @@ -122,7 +123,7 @@ bool ViewProviderDimension::doubleClicked() void ViewProviderDimension::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) { - Gui::ActionFunction* func = new Gui::ActionFunction(menu); + auto* func = new Gui::ActionFunction(menu); QAction* act = menu->addAction(QObject::tr("Edit %1").arg(QString::fromUtf8(getObject()->Label.getValue()))); act->setData(QVariant((int)ViewProvider::Default)); func->trigger(act, [this](){ @@ -201,34 +202,34 @@ void ViewProviderDimension::setPixmapForType() } } -void ViewProviderDimension::onChanged(const App::Property* p) +void ViewProviderDimension::onChanged(const App::Property* prop) { - if ((p == &Font) || - (p == &Fontsize) || - (p == &Arrowsize) || - (p == &LineWidth) || - (p == &StandardAndStyle) || - (p == &RenderingExtent) || - (p == &FlipArrowheads) || - (p == &GapFactorASME) || - (p == &GapFactorISO) || - p == &LineSpacingFactorISO) { - QGIView* qgiv = getQView(); + if ((prop == &Font) || + (prop == &Fontsize) || + (prop == &Arrowsize) || + (prop == &LineWidth) || + (prop == &StandardAndStyle) || + (prop == &RenderingExtent) || + (prop == &FlipArrowheads) || + (prop == &GapFactorASME) || + (prop == &GapFactorISO) || + prop == &LineSpacingFactorISO) { + auto* qgiv = getQView(); if (qgiv) { qgiv->updateView(true); } } - if (p == &Color) { - QGIView* qgiv = getQView(); + if (prop == &Color) { + auto* qgiv = getQView(); if (qgiv) { - QGIViewDimension* qgivd = dynamic_cast(qgiv); + auto* qgivd = dynamic_cast(qgiv); if (qgivd) { qgivd->setNormalColorAll(); } } } - ViewProviderDrawingView::onChanged(p); + ViewProviderDrawingView::onChanged(prop); } TechDraw::DrawViewDimension* ViewProviderDimension::getViewObject() const @@ -292,7 +293,6 @@ bool ViewProviderDimension::canDelete(App::DocumentObject *obj) const bool ViewProviderDimension::onDelete(const std::vector & parms) { Q_UNUSED(parms) -// Base::Console().Message("VPB::onDelete() - parms: %d\n", parms.size()); auto dlg = Gui::Control().activeDialog(); auto ourDlg = dynamic_cast(dlg); if (ourDlg) { @@ -308,3 +308,23 @@ bool ViewProviderDimension::onDelete(const std::vector & parms) return true; } + +std::vector ViewProviderDimension::claimChildren() const +{ + // What can reasonably have a Dimension as a parent? A leader? a bit unconventional, but not forbidden. + // A RichAnno? Maybe? Balloons? This is a bit of a corner case. Typically, a + // Dimension would belong to something rather than owning something. + // Pages will appear in the inList, but should not be treated as a child of the dimension! + + std::vector temp; + const std::vector& candidates = getViewObject()->getInList(); + for (auto& obj : candidates) { + if (obj->isDerivedFrom() || + obj->isDerivedFrom() || + obj->isDerivedFrom() ) { + temp.push_back(obj); + } + } + return temp; +} + diff --git a/src/Mod/TechDraw/Gui/ViewProviderDimension.h b/src/Mod/TechDraw/Gui/ViewProviderDimension.h index d385d66b79..04213422f9 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderDimension.h +++ b/src/Mod/TechDraw/Gui/ViewProviderDimension.h @@ -41,7 +41,7 @@ public: /// constructor ViewProviderDimension(); /// destructor - ~ViewProviderDimension() override; + ~ViewProviderDimension() override = default; App::PropertyFont Font; App::PropertyLength Fontsize; @@ -90,6 +90,9 @@ public: bool canDelete(App::DocumentObject* obj) const override; void setPixmapForType(); + std::vector claimChildren() const override; + + protected: void handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property * prop) override; diff --git a/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp b/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp index 28de10104c..79fee565eb 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp @@ -100,18 +100,18 @@ bool ViewProviderLeader::doubleClicked() return true; } -void ViewProviderLeader::onChanged(const App::Property* p) +void ViewProviderLeader::onChanged(const App::Property* prop) { - if ((p == &Color) || - (p == &LineWidth) || - (p == &LineStyle) || - (p == &UseOldCoords)) { - QGIView* qgiv = getQView(); + if ((prop == &Color) || + (prop == &LineWidth) || + (prop == &LineStyle) || + (prop == &UseOldCoords)) { + auto* qgiv = getQView(); if (qgiv) { qgiv->updateView(true); } } - ViewProviderDrawingView::onChanged(p); + ViewProviderDrawingView::onChanged(prop); } std::vector ViewProviderLeader::claimChildren() const diff --git a/src/Mod/TechDraw/Gui/ViewProviderProjGroup.cpp b/src/Mod/TechDraw/Gui/ViewProviderProjGroup.cpp index 37b1153128..bf94945816 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderProjGroup.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderProjGroup.cpp @@ -35,7 +35,9 @@ #include #include +#include #include +#include #include #include #include @@ -55,16 +57,6 @@ ViewProviderProjGroup::ViewProviderProjGroup() sPixmap = "TechDraw_TreeProjGroup"; } -ViewProviderProjGroup::~ViewProviderProjGroup() -{ -} - -void ViewProviderProjGroup::setupContextMenu(QMenu* menu, QObject* receiver, const char* member) -{ - Q_UNUSED(menu); - Q_UNUSED(receiver); - Q_UNUSED(member); -} bool ViewProviderProjGroup::setEdit(int ModNum) { @@ -72,10 +64,11 @@ bool ViewProviderProjGroup::setEdit(int ModNum) // When double-clicking on the item for this sketch the // object unsets and sets its edit mode without closing // the task panel - Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); - TaskDlgProjGroup *projDlg = qobject_cast(dlg); - if (projDlg && projDlg->getViewProvider() != this) + auto* dlg = Gui::Control().activeDialog(); + auto* projDlg = qobject_cast(dlg); + if (projDlg && projDlg->getViewProvider() != this) { projDlg = nullptr; // another sketch left open its task panel + } // clear the selection (convenience) Gui::Selection().clearSelection(); @@ -97,8 +90,9 @@ bool ViewProviderProjGroup::doubleClicked() return true; } -bool ViewProviderProjGroup::onDelete(const std::vector &) +bool ViewProviderProjGroup::onDelete(const std::vector & parms) { + Q_UNUSED(parms) // warn the user if the ProjGroup is not empty QString bodyMessage; @@ -142,8 +136,9 @@ bool ViewProviderProjGroup::onDelete(const std::vector &) bodyMessageStream << qApp->translate("Std_Delete", "The group cannot be deleted because its items have the following\nsection or detail views, or leader lines that would get broken:"); bodyMessageStream << '\n'; - for (const auto& ListIterator : ViewList) + for (const auto& ListIterator : ViewList) { bodyMessageStream << '\n' << QString::fromUtf8(ListIterator.c_str()); + } QMessageBox::warning(Gui::getMainWindow(), qApp->translate("Std_Delete", "Object dependencies"), bodyMessage, QMessageBox::Ok); @@ -156,20 +151,17 @@ bool ViewProviderProjGroup::onDelete(const std::vector &) bodyMessageStream << qApp->translate("Std_Delete", "The projection group is not empty, therefore\nthe following referencing objects might be lost:"); bodyMessageStream << '\n'; - for (auto ObjIterator : objs) + for (auto ObjIterator : objs) { bodyMessageStream << '\n' << QString::fromUtf8(ObjIterator->Label.getValue()); + } bodyMessageStream << "\n\n" << QObject::tr("Are you sure you want to continue?"); // show and evaluate dialog int DialogResult = QMessageBox::warning(Gui::getMainWindow(), qApp->translate("Std_Delete", "Object dependencies"), bodyMessage, QMessageBox::Yes, QMessageBox::No); - if (DialogResult == QMessageBox::Yes) - return true; - else - return false; + return (DialogResult == QMessageBox::Yes); } - else - return true; + return true; } bool ViewProviderProjGroup::canDelete(App::DocumentObject *obj) const @@ -183,17 +175,36 @@ bool ViewProviderProjGroup::canDelete(App::DocumentObject *obj) const std::vector ViewProviderProjGroup::claimChildren() const { - // Collect any child fields + // Collect any child Document Objects and put them in the right place in the Feature tree + // valid children of an ProjGroup are: + // - Balloons + // - Leaders + // - RichAnno std::vector temp; + const std::vector& candidates = getViewObject()->getInList(); + // DPGI's do not point at the DPG, the DPG/DVC maintains links to the items + + // why does this need a try/catch?? try { - for (auto* view : getObject()->Views.getValues()) { - temp.push_back(view); - } - return temp; - } catch (...) { - std::vector tmp; - return tmp; + for (auto& obj : candidates) { + if (obj->isDerivedFrom() || + obj->isDerivedFrom() || + obj->isDerivedFrom()) { + temp.push_back(obj); + } + } +// return temp; } + catch (...) { + return {}; + } + + // plus the individual ProjGroupItems + for (auto& view : getViewObject()->Views.getValues()) { + temp.push_back(view); + } + + return temp; } TechDraw::DrawProjGroup* ViewProviderProjGroup::getViewObject() const diff --git a/src/Mod/TechDraw/Gui/ViewProviderProjGroup.h b/src/Mod/TechDraw/Gui/ViewProviderProjGroup.h index 182c94521f..2495cb1e83 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderProjGroup.h +++ b/src/Mod/TechDraw/Gui/ViewProviderProjGroup.h @@ -22,8 +22,8 @@ #ifndef DRAWINGGUI_VIEWPROVIDERVIEWGROUP_H #define DRAWINGGUI_VIEWPROVIDERVIEWGROUP_H - -#include + +#include #include @@ -39,20 +39,19 @@ class TechDrawGuiExport ViewProviderProjGroup : public ViewProviderDrawingView public: ViewProviderProjGroup(); /// constructor - ~ViewProviderProjGroup() override; /// destructor + ~ViewProviderProjGroup() override = default; /// destructor bool useNewSelectionModel() const override {return false;} - /// Claim all the views for the page + /// Claim all the views for the group std::vector claimChildren() const override; /// Is called by the tree if the user double click on the object bool doubleClicked() override; - void setupContextMenu(QMenu*, QObject*, const char*) override; TechDraw::DrawProjGroup* getObject() const; TechDraw::DrawProjGroup* getViewObject() const override; - bool onDelete(const std::vector &) override; + bool onDelete(const std::vector &parms) override; bool canDelete(App::DocumentObject* obj) const override; protected: diff --git a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp index 0254fbcf94..7379d11cc2 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.cpp @@ -28,14 +28,16 @@ #include #include -#include +#include +#include +#include + #include #include "PreferencesGui.h" #include "ZVALUE.h" #include "QGIView.h" #include "TaskRichAnno.h" #include "QGSPage.h" -#include "ViewProviderPage.h" #include "ViewProviderRichAnno.h" using namespace TechDrawGui; @@ -68,9 +70,6 @@ ViewProviderRichAnno::ViewProviderRichAnno() StackOrder.setValue(ZVALUE::DIMENSION); } -ViewProviderRichAnno::~ViewProviderRichAnno() -{ -} bool ViewProviderRichAnno::doubleClicked() { @@ -79,7 +78,7 @@ bool ViewProviderRichAnno::doubleClicked() return true; } -void ViewProviderRichAnno::updateData(const App::Property* p) +void ViewProviderRichAnno::updateData(const App::Property* prop) { // only if there is a frame we can enable the frame line parameters if (getViewObject()) { @@ -95,21 +94,21 @@ void ViewProviderRichAnno::updateData(const App::Property* p) } } - ViewProviderDrawingView::updateData(p); + ViewProviderDrawingView::updateData(prop); } -void ViewProviderRichAnno::onChanged(const App::Property* p) +void ViewProviderRichAnno::onChanged(const App::Property* prop) { - if ((p == &LineColor) || - (p == &LineWidth) || - (p == &LineStyle)) { - QGIView* qgiv = getQView(); + if ((prop == &LineColor) || + (prop == &LineWidth) || + (prop == &LineStyle)) { + auto* qgiv = getQView(); if (qgiv) { qgiv->updateView(true); } } - ViewProviderDrawingView::onChanged(p); + ViewProviderDrawingView::onChanged(prop); } TechDraw::DrawRichAnno* ViewProviderRichAnno::getViewObject() const @@ -183,3 +182,23 @@ bool ViewProviderRichAnno::canDelete(App::DocumentObject *obj) const Q_UNUSED(obj) return true; } + + +std::vector ViewProviderRichAnno::claimChildren() const +{ + // What can reasonably have a RichAnno as a parent? A leader? a bit unconventional, but not forbidden. + // Another RichAnno? Maybe? Balloons? Dimensions? This is a bit of a corner case. Typically, a + // RichAnno would belong to something rather than owning something. + + std::vector temp; + const std::vector& candidates = getViewObject()->getInList(); + for (auto& obj : candidates) { + if (obj->isDerivedFrom() || + obj->isDerivedFrom() || + obj->isDerivedFrom() || + obj->isDerivedFrom() ) { + temp.push_back(obj); + } + } + return temp; +} diff --git a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h index 2d3e37998c..ebff4129f1 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h +++ b/src/Mod/TechDraw/Gui/ViewProviderRichAnno.h @@ -46,15 +46,15 @@ public: /// constructor ViewProviderRichAnno(); /// destructor - ~ViewProviderRichAnno() override; + ~ViewProviderRichAnno() override = default; App::PropertyLength LineWidth; App::PropertyEnumeration LineStyle; App::PropertyColor LineColor; bool useNewSelectionModel() const override {return false;} - void updateData(const App::Property*) override; - void onChanged(const App::Property* p) override; + void updateData(const App::Property* prop) override; + void onChanged(const App::Property* prop) override; bool doubleClicked() override; bool canDelete(App::DocumentObject* obj) const override; @@ -63,6 +63,10 @@ public: TechDraw::DrawRichAnno* getViewObject() const override; TechDraw::DrawRichAnno* getFeature() const; + /// Claim any views that have this as a parent + std::vector claimChildren() const override; + + protected: App::Color getDefLineColor(); std::string getDefFont(); diff --git a/src/Mod/TechDraw/Gui/ZVALUE.h b/src/Mod/TechDraw/Gui/ZVALUE.h index 9425ba6c63..36497cbf1a 100644 --- a/src/Mod/TechDraw/Gui/ZVALUE.h +++ b/src/Mod/TechDraw/Gui/ZVALUE.h @@ -16,7 +16,8 @@ namespace ZVALUE { const int SECTIONLINE = 90; const int MATTING = 100; const int DIMENSION = 110; - const int LABEL = 120; + const int BALLOON = 120; + const int ANNOTATION = 120; const int TRACKER = 125; const int LOCK = 200; }