From 864872ed618e3c2853728f872cce6cf6282c617d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stig=20Bj=C3=B8rlykke?= Date: Wed, 11 Nov 2015 15:05:33 +0100 Subject: [PATCH] Qt: Added IO Graph save to clipboard button. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also added save as CSV file. Do not add double quotes for values as we do in GTK. Change-Id: I8576a73e10b71cdba0c8c80db8b21927d19528da Reviewed-on: https://code.wireshark.org/review/11732 Petri-Dish: Stig Bjørlykke Reviewed-by: Jim Young Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- ui/qt/io_graph_dialog.cpp | 70 ++++++++++++++++++++++++++++++++++++--- ui/qt/io_graph_dialog.h | 7 +++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/ui/qt/io_graph_dialog.cpp b/ui/qt/io_graph_dialog.cpp index 86f37f528c..4512fc8067 100644 --- a/ui/qt/io_graph_dialog.cpp +++ b/ui/qt/io_graph_dialog.cpp @@ -200,6 +200,9 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf) : QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save); save_bt->setText(tr("Save As" UTF8_HORIZONTAL_ELLIPSIS)); + QPushButton *copy_bt = ui->buttonBox->addButton(tr("Copy"), QDialogButtonBox::ApplyRole); + connect (copy_bt, SIGNAL(clicked()), this, SLOT(on_buttonBox_copyAsCsv_triggered())); + stat_timer_ = new QTimer(this); connect(stat_timer_, SIGNAL(timeout()), this, SLOT(updateStatistics())); stat_timer_->start(stat_update_interval_); @@ -1505,6 +1508,14 @@ void IOGraphDialog::on_buttonBox_helpRequested() wsApp->helpTopicAction(HELP_STATS_IO_GRAPH_DIALOG); } +void IOGraphDialog::on_buttonBox_copyAsCsv_triggered() +{ + QString csv; + QTextStream stream(&csv, QIODevice::Text); + makeCsv(stream); + wsApp->clipboard()->setText(stream.readAll()); +} + // XXX - Copied from tcp_stream_dialog. This should be common code. void IOGraphDialog::on_buttonBox_accepted() { @@ -1515,11 +1526,13 @@ void IOGraphDialog::on_buttonBox_accepted() QString bmp_filter = tr("Windows Bitmap (*.bmp)"); // Gaze upon my beautiful graph with lossy artifacts! QString jpeg_filter = tr("JPEG File Interchange Format (*.jpeg *.jpg)"); - QString filter = QString("%1;;%2;;%3;;%4") + QString csv_filter = tr("Comma Separated Values (*.csv)"); + QString filter = QString("%1;;%2;;%3;;%4;;%5") .arg(pdf_filter) .arg(png_filter) .arg(bmp_filter) - .arg(jpeg_filter); + .arg(jpeg_filter) + .arg(csv_filter); QString save_file = path.canonicalPath(); if (!file_closed_) { @@ -1538,6 +1551,8 @@ void IOGraphDialog::on_buttonBox_accepted() save_ok = ui->ioPlot->saveBmp(file_name); } else if (extension.compare(jpeg_filter) == 0) { save_ok = ui->ioPlot->saveJpg(file_name); + } else if (extension.compare(csv_filter) == 0) { + save_ok = saveCsv(file_name); } // else error dialog? if (save_ok) { @@ -1547,6 +1562,53 @@ void IOGraphDialog::on_buttonBox_accepted() } } +void IOGraphDialog::makeCsv(QTextStream &stream) const +{ + QList activeGraphs; + + int ui_interval = ui->intervalComboBox->itemData(ui->intervalComboBox->currentIndex()).toInt(); + int max_interval = 0; + + stream << "\"Interval start\""; + for (int i = 0; i < ui->graphTreeWidget->topLevelItemCount(); i++) { + QTreeWidgetItem *ti = ui->graphTreeWidget->topLevelItem(i); + if (ti && ti->checkState(name_col_) == Qt::Checked) { + IOGraph *iog = ti->data(name_col_, Qt::UserRole).value(); + QString name = iog->name().toUtf8(); + name.replace("\"", "\"\""); // RFC 4180 2.7 + stream << ",\"" << name << "\""; + activeGraphs.append(iog); + if (max_interval < iog->maxInterval()) { + max_interval = iog->maxInterval(); + } + } + } + stream << "\n"; + + for (int interval = 0; interval <= max_interval; interval++) { + double interval_start = (double)interval * ((double)ui_interval / 1000.0); + stream << interval_start; + foreach (IOGraph *iog, activeGraphs) { + double value = 0.0; + if (interval <= iog->maxInterval()) { + value = iog->getItemValue(interval, cap_file_.capFile()); + } + stream << "," << value; + } + stream << "\n"; + } +} + +bool IOGraphDialog::saveCsv(const QString &file_name) const +{ + QFile save_file(file_name); + save_file.open(QFile::WriteOnly); + QTextStream out(&save_file); + makeCsv(out); + + return true; +} + // IOGraph IOGraph::IOGraph(QCustomPlot *parent) : @@ -1998,11 +2060,11 @@ void IOGraph::setInterval(int interval) // Get the value at the given interval (idx) for the current value unit. // Adapted from get_it_value in gtk/io_stat.c. -double IOGraph::getItemValue(int idx, capture_file *cap_file) +double IOGraph::getItemValue(int idx, const capture_file *cap_file) const { double value = 0; /* FIXME: loss of precision, visible on the graph for small values */ int adv_type; - io_graph_item_t *item; + const io_graph_item_t *item; guint32 interval; g_assert(idx < max_io_items_); diff --git a/ui/qt/io_graph_dialog.h b/ui/qt/io_graph_dialog.h index 281ecf1d98..dae536da81 100644 --- a/ui/qt/io_graph_dialog.h +++ b/ui/qt/io_graph_dialog.h @@ -34,6 +34,7 @@ #include #include +#include class QComboBox; class QLineEdit; @@ -83,6 +84,8 @@ public: QCPBars *bars() { return bars_; } double startOffset(); int packetFromTime(double ts); + double getItemValue(int idx, const capture_file *cap_file) const; + int maxInterval () const { return cur_idx_; }; void clearAllData(); @@ -103,7 +106,6 @@ signals: void requestRetap(); private: - double getItemValue(int idx, capture_file *cap_file); // Callbacks for register_tap_listener static void tapReset(void *iog_ptr); static gboolean tapPacket(void *iog_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *data); @@ -200,6 +202,8 @@ private: QRectF getZoomRanges(QRect zoom_rect); void itemEditingFinished(QTreeWidgetItem *item); void loadProfileGraphs(); + void makeCsv(QTextStream &stream) const; + bool saveCsv(const QString &file_name) const; private slots: void updateWidgets(); @@ -245,6 +249,7 @@ private slots: void on_actionToggleTimeOrigin_triggered(); void on_actionCrosshairs_triggered(); void on_buttonBox_helpRequested(); + void on_buttonBox_copyAsCsv_triggered(); void on_buttonBox_accepted(); };