Fix #3367: view/data pane is unselected

- error in coordination of Tree & QGraphicsScene
  selection logic caused Feature to become
  unselected during update.
This commit is contained in:
wandererfan
2018-03-17 11:06:33 -04:00
committed by wmayer
parent 91a0aff25f
commit 2d4865bb11
8 changed files with 170 additions and 119 deletions

View File

@@ -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<QGIView *> 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<TechDraw::DrawHatch*>(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<Gui::SelectionSingleton::SelObj> 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<QGraphicsItem*> selection = m_view->scene()->selectedItems();
bool saveBlock = blockConnection(true); // avoid to be notified by itself
blockSelection(true);
std::vector<Gui::SelectionObject> treeSel = Gui::Selection().getSelectionEx();
QList<QGraphicsItem*> 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<QGraphicsItem*>::iterator it = selection.begin(); it != selection.end(); ++it) {
QList<QGraphicsItem*> sceneSel = m_view->scene()->selectedItems();
for (QList<QGraphicsItem*>::iterator it = sceneSel.begin(); it != sceneSel.end(); ++it) {
QGIView *itemView = dynamic_cast<QGIView *>(*it);
if(itemView == 0) {
QGIEdge *edge = dynamic_cast<QGIEdge *>(*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<Gui::SelectionObject>& treeSel,QList<QGraphicsItem*>& 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<std::string> treeNames;
std::vector<std::string> 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<QGIView *>(sn);
if(itemView == 0) {
QGIPrimPath* pp = dynamic_cast<QGIPrimPath*>(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 //////////////////////