From f3fa2ba9c9b1999e5c32d3ae544481b6e17553bb Mon Sep 17 00:00:00 2001 From: Tomas Pavlicek Date: Fri, 22 Dec 2023 14:25:58 +0100 Subject: [PATCH] [TechDraw] Implement proper selection of subitems (#11804) --- src/Mod/TechDraw/Gui/DrawGuiUtil.cpp | 30 ++++++++ src/Mod/TechDraw/Gui/DrawGuiUtil.h | 3 + src/Mod/TechDraw/Gui/MDIViewPage.cpp | 65 ++++++---------- src/Mod/TechDraw/Gui/MDIViewPage.h | 2 +- src/Mod/TechDraw/Gui/QGIView.cpp | 13 ++++ src/Mod/TechDraw/Gui/QGIView.h | 2 + src/Mod/TechDraw/Gui/QGIViewBalloon.cpp | 5 ++ src/Mod/TechDraw/Gui/QGIViewBalloon.h | 1 + src/Mod/TechDraw/Gui/QGIViewDimension.cpp | 5 ++ src/Mod/TechDraw/Gui/QGIViewDimension.h | 1 + src/Mod/TechDraw/Gui/QGIViewPart.cpp | 91 +++++++++++++++++++++++ src/Mod/TechDraw/Gui/QGIViewPart.h | 6 ++ 12 files changed, 181 insertions(+), 43 deletions(-) diff --git a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp index 495e2f1ccc..f528545c8b 100644 --- a/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp +++ b/src/Mod/TechDraw/Gui/DrawGuiUtil.cpp @@ -539,3 +539,33 @@ double DrawGuiUtil::roundToDigits(double original, int digits) temp = rounded / factor; return temp; } + +// Returns true if the item or any of its descendants is selected +bool DrawGuiUtil::isSelectedInTree(QGraphicsItem *item) +{ + if (item) { + if (item->isSelected()) { + return true; + } + + for (QGraphicsItem *child : item->childItems()) { + if (isSelectedInTree(child)) { + return true; + } + } + } + + return false; +} + +// Selects or deselects the item and all its descendants +void DrawGuiUtil::setSelectedTree(QGraphicsItem *item, bool selected) +{ + if (item) { + item->setSelected(selected); + + for (QGraphicsItem *child : item->childItems()) { + setSelectedTree(child, selected); + } + } +} diff --git a/src/Mod/TechDraw/Gui/DrawGuiUtil.h b/src/Mod/TechDraw/Gui/DrawGuiUtil.h index 29a7e2fca8..bad49919a8 100644 --- a/src/Mod/TechDraw/Gui/DrawGuiUtil.h +++ b/src/Mod/TechDraw/Gui/DrawGuiUtil.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -77,6 +78,8 @@ class TechDrawGuiExport DrawGuiUtil { static double roundToDigits(double original, int digits); + static bool isSelectedInTree(QGraphicsItem *item); + static void setSelectedTree(QGraphicsItem *item, bool selected); }; diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index b8cce38da7..3af07c9e06 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -62,6 +62,7 @@ #include #include +#include "DrawGuiUtil.h" #include "MDIViewPage.h" #include "QGIEdge.h" #include "QGIFace.h" @@ -641,7 +642,6 @@ void MDIViewPage::blockSceneSelection(const bool isBlocked) { isSelectionBlocked void MDIViewPage::clearSceneSelection() { // Base::Console().Message("MDIVP::clearSceneSelection()\n"); - blockSceneSelection(true); m_qgSceneSelected.clear(); std::vector views = m_scene->getViews(); @@ -649,71 +649,52 @@ void MDIViewPage::clearSceneSelection() // Iterate through all views and unselect all for (std::vector::iterator it = views.begin(); it != views.end(); ++it) { QGIView* item = *it; - bool state = item->isSelected(); - - //handle oddballs - QGIViewDimension* dim = dynamic_cast(*it); - if (dim) { - state = dim->getDatumLabel()->isSelected(); - } - else { - QGIViewBalloon* bal = dynamic_cast(*it); - if (bal) { - state = bal->getBalloonLabel()->isSelected(); - } - } - - if (state) { + if (item->getGroupSelection()) { item->setGroupSelection(false); item->updateView(); } } - - blockSceneSelection(false); } //!Update QGIView's selection state based on Selection made outside Drawing Interface -void MDIViewPage::selectQGIView(App::DocumentObject* obj, const bool isSelected) +void MDIViewPage::selectQGIView(App::DocumentObject *obj, bool isSelected, + const std::vector &subNames) { QGIView* view = m_scene->findQViewForDocObj(obj); - - blockSceneSelection(true); if (view) { - view->setGroupSelection(isSelected); + view->setGroupSelection(isSelected, subNames); view->updateView(); } - blockSceneSelection(false); } //! invoked by selection change made in Tree via father MDIView //really "onTreeSelectionChanged" void MDIViewPage::onSelectionChanged(const Gui::SelectionChanges& msg) { - // Base::Console().Message("MDIVP::onSelectionChanged()\n"); - std::vector selObjs = - Gui::Selection().getSelection(msg.pDocName); - if (msg.Type == Gui::SelectionChanges::ClrSelection) { + blockSceneSelection(true); + + if (msg.Type == Gui::SelectionChanges::ClrSelection || msg.Type == Gui::SelectionChanges::SetSelection) { clearSceneSelection(); - } - else if (msg.Type == Gui::SelectionChanges::SetSelection) {//replace entire selection set - clearSceneSelection(); - blockSceneSelection(true); - for (auto& so : selObjs) { - if (so.pObject->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { - selectQGIView(so.pObject, true); + + if (msg.Type == Gui::SelectionChanges::SetSelection) { + std::vector selObjs = Gui::Selection().getSelectionEx(msg.pDocName); + for (auto &so : selObjs) { + App::DocumentObject *docObj = so.getObject(); + if (docObj->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { + selectQGIView(docObj, true, so.getSubNames()); + } } } - blockSceneSelection(false); } - else if (msg.Type == Gui::SelectionChanges::AddSelection) { - blockSceneSelection(true); - for (auto& so : selObjs) { - if (so.pObject->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { - selectQGIView(so.pObject, true); - } + else if (msg.Type == Gui::SelectionChanges::AddSelection || msg.Type == Gui::SelectionChanges::RmvSelection) { + App::DocumentObject *docObj = msg.Object.getSubObject(); + if (docObj->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { + bool isSelected = msg.Type != Gui::SelectionChanges::RmvSelection; + selectQGIView(docObj, isSelected, std::vector(1, std::string(msg.pSubName ? msg.pSubName : ""))); } - blockSceneSelection(false); } + + blockSceneSelection(false); } //! maintain QGScene selected items in selection order diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.h b/src/Mod/TechDraw/Gui/MDIViewPage.h index 25ba8687f8..474247305f 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.h +++ b/src/Mod/TechDraw/Gui/MDIViewPage.h @@ -69,7 +69,7 @@ public: void preSelectionChanged(const QPoint &pos); /// QGraphicsScene selection routines - void selectQGIView(App::DocumentObject *obj, bool isSelected); + void selectQGIView(App::DocumentObject *obj, bool isSelected, const std::vector &subNames); void clearSceneSelection(); void blockSceneSelection(bool isBlocked); diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index 109cb440aa..87c1f7a0e0 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -130,6 +130,12 @@ bool QGIView::isVisible() return vpdo->Visibility.getValue(); } +//Gets selection state for this view and/or eventually its children +bool QGIView::getGroupSelection() +{ + return isSelected(); +} + //Set selection state for this and its children //required for items like dimensions & balloons void QGIView::setGroupSelection(bool isSelected) @@ -137,6 +143,13 @@ void QGIView::setGroupSelection(bool isSelected) setSelected(isSelected); } +// Set selection state of the feature (empty subName) or its sub items +void QGIView::setGroupSelection(bool isSelected, const std::vector &subNames) +{ + Q_UNUSED(subNames); + setGroupSelection(isSelected); +} + void QGIView::alignTo(QGraphicsItem*item, const QString &alignment) { alignHash.clear(); diff --git a/src/Mod/TechDraw/Gui/QGIView.h b/src/Mod/TechDraw/Gui/QGIView.h index 72facfca7d..72b1b76ac3 100644 --- a/src/Mod/TechDraw/Gui/QGIView.h +++ b/src/Mod/TechDraw/Gui/QGIView.h @@ -102,7 +102,9 @@ public: virtual void isVisible(bool state); virtual bool isVisible(); + virtual bool getGroupSelection(); virtual void setGroupSelection(bool isSelected); + virtual void setGroupSelection(bool isSelected, const std::vector &subNames); virtual void draw(); virtual void drawCaption(); diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp index 739dbdce2c..4798012538 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.cpp @@ -313,6 +313,11 @@ QVariant QGIViewBalloon::itemChange(GraphicsItemChange change, const QVariant& v return QGIView::itemChange(change, value); } +bool QGIViewBalloon::getGroupSelection() +{ + return balloonLabel->isSelected(); +} + //Set selection state for this and its children void QGIViewBalloon::setGroupSelection(bool isSelected) { diff --git a/src/Mod/TechDraw/Gui/QGIViewBalloon.h b/src/Mod/TechDraw/Gui/QGIViewBalloon.h index 00cccbbf73..4181e3327e 100644 --- a/src/Mod/TechDraw/Gui/QGIViewBalloon.h +++ b/src/Mod/TechDraw/Gui/QGIViewBalloon.h @@ -193,6 +193,7 @@ public: void setPrettySel(); void setPrettyNormal(); + bool getGroupSelection() override; void setGroupSelection(bool isSelected) override; virtual QGIBalloonLabel* getBalloonLabel() { diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp index 9f221cb7a8..1064c7d17f 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.cpp @@ -525,6 +525,11 @@ QVariant QGIViewDimension::itemChange(GraphicsItemChange change, const QVariant& return QGIView::itemChange(change, value); } +bool QGIViewDimension::getGroupSelection() +{ + return datumLabel->isSelected(); +} + //Set selection state for this and its children void QGIViewDimension::setGroupSelection(bool isSelected) { diff --git a/src/Mod/TechDraw/Gui/QGIViewDimension.h b/src/Mod/TechDraw/Gui/QGIViewDimension.h index 46e16e802c..891260abb8 100644 --- a/src/Mod/TechDraw/Gui/QGIViewDimension.h +++ b/src/Mod/TechDraw/Gui/QGIViewDimension.h @@ -176,6 +176,7 @@ public: void setPrettySel(); void setPrettyNormal(); + bool getGroupSelection() override; void setGroupSelection(bool isSelected) override; virtual QGIDatumLabel* getDatumLabel() const { return datumLabel; } diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index 6ce86f0fa4..6b0092698b 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -44,6 +44,7 @@ #include #include +#include "DrawGuiUtil.h" #include "MDIViewPage.h" #include "PreferencesGui.h" #include "QGICMark.h" @@ -1058,3 +1059,93 @@ bool QGIViewPart::prefPrintCenters() bool printCenters = Preferences::getPreferenceGroup("Decorations")->GetBool("PrintCenterMarks", false);//true matches v0.18 behaviour return printCenters; } + +QGraphicsItem *QGIViewPart::getQGISubItemByName(const std::string &subName) const +{ + int scanType = 0; + try { + const std::string &subType = TechDraw::DrawUtil::getGeomTypeFromName(subName); + if (subType == "Vertex") { + scanType = QGIVertex::Type; + } + else if (subType == "Edge") { + scanType = QGIEdge::Type; + } + else if (subType == "Face") { + scanType = QGIFace::Type; + } + } + catch (Base::ValueError e) { + // No action + } + if (!scanType) { + return nullptr; + } + + int scanIndex = -1; + try { + scanIndex = TechDraw::DrawUtil::getIndexFromName(subName); + } + catch (Base::ValueError e) { + // No action + } + if (scanIndex < 0) { + return nullptr; + } + + for (auto child : childItems()) { + if (child->type() != scanType) { + continue; + } + + int projIndex; + switch (scanType) { + case QGIVertex::Type: + projIndex = static_cast(child)->getProjIndex(); + break; + case QGIEdge::Type: + projIndex = static_cast(child)->getProjIndex(); + break; + case QGIFace::Type: + projIndex = static_cast(child)->getProjIndex(); + break; + default: + projIndex = -1; + break; + } + + if (projIndex == scanIndex) { + return child; + } + } + + return nullptr; +} + +bool QGIViewPart::getGroupSelection() { + return DrawGuiUtil::isSelectedInTree(this); +} + +void QGIViewPart::setGroupSelection(bool isSelected) { + DrawGuiUtil::setSelectedTree(this, isSelected); +} + +void QGIViewPart::setGroupSelection(bool isSelected, const std::vector &subNames) +{ + if (subNames.empty()) { + setSelected(isSelected); + return; + } + + for (const std::string &subName : subNames) { + if (subName.empty()) { + setSelected(isSelected); + continue; + } + + QGraphicsItem *subItem = getQGISubItemByName(subName); + if (subItem) { + subItem->setSelected(isSelected); + } + } +} diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.h b/src/Mod/TechDraw/Gui/QGIViewPart.h index 1df080f87c..f804e0ca09 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.h +++ b/src/Mod/TechDraw/Gui/QGIViewPart.h @@ -109,6 +109,12 @@ public: double x, double y, double curx, double cury); + bool getGroupSelection() override; + void setGroupSelection(bool isSelected) override; + void setGroupSelection(bool isSelected, const std::vector &subNames) override; + + virtual QGraphicsItem *getQGISubItemByName(const std::string &subName) const; + protected: QPainterPath drawPainterPath(TechDraw::BaseGeomPtr baseGeom) const; void drawViewPart();