From ff14c58ccc83192e787d786116ff5568e3a367a1 Mon Sep 17 00:00:00 2001 From: pavltom Date: Sun, 11 Feb 2024 13:53:48 +0100 Subject: [PATCH] [TechDraw] Add Owner property to Symbols --- src/Mod/TechDraw/App/DrawView.cpp | 5 ++ src/Mod/TechDraw/App/DrawView.h | 2 + src/Mod/TechDraw/App/DrawViewSymbol.cpp | 46 +++++++++++ src/Mod/TechDraw/App/DrawViewSymbol.h | 5 ++ src/Mod/TechDraw/App/Geometry.cpp | 10 +++ src/Mod/TechDraw/App/Geometry.h | 2 + src/Mod/TechDraw/Gui/CommandAnnotate.cpp | 37 +++++++-- src/Mod/TechDraw/Gui/QGIView.cpp | 20 +++++ src/Mod/TechDraw/Gui/QGIView.h | 2 +- src/Mod/TechDraw/Gui/QGSPage.cpp | 9 ++- .../TechDraw/Gui/TaskSurfaceFinishSymbols.cpp | 77 +++++++++++++++++-- .../TechDraw/Gui/TaskSurfaceFinishSymbols.h | 8 +- .../TechDraw/Gui/ViewProviderDrawingView.cpp | 20 +++++ .../TechDraw/Gui/ViewProviderDrawingView.h | 2 + src/Mod/TechDraw/Gui/ViewProviderLeader.cpp | 6 ++ src/Mod/TechDraw/Gui/ViewProviderPage.cpp | 6 ++ src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp | 18 +++-- src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp | 6 ++ 18 files changed, 254 insertions(+), 27 deletions(-) diff --git a/src/Mod/TechDraw/App/DrawView.cpp b/src/Mod/TechDraw/App/DrawView.cpp index 8386112c9e..39d9206280 100644 --- a/src/Mod/TechDraw/App/DrawView.cpp +++ b/src/Mod/TechDraw/App/DrawView.cpp @@ -375,6 +375,11 @@ bool DrawView::isInClip() return false; } +DrawView *DrawView::claimParent() const +{ + return nullptr; +} + DrawViewClip* DrawView::getClipGroup() { std::vector parent = getInList(); diff --git a/src/Mod/TechDraw/App/DrawView.h b/src/Mod/TechDraw/App/DrawView.h index 7bd6adce88..d635bb67c5 100644 --- a/src/Mod/TechDraw/App/DrawView.h +++ b/src/Mod/TechDraw/App/DrawView.h @@ -84,6 +84,8 @@ public: virtual DrawPage* findParentPage() const; virtual std::vector findAllParentPages() const; + virtual DrawView *claimParent() const; + virtual int countParentPages() const; virtual QRectF getRect() const; //must be overridden by derived class QRectF getRectAligned() const; diff --git a/src/Mod/TechDraw/App/DrawViewSymbol.cpp b/src/Mod/TechDraw/App/DrawViewSymbol.cpp index 9209f7c23a..03fe609c93 100644 --- a/src/Mod/TechDraw/App/DrawViewSymbol.cpp +++ b/src/Mod/TechDraw/App/DrawViewSymbol.cpp @@ -51,6 +51,9 @@ DrawViewSymbol::DrawViewSymbol() ADD_PROPERTY_TYPE(Symbol, (""), vgroup, App::Prop_None, "The SVG code defining this symbol"); ADD_PROPERTY_TYPE(EditableTexts, (""), vgroup, App::Prop_None, "Substitution values for the editable strings in this symbol"); + 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::ReadOnly, false); Symbol.setStatus(App::Property::Hidden, true); @@ -58,6 +61,28 @@ DrawViewSymbol::DrawViewSymbol() DrawViewSymbol::~DrawViewSymbol() {} +void DrawViewSymbol::touchTreeOwner() +{ + auto owner = dynamic_cast(Owner.getValue()); + if (owner) { + owner->touch(); + } + else { // If no owner is specified, touch all parent pages + for (auto page : findAllParentPages()) { + page->touch(); + } + } +} + +void DrawViewSymbol::onBeforeChange(const App::Property *prop) +{ + if (prop == &Owner && !isRestoring()) { + touchTreeOwner(); + } + + TechDraw::DrawView::onBeforeChange(prop); +} + void DrawViewSymbol::onChanged(const App::Property* prop) { if (prop == &Symbol) { @@ -72,10 +97,26 @@ void DrawViewSymbol::onChanged(const App::Property* prop) //1 cycle updateFieldsInSymbol(); } + else if (prop == &Owner) { + if (!isRestoring()) { + touchTreeOwner(); + } + } TechDraw::DrawView::onChanged(prop); } +short DrawViewSymbol::mustExecute() const +{ + if (!isRestoring()) { + if (Owner.isTouched()) { + return 1; + } + } + + return DrawView::mustExecute(); +} + App::DocumentObjectExecReturn* DrawViewSymbol::execute() { //nothing to do. DVS is just a container for properties. @@ -83,6 +124,11 @@ App::DocumentObjectExecReturn* DrawViewSymbol::execute() return DrawView::execute(); } +DrawView *DrawViewSymbol::claimParent() const +{ + return dynamic_cast(Owner.getValue()); +} + QRectF DrawViewSymbol::getRect() const { double w = 64.0;//must default to something diff --git a/src/Mod/TechDraw/App/DrawViewSymbol.h b/src/Mod/TechDraw/App/DrawViewSymbol.h index 3780e2ea76..85f52b2e69 100644 --- a/src/Mod/TechDraw/App/DrawViewSymbol.h +++ b/src/Mod/TechDraw/App/DrawViewSymbol.h @@ -48,7 +48,9 @@ public: App::PropertyString Symbol; App::PropertyStringList EditableTexts; + App::PropertyLink Owner; + short mustExecute() const override; /** @name methods override Feature */ //@{ /// recalculate the Feature @@ -59,6 +61,7 @@ public: const char* getViewProviderName() const override { return "TechDrawGui::ViewProviderSymbol"; } + DrawView *claimParent(void) const override; QRectF getRect() const override; bool checkFit(TechDraw::DrawPage* p) const override; @@ -66,6 +69,8 @@ public: PyObject *getPyObject() override; protected: + void touchTreeOwner(); + void onBeforeChange(const App::Property* prop) override; void onChanged(const App::Property* prop) override; Base::BoundBox3d bbox; diff --git a/src/Mod/TechDraw/App/Geometry.cpp b/src/Mod/TechDraw/App/Geometry.cpp index 67dbd31ec6..9aa51f5b1f 100644 --- a/src/Mod/TechDraw/App/Geometry.cpp +++ b/src/Mod/TechDraw/App/Geometry.cpp @@ -36,6 +36,7 @@ # include # include # include +# include # include # include # include @@ -43,6 +44,7 @@ # include # include # include +# include # include # include # include @@ -158,6 +160,14 @@ TopoDS_Face Face::toOccFace() const return TopoDS_Face(); } +//**** Face +Base::Vector3d Face::getCenter() const { + GProp_GProps faceProps; + BRepGProp::SurfaceProperties(toOccFace(), faceProps); + + return DrawUtil::toVector3d(faceProps.CentreOfMass()); +} + Face::~Face() { for(auto it : wires) { diff --git a/src/Mod/TechDraw/App/Geometry.h b/src/Mod/TechDraw/App/Geometry.h index 33b6479ae6..6c23407c32 100644 --- a/src/Mod/TechDraw/App/Geometry.h +++ b/src/Mod/TechDraw/App/Geometry.h @@ -347,6 +347,8 @@ class TechDrawExport Face ~Face(); TopoDS_Face toOccFace() const; std::vector wires; + + Base::Vector3d getCenter() const; }; using FacePtr = std::shared_ptr; diff --git a/src/Mod/TechDraw/Gui/CommandAnnotate.cpp b/src/Mod/TechDraw/Gui/CommandAnnotate.cpp index 209456e6f2..620293d679 100644 --- a/src/Mod/TechDraw/Gui/CommandAnnotate.cpp +++ b/src/Mod/TechDraw/Gui/CommandAnnotate.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -1618,19 +1619,39 @@ CmdTechDrawSurfaceFinishSymbols::CmdTechDrawSurfaceFinishSymbols() void CmdTechDrawSurfaceFinishSymbols::activated(int iMsg) { Q_UNUSED(iMsg); + + std::string ownerName; std::vector selection = this->getSelection().getSelectionEx(); if (selection.empty()) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("SurfaceFinishSymbols"), QObject::tr("Selection is empty")); - return; + TechDraw::DrawPage *page = DrawGuiUtil::findPage(this); + if (!page) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("SurfaceFinishSymbols"), + QObject::tr("No page to insert the symbol!")); + return; + } + + ownerName = page->getNameInDocument(); } - TechDraw::DrawViewPart* objFeat = dynamic_cast (selection[0].getObject()); - if(!objFeat) - { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("SurfaceFinishSymbols"), QObject::tr("No object selected")); - return; + else { + auto objFeat = dynamic_cast(selection.front().getObject()); + if (!objFeat->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId()) + && !objFeat->isDerivedFrom(TechDraw::DrawLeaderLine::getClassTypeId())) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("SurfaceFinishSymbols"), + QObject::tr("Selected object is not a part view, nor a leader line")); + return; + } + + ownerName = objFeat->getNameInDocument(); + + const std::vector &subNames = selection.front().getSubNames(); + if (!subNames.empty()) { + ownerName += '.'; + ownerName += subNames.front(); + } } - Gui::Control().showDialog(new TechDrawGui::TaskDlgSurfaceFinishSymbols(objFeat)); + + Gui::Control().showDialog(new TechDrawGui::TaskDlgSurfaceFinishSymbols(ownerName)); } bool CmdTechDrawSurfaceFinishSymbols::isActive() diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index d0b3d5faeb..ba6325d1a2 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -663,6 +663,26 @@ void QGIView::addArbitraryItem(QGraphicsItem* qgi) } } +void QGIView::switchParentItem(QGIView *targetParent) +{ + auto currentParent = dynamic_cast(this->parentItem()); + if (currentParent != targetParent) { + if (targetParent) { + targetParent->addToGroup(this); + } + else { + currentParent->removeFromGroup(this); + } + + if (currentParent) { + currentParent->updateView(); + } + if (targetParent) { + targetParent->updateView(); + } + } +} + void QGIView::setStack(int z) { m_zOrder = z; diff --git a/src/Mod/TechDraw/Gui/QGIView.h b/src/Mod/TechDraw/Gui/QGIView.h index 72b1b76ac3..77c2ca7a4f 100644 --- a/src/Mod/TechDraw/Gui/QGIView.h +++ b/src/Mod/TechDraw/Gui/QGIView.h @@ -155,8 +155,8 @@ public: static int exactFontSize(std::string fontFamily, double nominalSize); virtual void removeChild(QGIView* child); - virtual void addArbitraryItem(QGraphicsItem* qgi); + virtual void switchParentItem(QGIView *targetParent); // Mouse handling void mousePressEvent(QGraphicsSceneMouseEvent *event) override; diff --git a/src/Mod/TechDraw/Gui/QGSPage.cpp b/src/Mod/TechDraw/Gui/QGSPage.cpp index a7af703077..e17e8b81b3 100644 --- a/src/Mod/TechDraw/Gui/QGSPage.cpp +++ b/src/Mod/TechDraw/Gui/QGSPage.cpp @@ -448,9 +448,16 @@ QGIView* QGSPage::addDrawViewAnnotation(TechDraw::DrawViewAnnotation* annoFeat) QGIView* QGSPage::addDrawViewSymbol(TechDraw::DrawViewSymbol* symbolFeat) { auto qview(new QGIViewSymbol); - qview->setViewFeature(symbolFeat); + auto owner = dynamic_cast(symbolFeat->Owner.getValue()); + if (owner) { + auto parent = dynamic_cast(findQViewForDocObj(owner)); + if (parent) { + qview->switchParentItem(parent); + } + } + addQView(qview); return qview; } diff --git a/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.cpp b/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.cpp index c6e95243a3..1ca67f7c00 100644 --- a/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.cpp +++ b/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.cpp @@ -32,10 +32,14 @@ #include #include #include +#include #include +#include "QGIView.h" #include "ui_TaskSurfaceFinishSymbols.h" #include "TaskSurfaceFinishSymbols.h" +#include "ViewProviderSymbol.h" +#include "ZVALUE.h" using namespace Gui; @@ -79,16 +83,60 @@ std::string SvgString::finish() // TaskSurfaceFinishSymbols //=========================================================================== -TaskSurfaceFinishSymbols::TaskSurfaceFinishSymbols(TechDraw::DrawViewPart* view) : - selectedView(view), +TaskSurfaceFinishSymbols::TaskSurfaceFinishSymbols(const std::string &ownerName) : ui(new Ui_TaskSurfaceFinishSymbols) { + App::Document *doc = App::GetApplication().getActiveDocument(); + if (doc) { + owner = doc->getObject(ownerName.c_str()); + std::string subName; + if (!owner) { + size_t dot = ownerName.rfind('.'); + if (dot != std::string::npos) { + subName = ownerName.substr(dot + 1); + owner = doc->getObject(ownerName.substr(0, dot).c_str()); + } + } + + auto page = dynamic_cast(owner); + if (page) { + placement.x = page->getPageWidth()/2.0; + placement.y = page->getPageHeight()/2.0; + } + + auto viewPart = dynamic_cast(owner); + if (viewPart && !subName.empty()) { + std::string subType = DrawUtil::getGeomTypeFromName(subName); + if (subType == "Vertex") { + TechDraw::VertexPtr vertex = viewPart->getVertex(subName); + if (vertex) { + placement = vertex->point(); + } + } + else if (subType == "Edge") { + TechDraw::BaseGeomPtr edge = viewPart->getEdge(subName); + if (edge) { + placement = edge->getMidPoint(); + } + } + else if (subType == "Face") { + TechDraw::FacePtr face = viewPart->getFace(subName); + if (face) { + placement = face->getCenter(); + } + } + + placement = DrawUtil::invertY(placement); + } + } + raValues = {"Ra50", "Ra25", "Ra12, 5", "Ra6, 3", "Ra3, 2", "Ra1, 6", "Ra0, 8", "Ra0, 4", "Ra0, 2", "Ra0, 1", "Ra0, 05", "Ra0, 025"}; laySymbols = {"", "=", "⟂", "X", "M", "C", "R"}; roughGrades = {"", "N1", "N2", "N3", "N4", "N5", "N6", "N7", "N8", "N9", "N10", "N11"}; + ui->setupUi(this); setUiEdit(); } @@ -324,8 +372,25 @@ bool TaskSurfaceFinishSymbols::accept() TechDraw::DrawViewSymbol *surfaceSymbol = dynamic_cast(docObject); surfaceSymbol->Symbol.setValue(completeSymbol()); surfaceSymbol->Rotation.setValue(ui->leAngle->text().toDouble()); - TechDraw::DrawPage* page = selectedView->findParentPage(); - page->addView(surfaceSymbol); + + auto view = dynamic_cast(owner); + auto page = dynamic_cast(owner); + if (!page && view) { + page = view->findParentPage(); + } + if (page) { + page->addView(surfaceSymbol); + } + + surfaceSymbol->Owner.setValue(view); + surfaceSymbol->X.setValue(placement.x); + surfaceSymbol->Y.setValue(placement.y); + + auto viewProvider = dynamic_cast(QGIView::getViewProvider(surfaceSymbol)); + if (viewProvider) { + viewProvider->StackOrder.setValue(ZVALUE::DIMENSION); + } + Gui::Command::commitCommand(); return true; } @@ -339,10 +404,10 @@ bool TaskSurfaceFinishSymbols::reject() // TaskDlgSurfaceFinishSymbols// //=========================================================================== -TaskDlgSurfaceFinishSymbols::TaskDlgSurfaceFinishSymbols(TechDraw::DrawViewPart* view) +TaskDlgSurfaceFinishSymbols::TaskDlgSurfaceFinishSymbols(const std::string &ownerName) : TaskDialog() { - widget = new TaskSurfaceFinishSymbols(view); + widget = new TaskSurfaceFinishSymbols(ownerName); taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_SurfaceFinishSymbols"), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); diff --git a/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.h b/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.h index cd9a14e987..4d537686e6 100644 --- a/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.h +++ b/src/Mod/TechDraw/Gui/TaskSurfaceFinishSymbols.h @@ -78,7 +78,7 @@ class TaskSurfaceFinishSymbols : public QWidget Q_OBJECT public: - explicit TaskSurfaceFinishSymbols(TechDraw::DrawViewPart* view); + explicit TaskSurfaceFinishSymbols(const std::string &ownerName); ~TaskSurfaceFinishSymbols() override = default; virtual bool accept(); @@ -89,12 +89,14 @@ protected: void changeEvent(QEvent *event) override; void setUiEdit(); + App::DocumentObject *owner; + Base::Vector3d placement; + private: enum symbolType {anyMethod=0, removeProhibit, removeRequired, anyMethodAll, removeProhibitAll, removeRequiredAll}; QPixmap baseSymbol(symbolType type); std::string completeSymbol(); - TechDraw::DrawViewPart* selectedView; QGraphicsScene* symbolScene; //note this is not QGSPage, but another scene only used to //display symbols in this task's ui std::vector raValues, laySymbols, roughGrades; @@ -117,7 +119,7 @@ class TaskDlgSurfaceFinishSymbols : public Gui::TaskView::TaskDialog Q_OBJECT public: - explicit TaskDlgSurfaceFinishSymbols(TechDraw::DrawViewPart* view); + explicit TaskDlgSurfaceFinishSymbols(const std::string &ownerName); ~TaskDlgSurfaceFinishSymbols() override; /// is called the TaskView when the dialog is opened diff --git a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp index b239c23b05..4e0cf2cc1d 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.cpp @@ -442,3 +442,23 @@ TechDraw::DrawView* ViewProviderDrawingView::getViewObject() const { return dynamic_cast(pcObject); } + +void ViewProviderDrawingView::switchOwnerProperty(App::PropertyLink &prop) +{ + QGIView *qv = getQView(); + if (!qv) { + return; + } + + QGIView *targetParent = nullptr; + auto owner = dynamic_cast(prop.getValue()); + if (owner) { + auto vp = dynamic_cast(QGIView::getViewProvider(owner)); + if (vp) { + targetParent = vp->getQView(); + } + } + + qv->switchParentItem(targetParent); + qv->updateView(); +} diff --git a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.h b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.h index f1828a9c2b..5e69e4ccae 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderDrawingView.h +++ b/src/Mod/TechDraw/Gui/ViewProviderDrawingView.h @@ -99,6 +99,8 @@ public: const char* whoAmI() const; + void switchOwnerProperty(App::PropertyLink &prop); + private: void multiParentPaint(std::vector& pages); void singleParentPaint(const TechDraw::DrawView* dv); diff --git a/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp b/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp index f3cad5c2ee..569dc1dc2f 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderLeader.cpp @@ -142,6 +142,12 @@ std::vector ViewProviderLeader::claimChildren() const const std::vector &views = getFeature()->getInList(); try { for(std::vector::const_iterator it = views.begin(); it != views.end(); ++it) { + auto view = dynamic_cast(*it); + if (view && view->claimParent() == getViewObject()) { + temp.push_back(view); + continue; + } + if ((*it)->isDerivedFrom()) { temp.push_back((*it)); } else if ((*it)->isDerivedFrom()) { diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp index 9b32581319..246a38e5a2 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp @@ -405,6 +405,12 @@ std::vector ViewProviderPage::claimChildren(void) const for (std::vector::const_iterator it = views.begin(); it != views.end(); ++it) { TechDraw::DrawView* featView = dynamic_cast(*it); + + // If the child view appoints a parent, skip it + if (featView && featView->claimParent()) { + continue; + } + App::DocumentObject* docObj = *it; //DrawRichAnno with no parent is child of Page TechDraw::DrawRichAnno* dra = dynamic_cast(*it); diff --git a/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp b/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp index 44ce3d8dbf..a0b93331a3 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderSymbol.cpp @@ -44,15 +44,17 @@ ViewProviderSymbol::~ViewProviderSymbol() void ViewProviderSymbol::updateData(const App::Property* prop) { - if (prop == &getViewObject()->Scale) { - onGuiRepaint(getViewObject()); - } else if (prop == &getViewObject()->Rotation) { - onGuiRepaint(getViewObject()); - } else if (prop == &getViewObject()->Symbol) { - onGuiRepaint(getViewObject()); - } else if (prop == &getViewObject()->EditableTexts) { - onGuiRepaint(getViewObject()); + TechDraw::DrawViewSymbol *obj = getViewObject(); + if (prop == &obj->Scale + || prop == &obj->Rotation + || prop == &obj->Symbol + || prop == &obj->EditableTexts) { + onGuiRepaint(obj); } + else if (prop == &obj->Owner) { + switchOwnerProperty(obj->Owner); + } + ViewProviderDrawingView::updateData(prop); } diff --git a/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp b/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp index 4d6de46286..dbd4587efc 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderViewPart.cpp @@ -217,6 +217,12 @@ std::vector ViewProviderViewPart::claimChildren() const const std::vector &views = getViewPart()->getInList(); try { for(std::vector::const_iterator it = views.begin(); it != views.end(); ++it) { + auto view = dynamic_cast(*it); + if (view && view->claimParent() == getViewPart()) { + temp.push_back(view); + continue; + } + if((*it)->isDerivedFrom()) { //TODO: make a list, then prune it. should be faster? bool skip = false;