Delete DPGI's when parent DPG deleted

Ensure Gui/QGIVxx is removed when App/DVxxxx is deleted
This commit is contained in:
WandererFan
2017-01-07 11:12:17 -05:00
parent 221f80e344
commit d6419b5a7e
11 changed files with 172 additions and 61 deletions

View File

@@ -38,6 +38,9 @@
#include <QPrinter>
#include <QPrintDialog>
#include <QPrintPreviewDialog>
#include <boost/signal.hpp>
#include <boost/bind.hpp>
#endif // #ifndef _PreComp_
#include <math.h>
@@ -146,6 +149,12 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget*
m_view->scene(), SIGNAL(selectionChanged()),
this , SLOT (selectionChanged())
);
//get informed by App side about deleted DocumentObjects
App::Document* appDoc = m_vpPage->getDocument()->getDocument();
auto bnd = boost::bind(&MDIViewPage::onDeleteObject, this, _1);
connectDeletedObject = appDoc->signalDeletedObject.connect(bnd);
// A fresh page is added and we iterate through its collected children and add these to Canvas View -MLP
// if docobj is a featureviewcollection (ex orthogroup), add its child views. if there are ever children that have children,
@@ -181,6 +190,7 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget*
MDIViewPage::~MDIViewPage()
{
connectDeletedObject.disconnect();
}
@@ -323,7 +333,18 @@ void MDIViewPage::removeView(QGIView *view)
(void) m_view->removeView(view);
}
void MDIViewPage::onDeleteObject(const App::DocumentObject& obj)
{
if (obj.isDerivedFrom(TechDraw::DrawView::getClassTypeId())) {
const App::DocumentObject* objPtr = &obj;
const TechDraw::DrawView* dv = static_cast<const TechDraw::DrawView*>(objPtr);
TechDraw::DrawPage* dvPg = dv->findParentPage();
if (dvPg == m_vpPage->getDrawPage()) {
//this is a DV that is on our page
(void) m_view->removeView(dv);
}
}
}
void MDIViewPage::updateTemplate(bool forceUpdate)
{
@@ -353,10 +374,19 @@ void MDIViewPage::updateTemplate(bool forceUpdate)
void MDIViewPage::updateDrawing(bool forceUpdate)
{
// We cannot guarantee if the number of graphical representations (QGIVxxxx) have changed so check the number (MLP)
// We cannot guarantee if the number of graphical representations (QGIVxxxx) have changed so check the number (MLP)
// WF: this should be fixed now with onDeletedObject signal from App side?
// WF: the QGVP views list may still not be 100% reliable
// TODO: build list of QGIV's from scene everytime?
//logging counters
int qgvpIn = 0;
int qgvpValid = 0;
int qgvpClean = 0;
int dpIn = 0;
const std::vector<QGIView *> &graphicsList = m_view->getViews();
qgvpIn = graphicsList.size();
const std::vector<App::DocumentObject*> &pageChildren = m_vpPage->getDrawPage()->Views.getValues();
// Count total # DocumentObjects in Page
unsigned int docObjCount = 0;
for(std::vector<App::DocumentObject*>::const_iterator it = pageChildren.begin(); it != pageChildren.end(); ++it) {
@@ -367,7 +397,12 @@ void MDIViewPage::updateDrawing(bool forceUpdate)
}
docObjCount += 1;
}
dpIn = docObjCount;
//TODO: should prune QGVP.views first always, then check if view in Page missing QGIVP
// this makes assumption that = numbers mean everythign is OK, but could be double failure - 1 extra QGIV, 1 DV missing graphics!
if(graphicsList.size() < docObjCount) {
// there are more DocumentObjects than graphical representations (QGIVxxxx's)
// Find which DocumentObjects have no graphical representation (QGIVxxxx)
@@ -379,31 +414,50 @@ void MDIViewPage::updateDrawing(bool forceUpdate)
attachView(*it);
}
} else if(graphicsList.size() > docObjCount) {
// There are more graphical representations (QGIVxxxx) than DocumentObjects
// Remove the orphans
std::vector<QGIView *>::const_iterator itGraphics = graphicsList.begin();
// prune any invalid entries in QGVP.views
// TODO: revisit this mess. is it still required with onDeletedItem signal implementation?
std::vector<QGIView *> newGraphicsList;
bool fnd = false;
while(itGraphics != graphicsList.end()) {
fnd = orphanExists((*itGraphics)->getViewName(), pageChildren);
if(fnd) {
newGraphicsList.push_back(*itGraphics);
} else {
if (m_view->scene() == (*itGraphics)->scene()) {
(*itGraphics)->hide();
m_view->scene()->removeItem(*itGraphics);
} else { // this "shouldn't" happen, but it does
Base::Console().Log("ERROR - MDIViewPage::updateDrawing - %s already removed from QGraphicsScene\n",
(*itGraphics)->getViewName());
QList<QGraphicsItem *> items = m_view->scene()->items();
for (auto& v: graphicsList) { //check that everything in QGVP views is valid
for (auto& i:items) {
if (v == i) { //this one is OK
newGraphicsList.push_back(v);
break;
}
}
itGraphics++;
}
// Update the QGVPage (QGraphicsView) list of QGIVxxxx
m_view->setViews(newGraphicsList);
qgvpValid = newGraphicsList.size();
//newGraphicsList now only contains valid QGIV's
//now prune the ones without docObjs
std::vector<QGIView *> cleanItems;
for (auto& i: newGraphicsList) {
std::string viewName = (i->data(1).toString()).toStdString();
App::DocumentObject* dObj = getAppDocument()->getObject(viewName.c_str());
if (dObj == nullptr) {
//need to remove from group/scene
QGraphicsItemGroup* grp = i->group();
if (grp) {
grp->removeFromGroup(i);
}
if (i->parentItem()) { //not top level
i->setParentItem(0);
}
if (i->scene()) {
i->scene()->removeItem(i);
}
//should delete i too to prevent leak? might be garbage pointer, though.
//add to delete list and delete outside of loop
} else {
QGIView* v = static_cast<QGIView*>(i);
cleanItems.push_back(v);
}
}
qgvpClean = cleanItems.size();
m_view->setViews(cleanItems);
Base::Console().Message("Log - MDIVP::updateDrawing pruning: docObjs: %d views in: %d valid views: %d views out: %d\n",
dpIn,qgvpIn,qgvpValid, qgvpClean);
}
// Update all the QGIVxxxx
const std::vector<QGIView *> &upviews = m_view->getViews();
for(std::vector<QGIView *>::const_iterator it = upviews.begin(); it != upviews.end(); ++it) {