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.
This commit is contained in:
Matthias Koefferlein 2017-09-23 13:17:26 +02:00
parent f1cfe207ff
commit 8b1e76ed0b
5 changed files with 62 additions and 41 deletions

View File

@ -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::pair<db::LayerProperties, db::Coord>, std::vector<std::vector<size_t> > > &results, const std::map<db::LayerProperties, size_t> &count_per_layer, const std::vector<db::Coord> &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));

View File

@ -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);
}
}
}

View File

@ -25,6 +25,8 @@
#include <QDialog>
#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<lay::LayoutView> mp_view;
};
}

View File

@ -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
}

View File

@ -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<MainWindow> dm_do_update_menu;
tl::DeferredMethod<MainWindow> dm_exit;
QTimer m_message_timer;
QTimer m_file_changed_timer;
QTimer m_menu_update_timer;