diff --git a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp index eaf4d5766..eda285ba2 100644 --- a/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp +++ b/retroshare-gui/src/gui/statistics/GxsTransportStatistics.cpp @@ -457,8 +457,8 @@ void GxsTransportStatistics::loadGroups() { mStateHelper->setLoading(GXSTRANS_GROUP_META, true); - // FIX: Use a QPointer to track 'this'. Since the window can now be closed via - // the Escape key, we must ensure the object still exists before updating it. + // Use a QPointer to safely track 'this'. Even if the window is static, + // this prevents crashes if the instance is ever released during async execution. QPointer self(this); RsThread::async([self]() @@ -478,7 +478,6 @@ void GxsTransportStatistics::loadGroups() return; } - // Only proceed if the widget hasn't been destroyed by the user if (self) { RsQThreadUtils::postToObject( [stats, self]() @@ -487,8 +486,6 @@ void GxsTransportStatistics::loadGroups() * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ - // Final safety check: ensure the object wasn't deleted while - // waiting for the GUI thread event loop. if (self) { // TODO: consider making mGroupStats an unique_ptr to avoid copying @@ -502,7 +499,7 @@ void GxsTransportStatistics::loadGroups() } else { - // Clean up memory if the window was closed during background processing + // Clean up memory if the object was somehow released delete stats; } }); diff --git a/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp b/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp index d72df73e7..a277ddb90 100644 --- a/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp +++ b/retroshare-gui/src/gui/statistics/StatisticsWindow.cpp @@ -98,26 +98,24 @@ void StatisticsWindow::releaseInstance() /********************************************** STATIC WINDOW *************************************/ - StatisticsWindow::StatisticsWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::StatisticsWindow) { ui->setupUi(this); - /* Automatically destroy the object when the window is closed */ - setAttribute(Qt::WA_DeleteOnClose); - Settings->loadWidgetInformation(this); + // Ensure the window is NOT destroyed on close to preserve temporal curves + // and avoid async race conditions. + this->setAttribute(Qt::WA_DeleteOnClose, false); + initStackedPage(); connect(ui->stackPages, SIGNAL(currentChanged(int)), this, SLOT(setNewPage(int))); ui->stackPages->setCurrentIndex(0); - int toolSize = Settings->getToolButtonSize(); ui->toolBar->setToolButtonStyle(Settings->getToolButtonStyle()); ui->toolBar->setIconSize(QSize(toolSize,toolSize)); - setWindowTitle("RetroShare Statistics - " + MainWindow::getInstance()->get_nameAndLocation()); } @@ -243,10 +241,10 @@ void StatisticsWindow::setNewPage(int page) void StatisticsWindow::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { - /* This will trigger the closeEvent and, thanks to WA_DeleteOnClose, the destructor */ - close(); + // Just call close(), which will hide the window without destroying + // the static instance or resetting statistics data. + this->close(); } else { - /* Pass the event to the base class for default handling */ QMainWindow::keyPressEvent(event); } }