summaryrefslogtreecommitdiffstats
path: root/ui/qt/print_dialog.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/print_dialog.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/print_dialog.cpp')
-rw-r--r--ui/qt/print_dialog.cpp361
1 files changed, 361 insertions, 0 deletions
diff --git a/ui/qt/print_dialog.cpp b/ui/qt/print_dialog.cpp
new file mode 100644
index 0000000..84c2d90
--- /dev/null
+++ b/ui/qt/print_dialog.cpp
@@ -0,0 +1,361 @@
+/* print_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "print_dialog.h"
+#include <ui_print_dialog.h>
+
+#include <wsutil/utf8_entities.h>
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#include "ui/packet_range.h"
+#include "ui/win32/file_dlg_win32.h"
+#endif
+
+#include <QPrintDialog>
+#include <QPageSetupDialog>
+#include <QPainter>
+#include <QPaintEngine>
+#include <QKeyEvent>
+#include <QMessageBox>
+
+#include "main_application.h"
+
+extern "C" {
+
+// Page element callbacks
+
+
+static gboolean
+print_preamble_pd(print_stream_t *self, gchar *, const char *)
+{
+ if (!self) return FALSE;
+ PrintDialog *print_dlg = static_cast<PrintDialog *>(self->data);
+ if (!print_dlg) return FALSE;
+
+ return print_dlg->printHeader();
+}
+
+static gboolean
+print_line_pd(print_stream_t *self, int indent, const char *line)
+{
+ if (!self) return FALSE;
+ PrintDialog *print_dlg = static_cast<PrintDialog *>(self->data);
+ if (!print_dlg) return FALSE;
+
+ return print_dlg->printLine(indent, line);
+}
+
+static gboolean
+new_page_pd(print_stream_t *self)
+{
+ if (!self) return FALSE;
+ PrintDialog *print_dlg = static_cast<PrintDialog *>(self->data);
+ if (!print_dlg) return FALSE;
+
+ return print_dlg->printHeader();
+}
+
+} // extern "C"
+
+PrintDialog::PrintDialog(QWidget *parent, capture_file *cf, QString selRange) :
+ QDialog(parent),
+ pd_ui_(new Ui::PrintDialog),
+ cur_printer_(NULL),
+ cur_painter_(NULL),
+ preview_(new QPrintPreviewWidget(&printer_)),
+ print_bt_(new QPushButton(tr("&Print…"))),
+ cap_file_(cf),
+ page_pos_(0),
+ in_preview_(FALSE)
+{
+ Q_ASSERT(cf);
+
+ pd_ui_->setupUi(this);
+ setWindowTitle(mainApp->windowTitleString(tr("Print")));
+
+ pd_ui_->previewLayout->insertWidget(0, preview_, Qt::AlignTop);
+
+ preview_->setMinimumWidth(preview_->height() / 2);
+ preview_->setToolTip(pd_ui_->zoomLabel->toolTip());
+
+ // XXX Make these configurable
+ header_font_.setFamily("Times");
+ header_font_.setPointSizeF(header_font_.pointSizeF() * 0.8);
+ packet_font_ = mainApp->monospaceFont();
+ packet_font_.setPointSizeF(packet_font_.pointSizeF() * 0.8);
+
+ memset(&print_args_, 0, sizeof(print_args_));
+ memset(&stream_ops_, 0, sizeof(stream_ops_));
+
+ /* Init the export range */
+ packet_range_init(&print_args_.range, cap_file_);
+ /* Default to displayed packets */
+ print_args_.range.process_filtered = TRUE;
+
+ stream_ops_.print_preamble = print_preamble_pd;
+ stream_ops_.print_line = print_line_pd;
+ stream_ops_.new_page = new_page_pd;
+
+ stream_.data = this;
+ stream_.ops = &stream_ops_;
+ print_args_.stream = &stream_;
+
+ gchar *display_basename = g_filename_display_basename(cap_file_->filename);
+ printer_.setDocName(display_basename);
+ g_free(display_basename);
+
+ pd_ui_->rangeGroupBox->initRange(&print_args_.range, selRange);
+
+ pd_ui_->buttonBox->addButton(print_bt_, QDialogButtonBox::ActionRole);
+ pd_ui_->buttonBox->addButton(tr("Page &Setup…"), QDialogButtonBox::ResetRole);
+ print_bt_->setDefault(true);
+
+ connect(preview_, SIGNAL(paintRequested(QPrinter*)), this, SLOT(paintPreview(QPrinter*)));
+ connect(pd_ui_->rangeGroupBox, SIGNAL(rangeChanged()),
+ this, SLOT(checkValidity()));
+ connect(pd_ui_->formatGroupBox, SIGNAL(formatChanged()),
+ this, SLOT(checkValidity()));
+ connect(pd_ui_->formFeedCheckBox, SIGNAL(toggled(bool)),
+ preview_, SLOT(updatePreview()));
+ connect(pd_ui_->bannerCheckBox, SIGNAL(toggled(bool)),
+ preview_, SLOT(updatePreview()));
+
+ checkValidity();
+}
+
+PrintDialog::~PrintDialog()
+{
+ packet_range_cleanup(&print_args_.range);
+ delete pd_ui_;
+}
+
+gboolean PrintDialog::printHeader()
+{
+ if (!cap_file_ || !cap_file_->filename || !cur_printer_ || !cur_painter_) return FALSE;
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ int page_top = cur_printer_->pageLayout().paintRectPixels(cur_printer_->resolution()).top();
+#else
+ int page_top = cur_printer_->pageRect().top();
+#endif
+
+ if (page_pos_ > page_top) {
+ if (in_preview_) {
+ // When generating a preview, only generate the first page;
+ // if we're past the first page, stop the printing process.
+ return FALSE;
+ }
+ // Second and subsequent pages only
+ cur_printer_->newPage();
+ page_pos_ = page_top;
+ }
+
+ if (pd_ui_->bannerCheckBox->isChecked()) {
+ QString banner = QString(tr("%1 %2 total packets, %3 shown"))
+ .arg(cap_file_->filename)
+ .arg(cap_file_->count)
+ .arg(cap_file_->displayed_count);
+ cur_painter_->setFont(header_font_);
+ cur_painter_->drawText(0, page_top, banner);
+ }
+ page_pos_ += cur_painter_->fontMetrics().height();
+ cur_painter_->setFont(packet_font_);
+ return TRUE;
+}
+
+gboolean PrintDialog::printLine(int indent, const char *line)
+{
+ QRect out_rect, page_rect;
+ QString out_line;
+
+ if (!line || !cur_printer_ || !cur_painter_) return FALSE;
+
+ /* Prepare the tabs for printing, depending on tree level */
+ out_line.fill(' ', indent * 4);
+ out_line += line;
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ page_rect = cur_printer_->pageLayout().paintRectPixels(cur_printer_->resolution());
+#else
+ page_rect = cur_printer_->pageRect();
+#endif
+
+ out_rect = cur_painter_->boundingRect(page_rect, Qt::TextWordWrap, out_line);
+
+ if (page_rect.height() < page_pos_ + out_rect.height()) {
+ //
+ // We're past the end of the page, so this line will be on
+ // the next page.
+ //
+ if (in_preview_) {
+ // When generating a preview, only generate the first page;
+ // if we're past the first page, stop the printing process.
+ return FALSE;
+ }
+ if (*line == '\0') {
+ // This is an empty line, so it's a separator; no need to
+ // waste space printing it at the top of a page, as the
+ // page break suffices as a separator.
+ return TRUE;
+ }
+ printHeader();
+ }
+
+ out_rect.translate(0, page_pos_);
+ cur_painter_->drawText(out_rect, Qt::TextWordWrap, out_line);
+ page_pos_ += out_rect.height();
+ return TRUE;
+}
+
+// Protected
+
+void PrintDialog::keyPressEvent(QKeyEvent *event)
+{
+ // XXX - This differs from the main window but matches other applications (e.g. Mozilla and Safari)
+ switch(event->key()) {
+ case Qt::Key_Minus:
+ case Qt::Key_Underscore: // Shifted minus on U.S. keyboards
+ preview_->zoomOut();
+ break;
+ case Qt::Key_Plus:
+ case Qt::Key_Equal: // Unshifted plus on U.S. keyboards
+ preview_->zoomIn();
+ break;
+ case Qt::Key_0:
+ case Qt::Key_ParenRight: // Shifted 0 on U.S. keyboards
+ // fitInView doesn't grow (at least in Qt 4.8.2) so make sure it shrinks.
+ preview_->setUpdatesEnabled(false);
+ preview_->setZoomFactor(1.0);
+ preview_->fitInView();
+ preview_->setUpdatesEnabled(true);
+ break;
+ }
+
+ QDialog::keyPressEvent(event);
+}
+
+// Private
+
+void PrintDialog::printPackets(QPrinter *printer, bool in_preview)
+{
+ QPainter painter;
+
+ if (!printer) return;
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
+ page_pos_ = printer->pageLayout().paintRectPixels(printer->resolution()).top();
+#else
+ page_pos_ = printer->pageRect().top();
+#endif
+ in_preview_ = in_preview;
+
+ /* Fill in our print args */
+
+ print_args_.format = PR_FMT_TEXT;
+ print_args_.print_summary = pd_ui_->formatGroupBox->summaryEnabled();
+ print_args_.print_col_headings = pd_ui_->formatGroupBox->includeColumnHeadingsEnabled();
+ print_args_.print_hex = pd_ui_->formatGroupBox->bytesEnabled();
+ print_args_.hexdump_options = pd_ui_->formatGroupBox->getHexdumpOptions();
+ print_args_.print_formfeed = pd_ui_->formFeedCheckBox->isChecked();
+
+ print_args_.print_dissections = print_dissections_none;
+ if (pd_ui_->formatGroupBox->detailsEnabled()) {
+ if (pd_ui_->formatGroupBox->allCollapsedEnabled())
+ print_args_.print_dissections = print_dissections_collapsed;
+ else if (pd_ui_->formatGroupBox->asDisplayedEnabled())
+ print_args_.print_dissections = print_dissections_as_displayed;
+ else if (pd_ui_->formatGroupBox->allExpandedEnabled())
+ print_args_.print_dissections = print_dissections_expanded;
+ }
+
+ // This should be identical to printer_. However, the QPrintPreviewWidget docs
+ // tell us to draw on the printer handed to us by the paintRequested() signal.
+ cur_printer_ = printer;
+ cur_painter_ = &painter;
+ if (!painter.begin(printer)) {
+ QMessageBox::warning(this, tr("Print Error"),
+ QString(tr("Unable to print to %1.")).arg(printer_.printerName()),
+ QMessageBox::Ok);
+ close();
+ }
+ // Don't show a progress bar if we're previewing; if it takes a
+ // significant amount of time to generate a preview of the first
+ // page, We Have A Real Problem
+ cf_print_packets(cap_file_, &print_args_, in_preview ? FALSE : TRUE);
+ cur_printer_ = NULL;
+ cur_painter_ = NULL;
+ painter.end();
+}
+
+void PrintDialog::paintPreview(QPrinter *printer)
+{
+ printPackets(printer, true);
+}
+
+void PrintDialog::checkValidity()
+{
+ bool enable = true;
+
+ if (!pd_ui_->rangeGroupBox->isValid()) enable = false;
+
+ if (!pd_ui_->formatGroupBox->summaryEnabled() &&
+ !pd_ui_->formatGroupBox->detailsEnabled() &&
+ !pd_ui_->formatGroupBox->bytesEnabled())
+ {
+ enable = false;
+ }
+
+ print_bt_->setEnabled(enable);
+ preview_->updatePreview();
+}
+
+void PrintDialog::on_buttonBox_helpRequested()
+{
+ mainApp->helpTopicAction(HELP_PRINT_DIALOG);
+}
+
+void PrintDialog::on_buttonBox_clicked(QAbstractButton *button)
+{
+ QPrintDialog *print_dlg;
+ QPageSetupDialog *ps_dlg;
+#ifdef Q_OS_WIN
+ HANDLE da_ctx;
+#endif
+
+ switch (pd_ui_->buttonBox->buttonRole(button)) {
+ case QDialogButtonBox::ActionRole:
+ int result;
+#ifdef Q_OS_WIN
+ da_ctx = set_thread_per_monitor_v2_awareness();
+#endif
+ print_dlg = new QPrintDialog(&printer_, this);
+ result = print_dlg->exec();
+#ifdef Q_OS_WIN
+ revert_thread_per_monitor_v2_awareness(da_ctx);
+#endif
+ if (result == QDialog::Accepted) {
+ printPackets(&printer_, false);
+ done(result);
+ }
+ break;
+ case QDialogButtonBox::ResetRole:
+#ifdef Q_OS_WIN
+ da_ctx = set_thread_per_monitor_v2_awareness();
+#endif
+ ps_dlg = new QPageSetupDialog(&printer_, this);
+ ps_dlg->exec();
+#ifdef Q_OS_WIN
+ revert_thread_per_monitor_v2_awareness(da_ctx);
+#endif
+ preview_->updatePreview();
+ break;
+ default: // Help, Cancel
+ break;
+ }
+}