Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / ui / qt / print_dialog.cpp
blob03fee84223e29fc183a8c02cf304f9622ae424bc
1 /* print_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include "print_dialog.h"
11 #include <ui_print_dialog.h>
13 #include <wsutil/utf8_entities.h>
15 #ifdef Q_OS_WIN
16 #include <windows.h>
17 #include "ui/packet_range.h"
18 #include "ui/win32/file_dlg_win32.h"
19 #endif
21 #include <QPrintDialog>
22 #include <QPageSetupDialog>
23 #include <QPainter>
24 #include <QPaintEngine>
25 #include <QKeyEvent>
26 #include <QMessageBox>
28 #include "main_application.h"
30 extern "C" {
32 // Page element callbacks
35 static bool
36 print_preamble_pd(print_stream_t *self, char *, const char *)
38 if (!self) return false;
39 PrintDialog *print_dlg = static_cast<PrintDialog *>(self->data);
40 if (!print_dlg) return false;
42 return print_dlg->printHeader();
45 static bool
46 print_line_pd(print_stream_t *self, int indent, const char *line)
48 if (!self) return false;
49 PrintDialog *print_dlg = static_cast<PrintDialog *>(self->data);
50 if (!print_dlg) return false;
52 return print_dlg->printLine(indent, line);
55 static bool
56 new_page_pd(print_stream_t *self)
58 if (!self) return false;
59 PrintDialog *print_dlg = static_cast<PrintDialog *>(self->data);
60 if (!print_dlg) return false;
62 return print_dlg->printHeader();
65 } // extern "C"
67 PrintDialog::PrintDialog(QWidget *parent, capture_file *cf, QString selRange) :
68 QDialog(parent),
69 pd_ui_(new Ui::PrintDialog),
70 cur_printer_(NULL),
71 cur_painter_(NULL),
72 preview_(new QPrintPreviewWidget(&printer_)),
73 print_bt_(new QPushButton(tr("&Print…"))),
74 cap_file_(cf),
75 page_pos_(0),
76 in_preview_(false)
78 Q_ASSERT(cf);
80 pd_ui_->setupUi(this);
81 setWindowTitle(mainApp->windowTitleString(tr("Print")));
83 pd_ui_->previewLayout->insertWidget(0, preview_, Qt::AlignTop);
85 preview_->setMinimumWidth(preview_->height() / 2);
86 preview_->setToolTip(pd_ui_->zoomLabel->toolTip());
88 // XXX Make these configurable
89 header_font_.setFamily("Times");
90 header_font_.setPointSizeF(header_font_.pointSizeF() * 0.8);
91 packet_font_ = mainApp->monospaceFont();
92 packet_font_.setPointSizeF(packet_font_.pointSizeF() * 0.8);
94 memset(&print_args_, 0, sizeof(print_args_));
95 memset(&stream_ops_, 0, sizeof(stream_ops_));
97 /* Init the export range */
98 packet_range_init(&print_args_.range, cap_file_);
99 /* Default to displayed packets */
100 print_args_.range.process_filtered = true;
102 stream_ops_.print_preamble = print_preamble_pd;
103 stream_ops_.print_line = print_line_pd;
104 stream_ops_.new_page = new_page_pd;
106 stream_.data = this;
107 stream_.ops = &stream_ops_;
108 print_args_.stream = &stream_;
110 char *display_basename = g_filename_display_basename(cap_file_->filename);
111 printer_.setDocName(display_basename);
112 g_free(display_basename);
114 pd_ui_->rangeGroupBox->initRange(&print_args_.range, selRange);
116 pd_ui_->buttonBox->addButton(print_bt_, QDialogButtonBox::ActionRole);
117 pd_ui_->buttonBox->addButton(tr("Page &Setup…"), QDialogButtonBox::ResetRole);
118 print_bt_->setDefault(true);
120 connect(preview_, SIGNAL(paintRequested(QPrinter*)), this, SLOT(paintPreview(QPrinter*)));
121 connect(pd_ui_->rangeGroupBox, SIGNAL(rangeChanged()),
122 this, SLOT(checkValidity()));
123 connect(pd_ui_->formatGroupBox, SIGNAL(formatChanged()),
124 this, SLOT(checkValidity()));
125 connect(pd_ui_->formFeedCheckBox, SIGNAL(toggled(bool)),
126 preview_, SLOT(updatePreview()));
127 connect(pd_ui_->bannerCheckBox, SIGNAL(toggled(bool)),
128 preview_, SLOT(updatePreview()));
130 checkValidity();
133 PrintDialog::~PrintDialog()
135 packet_range_cleanup(&print_args_.range);
136 delete pd_ui_;
139 bool PrintDialog::printHeader()
141 if (!cap_file_ || !cap_file_->filename || !cur_printer_ || !cur_painter_) return false;
142 int page_top = cur_printer_->pageLayout().paintRectPixels(cur_printer_->resolution()).top();
144 if (page_pos_ > page_top) {
145 if (in_preview_) {
146 // When generating a preview, only generate the first page;
147 // if we're past the first page, stop the printing process.
148 return false;
150 // Second and subsequent pages only
151 cur_printer_->newPage();
152 page_pos_ = page_top;
155 if (pd_ui_->bannerCheckBox->isChecked()) {
156 QString banner = tr("%1 %2 total packets, %3 shown")
157 .arg(cap_file_->filename)
158 .arg(cap_file_->count)
159 .arg(packet_range_count(&print_args_.range));
160 cur_painter_->setFont(header_font_);
161 cur_painter_->drawText(0, page_top, banner);
163 page_pos_ += cur_painter_->fontMetrics().height();
164 cur_painter_->setFont(packet_font_);
165 return true;
168 bool PrintDialog::printLine(int indent, const char *line)
170 QRect out_rect, page_rect;
171 QString out_line;
173 if (!line || !cur_printer_ || !cur_painter_) return false;
175 /* Prepare the tabs for printing, depending on tree level */
176 out_line.fill(' ', indent * 4);
177 out_line += line;
179 page_rect = cur_printer_->pageLayout().paintRectPixels(cur_printer_->resolution());
181 out_rect = cur_painter_->boundingRect(page_rect, Qt::TextWordWrap, out_line);
183 if (page_rect.height() < page_pos_ + out_rect.height()) {
185 // We're past the end of the page, so this line will be on
186 // the next page.
188 if (in_preview_) {
189 // When generating a preview, only generate the first page;
190 // if we're past the first page, stop the printing process.
191 return false;
193 if (*line == '\0') {
194 // This is an empty line, so it's a separator; no need to
195 // waste space printing it at the top of a page, as the
196 // page break suffices as a separator.
197 return true;
199 printHeader();
202 out_rect.translate(0, page_pos_);
203 cur_painter_->drawText(out_rect, Qt::TextWordWrap, out_line);
204 page_pos_ += out_rect.height();
205 return true;
208 // Protected
210 void PrintDialog::keyPressEvent(QKeyEvent *event)
212 // XXX - This differs from the main window but matches other applications (e.g. Mozilla and Safari)
213 switch(event->key()) {
214 case Qt::Key_Minus:
215 case Qt::Key_Underscore: // Shifted minus on U.S. keyboards
216 preview_->zoomOut();
217 break;
218 case Qt::Key_Plus:
219 case Qt::Key_Equal: // Unshifted plus on U.S. keyboards
220 preview_->zoomIn();
221 break;
222 case Qt::Key_0:
223 case Qt::Key_ParenRight: // Shifted 0 on U.S. keyboards
224 // fitInView doesn't grow (at least in Qt 4.8.2) so make sure it shrinks.
225 preview_->setUpdatesEnabled(false);
226 preview_->setZoomFactor(1.0);
227 preview_->fitInView();
228 preview_->setUpdatesEnabled(true);
229 break;
232 QDialog::keyPressEvent(event);
235 // Private
237 void PrintDialog::printPackets(QPrinter *printer, bool in_preview)
239 QPainter painter;
241 if (!printer) return;
243 page_pos_ = printer->pageLayout().paintRectPixels(printer->resolution()).top();
244 in_preview_ = in_preview;
246 /* Fill in our print args */
248 print_args_.format = PR_FMT_TEXT;
249 print_args_.print_summary = pd_ui_->formatGroupBox->summaryEnabled();
250 print_args_.print_col_headings = pd_ui_->formatGroupBox->includeColumnHeadingsEnabled();
251 print_args_.print_hex = pd_ui_->formatGroupBox->bytesEnabled();
252 print_args_.hexdump_options = pd_ui_->formatGroupBox->getHexdumpOptions();
253 print_args_.print_formfeed = pd_ui_->formFeedCheckBox->isChecked();
255 print_args_.print_dissections = print_dissections_none;
256 if (pd_ui_->formatGroupBox->detailsEnabled()) {
257 if (pd_ui_->formatGroupBox->allCollapsedEnabled())
258 print_args_.print_dissections = print_dissections_collapsed;
259 else if (pd_ui_->formatGroupBox->asDisplayedEnabled())
260 print_args_.print_dissections = print_dissections_as_displayed;
261 else if (pd_ui_->formatGroupBox->allExpandedEnabled())
262 print_args_.print_dissections = print_dissections_expanded;
265 // This should be identical to printer_. However, the QPrintPreviewWidget docs
266 // tell us to draw on the printer handed to us by the paintRequested() signal.
267 cur_printer_ = printer;
268 cur_painter_ = &painter;
269 if (!painter.begin(printer)) {
270 QMessageBox::warning(this, tr("Print Error"),
271 tr("Unable to print to %1.").arg(printer_.printerName()),
272 QMessageBox::Ok);
273 close();
275 // Don't show a progress bar if we're previewing; if it takes a
276 // significant amount of time to generate a preview of the first
277 // page, We Have A Real Problem
278 cf_print_packets(cap_file_, &print_args_, in_preview ? false : true);
279 cur_printer_ = NULL;
280 cur_painter_ = NULL;
281 painter.end();
284 void PrintDialog::paintPreview(QPrinter *printer)
286 printPackets(printer, true);
289 void PrintDialog::checkValidity()
291 bool enable = true;
293 if (!pd_ui_->rangeGroupBox->isValid()) enable = false;
295 if (!pd_ui_->formatGroupBox->summaryEnabled() &&
296 !pd_ui_->formatGroupBox->detailsEnabled() &&
297 !pd_ui_->formatGroupBox->bytesEnabled())
299 enable = false;
302 print_bt_->setEnabled(enable);
303 preview_->updatePreview();
306 void PrintDialog::on_buttonBox_helpRequested()
308 mainApp->helpTopicAction(HELP_PRINT_DIALOG);
311 void PrintDialog::on_buttonBox_clicked(QAbstractButton *button)
313 QPrintDialog *print_dlg;
314 QPageSetupDialog *ps_dlg;
315 #ifdef Q_OS_WIN
316 HANDLE da_ctx;
317 #endif
319 switch (pd_ui_->buttonBox->buttonRole(button)) {
320 case QDialogButtonBox::ActionRole:
321 int result;
322 #ifdef Q_OS_WIN
323 da_ctx = set_thread_per_monitor_v2_awareness();
324 #endif
325 print_dlg = new QPrintDialog(&printer_, this);
326 result = print_dlg->exec();
327 #ifdef Q_OS_WIN
328 revert_thread_per_monitor_v2_awareness(da_ctx);
329 #endif
330 if (result == QDialog::Accepted) {
331 printPackets(&printer_, false);
332 done(result);
334 break;
335 case QDialogButtonBox::ResetRole:
336 #ifdef Q_OS_WIN
337 da_ctx = set_thread_per_monitor_v2_awareness();
338 #endif
339 ps_dlg = new QPageSetupDialog(&printer_, this);
340 ps_dlg->exec();
341 #ifdef Q_OS_WIN
342 revert_thread_per_monitor_v2_awareness(da_ctx);
343 #endif
344 preview_->updatePreview();
345 break;
346 default: // Help, Cancel
347 break;