[TD]fix segfault on repeated open/close

[TD]fix memory leak in ViewProviderPage

[TD]fix QGView redraws at idle
This commit is contained in:
Wanderer Fan
2022-07-24 14:16:40 -04:00
committed by WandererFan
parent 80d5e9a0b8
commit 2c047e361d
5 changed files with 22 additions and 28 deletions

View File

@@ -153,6 +153,7 @@ void MDIViewPage::setScene(QGSPage* scene, QGVPage* viewWidget)
void MDIViewPage::setDocumentObject(const std::string& name)
{
m_objectName = name;
setObjectName(Base::Tools::fromStdString(name));
}
void MDIViewPage::setDocumentName(const std::string& name)
@@ -162,6 +163,7 @@ void MDIViewPage::setDocumentName(const std::string& name)
void MDIViewPage::closeEvent(QCloseEvent* ev)
{
// Base::Console().Message("MDIVP::closeEvent()\n");
MDIView::closeEvent(ev);
if (!ev->isAccepted())
return;

View File

@@ -91,6 +91,7 @@ public:
void setDocumentObject(const std::string&);
void setDocumentName(const std::string&);
PyObject* getPyObject() override;
TechDraw::DrawPage * getPage() { return m_vpPage->getDrawPage(); }
@@ -138,11 +139,11 @@ private:
std::string m_objectName;
std::string m_documentName;
bool isSelectionBlocked;
QGSPage* m_scene;
QGVPage *m_view;
QPointer<QGSPage> m_scene;
QPointer<QGVPage> m_view;
QString m_currentPath;
ViewProviderPage *m_vpPage;
ViewProviderPage* m_vpPage;
QList<QGraphicsItem*> m_qgSceneSelected; //items in selection order

View File

@@ -134,6 +134,8 @@ QGSPage::QGSPage(ViewProviderPage *vp, QWidget *parent)
{
assert(vp);
m_vpPage = vp;
setItemIndexMethod(QGraphicsScene::BspTreeIndex); //the default
// setItemIndexMethod(QGraphicsScene::NoIndex); //sometimes faster
}
QGSPage::~QGSPage()

View File

@@ -251,11 +251,10 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGSPage* s, QWidget *parent)
m_parentMDI = static_cast<MDIViewPage*>(parent);
m_saveContextEvent = nullptr;
setViewportUpdateMode(QGraphicsView::FullViewportUpdate); //this prevents crash when deleting dims.
//scene(view?) indices of dirty regions gets
//out of sync. missing prepareGeometryChange
//somewhere???? QTBUG-18021????
setCacheMode(QGraphicsView::CacheBackground);
setRenderer(Native);
// setRenderer(OpenGL); //gives rotten quality, don't use this
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
d->init();
if (m_atCursor) {
@@ -270,8 +269,6 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGSPage* s, QWidget *parent)
// setDragMode(ScrollHandDrag);
setDragMode(QGraphicsView::NoDrag);
resetCursor();
setRenderer(Native);
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
bkgBrush = new QBrush(getBackgroundColor());
@@ -279,8 +276,6 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGSPage* s, QWidget *parent)
balloonCursor->setPixmap(prepareCursorPixmap("TechDraw_Balloon.svg", balloonHotspot = QPoint(8, 59)));
balloonCursor->hide();
resetCachedContent();
initNavigationStyle();
createStandardCursors(devicePixelRatio());
@@ -294,8 +289,7 @@ QGVPage::~QGVPage()
void QGVPage::centerOnPage(void)
{
// Base::Console().Message("QGVP::centerOnPage()\n");
centerOn(m_scene->getTemplateCenter());
centerOn(m_vpPage->getGraphicsScene()->getTemplateCenter());
}
void QGVPage::initNavigationStyle()
@@ -382,8 +376,6 @@ void QGVPage::drawBackground(QPainter *p, const QRectF &)
p->save();
p->resetTransform();
resetCachedContent();
p->setBrush(*bkgBrush);
p->drawRect(viewport()->rect().adjusted(-2,-2,2,2)); //just bigger than viewport to prevent artifacts
@@ -405,7 +397,6 @@ void QGVPage::drawBackground(QPainter *p, const QRectF &)
p->setBrush(pageBrush);
p->drawRect(poly.boundingRect());
resetCachedContent();
p->restore();
}
@@ -416,10 +407,13 @@ void QGVPage::setRenderer(RendererType type)
if (m_renderer == OpenGL) {
#ifndef QT_NO_OPENGL
setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
// setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); //QGLWidget is obsolete
setViewport(new QOpenGLWidget);
setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
#endif
} else {
setViewport(new QWidget);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
}

