From 757fe65474a37d94e7eba1b6b4bb6df23b69ba56 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Tue, 10 Nov 2015 10:12:56 -0800 Subject: [PATCH] Qt: Freeze+thaw the main window during nested operations. As noted in main_window.cpp: // Our event loop becomes nested whenever we call update_progress_dlg, which // includes several places in file.c. The GTK+ UI stays out of trouble by // showing a modal progress dialog. We attempt to do the equivalent below by // disabling parts of the main window. At a minumum the ProgressFrame in the // main status bar must remain accessible. Move the freeze+thaw code from captureFileRetapStarted and captureFileRetapFinished to its own set of member functions. Call them when we {,un}mark and {,un}ignore packets and note that we should probably call them elsewhere. Disable mark and ignore actions when we freeze and restore their states when we thaw. Bug: 11681 Change-Id: I6f015f7f5f6c98cd48ace2c87f43f48efe51a88b Reviewed-on: https://code.wireshark.org/review/11690 Petri-Dish: Gerald Combs Tested-by: Petri Dish Buildbot Reviewed-by: Gerald Combs --- ui/qt/main_window.cpp | 55 +++++++++++++++++++++++++++++++++++++ ui/qt/main_window.h | 6 ++++ ui/qt/main_window_slots.cpp | 28 +++++++++---------- 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index d5ac92767f..e39a7acbcb 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -223,6 +223,7 @@ MainWindow::MainWindow(QWidget *parent) : time_display_actions_(NULL), time_precision_actions_(NULL), funnel_statistics_(new FunnelStatistics(this, capture_file_)), + freeze_focus_(NULL), capture_stopping_(false), capture_filter_valid_(false), #ifdef _WIN32 @@ -375,6 +376,7 @@ MainWindow::MainWindow(QWidget *parent) : initShowHideMainWidgets(); initTimeDisplayFormatMenu(); initTimePrecisionFormatMenu(); + initFreezeActions(); updatePreferenceActions(); setForCaptureInProgress(false); @@ -846,6 +848,38 @@ QWidget* MainWindow::getLayoutWidget(layout_pane_content_e type) { } } +// Our event loop becomes nested whenever we call update_progress_dlg, which +// includes several places in file.c. The GTK+ UI stays out of trouble by +// showing a modal progress dialog. We attempt to do the equivalent below by +// disabling parts of the main window. At a minumum the ProgressFrame in the +// main status bar must remain accessible. +// +// We might want to do this any time the main status bar progress frame is +// shown and hidden. +void MainWindow::freeze() +{ + freeze_focus_ = wsApp->focusWidget(); + + // XXX Alternatively we could just disable and enable the main menu. + for (int i = 0; i < freeze_actions_.size(); i++) { + QAction *action = freeze_actions_[i].first; + freeze_actions_[i].second = action->isEnabled(); + action->setEnabled(false); + } + main_ui_->centralWidget->setEnabled(false); +} + +void MainWindow::thaw() +{ + main_ui_->centralWidget->setEnabled(true); + for (int i = 0; i < freeze_actions_.size(); i++) { + freeze_actions_[i].first->setEnabled(freeze_actions_[i].second); + } + + if (freeze_focus_) freeze_focus_->setFocus(); + freeze_focus_ = NULL; +} + void MainWindow::mergeCaptureFile() { QString file_name = ""; @@ -1764,6 +1798,27 @@ void MainWindow::initTimePrecisionFormatMenu() connect(time_precision_actions_, SIGNAL(triggered(QAction*)), this, SLOT(setTimestampPrecision(QAction*))); } +// Menu items which will be disabled when we freeze() and whose state will +// be restored when we thaw(). Add to the list as needed. +void MainWindow::initFreezeActions() +{ + QList freeze_actions = QList() + << main_ui_->actionFileClose + << main_ui_->actionViewReload + << main_ui_->actionEditMarkPacket + << main_ui_->actionEditMarkAllDisplayed + << main_ui_->actionEditUnmarkAllDisplayed + << main_ui_->actionEditIgnorePacket + << main_ui_->actionEditIgnoreAllDisplayed + << main_ui_->actionEditUnignoreAllDisplayed + << main_ui_->actionEditSetTimeReference + << main_ui_->actionEditUnsetAllTimeReferences; + + foreach (QAction *action, freeze_actions) { + freeze_actions_ << QPair(action, false); + } +} + // Titlebar void MainWindow::setTitlebarForCaptureFile() { diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 2fbf527c73..9c0a161247 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -140,6 +140,8 @@ private: QActionGroup *time_display_actions_; QActionGroup *time_precision_actions_; FunnelStatistics *funnel_statistics_; + QList > freeze_actions_; + QWidget *freeze_focus_; bool capture_stopping_; bool capture_filter_valid_; @@ -161,6 +163,9 @@ private: QWidget* getLayoutWidget(layout_pane_content_e type); + void freeze(); + void thaw(); + void mergeCaptureFile(); void importCaptureFile(); void saveCaptureFile(capture_file *cf, bool dont_reopen); @@ -176,6 +181,7 @@ private: void initShowHideMainWidgets(); void initTimeDisplayFormatMenu(); void initTimePrecisionFormatMenu(); + void initFreezeActions(); void setTitlebarForSelectedTreeRow(); void setTitlebarForCaptureFile(); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index d4867b8050..ede235c2ba 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -684,27 +684,15 @@ void MainWindow::captureFileReadFinished() { emit setDissectedCaptureFile(capture_file_.capFile()); } -// Our event loop becomes nested whenever we call update_progress_dlg, which -// includes several places in file.c. The GTK+ UI stays out of trouble by -// showing a modal progress dialog. We attempt to do the equivalent below by -// disabling parts of the main window. At a minumum the ProgressFrame in the -// main status bar must remain accessible. -// -// We might want to do this any time the main status bar progress frame is -// shown and hidden. void MainWindow::captureFileRetapStarted() { // XXX Push a status message? - main_ui_->actionFileClose->setEnabled(false); - main_ui_->actionViewReload->setEnabled(false); - main_ui_->centralWidget->setEnabled(false); + freeze(); } void MainWindow::captureFileRetapFinished() { - main_ui_->actionFileClose->setEnabled(true); - main_ui_->actionViewReload->setEnabled(true); - main_ui_->centralWidget->setEnabled(true); + thaw(); } void MainWindow::captureFileClosing() { @@ -1902,17 +1890,23 @@ void MainWindow::on_actionEditFindPrevious_triggered() void MainWindow::on_actionEditMarkPacket_triggered() { + freeze(); packet_list_->markFrame(); + thaw(); } void MainWindow::on_actionEditMarkAllDisplayed_triggered() { + freeze(); packet_list_->markAllDisplayedFrames(true); + thaw(); } void MainWindow::on_actionEditUnmarkAllDisplayed_triggered() { + freeze(); packet_list_->markAllDisplayedFrames(false); + thaw(); } void MainWindow::on_actionEditNextMark_triggered() @@ -1929,17 +1923,23 @@ void MainWindow::on_actionEditPreviousMark_triggered() void MainWindow::on_actionEditIgnorePacket_triggered() { + freeze(); packet_list_->ignoreFrame(); + thaw(); } void MainWindow::on_actionEditIgnoreAllDisplayed_triggered() { + freeze(); packet_list_->ignoreAllDisplayedFrames(true); + thaw(); } void MainWindow::on_actionEditUnignoreAllDisplayed_triggered() { + freeze(); packet_list_->ignoreAllDisplayedFrames(false); + thaw(); } void MainWindow::on_actionEditSetTimeReference_triggered()