summaryrefslogtreecommitdiffstats
path: root/ui/qt/progress_frame.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /ui/qt/progress_frame.cpp
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ui/qt/progress_frame.cpp')
-rw-r--r--ui/qt/progress_frame.cpp323
1 files changed, 323 insertions, 0 deletions
diff --git a/ui/qt/progress_frame.cpp b/ui/qt/progress_frame.cpp
new file mode 100644
index 0000000..2e40ac8
--- /dev/null
+++ b/ui/qt/progress_frame.cpp
@@ -0,0 +1,323 @@
+/* progress_frame.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include "progress_frame.h"
+#include <ui_progress_frame.h>
+
+#include "ui/progress_dlg.h"
+
+#include <QDialogButtonBox>
+#include <QGraphicsOpacityEffect>
+#include <QBoxLayout>
+#include <QPropertyAnimation>
+
+#include <ui/qt/widgets/stock_icon_tool_button.h>
+#include "main_application.h"
+
+// To do:
+// - Add an NSProgressIndicator to the dock icon on macOS.
+// - Start adding the progress bar to dialogs.
+// - Don't complain so loudly when the user stops a capture.
+
+progdlg_t *
+create_progress_dlg(gpointer top_level_window, const gchar *task_title, const gchar *item_title,
+ gboolean terminate_is_stop, gboolean *stop_flag) {
+ ProgressFrame *pf;
+ QWidget *main_window;
+
+ if (!top_level_window) {
+ return nullptr;
+ }
+
+ main_window = qobject_cast<QWidget *>((QObject *)top_level_window);
+
+ if (!main_window) {
+ return nullptr;
+ }
+
+ pf = main_window->findChild<ProgressFrame *>();
+
+ if (!pf) {
+ return nullptr;
+ }
+
+ QString title = task_title;
+ if (item_title && strlen(item_title) > 0) {
+ title.append(" ").append(item_title);
+ }
+ return pf->showProgress(title, true, terminate_is_stop, stop_flag, 0);
+}
+
+progdlg_t *
+delayed_create_progress_dlg(gpointer top_level_window, const gchar *task_title, const gchar *item_title,
+ gboolean terminate_is_stop, gboolean *stop_flag,
+ gfloat progress)
+{
+ progdlg_t *progress_dialog = create_progress_dlg(top_level_window, task_title, item_title, terminate_is_stop, stop_flag);
+ update_progress_dlg(progress_dialog, progress, item_title);
+ return progress_dialog;
+}
+
+/*
+ * Update the progress information of the progress bar box.
+ */
+void
+update_progress_dlg(progdlg_t *dlg, gfloat percentage, const gchar *)
+{
+ if (!dlg) return;
+
+ dlg->progress_frame->setValue((int)(percentage * 100));
+
+ /*
+ * Flush out the update and process any input events.
+ */
+ MainApplication::processEvents();
+}
+
+/*
+ * Destroy the progress bar.
+ */
+void
+destroy_progress_dlg(progdlg_t *dlg)
+{
+ dlg->progress_frame->hide();
+}
+
+ProgressFrame::ProgressFrame(QWidget *parent) :
+ QFrame(parent),
+ ui(new Ui::ProgressFrame)
+ , terminate_is_stop_(false)
+ , stop_flag_(nullptr)
+ , show_timer_(-1)
+ , effect_(nullptr)
+ , animation_(nullptr)
+#ifdef QWINTASKBARPROGRESS_H
+ , update_taskbar_(false)
+ , taskbar_progress_(NULL)
+#endif
+{
+ ui->setupUi(this);
+
+ progress_dialog_.progress_frame = this;
+ progress_dialog_.top_level_window = window();
+
+#ifdef Q_OS_MAC
+ ui->label->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ ui->label->setStyleSheet(QString(
+ "QLabel {"
+ " background: transparent;"
+ "}"));
+
+ ui->progressBar->setStyleSheet(QString(
+ "QProgressBar {"
+ " max-width: 20em;"
+ " min-height: 0.5em;"
+ " max-height: 1em;"
+ " border-bottom: 0px;"
+ " border-top: 0px;"
+ " background: transparent;"
+ "}"));
+
+ ui->stopButton->setStockIcon("x-filter-clear");
+ ui->stopButton->setIconSize(QSize(14, 14));
+ ui->stopButton->setStyleSheet(
+ "QToolButton {"
+ " border: none;"
+ " background: transparent;" // Disables platform style on Windows.
+ " padding: 0px;"
+ " margin: 0px;"
+ " min-height: 0.8em;"
+ " max-height: 1em;"
+ " min-width: 0.8em;"
+ " max-width: 1em;"
+ "}"
+ );
+
+ effect_ = new QGraphicsOpacityEffect(this);
+ animation_ = new QPropertyAnimation(effect_, "opacity", this);
+ connect(this, SIGNAL(showRequested(bool,bool,gboolean*)),
+ this, SLOT(show(bool,bool,gboolean*)));
+ hide();
+}
+
+ProgressFrame::~ProgressFrame()
+{
+ delete ui;
+}
+
+struct progdlg *ProgressFrame::showProgress(const QString &title, bool animate, bool terminate_is_stop, gboolean *stop_flag, int value)
+{
+ setMaximumValue(100);
+ ui->progressBar->setValue(value);
+ QString elided_title = title;
+ int max_w = fontMetrics().height() * 20; // em-widths, arbitrary
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
+ int title_w = fontMetrics().horizontalAdvance(title);
+#else
+ int title_w = fontMetrics().width(title);
+#endif
+ if (title_w > max_w) {
+ elided_title = fontMetrics().elidedText(title, Qt::ElideRight, max_w);
+ }
+ // If we're in the main status bar, should we push this as a status message instead?
+ ui->label->setText(elided_title);
+ emit showRequested(animate, terminate_is_stop, stop_flag);
+ return &progress_dialog_;
+}
+
+progdlg *ProgressFrame::showBusy(bool animate, bool terminate_is_stop, gboolean *stop_flag)
+{
+ setMaximumValue(0);
+ emit showRequested(animate, terminate_is_stop, stop_flag);
+ return &progress_dialog_;
+}
+
+void ProgressFrame::addToButtonBox(QDialogButtonBox *button_box, QObject *main_window)
+{
+ // We have a ProgressFrame in the main status bar which is controlled
+ // from the capture file and other parts of the application via
+ // create_progress_dlg and delayed_create_progress_dlg.
+ // Create a new ProgressFrame and pair it with the main instance.
+ ProgressFrame *main_progress_frame = main_window->findChild<ProgressFrame *>();
+ if (!button_box || !main_progress_frame) return;
+
+ QBoxLayout *layout = qobject_cast<QBoxLayout *>(button_box->layout());
+ if (!layout) return;
+
+ ProgressFrame *progress_frame = new ProgressFrame(button_box);
+
+ // Insert ourselves after the first spacer we find, otherwise the
+ // far right of the button box.
+ int idx = layout->count();
+ for (int i = 0; i < layout->count(); i++) {
+ if (layout->itemAt(i)->spacerItem()) {
+ idx = i + 1;
+ break;
+ }
+ }
+ layout->insertWidget(idx, progress_frame);
+
+ int one_em = progress_frame->fontMetrics().height();
+ progress_frame->setMaximumWidth(one_em * 8);
+ connect(main_progress_frame, SIGNAL(showRequested(bool,bool,gboolean*)),
+ progress_frame, SLOT(show(bool,bool,gboolean*)));
+ connect(main_progress_frame, SIGNAL(maximumValueChanged(int)),
+ progress_frame, SLOT(setMaximumValue(int)));
+ connect(main_progress_frame, SIGNAL(valueChanged(int)),
+ progress_frame, SLOT(setValue(int)));
+ connect(main_progress_frame, SIGNAL(setHidden()),
+ progress_frame, SLOT(hide()));
+
+ connect(progress_frame, SIGNAL(stopLoading()),
+ main_progress_frame, SIGNAL(stopLoading()));
+}
+
+void ProgressFrame::captureFileClosing()
+{
+ // Hide any paired ProgressFrames and disconnect from them.
+ emit setHidden();
+ disconnect(SIGNAL(showRequested(bool,bool,gboolean*)));
+ disconnect(SIGNAL(maximumValueChanged(int)));
+ disconnect(SIGNAL(valueChanged(int)));
+
+ connect(this, SIGNAL(showRequested(bool,bool,gboolean*)),
+ this, SLOT(show(bool,bool,gboolean*)));
+}
+
+void ProgressFrame::setValue(int value)
+{
+ ui->progressBar->setValue(value);
+ emit valueChanged(value);
+}
+
+void ProgressFrame::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == show_timer_) {
+ killTimer(show_timer_);
+ show_timer_ = -1;
+
+ this->setGraphicsEffect(effect_);
+
+ animation_->setDuration(200);
+ animation_->setStartValue(0.1);
+ animation_->setEndValue(1.0);
+ animation_->setEasingCurve(QEasingCurve::InOutQuad);
+ animation_->start();
+
+ QFrame::show();
+ } else {
+ QFrame::timerEvent(event);
+ }
+}
+
+void ProgressFrame::hide()
+{
+ show_timer_ = -1;
+ emit setHidden();
+ QFrame::hide();
+#ifdef QWINTASKBARPROGRESS_H
+ if (taskbar_progress_) {
+ disconnect(this, SIGNAL(valueChanged(int)), taskbar_progress_, SLOT(setValue(int)));
+ taskbar_progress_->reset();
+ taskbar_progress_->hide();
+ }
+#endif
+}
+
+void ProgressFrame::on_stopButton_clicked()
+{
+ emit stopLoading();
+}
+
+const int show_delay_ = 150; // ms
+
+void ProgressFrame::show(bool animate, bool terminate_is_stop, gboolean *stop_flag)
+{
+ terminate_is_stop_ = terminate_is_stop;
+ stop_flag_ = stop_flag;
+
+ if (stop_flag) {
+ ui->stopButton->show();
+ } else {
+ ui->stopButton->hide();
+ }
+
+ if (animate) {
+ show_timer_ = startTimer(show_delay_);
+ } else {
+ QFrame::show();
+ }
+
+#ifdef QWINTASKBARPROGRESS_H
+ // windowHandle() is picky about returning a non-NULL value so we check it
+ // each time.
+ if (update_taskbar_ && !taskbar_progress_ && window()->windowHandle()) {
+ QWinTaskbarButton *taskbar_button = new QWinTaskbarButton(this);
+ if (taskbar_button) {
+ taskbar_button->setWindow(window()->windowHandle());
+ taskbar_progress_ = taskbar_button->progress();
+ }
+ }
+ if (taskbar_progress_) {
+ taskbar_progress_->show();
+ taskbar_progress_->reset();
+ connect(this, SIGNAL(valueChanged(int)), taskbar_progress_, SLOT(setValue(int)));
+ }
+#endif
+}
+
+void ProgressFrame::setMaximumValue(int value)
+{
+ ui->progressBar->setMaximum(value);
+ emit maximumValueChanged(value);
+}