View File

@@ -103,6 +103,7 @@ ViewProviderPage::ViewProviderPage()
ViewProviderPage::~ViewProviderPage()
{
removeMDIView(); //if the MDIViewPage is still in MainWindow, remove it.
m_graphicsScene->deleteLater();
}
void ViewProviderPage::attach(App::DocumentObject *pcFeat)
@@ -269,14 +270,12 @@ bool ViewProviderPage::doubleClicked(void)
void ViewProviderPage::show(void)
{
// Base::Console().Message("VPP::show()\n");
showMDIViewPage();
ViewProviderDocumentObject::show();
}
void ViewProviderPage::hide(void)
{
// Base::Console().Message("VPP::hide()\n");
if (getMDIView()) {
getMDIView()->hide(); //this doesn't remove the mdiViewPage from the mainWindow
removeMDIView();
@@ -303,12 +302,13 @@ bool ViewProviderPage::showMDIViewPage()
setGrid();
Visibility.setValue(true);
return true;
}
void ViewProviderPage::createMDIViewPage()
{
// Base::Console().Message("VPP::createMDIViewPage()\n");
Gui::Document* doc = Gui::Application::Instance->getDocument
(pcObject->getDocument());
m_mdiView = new MDIViewPage(this, doc, Gui::getMainWindow());
@@ -318,7 +318,6 @@ void ViewProviderPage::createMDIViewPage()
m_graphicsView->setObjectName(QString::fromLocal8Bit(objName.c_str()));
}
m_mdiView->setScene(m_graphicsScene, m_graphicsView);
m_graphicsScene->setParent(m_graphicsView); //for QObjectParent. required??
QString tabTitle = QString::fromUtf8(getDrawPage()->Label.getValue());
m_mdiView->setDocumentObject(getDrawPage()->getNameInDocument());
@@ -330,20 +329,16 @@ void ViewProviderPage::createMDIViewPage()
Gui::getMainWindow()->setActiveWindow(m_mdiView);
}
//NOTE: removing MDIViewPage (parent) destroys QGVPage which will
//delete QGSPage if still parented to QGVPage
//NOTE: removing MDIViewPage (parent) destroys QGVPage (eventually)
void ViewProviderPage::removeMDIView(void)
{
// Base::Console().Message("VPP::removeMDIViewPage()\n");
if (!m_mdiView.isNull()) { //m_mdiView is a QPointer
// https://forum.freecadweb.org/viewtopic.php?f=3&t=22797&p=182614#p182614
//Gui::getMainWindow()->activatePreviousWindow();
QList<QWidget*> wList= Gui::getMainWindow()->windows();
bool found = wList.contains(m_mdiView);
if (found) {
m_graphicsScene->setParent(nullptr);
Gui::getMainWindow()->removeWindow(m_mdiView);
m_graphicsView = nullptr; //m_graphicsView has been deleted by m_mdiView
m_mdiView = nullptr; //m_mdiView will eventually be deleted and
m_graphicsView = nullptr; //will take m_graphicsView with it
Gui::MDIView* aw = Gui::getMainWindow()->activeWindow(); //WF: this bit should be in the remove window logic, not here.
if (aw != nullptr) {
aw->showMaximized();