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 <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
Gerald Combs 2015-11-10 10:12:56 -08:00
parent 8930b0d5e0
commit 757fe65474
3 changed files with 75 additions and 14 deletions

View File

@ -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<QAction *> freeze_actions = QList<QAction *>()
<< 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<QAction *, bool>(action, false);
}
}
// Titlebar
void MainWindow::setTitlebarForCaptureFile()
{

View File

@ -140,6 +140,8 @@ private:
QActionGroup *time_display_actions_;
QActionGroup *time_precision_actions_;
FunnelStatistics *funnel_statistics_;
QList<QPair<QAction *, bool> > 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();

View File

@ -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()