[TechDraw] Implement proper selection of subitems (#11804)

This commit is contained in:
Tomas Pavlicek
2023-12-22 14:25:58 +01:00
committed by GitHub
parent 23ec682cbe
commit f3fa2ba9c9
12 changed files with 181 additions and 43 deletions

View File

@@ -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);
}
}
}

View File

@@ -25,6 +25,7 @@
#include <string>
#include <QCoreApplication>
#include <QGraphicsItem>
#include <Base/Vector3D.h>
#include <Mod/TechDraw/TechDrawGlobal.h>
@@ -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);
};

View File

@@ -62,6 +62,7 @@
#include <Mod/TechDraw/App/DrawTemplate.h>
#include <Mod/TechDraw/App/Preferences.h>
#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<QGIView*> views = m_scene->getViews();
@@ -649,71 +649,52 @@ void MDIViewPage::clearSceneSelection()
// Iterate through all views and unselect all
for (std::vector<QGIView*>::iterator it = views.begin(); it != views.end(); ++it) {
QGIView* item = *it;
bool state = item->isSelected();
//handle oddballs
QGIViewDimension* dim = dynamic_cast<QGIViewDimension*>(*it);
if (dim) {
state = dim->getDatumLabel()->isSelected();
}
else {
QGIViewBalloon* bal = dynamic_cast<QGIViewBalloon*>(*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<std::string> &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<Gui::SelectionSingleton::SelObj> 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<Gui::SelectionObject> 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

View File

@@ -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<std::string> &subNames);
void clearSceneSelection();
void blockSceneSelection(bool isBlocked);

View File

@@ -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<std::string> &subNames)
{
Q_UNUSED(subNames);
setGroupSelection(isSelected);
}
void QGIView::alignTo(QGraphicsItem*item, const QString &alignment)
{
alignHash.clear();

View File

@@ -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<std::string> &subNames);
virtual void draw();
virtual void drawCaption();

View File

@@ -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)
{

View File

@@ -193,6 +193,7 @@ public:
void setPrettySel();
void setPrettyNormal();
bool getGroupSelection() override;
void setGroupSelection(bool isSelected) override;
virtual QGIBalloonLabel* getBalloonLabel()
{

View File

@@ -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)
{

View File

@@ -176,6 +176,7 @@ public:
void setPrettySel();
void setPrettyNormal();
bool getGroupSelection() override;
void setGroupSelection(bool isSelected) override;
virtual QGIDatumLabel* getDatumLabel() const { return datumLabel; }

View File

@@ -44,6 +44,7 @@
#include <Mod/TechDraw/App/DrawViewSection.h>
#include <Mod/TechDraw/App/Geometry.h>
#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<QGIVertex *>(child)->getProjIndex();
break;
case QGIEdge::Type:
projIndex = static_cast<QGIEdge *>(child)->getProjIndex();
break;
case QGIFace::Type:
projIndex = static_cast<QGIFace *>(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<std::string> &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);
}
}
}

View File

@@ -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<std::string> &subNames) override;
virtual QGraphicsItem *getQGISubItemByName(const std::string &subName) const;
protected:
QPainterPath drawPainterPath(TechDraw::BaseGeomPtr baseGeom) const;
void drawViewPart();