forked from osmocom/wireshark
Qt: Added IO Graph save to clipboard button.
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 <stig@bjorlykke.org> Reviewed-by: Jim Young <jim.young.ws@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
a67d426b1d
commit
864872ed61
|
@ -200,6 +200,9 @@ IOGraphDialog::IOGraphDialog(QWidget &parent, CaptureFile &cf) :
|
||||||
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
|
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
|
||||||
save_bt->setText(tr("Save As" UTF8_HORIZONTAL_ELLIPSIS));
|
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);
|
stat_timer_ = new QTimer(this);
|
||||||
connect(stat_timer_, SIGNAL(timeout()), this, SLOT(updateStatistics()));
|
connect(stat_timer_, SIGNAL(timeout()), this, SLOT(updateStatistics()));
|
||||||
stat_timer_->start(stat_update_interval_);
|
stat_timer_->start(stat_update_interval_);
|
||||||
|
@ -1505,6 +1508,14 @@ void IOGraphDialog::on_buttonBox_helpRequested()
|
||||||
wsApp->helpTopicAction(HELP_STATS_IO_GRAPH_DIALOG);
|
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.
|
// XXX - Copied from tcp_stream_dialog. This should be common code.
|
||||||
void IOGraphDialog::on_buttonBox_accepted()
|
void IOGraphDialog::on_buttonBox_accepted()
|
||||||
{
|
{
|
||||||
|
@ -1515,11 +1526,13 @@ void IOGraphDialog::on_buttonBox_accepted()
|
||||||
QString bmp_filter = tr("Windows Bitmap (*.bmp)");
|
QString bmp_filter = tr("Windows Bitmap (*.bmp)");
|
||||||
// Gaze upon my beautiful graph with lossy artifacts!
|
// Gaze upon my beautiful graph with lossy artifacts!
|
||||||
QString jpeg_filter = tr("JPEG File Interchange Format (*.jpeg *.jpg)");
|
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(pdf_filter)
|
||||||
.arg(png_filter)
|
.arg(png_filter)
|
||||||
.arg(bmp_filter)
|
.arg(bmp_filter)
|
||||||
.arg(jpeg_filter);
|
.arg(jpeg_filter)
|
||||||
|
.arg(csv_filter);
|
||||||
|
|
||||||
QString save_file = path.canonicalPath();
|
QString save_file = path.canonicalPath();
|
||||||
if (!file_closed_) {
|
if (!file_closed_) {
|
||||||
|
@ -1538,6 +1551,8 @@ void IOGraphDialog::on_buttonBox_accepted()
|
||||||
save_ok = ui->ioPlot->saveBmp(file_name);
|
save_ok = ui->ioPlot->saveBmp(file_name);
|
||||||
} else if (extension.compare(jpeg_filter) == 0) {
|
} else if (extension.compare(jpeg_filter) == 0) {
|
||||||
save_ok = ui->ioPlot->saveJpg(file_name);
|
save_ok = ui->ioPlot->saveJpg(file_name);
|
||||||
|
} else if (extension.compare(csv_filter) == 0) {
|
||||||
|
save_ok = saveCsv(file_name);
|
||||||
}
|
}
|
||||||
// else error dialog?
|
// else error dialog?
|
||||||
if (save_ok) {
|
if (save_ok) {
|
||||||
|
@ -1547,6 +1562,53 @@ void IOGraphDialog::on_buttonBox_accepted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IOGraphDialog::makeCsv(QTextStream &stream) const
|
||||||
|
{
|
||||||
|
QList<IOGraph *> 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<IOGraph *>();
|
||||||
|
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::IOGraph(QCustomPlot *parent) :
|
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.
|
// Get the value at the given interval (idx) for the current value unit.
|
||||||
// Adapted from get_it_value in gtk/io_stat.c.
|
// 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 */
|
double value = 0; /* FIXME: loss of precision, visible on the graph for small values */
|
||||||
int adv_type;
|
int adv_type;
|
||||||
io_graph_item_t *item;
|
const io_graph_item_t *item;
|
||||||
guint32 interval;
|
guint32 interval;
|
||||||
|
|
||||||
g_assert(idx < max_io_items_);
|
g_assert(idx < max_io_items_);
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
|
@ -83,6 +84,8 @@ public:
|
||||||
QCPBars *bars() { return bars_; }
|
QCPBars *bars() { return bars_; }
|
||||||
double startOffset();
|
double startOffset();
|
||||||
int packetFromTime(double ts);
|
int packetFromTime(double ts);
|
||||||
|
double getItemValue(int idx, const capture_file *cap_file) const;
|
||||||
|
int maxInterval () const { return cur_idx_; };
|
||||||
|
|
||||||
void clearAllData();
|
void clearAllData();
|
||||||
|
|
||||||
|
@ -103,7 +106,6 @@ signals:
|
||||||
void requestRetap();
|
void requestRetap();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double getItemValue(int idx, capture_file *cap_file);
|
|
||||||
// Callbacks for register_tap_listener
|
// Callbacks for register_tap_listener
|
||||||
static void tapReset(void *iog_ptr);
|
static void tapReset(void *iog_ptr);
|
||||||
static gboolean tapPacket(void *iog_ptr, packet_info *pinfo, epan_dissect_t *edt, const void *data);
|
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);
|
QRectF getZoomRanges(QRect zoom_rect);
|
||||||
void itemEditingFinished(QTreeWidgetItem *item);
|
void itemEditingFinished(QTreeWidgetItem *item);
|
||||||
void loadProfileGraphs();
|
void loadProfileGraphs();
|
||||||
|
void makeCsv(QTextStream &stream) const;
|
||||||
|
bool saveCsv(const QString &file_name) const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
@ -245,6 +249,7 @@ private slots:
|
||||||
void on_actionToggleTimeOrigin_triggered();
|
void on_actionToggleTimeOrigin_triggered();
|
||||||
void on_actionCrosshairs_triggered();
|
void on_actionCrosshairs_triggered();
|
||||||
void on_buttonBox_helpRequested();
|
void on_buttonBox_helpRequested();
|
||||||
|
void on_buttonBox_copyAsCsv_triggered();
|
||||||
void on_buttonBox_accepted();
|
void on_buttonBox_accepted();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue