From 8b1e76ed0bf6b290912d8f86aa7c93d12ed7e845 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 23 Sep 2017 13:17:26 +0200 Subject: [PATCH] Bugfix: XOR was segfaulting when the window was closed during run This fix consists of multiple parts: * Actual closing of the window is deferred until excecution is over * weak pointers in XOR for view so the view can be destroyed with out not knowing * The "keep data" message is not shown when the application window was closed. --- src/ext/ext/extXORProgress.cc | 4 +-- src/ext/ext/extXORToolDialog.cc | 39 +++++++++++++++--------- src/ext/ext/extXORToolDialog.h | 4 ++- src/lay/lay/layMainWindow.cc | 54 +++++++++++++++++++-------------- src/lay/lay/layMainWindow.h | 2 ++ 5 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/ext/ext/extXORProgress.cc b/src/ext/ext/extXORProgress.cc index 91d697725..daaccc1de 100644 --- a/src/ext/ext/extXORProgress.cc +++ b/src/ext/ext/extXORProgress.cc @@ -117,7 +117,7 @@ public: { int w = int (m_tolerance_labels.size ()) * (m_column_width + m_spacing) + m_first_column_width; int col = std::max (1, width () / w); - return QSize (w * col, (m_line_height + m_spacing) * ((int (m_layer_labels.size ()) + col - 1) / col) + m_font_height * 2 + m_spacing); + return QSize (w * std::min (int (m_layer_labels.size ()), col), (m_line_height + m_spacing) * ((int (m_layer_labels.size ()) + col - 1) / col) + m_font_height * 2 + m_spacing); } void set_results (double dbu, int nx, int ny, const std::map, std::vector > > &results, const std::map &count_per_layer, const std::vector &tolerances) @@ -261,7 +261,7 @@ public: bool ellipsis = false; int visible_lines = std::max (1, (height () - m_font_height * 2 - m_spacing) / (m_line_height + m_spacing)); - int columns = std::max (1, width () / std::max (1, szh.width ())); + int columns = std::min (std::max (1, width () / std::max (1, szh.width ())), int (m_layer_labels.size ())); int x0 = std::max (0, (width () - szh.width () * columns) / 2); int visible_columns = std::max (0, (width () - m_first_column_width + 20) / (m_column_width + m_spacing)); diff --git a/src/ext/ext/extXORToolDialog.cc b/src/ext/ext/extXORToolDialog.cc index 9d561b857..a41558c61 100644 --- a/src/ext/ext/extXORToolDialog.cc +++ b/src/ext/ext/extXORToolDialog.cc @@ -37,6 +37,7 @@ #include "layCellView.h" #include "layLayoutView.h" #include "layApplication.h" +#include "layMainWindow.h" #include "ui_XORToolDialog.h" @@ -1371,7 +1372,7 @@ XORToolDialog::run_xor () } if (job.has_error ()) { - if (output_mode == OMMarkerDatabase) { + if (mp_view && output_mode == OMMarkerDatabase) { mp_view->remove_rdb (rdb_index); } throw tl::Exception (tl::to_string (QObject::tr ("Errors occured during processing. First error message says:\n")) + job.error_messages ().front ()); @@ -1382,26 +1383,34 @@ XORToolDialog::run_xor () if (was_cancelled && output_mode == OMMarkerDatabase) { // If the output mode is database, ask whether to keep the data collected so far. // If the answer is yes, remove the RDB. - QMessageBox msgbox (QMessageBox::Question, - QObject::tr ("Keep Data For Cancelled Job"), - QObject::tr ("The job has been cancelled. Keep the data collected so far?"), - QMessageBox::Yes | QMessageBox::No); - if (msgbox.exec () == QMessageBox::No) { - mp_view->remove_rdb (rdb_index); - output_mode = OMNone; - } + // Don't ask if the application has exit (window was closed) + if (lay::Application::instance ()->main_window () && !lay::Application::instance ()->main_window ()->exited ()) { + QMessageBox msgbox (QMessageBox::Question, + QObject::tr ("Keep Data For Cancelled Job"), + QObject::tr ("The job has been cancelled. Keep the data collected so far?"), + QMessageBox::Yes | QMessageBox::No); + if (msgbox.exec () == QMessageBox::No) { + if (mp_view) { + mp_view->remove_rdb (rdb_index); + } + output_mode = OMNone; + } + } } } - if (output_mode == OMMarkerDatabase) { - mp_view->open_rdb_browser (rdb_index, cv_index_a); - } + if (mp_view) { - mp_view->update_content (); + if (output_mode == OMMarkerDatabase) { + mp_view->open_rdb_browser (rdb_index, cv_index_a); + } - if (output_mode == OMNewLayout && output_cell != 0 && output_cv >= 0) { - mp_view->select_cell (output_cell->cell_index (), output_cv); + mp_view->update_content (); + + if (output_mode == OMNewLayout && output_cell != 0 && output_cv >= 0) { + mp_view->select_cell (output_cell->cell_index (), output_cv); + } } } diff --git a/src/ext/ext/extXORToolDialog.h b/src/ext/ext/extXORToolDialog.h index bd68de7f1..0286e0f73 100644 --- a/src/ext/ext/extXORToolDialog.h +++ b/src/ext/ext/extXORToolDialog.h @@ -25,6 +25,8 @@ #include +#include "tlObject.h" + namespace Ui { class XORToolDialog; @@ -71,7 +73,7 @@ protected slots: private: Ui::XORToolDialog *mp_ui; - lay::LayoutView *mp_view; + tl::weak_ptr mp_view; }; } diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 2f1ba3221..d3420c569 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -48,7 +48,6 @@ #include "tlTimer.h" #include "tlLog.h" #include "tlAssert.h" -#include "tlDeferredExecution.h" #include "tlStream.h" #include "tlExceptions.h" #include "dbMemStatistics.h" @@ -451,7 +450,8 @@ MainWindow::MainWindow (QApplication *app, const char *name) m_disable_tab_selected (false), m_exited (false), dm_do_update_menu (this, &MainWindow::do_update_menu), - m_grid_micron (0.001), + dm_exit (this, &MainWindow::exit), + m_grid_micron (0.001), m_default_grids_updated (true), m_new_cell_window_size (2.0), m_new_layout_current_panel (false), @@ -691,7 +691,7 @@ MainWindow::MainWindow (QApplication *app, const char *name) connect (&m_file_changed_timer, SIGNAL (timeout ()), this, SLOT (file_changed_timer())); m_file_changed_timer.setSingleShot (true); - // install timer for menu update + // install timer for menu update a connect (&m_menu_update_timer, SIGNAL (timeout ()), this, SLOT (update_action_states ())); m_menu_update_timer.setSingleShot (false); m_menu_update_timer.start (200); @@ -1837,8 +1837,30 @@ void MainWindow::exit () { m_exited = true; - do_close (); - QMainWindow::close (); + + // If there is a operation ongoing, request a break and delay execution of the exit operation. + if (mp_pr && mp_pr->is_busy ()) { + mp_pr->signal_break (); + dm_exit (); + return; + } + + // We also don't exit if a dialog is shown (deferred execution may be called from + // the dialog's exec loop). + if (QApplication::activeModalWidget ()) { + dm_exit (); + return; + } + + // Only after other operation has finished we ask whether to save and close eventually + if (can_close ()) { + + do_close (); + QMainWindow::close (); + + emit closed (); + + } } int @@ -1950,23 +1972,12 @@ void MainWindow::closeEvent (QCloseEvent *event) { if (! m_exited) { - BEGIN_PROTECTED - - if (mp_pr) { - mp_pr->signal_break (); - } - - if (! can_close ()) { - event->ignore (); - } else { - do_close (); - emit closed (); - } - + exit (); END_PROTECTED - } + + event->ignore (); } void @@ -2074,10 +2085,7 @@ void MainWindow::cm_exit () { BEGIN_PROTECTED - if (can_close ()) { - // actually exit. - exit (); - } + exit (); END_PROTECTED } diff --git a/src/lay/lay/layMainWindow.h b/src/lay/lay/layMainWindow.h index 666abd0c4..ff80d0cfb 100644 --- a/src/lay/lay/layMainWindow.h +++ b/src/lay/lay/layMainWindow.h @@ -49,6 +49,7 @@ #include "tlException.h" #include "tlDeferredExecution.h" #include "tlObjectCollection.h" +#include "tlDeferredExecution.h" #include "gsi.h" class QTabBar; @@ -910,6 +911,7 @@ private: bool m_disable_tab_selected; bool m_exited; tl::DeferredMethod dm_do_update_menu; + tl::DeferredMethod dm_exit; QTimer m_message_timer; QTimer m_file_changed_timer; QTimer m_menu_update_timer;