diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.cpp b/src/Mod/TechDraw/Gui/MDIViewPage.cpp index bb25407f38..6a5290d230 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.cpp +++ b/src/Mod/TechDraw/Gui/MDIViewPage.cpp @@ -147,7 +147,7 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget* // Connect Signals and Slots QObject::connect( m_view->scene(), SIGNAL(selectionChanged()), - this , SLOT (selectionChanged()) + this , SLOT (sceneSelectionChanged()) ); //get informed by App side about deleted DocumentObjects @@ -833,6 +833,7 @@ void MDIViewPage::saveSVG(std::string file) /////////////// Selection Routines /////////////////// // wf: this is never executed??? // needs a signal from Scene? hoverEvent? Scene does not emit signal for "preselect" +// there is no "preSelect" signal from Gui either. void MDIViewPage::preSelectionChanged(const QPoint &pos) { QObject *obj = QObject::sender(); @@ -892,13 +893,15 @@ void MDIViewPage::preSelectionChanged(const QPoint &pos) } } +//flag to prevent selection activity within mdivp void MDIViewPage::blockSelection(const bool state) { isSelectionBlocked = state; } -void MDIViewPage::clearSelection() +//Set all QGIViews to unselected state +void MDIViewPage::clearSceneSelection() { blockSelection(true); std::vector views = m_view->getViews(); @@ -913,9 +916,8 @@ void MDIViewPage::clearSelection() blockSelection(false); } -//!Update QGVPage's selection based on Selection made outside Drawing Interface -//invoked from VPP -void MDIViewPage::selectFeature(App::DocumentObject *obj, const bool isSelected) +//!Update QGIView's selection state based on Selection made outside Drawing Interface +void MDIViewPage::selectQGIView(App::DocumentObject *obj, const bool isSelected) { App::DocumentObject* objCopy = obj; TechDraw::DrawHatch* hatchObj = dynamic_cast(objCopy); @@ -932,39 +934,61 @@ void MDIViewPage::selectFeature(App::DocumentObject *obj, const bool isSelected) blockSelection(false); } -//! invoked by selection change made in Tree? -// wf: seems redundant? executed, but no real logic. +//! invoked by selection change made in Tree via father MDIView +//really "onTreeSelectionChanged" void MDIViewPage::onSelectionChanged(const Gui::SelectionChanges& msg) { + std::vector selObjs = Gui::Selection().getSelection(msg.pDocName); if (msg.Type == Gui::SelectionChanges::ClrSelection) { - - } - else if (msg.Type == Gui::SelectionChanges::AddSelection || - msg.Type == Gui::SelectionChanges::RmvSelection) { - //bool add = (msg.Type == Gui::SelectionChanges::AddSelection); - // Check if it is a view object - std::string feat = msg.pObjectName; - std::string sub = msg.pSubName; - } - else if (msg.Type == Gui::SelectionChanges::SetSelection) { - // do nothing here wf: handled by VPP::onSelectionChanged? + clearSceneSelection(); + } else if(msg.Type == Gui::SelectionChanges::SetSelection) { //replace entire selection set + clearSceneSelection(); + blockSelection(true); + for (auto& so: selObjs){ + if (so.pObject->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { + selectQGIView(so.pObject, true); + } + } + blockSelection(false); + } else { + bool selectState = (msg.Type == Gui::SelectionChanges::AddSelection) ? true : false; + blockSelection(true); + for (auto& so: selObjs){ + if (so.pObject->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { + selectQGIView(so.pObject, selectState); + } + } + blockSelection(false); } } -//! update FC Selection from QGraphicsScene selection +//! update Tree Selection from QGraphicsScene selection //trigged by m_view->scene() signal -void MDIViewPage::selectionChanged() +void MDIViewPage::sceneSelectionChanged() { if(isSelectionBlocked) { - return; + return; } - QList selection = m_view->scene()->selectedItems(); - bool saveBlock = blockConnection(true); // avoid to be notified by itself - blockSelection(true); + std::vector treeSel = Gui::Selection().getSelectionEx(); + QList sceneSel = m_view->scene()->selectedItems(); + //check if really need to change selection + bool sameSel = compareSelections(treeSel,sceneSel); + if (sameSel) { + return; + } + + setTreeToSceneSelect(); +} + +void MDIViewPage::setTreeToSceneSelect(void) +{ + bool saveBlock = blockConnection(true); // block selectionChanged signal from Tree/Observer + blockSelection(true); Gui::Selection().clearSelection(); - for (QList::iterator it = selection.begin(); it != selection.end(); ++it) { + QList sceneSel = m_view->scene()->selectedItems(); + for (QList::iterator it = sceneSel.begin(); it != sceneSel.end(); ++it) { QGIView *itemView = dynamic_cast(*it); if(itemView == 0) { QGIEdge *edge = dynamic_cast(*it); @@ -1056,7 +1080,7 @@ void MDIViewPage::selectionChanged() } const char* name = dimObj->getNameInDocument(); if (!name) { //can happen during undo/redo if Dim is selected??? - //Base::Console().Log("INFO - MDIVP::selectionChanged - dimObj name is null!\n"); + //Base::Console().Log("INFO - MDIVP::sceneSelectionChanged - dimObj name is null!\n"); continue; } @@ -1077,9 +1101,78 @@ void MDIViewPage::selectionChanged() } } - blockConnection(saveBlock); blockSelection(false); -} // end MDIViewPage::selectionChanged() + blockConnection(saveBlock); +} + +bool MDIViewPage::compareSelections(std::vector& treeSel,QList& sceneSel) +{ + bool result = true; + + if (treeSel.empty() && sceneSel.empty()) { + return true; + } else if (treeSel.empty() && !sceneSel.empty()) { + return false; + } else if (!treeSel.empty() && sceneSel.empty()) { + return false; + } + + int treeCount = 0; + int sceneCount = 0; + int subCount = 0; + int ppCount = 0; + std::vector treeNames; + std::vector sceneNames; + + for (auto& tn: treeSel) { + if (tn.getObject()->isDerivedFrom(TechDraw::DrawView::getClassTypeId())) { + int treeSubs = tn.getSubNames().size(); + subCount += treeSubs; + std::string s = tn.getObject()->getNameInDocument(); + treeNames.push_back(s); + } + } + std::sort(treeNames.begin(),treeNames.end()); + treeCount = treeNames.size(); + + for (auto& sn:sceneSel){ + QGIView *itemView = dynamic_cast(sn); + if(itemView == 0) { + QGIPrimPath* pp = dynamic_cast(sn); //count Vertex/Edge/Face + if (pp != nullptr) { + ppCount++; + } + } else { + std::string s = itemView->getViewNameAsString(); + sceneNames.push_back(s); + } + } + std::sort(sceneNames.begin(),sceneNames.end()); + sceneCount = sceneNames.size(); + + //different # of DrawView* vs QGIV* + if (sceneCount != treeCount) { + return false; + } + +// even of counts match, have to check that names in scene == names in tree + auto treePtr = treeNames.begin(); + for (auto& s: sceneNames){ + if (s == (*treePtr)) { + treePtr++; + continue; + } else { + return false; + } + } + + //Objects all match, check subs + if (treeCount != ppCount) { + return false; + } + + return result; +} ///////////////////end Selection Routines ////////////////////// diff --git a/src/Mod/TechDraw/Gui/MDIViewPage.h b/src/Mod/TechDraw/Gui/MDIViewPage.h index 512161538d..4aaa7d30fa 100644 --- a/src/Mod/TechDraw/Gui/MDIViewPage.h +++ b/src/Mod/TechDraw/Gui/MDIViewPage.h @@ -55,11 +55,13 @@ public: MDIViewPage(ViewProviderPage *page, Gui::Document* doc, QWidget* parent = 0); virtual ~MDIViewPage(); - /// Observer message from the Selection + /// Observer message from the Tree Selection mechanism void onSelectionChanged(const Gui::SelectionChanges& msg); void preSelectionChanged(const QPoint &pos); - void selectFeature(App::DocumentObject *obj, bool state); - void clearSelection(); + + /// QGraphicsScene seletion routines + void selectQGIView(App::DocumentObject *obj, bool state); + void clearSceneSelection(); void blockSelection(bool isBlocked); void attachTemplate(TechDraw::DrawTemplate *obj); @@ -100,7 +102,7 @@ public Q_SLOTS: void setRenderer(QAction *action); void viewAll(); void saveSVG(void); - void selectionChanged(); + void sceneSelectionChanged(); protected: void findMissingViews( const std::vector &list, std::vector &missing); @@ -121,6 +123,9 @@ protected: typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection; Connection connectDeletedObject; + bool compareSelections(std::vector& treeSel,QList& sceneSel); + void setTreeToSceneSelect(void); + private: QAction *m_nativeAction; QAction *m_glAction; diff --git a/src/Mod/TechDraw/Gui/QGIView.cpp b/src/Mod/TechDraw/Gui/QGIView.cpp index 994f5b22f4..192652bd35 100644 --- a/src/Mod/TechDraw/Gui/QGIView.cpp +++ b/src/Mod/TechDraw/Gui/QGIView.cpp @@ -60,6 +60,7 @@ #include "QGCustomClip.h" #include "QGIViewClip.h" #include "ViewProviderDrawingView.h" +#include "MDIViewPage.h" #include #include @@ -296,6 +297,11 @@ const char * QGIView::getViewName() const { return viewName.c_str(); } +const std::string QGIView::getViewNameAsString() const +{ + return viewName; +} + TechDraw::DrawView * QGIView::getViewObject() const { @@ -481,6 +487,22 @@ Gui::ViewProvider* QGIView::getViewProvider(App::DocumentObject* obj) return result; } +MDIViewPage* QGIView::getMDIViewPage(void) const +{ + MDIViewPage* result = nullptr; + QGraphicsScene* s = scene(); + QObject* parent = nullptr; + if (s != nullptr) { + parent = s->parent(); + } + if (parent != nullptr) { + MDIViewPage* mdi = dynamic_cast(parent); + if (mdi != nullptr) { + result = mdi; + } + } + return result; +} QColor QGIView::getNormalColor() { diff --git a/src/Mod/TechDraw/Gui/QGIView.h b/src/Mod/TechDraw/Gui/QGIView.h index f319cb07a1..04d8fe799f 100644 --- a/src/Mod/TechDraw/Gui/QGIView.h +++ b/src/Mod/TechDraw/Gui/QGIView.h @@ -46,6 +46,7 @@ class QGCustomBorder; class QGCustomLabel; class QGCustomText; class QGICaption; +class MDIViewPage; class TechDrawGuiExport QGIView : public QGraphicsItemGroup { @@ -61,7 +62,8 @@ public: const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr ) override; - const char * getViewName() const; + const char * getViewName() const; + const std::string getViewNameAsString() const; void setViewFeature(TechDraw::DrawView *obj); TechDraw::DrawView * getViewObject() const; @@ -92,6 +94,7 @@ public: virtual QColor getSelectColor(void); static Gui::ViewProvider* getViewProvider(App::DocumentObject* obj); + MDIViewPage* getMDIViewPage(void) const; protected: QGIView* getQGIVByName(std::string name); diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index 40019cc938..8ed7b67166 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -72,6 +72,7 @@ #include "ViewProviderGeomHatch.h" #include "ViewProviderHatch.h" #include "ViewProviderViewPart.h" +#include "MDIViewPage.h" using namespace TechDrawGui; using namespace TechDrawGeometry; @@ -99,20 +100,7 @@ QGIViewPart::~QGIViewPart() QVariant QGIViewPart::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == ItemSelectedHasChanged && scene()) { - QList items = childItems(); - for(QList::iterator it = items.begin(); it != items.end(); ++it) { - //Highlight the children if this is highlighted!? seems to mess up Face selection? - QGIEdge *edge = dynamic_cast(*it); - QGIVertex *vert = dynamic_cast(*it); - QGIFace *face = dynamic_cast(*it); - if(edge) { - //edge->setHighlighted(isSelected()); - } else if(vert){ - //vert->setHighlighted(isSelected()); - } else if(face){ - //face->setHighlighted(isSelected()); - } - } + //There's nothing special for QGIVP to do when selection changes! } else if(change == ItemSceneChange && scene()) { tidy(); } @@ -334,15 +322,6 @@ void QGIViewPart::updateView(bool update) } else if (update || vp->LineWidth.isTouched() || vp->HiddenWidth.isTouched()) { - QList items = childItems(); - for(QList::iterator it = items.begin(); it != items.end(); ++it) { - QGIEdge *edge = dynamic_cast(*it); - if(edge && edge->getHiddenEdge()) { - edge->setWidth(vp->HiddenWidth.getValue() * lineScaleFactor); - } else if (edge){ - edge->setWidth(vp->LineWidth.getValue() * lineScaleFactor); - } - } draw(); } else { QGIView::draw(); @@ -557,9 +536,14 @@ QGIFace* QGIViewPart::drawFace(TechDrawGeometry::Face* f, int idx) } //! Remove all existing QGIPrimPath items(Vertex,Edge,Face) +//note this triggers scene selectionChanged signal if vertex/edge/face is selected void QGIViewPart::removePrimitives() { QList children = childItems(); + MDIViewPage* mdi = getMDIViewPage(); + if (mdi != nullptr) { + getMDIViewPage()->blockSelection(true); + } for (auto& c:children) { QGIPrimPath* prim = dynamic_cast(c); if (prim) { @@ -568,6 +552,9 @@ void QGIViewPart::removePrimitives() delete prim; } } + if (mdi != nullptr) { + getMDIViewPage()->blockSelection(false); + } } //! Remove all existing QGIDecoration items(SectionLine,SectionMark,...) diff --git a/src/Mod/TechDraw/Gui/QGVPage.cpp b/src/Mod/TechDraw/Gui/QGVPage.cpp index 900b78802f..fc9a170b55 100644 --- a/src/Mod/TechDraw/Gui/QGVPage.cpp +++ b/src/Mod/TechDraw/Gui/QGVPage.cpp @@ -38,10 +38,12 @@ #endif #include +#include #include #include #include #include +#include #include #include diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp index fd5903bc19..ba53fe3818 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.cpp +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.cpp @@ -37,8 +37,6 @@ /// Here the FreeCAD includes sorted by Base,App,Gui...... #include #include -#include -#include #include #include @@ -46,15 +44,9 @@ #include #include -#include -#include #include #include -#include -#include #include -#include - #include "MDIViewPage.h" #include "ViewProviderPage.h" @@ -291,50 +283,6 @@ MDIViewPage* ViewProviderPage::getMDIViewPage() } } -void ViewProviderPage::onSelectionChanged(const Gui::SelectionChanges& msg) -{ - if(!m_mdiView.isNull()) { - if(msg.Type == Gui::SelectionChanges::SetSelection) { - m_mdiView->clearSelection(); - std::vector objs = Gui::Selection().getSelection(msg.pDocName); - - for (std::vector::iterator it = objs.begin(); it != objs.end(); ++it) { - Gui::SelectionSingleton::SelObj selObj = *it; - if(selObj.pObject == getDrawPage()) - continue; - - std::string str = msg.pSubName; - // If it's a subfeature, don't select feature - if (!str.empty()) { - if (TechDraw::DrawUtil::getGeomTypeFromName(str) == "Face" || - TechDraw::DrawUtil::getGeomTypeFromName(str) == "Edge" || - TechDraw::DrawUtil::getGeomTypeFromName(str) == "Vertex") { - // TODO implement me wf: don't think this is ever executed - } - } else { - m_mdiView->selectFeature(selObj.pObject, true); - } - } - } else { - bool selectState = (msg.Type == Gui::SelectionChanges::AddSelection) ? true : false; - Gui::Document* doc = Gui::Application::Instance->getDocument(pcObject->getDocument()); - App::DocumentObject *obj = doc->getDocument()->getObject(msg.pObjectName); - if(obj) { - std::string str = msg.pSubName; - // If it's a subfeature, don't select feature - if (!str.empty()) { - if (TechDraw::DrawUtil::getGeomTypeFromName(str) == "Face" || - TechDraw::DrawUtil::getGeomTypeFromName(str) == "Edge" || - TechDraw::DrawUtil::getGeomTypeFromName(str) == "Vertex") { - // TODO implement me - } else { - m_mdiView->selectFeature(obj, selectState); - } - } - } - } //else (Gui::SelectionChanges::SetPreselect) - } -} void ViewProviderPage::onChanged(const App::Property *prop) { diff --git a/src/Mod/TechDraw/Gui/ViewProviderPage.h b/src/Mod/TechDraw/Gui/ViewProviderPage.h index e12be67fb7..e24f55073a 100644 --- a/src/Mod/TechDraw/Gui/ViewProviderPage.h +++ b/src/Mod/TechDraw/Gui/ViewProviderPage.h @@ -26,9 +26,7 @@ #define DRAWINGGUI_VIEWPROVIDERPAGE_H #include -#include -#include -#include +#include namespace TechDraw{ class DrawPage; @@ -38,8 +36,7 @@ namespace TechDrawGui { class MDIViewPage; -class TechDrawGuiExport ViewProviderPage : public Gui::ViewProviderDocumentObject, - public Gui::SelectionObserver +class TechDrawGuiExport ViewProviderPage : public Gui::ViewProviderDocumentObject { PROPERTY_HEADER(TechDrawGui::ViewProviderPage); @@ -49,10 +46,6 @@ public: /// destructor virtual ~ViewProviderPage(); - //App::PropertyFloat HintScale; - //App::PropertyFloat HintOffsetX; - //App::PropertyFloat HintOffsetY; - virtual void attach(App::DocumentObject *); virtual void setDisplayMode(const char* ModeName); virtual bool useNewSelectionModel(void) const {return false;} @@ -64,8 +57,6 @@ public: virtual void show(void); virtual bool isShow(void) const; - void onSelectionChanged(const Gui::SelectionChanges& msg); - /// Claim all the views for the page std::vector claimChildren(void) const;