diff options
author | Gerald Combs <gerald@wireshark.org> | 2012-11-01 20:57:45 +0000 |
---|---|---|
committer | Gerald Combs <gerald@wireshark.org> | 2012-11-01 20:57:45 +0000 |
commit | e7c47148eada3ecc0f5d144ccc460d0b5781183e (patch) | |
tree | 1f401970cafdea1b821785b97307fe5d3bfa8db4 /ui/qt | |
parent | e7c01324d9c600c3af5ea07bfa3474f913425023 (diff) |
Add a print dialog to the Qt UI. Add support for null page element
callbacks in print.c. Clean up some other issues in print.c.
svn path=/trunk/; revision=45860
Diffstat (limited to 'ui/qt')
-rw-r--r-- | ui/qt/CMakeLists.txt | 3 | ||||
-rw-r--r-- | ui/qt/Makefile.common | 5 | ||||
-rw-r--r-- | ui/qt/QtShark.pro | 9 | ||||
-rw-r--r-- | ui/qt/export_dissection_dialog.cpp | 1 | ||||
-rw-r--r-- | ui/qt/main_window.h | 1 | ||||
-rw-r--r-- | ui/qt/main_window_slots.cpp | 8 | ||||
-rw-r--r-- | ui/qt/packet_range_group_box.cpp | 1 | ||||
-rw-r--r-- | ui/qt/packet_range_group_box.h | 1 | ||||
-rw-r--r-- | ui/qt/print_dialog.cpp | 322 | ||||
-rw-r--r-- | ui/qt/print_dialog.h | 82 | ||||
-rw-r--r-- | ui/qt/print_dialog.ui | 136 |
11 files changed, 564 insertions, 5 deletions
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index d16a27ecf6..1a6aa0f0f5 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -47,6 +47,7 @@ set(QTSHARK_H_SRC packet_list.h packet_list_model.h packet_range_group_box.h + print_dialog.h progress_bar.h proto_tree.h recent_file_status.h @@ -86,6 +87,7 @@ set(QTSHARK_CPP_SRC packet_list_model.cpp packet_list_record.cpp packet_range_group_box.cpp + print_dialog.cpp progress_bar.cpp proto_tree.cpp qt_ui_utils.cpp @@ -108,6 +110,7 @@ set(QTSHARK_UI main_window.ui packet_format_group_box.ui packet_range_group_box.ui + print_dialog.ui ) set(QTSHARK_QRC diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index 3cb2849a8f..80b05e5d33 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -34,7 +34,8 @@ GENERATED_NODIST_HEADER_FILES = \ ui_file_set_dialog.h \ ui_main_welcome.h \ ui_main_window.h \ - ui_packet_range_group_box.h + ui_packet_range_group_box.h \ + ui_print_dialog.h # Generated C source files that we want in the distribution. GENERATED_C_FILES = @@ -90,6 +91,7 @@ MOC_HDRS = \ packet_list.h \ packet_list_model.h \ packet_range_group_box.h \ + print_dialog.h \ progress_bar.h \ proto_tree.h \ recent_file_status.h \ @@ -149,6 +151,7 @@ WIRESHARK_QT_SRC = \ packet_list_model.cpp \ packet_list_record.cpp \ packet_range_group_box.cpp \ + print_dialog.cpp \ progress_bar.cpp \ proto_tree.cpp \ qt_ui_utils.cpp \ diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index b1c92780c3..78fa0ee475 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -183,7 +183,8 @@ FORMS += main_window.ui \ file_set_dialog.ui \ packet_range_group_box.ui \ packet_format_group_box.ui \ - export_object_dialog.ui + export_object_dialog.ui \ + print_dialog.ui win32 { ## These should be in config.pri ?? !isEmpty(PORTAUDIO_DIR) { @@ -209,7 +210,8 @@ win32 { ## These should be in config.pri ?? HEADERS += $$HEADERS_WS_C \ export_dissection_dialog.h \ packet_format_group_box.h \ - export_object_dialog.h + export_object_dialog.h \ + print_dialog.h win32 { OBJECTS_WS_C = $$SOURCES_WS_C @@ -417,4 +419,5 @@ SOURCES += \ wireshark_application.cpp \ export_dissection_dialog.cpp \ packet_format_group_box.cpp \ - export_object_dialog.cpp + export_object_dialog.cpp \ + print_dialog.cpp diff --git a/ui/qt/export_dissection_dialog.cpp b/ui/qt/export_dissection_dialog.cpp index 2f767d940e..33e6c946c9 100644 --- a/ui/qt/export_dissection_dialog.cpp +++ b/ui/qt/export_dissection_dialog.cpp @@ -145,7 +145,6 @@ int ExportDissectionDialog::exec() print_args_.print_hex = FALSE; print_args_.print_formfeed = FALSE; - switch (export_type_) { case export_type_text: /* Text */ print_args_.print_summary = packet_format_group_box_.summaryEnabled(); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 6f821f0898..9af564cd9c 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -173,6 +173,7 @@ private slots: void on_actionFileExportObjectsDICOM_triggered(); void on_actionFileExportObjectsHTTP_triggered(); void on_actionFileExportObjectsSMB_triggered(); + void on_actionFilePrint_triggered(); void on_actionGoGoToPacket_triggered(); void resetPreviousFocus(); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 7ed09ff70f..bf56ee5423 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -61,6 +61,7 @@ #include "wireshark_application.h" #include "capture_file_dialog.h" #include "export_object_dialog.h" +#include "print_dialog.h" // // Public slots @@ -816,6 +817,13 @@ void MainWindow::on_actionFileExportObjectsSMB_triggered() new ExportObjectDialog(this, cap_file_, ExportObjectDialog::Smb); } +void MainWindow::on_actionFilePrint_triggered() +{ + PrintDialog pdlg(this, cap_file_); + + pdlg.exec(); +} + // View Menu // Expand / collapse slots in proto_tree diff --git a/ui/qt/packet_range_group_box.cpp b/ui/qt/packet_range_group_box.cpp index af49256c89..deee6b25cc 100644 --- a/ui/qt/packet_range_group_box.cpp +++ b/ui/qt/packet_range_group_box.cpp @@ -273,6 +273,7 @@ void PacketRangeGroupBox::updateCounts() { pr_ui_->rangeLineEdit->setSyntaxState(syntax_state_); emit validityChanged(isValid()); } + emit rangeChanged(); } // Slots diff --git a/ui/qt/packet_range_group_box.h b/ui/qt/packet_range_group_box.h index acf997cb1e..9d874dea33 100644 --- a/ui/qt/packet_range_group_box.h +++ b/ui/qt/packet_range_group_box.h @@ -49,6 +49,7 @@ public: signals: void validityChanged(bool is_valid); + void rangeChanged(); private: void updateCounts(); diff --git a/ui/qt/print_dialog.cpp b/ui/qt/print_dialog.cpp new file mode 100644 index 0000000000..097ed59e85 --- /dev/null +++ b/ui/qt/print_dialog.cpp @@ -0,0 +1,322 @@ +/* print_dialog.cpp + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "print_dialog.h" +#include "ui_print_dialog.h" + +#include <QPrintDialog> +#include <QPageSetupDialog> +#include <QPainter> +#include <QPaintEngine> +#include <QKeyEvent> +#include <QMessageBox> + +#include "wireshark_application.h" + +extern "C" { + +// Page element callbacks + +static gboolean +print_preamble_pd(print_stream_t *self, gchar *filename) +{ + Q_UNUSED(filename); + + 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) : + 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) +{ + if (!cf) close(); // ...or assert? + + pd_ui_->setupUi(this); + + 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_ = wsApp->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); + + 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())); + + checkValidity(); +} + +PrintDialog::~PrintDialog() +{ + delete pd_ui_; +} + +// Public + +gboolean PrintDialog::printHeader() +{ + if (!cap_file_ || !cap_file_->filename || !cur_printer_ || !cur_painter_) return FALSE; + int page_top = cur_printer_->pageRect().top(); + + if (page_pos_ > page_top) { + if (in_preview_) { + return FALSE; + } + // Second and subsequent pages only + cur_printer_->newPage(); + page_pos_ = page_top; + } + + QString banner = QString("%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; + 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; + + out_rect = cur_painter_->boundingRect(cur_printer_->pageRect(), Qt::TextWordWrap, out_line); + + if (cur_printer_->pageRect().height() < page_pos_ + out_rect.height()) { + if (in_preview_) { + return FALSE; + } + if (*line == '\0') { // 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; + cf_print_status_t status; + + if (!printer) return; + + page_pos_ = printer->pageRect().top(); + 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_hex = pd_ui_->formatGroupBox->bytesEnabled(); + 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(); + } + // cf_print_packets updates the progress bar which in turn calls + // WiresharkApplication::processEvents(), which can make the preview trip + // over itself. + preview_->setUpdatesEnabled(false); + status = cf_print_packets(cap_file_, &print_args_); + preview_->setUpdatesEnabled(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() +{ + wsApp->helpTopicAction(HELP_PRINT_DIALOG); +} + +void PrintDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + QPrintDialog *print_dlg; + QPageSetupDialog *ps_dlg; + + switch (pd_ui_->buttonBox->buttonRole(button)) { + case QDialogButtonBox::ActionRole: + int result; + print_dlg = new QPrintDialog(&printer_, this); + result = print_dlg->exec(); + if (result == QDialog::Accepted) { + printPackets(&printer_, false); + done(result); + } + break; + case QDialogButtonBox::ResetRole: + ps_dlg = new QPageSetupDialog(&printer_, this); + ps_dlg->exec(); + preview_->updatePreview(); + break; + default: // Help, Cancel + break; + } +} diff --git a/ui/qt/print_dialog.h b/ui/qt/print_dialog.h new file mode 100644 index 0000000000..baa003e3ab --- /dev/null +++ b/ui/qt/print_dialog.h @@ -0,0 +1,82 @@ +/* print_dialog.h + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef PRINT_DIALOG_H +#define PRINT_DIALOG_H + +#include "config.h" + +#include <glib.h> + +#include "file.h" + +#include <QDialog> +#include <QPrinter> +#include <QPrintPreviewWidget> +#include <QPushButton> + +namespace Ui { +class PrintDialog; +} + +class PrintDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PrintDialog(QWidget *parent = 0, capture_file *cf = NULL); + ~PrintDialog(); + gboolean printHeader(); + gboolean printLine(int indent, const char *line); + +protected: + void keyPressEvent(QKeyEvent *event); + +private: + void printPackets(QPrinter *printer = NULL, bool in_preview = false); + + Ui::PrintDialog *pd_ui_; + + QPrinter printer_; + QPrinter *cur_printer_; + QPainter *cur_painter_; + QPrintPreviewWidget *preview_; + QPushButton *print_bt_; + QFont header_font_; + QFont packet_font_; + capture_file *cap_file_; + print_args_t print_args_; + print_stream_ops_t stream_ops_; + print_stream_t stream_; + int page_pos_; + bool in_preview_; + +private slots: + void paintPreview(QPrinter *printer); + void checkValidity(); + void on_buttonBox_helpRequested(); + void on_buttonBox_clicked(QAbstractButton *button); +}; + + +#endif // PRINT_DIALOG_H diff --git a/ui/qt/print_dialog.ui b/ui/qt/print_dialog.ui new file mode 100644 index 0000000000..92565f51f8 --- /dev/null +++ b/ui/qt/print_dialog.ui @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PrintDialog</class> + <widget class="QDialog" name="PrintDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>496</width> + <height>328</height> + </rect> + </property> + <property name="windowTitle"> + <string>Wireshark: Print</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="previewLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="PacketFormatGroupBox" name="formatGroupBox"> + <property name="title"> + <string>Packet Format</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="formFeedCheckBox"> + <property name="text"> + <string>Print each packet on a new page</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>118</width> + <height>28</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="zoomLabel"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="toolTip"> + <string><html><head/><body><p>Use the &quot;+&quot; and &quot;-&quot; keys to zoom the preview in and out. Use the &quot;0&quot; key to reset the zoom level.</p></body></html></string> + </property> + <property name="text"> + <string><html><head/><body><p><span style=" font-size:small; font-style:italic;">+ and - zoom, 0 resets</span></p></body></html></string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <widget class="PacketRangeGroupBox" name="rangeGroupBox"> + <property name="title"> + <string>Packet Range</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Help</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>PacketRangeGroupBox</class> + <extends>QGroupBox</extends> + <header>packet_range_group_box.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>PacketFormatGroupBox</class> + <extends>QGroupBox</extends> + <header>packet_format_group_box.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PrintDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PrintDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> |