summaryrefslogtreecommitdiff
path: root/src/analyze
diff options
context:
space:
mode:
authorAlexey Chernobaev <achernobaev@dev.rtsoft.ru>2018-03-25 01:48:26 +0300
committerAlexey Chernobaev <achernobaev@dev.rtsoft.ru>2018-03-25 01:48:26 +0300
commitf1d2f7d7dad7a4d8ae6dd8164e4b103a312f04c4 (patch)
tree0d5f1436dada0a46761ca3d5eb9910b2bfd6581f /src/analyze
parent62ad2e1d17a8b820a3c104356494c8112b41f12b (diff)
downloadheaptrack-f1d2f7d7dad7a4d8ae6dd8164e4b103a312f04c4.tar.gz
heaptrack-f1d2f7d7dad7a4d8ae6dd8164e4b103a312f04c4.tar.bz2
heaptrack-f1d2f7d7dad7a4d8ae6dd8164e4b103a312f04c4.zip
added a context menu to histogram (QWT)
Diffstat (limited to 'src/analyze')
-rw-r--r--src/analyze/gui/chartwidget.cpp81
-rw-r--r--src/analyze/gui/chartwidget.h9
-rw-r--r--src/analyze/gui/chartwidgetqwtplot.cpp32
-rw-r--r--src/analyze/gui/chartwidgetqwtplot.h17
-rw-r--r--src/analyze/gui/contextmenuqwt.cpp2
-rw-r--r--src/analyze/gui/contextmenuqwt.h2
-rw-r--r--src/analyze/gui/histogrammodel.cpp7
-rw-r--r--src/analyze/gui/histogrammodel.h2
-rw-r--r--src/analyze/gui/histogramwidget.cpp51
-rw-r--r--src/analyze/gui/histogramwidget.h20
-rw-r--r--src/analyze/gui/histogramwidgetqwtplot.cpp132
-rw-r--r--src/analyze/gui/histogramwidgetqwtplot.h14
-rw-r--r--src/analyze/gui/mainwindow.cpp14
-rw-r--r--src/analyze/gui/mainwindow.h2
-rw-r--r--src/analyze/gui/util.cpp57
-rw-r--r--src/analyze/gui/util.h11
16 files changed, 330 insertions, 123 deletions
diff --git a/src/analyze/gui/chartwidget.cpp b/src/analyze/gui/chartwidget.cpp
index bf4e3a5..95baca7 100644
--- a/src/analyze/gui/chartwidget.cpp
+++ b/src/analyze/gui/chartwidget.cpp
@@ -37,11 +37,7 @@
#elif defined(QWT_FOUND)
#include <QAction>
#include <QContextMenuEvent>
-#include <QFileDialog>
-#include <QFileInfo>
#include <QMenu>
-#include <QMessageBox>
-#include <QRegularExpression>
#endif
#ifdef NO_K_LIB
@@ -132,15 +128,10 @@ protected:
virtual void closeEvent(QCloseEvent *event) override
{
QMainWindow::closeEvent(event);
- ChartWidget::GlobalOptions = ChartOptions::setOption(ChartWidget::GlobalOptions, ChartOptions::ShowHelp, false);
+ ChartOptions::GlobalOptions = ChartOptions::setOption(ChartOptions::GlobalOptions, ChartOptions::ShowHelp, false);
}
};
-ChartOptions::Options ChartWidget::GlobalOptions(
- ChartOptions::ShowHelp |
- ChartOptions::ShowTotal | ChartOptions::ShowUnresolved |
- ChartOptions::ShowLegend | ChartOptions::ShowCurveBorders);
-
QWidget* ChartWidget::HelpWindow;
QWidget* ChartWidget::MainWindow;
#endif // QWT_FOUND
@@ -150,7 +141,7 @@ ChartWidget::ChartWidget(QWidget* parent)
#if defined(KChart_FOUND)
, m_chart(new Chart(this))
#elif defined(QWT_FOUND)
- , m_plot(new ChartWidgetQwtPlot(this, GlobalOptions))
+ , m_plot(new ChartWidgetQwtPlot(this, ChartOptions::GlobalOptions))
, m_contextMenuQwt(new ContextMenuQwt(this, false))
#endif
#ifdef SHOW_TABLES
@@ -164,7 +155,7 @@ ChartWidget::ChartWidget(QWidget* parent)
#elif defined(QWT_FOUND)
layout->addWidget(m_plot);
- createActions();
+ connectContextMenu();
#endif
#ifdef SHOW_TABLES
auto hLayout = new QHBoxLayout();
@@ -190,14 +181,14 @@ ChartWidget::~ChartWidget() = default;
void ChartWidget::updateOnSelected(QWidget *mainWindow)
{
MainWindow = mainWindow;
- m_plot->setOptions(GlobalOptions);
- if (m_plot->hasOption(ChartWidgetQwtPlot::ShowHelp))
+ m_plot->setOptions(ChartOptions::GlobalOptions);
+ if (m_plot->hasOption(ChartOptions::ShowHelp))
{
showHelp();
}
}
-void ChartWidget::createActions()
+void ChartWidget::connectContextMenu()
{
connect(m_contextMenuQwt->resetZoomAction(), &QAction::triggered, this, &ChartWidget::resetZoom);
connect(m_contextMenuQwt->showTotalAction(), &QAction::triggered, this, &ChartWidget::toggleShowTotal);
@@ -206,7 +197,9 @@ void ChartWidget::createActions()
connect(m_contextMenuQwt->showCurveBordersAction(), &QAction::triggered, this, &ChartWidget::toggleShowCurveBorders);
connect(m_contextMenuQwt->showSymbolsAction(), &QAction::triggered, this, &ChartWidget::toggleShowSymbols);
connect(m_contextMenuQwt->showVLinesAction(), &QAction::triggered, this, &ChartWidget::toggleShowVLines);
- connect(m_contextMenuQwt->exportChartAction(), &QAction::triggered, this, &ChartWidget::exportChart);
+ connect(m_contextMenuQwt->exportChartAction(), &QAction::triggered, this, [=]() {
+ Util::exportChart(this, *m_plot, m_plot->model()->headerData(1, Qt::Horizontal).toString());
+ });
connect(m_contextMenuQwt->showHelpAction(), &QAction::triggered, this, &ChartWidget::toggleShowHelp);
setFocusPolicy(Qt::StrongFocus);
@@ -347,8 +340,8 @@ void ChartWidget::modelReset()
void ChartWidget::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
- m_plot->setOption(ChartWidgetQwtPlot::ShowHelp,
- ChartWidgetQwtPlot::hasOption(GlobalOptions, ChartWidgetQwtPlot::ShowHelp));
+ m_plot->setOption(ChartOptions::ShowHelp,
+ ChartOptions::hasOption(ChartOptions::GlobalOptions, ChartOptions::ShowHelp));
m_contextMenuQwt->initializeMenu(menu, m_plot->options());
menu.exec(event->globalPos());
}
@@ -356,7 +349,7 @@ void ChartWidget::contextMenuEvent(QContextMenuEvent *event)
void ChartWidget::keyPressEvent(QKeyEvent *event)
{
- m_contextMenuQwt->handleKeyPress(event, m_plot->options());
+ m_contextMenuQwt->handleKeyPress(event);
}
void ChartWidget::resetZoom()
@@ -366,37 +359,37 @@ void ChartWidget::resetZoom()
void ChartWidget::toggleShowTotal()
{
- GlobalOptions = m_plot->toggleOption(ChartWidgetQwtPlot::ShowTotal);
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowTotal);
}
void ChartWidget::toggleShowUnresolved()
{
- GlobalOptions = m_plot->toggleOption(ChartWidgetQwtPlot::ShowUnresolved);
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowUnresolved);
}
void ChartWidget::toggleShowLegend()
{
- GlobalOptions = m_plot->toggleOption(ChartWidgetQwtPlot::ShowLegend);
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowLegend);
}
void ChartWidget::toggleShowCurveBorders()
{
- GlobalOptions = m_plot->toggleOption(ChartWidgetQwtPlot::ShowCurveBorders);
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowCurveBorders);
}
void ChartWidget::toggleShowSymbols()
{
- GlobalOptions = m_plot->toggleOption(ChartWidgetQwtPlot::ShowSymbols);
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowSymbols);
}
void ChartWidget::toggleShowVLines()
{
- GlobalOptions = m_plot->toggleOption(ChartWidgetQwtPlot::ShowVLines);
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowVLines);
}
void ChartWidget::toggleShowHelp()
{
- bool checked = !ChartOptions::hasOption(GlobalOptions, ChartOptions::ShowHelp);
+ bool checked = !ChartOptions::hasOption(ChartOptions::GlobalOptions, ChartOptions::ShowHelp);
if (checked)
{
showHelp();
@@ -409,7 +402,8 @@ void ChartWidget::toggleShowHelp()
HelpWindow = nullptr;
}
}
- GlobalOptions = ChartOptions::setOption(GlobalOptions, ChartOptions::ShowHelp, checked);
+ ChartOptions::GlobalOptions = ChartOptions::setOption(ChartOptions::GlobalOptions,
+ ChartOptions::ShowHelp, checked);
}
void ChartWidget::showHelp()
@@ -422,39 +416,6 @@ void ChartWidget::showHelp()
}
HelpWindow->show();
}
-
-void ChartWidget::exportChart()
-{
- QString selectedFilter;
- QString saveFilename = QFileDialog::getSaveFileName(this, "Save Chart As",
- m_plot->model()->headerData(1, Qt::Horizontal).toString(),
- "PNG (*.png);; BMP (*.bmp);; JPEG (*.jpg *.jpeg)", &selectedFilter);
- if (!saveFilename.isEmpty())
- {
- QFileInfo fi(saveFilename);
- if (fi.suffix().isEmpty()) // can be on some platforms
- {
- int i = selectedFilter.indexOf("*.");
- if (i >= 0)
- {
- static QRegularExpression delimiters("[ )]");
- i += 2;
- int j = selectedFilter.indexOf(delimiters, i);
- if (j > i)
- {
- --i;
- QString suffix = selectedFilter.mid(i, j - i);
- saveFilename += suffix;
- }
- }
- }
- if (!m_plot->grab().save(saveFilename))
- {
- QMessageBox::warning(this, "Error",
- QString("Cannot save the chart to \"%1\".").arg(saveFilename), QMessageBox::Ok);
- }
- }
-}
#endif // QWT_FOUND
#include "chartwidget.moc"
diff --git a/src/analyze/gui/chartwidget.h b/src/analyze/gui/chartwidget.h
index c797613..74ab07c 100644
--- a/src/analyze/gui/chartwidget.h
+++ b/src/analyze/gui/chartwidget.h
@@ -23,7 +23,6 @@
#include "contextmenuqwt.h"
#include <memory>
-
#include <QWidget>
//!! for debugging
@@ -57,17 +56,16 @@ public:
QSize sizeHint() const override;
-#if defined(QWT_FOUND)
+#ifdef QWT_FOUND
void updateOnSelected(QWidget *mainWindow);
- static ChartOptions::Options GlobalOptions;
static QWidget* HelpWindow;
static QWidget* MainWindow;
public slots:
void modelReset();
-#ifndef QT_NO_CONTEXTMENU
protected:
+#ifndef QT_NO_CONTEXTMENU
virtual void contextMenuEvent(QContextMenuEvent *event) override;
#endif
// workaround for handling the context menu shortcuts
@@ -87,9 +85,8 @@ private slots:
void toggleShowSymbols();
void toggleShowVLines();
void toggleShowHelp();
- void exportChart();
private:
- void createActions();
+ void connectContextMenu();
void showHelp();
diff --git a/src/analyze/gui/chartwidgetqwtplot.cpp b/src/analyze/gui/chartwidgetqwtplot.cpp
index eab0613..08cefeb 100644
--- a/src/analyze/gui/chartwidgetqwtplot.cpp
+++ b/src/analyze/gui/chartwidgetqwtplot.cpp
@@ -16,6 +16,11 @@
#include <limits>
+ChartOptions::Options ChartOptions::GlobalOptions(
+ ChartOptions::ShowHelp |
+ ChartOptions::ShowTotal | ChartOptions::ShowUnresolved |
+ ChartOptions::ShowLegend | ChartOptions::ShowCurveBorders);
+
class TimeScaleDraw: public QwtScaleDraw
{
virtual QwtText label(double value) const
@@ -99,6 +104,17 @@ ChartOptions::Options ChartOptions::setOption(Options options, Options option, b
return (isOn ? (options | option) : Options(options & ~option));
}
+ChartOptions::Options ChartOptions::setOption(Options option, bool isOn)
+{
+ setOptions(ChartOptions::setOption(m_options, option, isOn));
+ return m_options;
+}
+
+ChartOptions::Options ChartOptions::toggleOption(Options option)
+{
+ return setOption(option, !hasOption(option));
+}
+
ChartWidgetQwtPlot::ChartWidgetQwtPlot(QWidget *parent, Options options)
: QwtPlot(parent), m_model(nullptr), m_isSizeModel(false), ChartOptions(options),
m_zoomer(new Zoomer(this))
@@ -130,17 +146,6 @@ void ChartWidgetQwtPlot::setModel(ChartModel* model)
model->type() == ChartModel::Temporary);
}
-ChartOptions::Options ChartWidgetQwtPlot::setOption(Options option, bool isOn)
-{
- setOptions(ChartOptions::setOption(m_options, option, isOn));
- return m_options;
-}
-
-ChartOptions::Options ChartWidgetQwtPlot::toggleOption(Options option)
-{
- return setOption(option, !hasOption(option));
-}
-
void ChartWidgetQwtPlot::setOptions(Options options)
{
if (m_options != options)
@@ -200,7 +205,8 @@ void ChartWidgetQwtPlot::rebuild(bool resetZoomAndPan)
for (; column < columns; column += 2)
{
QString columnLabel = m_model->getColumnLabel(column);
- if (!hasOption(ShowUnresolved) && columnLabel.startsWith("<unresolved function>"))
+ if (!hasOption(ShowUnresolved) &&
+ Util::isUnresolvedFunction(columnLabel)) // column label starts with a function name
{
continue;
}
@@ -313,7 +319,7 @@ bool ChartWidgetQwtPlot::getCurveTooltip(const QPointF &position, QString &toolt
for (; column < columns; column += 2)
{
if (!hasOption(ShowUnresolved) &&
- m_model->getColumnLabel(column).startsWith("<unresolved function>"))
+ Util::isUnresolvedFunction(m_model->getColumnLabel(column))) // column label starts with a function name
{
continue;
}
diff --git a/src/analyze/gui/chartwidgetqwtplot.h b/src/analyze/gui/chartwidgetqwtplot.h
index e64410e..3bffea5 100644
--- a/src/analyze/gui/chartwidgetqwtplot.h
+++ b/src/analyze/gui/chartwidgetqwtplot.h
@@ -24,6 +24,8 @@ public:
ShowVLines = 0x80
};
+ static Options GlobalOptions;
+
explicit ChartOptions(Options options) { m_options = options; }
static bool hasOption(Options options, Options option) { return (options & option) != 0; }
@@ -34,8 +36,17 @@ public:
bool hasOption(Options option) const { return hasOption(m_options, option); }
+ Options setOption(Options option, bool isOn);
+
+ Options toggleOption(Options option);
+
+ virtual void setOptions(Options options) = 0;
+
protected:
Options m_options;
+
+private:
+ ChartOptions() { }
};
class ChartWidgetQwtPlot : public QwtPlot, public ChartOptions
@@ -49,11 +60,7 @@ public:
bool isSizeModel() const { return m_isSizeModel; }
- Options setOption(Options option, bool isOn);
-
- Options toggleOption(Options option);
-
- void setOptions(Options options);
+ virtual void setOptions(Options options) override;
void rebuild(bool resetZoomAndPan);
diff --git a/src/analyze/gui/contextmenuqwt.cpp b/src/analyze/gui/contextmenuqwt.cpp
index 3defe7e..d844803 100644
--- a/src/analyze/gui/contextmenuqwt.cpp
+++ b/src/analyze/gui/contextmenuqwt.cpp
@@ -133,7 +133,7 @@ void ContextMenuQwt::initializeMenu(QMenu& menu, ChartOptions::Options options)
}
}
-void ContextMenuQwt::handleKeyPress(QKeyEvent *event, ChartOptions::Options options)
+void ContextMenuQwt::handleKeyPress(QKeyEvent *event)
{
if (event->modifiers() & Qt::AltModifier)
{
diff --git a/src/analyze/gui/contextmenuqwt.h b/src/analyze/gui/contextmenuqwt.h
index e15fa80..b2327da 100644
--- a/src/analyze/gui/contextmenuqwt.h
+++ b/src/analyze/gui/contextmenuqwt.h
@@ -24,7 +24,7 @@ public:
void initializeMenu(QMenu& menu, ChartOptions::Options options) const;
- void handleKeyPress(QKeyEvent *event, ChartOptions::Options options);
+ void handleKeyPress(QKeyEvent *event);
private:
QAction* m_resetZoomAction;
diff --git a/src/analyze/gui/histogrammodel.cpp b/src/analyze/gui/histogrammodel.cpp
index 0ddb112..3367922 100644
--- a/src/analyze/gui/histogrammodel.cpp
+++ b/src/analyze/gui/histogrammodel.cpp
@@ -148,3 +148,10 @@ QColor HistogramModel::getColumnColor(int column) const
{
return colorForColumn(column, columnCount());
}
+
+LocationData::Ptr HistogramModel::getLocationData(int row, int column) const
+{
+ const auto& rowData = m_data.at(row);
+ const auto& columnData = rowData.columns[column];
+ return columnData.location;
+}
diff --git a/src/analyze/gui/histogrammodel.h b/src/analyze/gui/histogrammodel.h
index d605423..d91f270 100644
--- a/src/analyze/gui/histogrammodel.h
+++ b/src/analyze/gui/histogrammodel.h
@@ -66,6 +66,8 @@ public:
QColor getColumnColor(int column) const;
+ LocationData::Ptr getLocationData(int row, int column) const;
+
private:
HistogramData m_data;
};
diff --git a/src/analyze/gui/histogramwidget.cpp b/src/analyze/gui/histogramwidget.cpp
index d67bfa3..45d97a5 100644
--- a/src/analyze/gui/histogramwidget.cpp
+++ b/src/analyze/gui/histogramwidget.cpp
@@ -17,6 +17,7 @@
*/
#include "histogramwidget.h"
+#include "chartwidget.h"
#include <QSortFilterProxyModel>
#include <QVBoxLayout>
@@ -32,6 +33,8 @@
#include <KChartGridAttributes>
#include <KChartHeaderFooter>
#include <KChartLegend>
+#elif defined(QWT_FOUND)
+#include <QMenu>
#endif
#ifdef NO_K_LIB
@@ -63,7 +66,6 @@ public:
const QString customizedLabel(const QString& label) const override
{
-//!! KFormat format(QLocale::system());
return Util::formatByteSize(label.toDouble(), 1);
}
};
@@ -102,7 +104,8 @@ HistogramWidget::HistogramWidget(QWidget* parent)
, m_total(new BarDiagram(this))
, m_detailed(new BarDiagram(this))
#elif defined(QWT_FOUND)
- , m_plot(new HistogramWidgetQwtPlot(this))
+ , m_plot(new HistogramWidgetQwtPlot(this, ChartOptions::GlobalOptions))
+ , m_contextMenuQwt(new ContextMenuQwt(this, true))
#endif
#ifdef SHOW_TABLES
, m_tableViewTotal(new QTableView(this))
@@ -114,6 +117,8 @@ HistogramWidget::HistogramWidget(QWidget* parent)
layout->addWidget(m_chart);
#elif defined(QWT_FOUND)
layout->addWidget(m_plot);
+
+ connectContextMenu();
#endif
#ifdef SHOW_TABLES
auto hLayout = new QHBoxLayout();
@@ -209,11 +214,51 @@ void HistogramWidget::setModel(HistogramModel *model)
#endif
}
-#if defined(QWT_FOUND)
+void HistogramWidget::updateOnSelected()
+{
+ m_plot->setOptions(ChartOptions::GlobalOptions);
+}
+
+#ifdef QWT_FOUND
void HistogramWidget::modelReset()
{
m_plot->rebuild();
}
+
+void HistogramWidget::connectContextMenu()
+{
+ connect(m_contextMenuQwt->showTotalAction(), &QAction::triggered, this, &HistogramWidget::toggleShowTotal);
+ connect(m_contextMenuQwt->showUnresolvedAction(), &QAction::triggered, this, &HistogramWidget::toggleShowUnresolved);
+ connect(m_contextMenuQwt->exportChartAction(), &QAction::triggered, this, [=]() {
+ Util::exportChart(this, *m_plot, "Allocation Histogram");
+ });
+
+ setFocusPolicy(Qt::StrongFocus);
+}
+
+#ifndef QT_NO_CONTEXTMENU
+void HistogramWidget::contextMenuEvent(QContextMenuEvent *event)
+{
+ QMenu menu(this);
+ m_contextMenuQwt->initializeMenu(menu, m_plot->options());
+ menu.exec(event->globalPos());
+}
#endif
+void HistogramWidget::keyPressEvent(QKeyEvent *event)
+{
+ m_contextMenuQwt->handleKeyPress(event);
+}
+
+void HistogramWidget::toggleShowTotal()
+{
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowTotal);
+}
+
+void HistogramWidget::toggleShowUnresolved()
+{
+ ChartOptions::GlobalOptions = m_plot->toggleOption(ChartOptions::ShowUnresolved);
+}
+#endif // QWT_FOUND
+
#include "histogramwidget.moc"
diff --git a/src/analyze/gui/histogramwidget.h b/src/analyze/gui/histogramwidget.h
index c05bd13..f2f9662 100644
--- a/src/analyze/gui/histogramwidget.h
+++ b/src/analyze/gui/histogramwidget.h
@@ -20,7 +20,9 @@
#define HISTOGRAMWIDGET_H
#include "gui_config.h"
+#include "contextmenuqwt.h"
+#include <memory>
#include <QWidget>
//!! for debugging
@@ -50,10 +52,18 @@ public:
void setModel(HistogramModel* model);
-#if defined(QWT_FOUND)
+ void updateOnSelected();
+
+#ifdef QWT_FOUND
public slots:
void modelReset();
+protected:
+#ifndef QT_NO_CONTEXTMENU
+ virtual void contextMenuEvent(QContextMenuEvent *event) override;
#endif
+ // workaround for handling the context menu shortcuts
+ virtual void keyPressEvent(QKeyEvent *event) override;
+#endif // QWT_FOUND
private:
#if defined(KChart_FOUND)
@@ -61,7 +71,15 @@ private:
KChart::BarDiagram* m_total;
KChart::BarDiagram* m_detailed;
#elif defined(QWT_FOUND)
+private slots:
+ void toggleShowTotal();
+ void toggleShowUnresolved();
+
+ void connectContextMenu();
+
+private:
HistogramWidgetQwtPlot* m_plot;
+ std::unique_ptr<ContextMenuQwt> m_contextMenuQwt;
#endif
#ifdef SHOW_TABLES
QTableView* m_tableViewTotal;
diff --git a/src/analyze/gui/histogramwidgetqwtplot.cpp b/src/analyze/gui/histogramwidgetqwtplot.cpp
index 3c99a4b..13a692e 100644
--- a/src/analyze/gui/histogramwidgetqwtplot.cpp
+++ b/src/analyze/gui/histogramwidgetqwtplot.cpp
@@ -1,6 +1,7 @@
#include "histogramwidgetqwtplot.h"
#include "histogrammodel.h"
#include "noklib.h"
+#include "util.h"
#include <math.h>
@@ -43,6 +44,12 @@ public:
m_barLeftRight.reserve(BarCount);
}
+ void clear()
+ {
+ m_barRects.clear();
+ m_barLeftRight.clear();
+ }
+
void setBarSize(int sampleIndex, int barIndex, const QwtColumnRect &qwtRect)
{
if (m_barRects.size() <= sampleIndex)
@@ -116,6 +123,13 @@ public:
setTrackerMode(QwtPlotPicker::AlwaysOn);
}
+ virtual void reset() override
+ {
+ QwtPlotPicker::reset();
+ m_totalBarSizes.clear();
+ m_barSizes.clear();
+ }
+
BarSizes m_totalBarSizes;
BarSizes m_barSizes;
@@ -123,7 +137,6 @@ protected:
virtual QwtText trackerText(const QPoint &pos) const
{
// qDebug() << "Picker: (" << pos.x() << "; " << pos.y() << ")";
-// QString s = QString(" (%1, %2) ").arg(pos.x()).arg(pos.y());
HistogramModel *model = m_plot->model();
if (!model)
{
@@ -133,13 +146,14 @@ protected:
QString s;
if (m_barSizes.findBar(pos, sampleIndex, barIndex))
{
-// s = QString("<br> Sample: %1. Bar: %2").arg(sampleIndex).arg(barIndex);
- s = model->data(model->index(sampleIndex, barIndex + 1), Qt::ToolTipRole).toString();
+ s = m_plot->getBarText(false, sampleIndex, barIndex);
+// s += QString("<br> Sample: %1. Bar: %2").arg(sampleIndex).arg(barIndex);
}
- else if (m_totalBarSizes.findBar(pos, sampleIndex, barIndex))
+ else if (m_plot->hasOption(ChartOptions::ShowTotal) &&
+ m_totalBarSizes.findBar(pos, sampleIndex, barIndex))
{
-// s = QString("<br> (Total) Sample: %1. Bar: %2").arg(sampleIndex).arg(barIndex);
- s = model->data(model->index(sampleIndex, 0), Qt::ToolTipRole).toString();
+ s = m_plot->getBarText(true, sampleIndex, barIndex);
+// s += QString("<br> (Total) Sample: %1. Bar: %2").arg(sampleIndex).arg(barIndex);
}
else
{
@@ -172,8 +186,7 @@ protected:
virtual void drawBar( QPainter *painter, int sampleIndex,
int barIndex, const QwtColumnRect &rect) const
{
-// qDebug() << "drawBar: (sampleIndex=" << sampleIndex << "; barIndex=" << barIndex
-// << "; " << rect.toRect() << ")";
+// qDebug() << "drawBar: (sampleIndex=" << sampleIndex << "; barIndex=" << barIndex << "; " << rect.toRect() << ")";
QwtPlotMultiBarChart::drawBar(painter, sampleIndex, barIndex, rect);
m_barSizes->setBarSize(sampleIndex, barIndex, rect);
@@ -183,8 +196,8 @@ private:
BarSizes *m_barSizes;
};
-HistogramWidgetQwtPlot::HistogramWidgetQwtPlot(QWidget *parent)
- : QwtPlot(parent), m_model(nullptr), m_picker(new Picker(this))
+HistogramWidgetQwtPlot::HistogramWidgetQwtPlot(QWidget *parent, Options options)
+ : QwtPlot(parent), ChartOptions(options), m_model(nullptr), m_picker(new Picker(this))
{
setCanvasBackground(Qt::white);
enableAxis(QwtPlot::yRight);
@@ -193,9 +206,21 @@ HistogramWidgetQwtPlot::HistogramWidgetQwtPlot(QWidget *parent)
setAxisTitle(QwtPlot::xBottom, i18n("Requested Allocation Size"));
}
+void HistogramWidgetQwtPlot::setOptions(Options options)
+{
+ if (m_options != options)
+ {
+ m_options = options;
+ rebuild();
+ }
+}
+
void HistogramWidgetQwtPlot::rebuild()
{
+ const double BarLayoutHint = 0.33;
+
detachItems();
+ m_picker->reset();
if (!m_model)
{
@@ -208,14 +233,18 @@ void HistogramWidgetQwtPlot::rebuild()
setAxisAutoScale(QwtPlot::yRight);
- auto totalBarChart = new MultiBarChart(&m_picker->m_totalBarSizes);
- totalBarChart->setStyle(QwtPlotMultiBarChart::Stacked);
- totalBarChart->setLayoutHint(0.33);
- totalBarChart->setLayoutPolicy(QwtPlotMultiBarChart::ScaleSamplesToAxes);
+ MultiBarChart *totalBarChart = nullptr;
+ if (hasOption(ShowTotal))
+ {
+ totalBarChart = new MultiBarChart(&m_picker->m_totalBarSizes);
+ totalBarChart->setStyle(QwtPlotMultiBarChart::Stacked);
+ totalBarChart->setLayoutHint(BarLayoutHint);
+ totalBarChart->setLayoutPolicy(QwtPlotMultiBarChart::ScaleSamplesToAxes);
+ }
auto barChart = new MultiBarChart(&m_picker->m_barSizes);
barChart->setStyle(QwtPlotMultiBarChart::Stacked);
- barChart->setLayoutHint(totalBarChart->layoutHint());
+ barChart->setLayoutHint(BarLayoutHint);
barChart->setLayoutPolicy(QwtPlotMultiBarChart::ScaleSamplesToAxes);
QVector<QString> rowNames;
@@ -228,15 +257,26 @@ void HistogramWidgetQwtPlot::rebuild()
{
rowNames.append(m_model->headerData(row, Qt::Vertical).toString());
- QVector<double> totalValues;
- totalValues.append(m_model->data(m_model->index(row, 0)).toDouble());
- totalSeries.append(totalValues);
+ if (totalBarChart)
+ {
+ QVector<double> totalValues;
+ totalValues.append(m_model->data(m_model->index(row, 0)).toDouble());
+ totalSeries.append(totalValues);
+ }
QVector<double> values;
for (int column = 1; column < columns; ++column)
{
+ if (!hasOption(ShowUnresolved))
+ {
+ LocationData::Ptr locData = m_model->getLocationData(row, column);
+ if (locData && Util::isUnresolvedFunction(locData->function))
+ {
+ continue;
+ }
+ }
double allocations = m_model->data(m_model->index(row, column)).toDouble();
- if ((allocations == 0) && (column > 1))
+ if (allocations == 0) // columns are sorted by allocations descending
{
break;
}
@@ -246,10 +286,14 @@ void HistogramWidgetQwtPlot::rebuild()
maxColumn = column;
}
}
+ if (values.isEmpty())
+ {
+ values.append(0);
+ }
series.append(values);
}
- for (int column = 0; column <= maxColumn; ++column)
+ for (int column = (totalBarChart ? 0 : 1); column <= maxColumn; ++column)
{
auto symbol = new QwtColumnSymbol(QwtColumnSymbol::Box);
symbol->setLineWidth(2);
@@ -264,7 +308,13 @@ void HistogramWidgetQwtPlot::rebuild()
}
}
- totalBarChart->setSamples(totalSeries);
+ if (totalBarChart)
+ {
+ totalBarChart->setSamples(totalSeries);
+ totalBarChart->setAxes(QwtPlot::xBottom, QwtPlot::yRight);
+ totalBarChart->attach(this);
+ }
+
barChart->setSamples(series);
auto bottomScale = new HistogramScaleDraw(rowNames);
@@ -272,9 +322,45 @@ void HistogramWidgetQwtPlot::rebuild()
bottomScale->enableComponent(QwtScaleDraw::Ticks, false);
setAxisScaleDraw(QwtPlot::xBottom, bottomScale);
- totalBarChart->setAxes(QwtPlot::xBottom, QwtPlot::yRight);
barChart->setAxes(QwtPlot::xBottom, QwtPlot::yRight);
- totalBarChart->attach(this);
barChart->attach(this);
+
+ replot();
+}
+
+QString HistogramWidgetQwtPlot::getBarText(bool isTotal, int sampleIndex, int barIndex) const
+{
+ QString result;
+ if (isTotal)
+ {
+ result = m_model->data(m_model->index(sampleIndex, 0), Qt::ToolTipRole).toString();
+ }
+ else
+ {
+ if (hasOption(ShowUnresolved))
+ {
+ result = m_model->data(m_model->index(sampleIndex, barIndex + 1), Qt::ToolTipRole).toString();
+ }
+ else // skip unresolved functions
+ {
+ int indexOfResolved = 0;
+ int columns = m_model->columnCount();
+ for (int column = 1; column < columns; ++column)
+ {
+ LocationData::Ptr locData = m_model->getLocationData(sampleIndex, column);
+ if (locData && Util::isUnresolvedFunction(locData->function))
+ {
+ continue;
+ }
+ if (indexOfResolved == barIndex)
+ {
+ result = m_model->data(m_model->index(sampleIndex, column), Qt::ToolTipRole).toString();
+ break;
+ }
+ ++indexOfResolved;
+ }
+ }
+ }
+ return result;
}
diff --git a/src/analyze/gui/histogramwidgetqwtplot.h b/src/analyze/gui/histogramwidgetqwtplot.h
index 6a20014..e42aad6 100644
--- a/src/analyze/gui/histogramwidgetqwtplot.h
+++ b/src/analyze/gui/histogramwidgetqwtplot.h
@@ -1,23 +1,33 @@
#ifndef HISTOGRAMWIDGETQWTPLOT_H
#define HISTOGRAMWIDGETQWTPLOT_H
+#include "chartwidgetqwtplot.h"
+
#include <qwt_plot.h>
+#include <QString>
+
class HistogramModel;
class Picker;
-class HistogramWidgetQwtPlot : public QwtPlot
+class HistogramWidgetQwtPlot : public QwtPlot, public ChartOptions
{
public:
- explicit HistogramWidgetQwtPlot(QWidget *parent);
+ explicit HistogramWidgetQwtPlot(QWidget *parent, Options options);
void setModel(HistogramModel *model) { m_model = model; }
HistogramModel *model() const { return m_model; }
+ virtual void setOptions(Options options) override;
+
void rebuild();
private:
+ friend class Picker;
+
+ QString getBarText(bool isTotal, int sampleIndex, int barIndex) const;
+
HistogramModel *m_model;
Picker *m_picker;
diff --git a/src/analyze/gui/mainwindow.cpp b/src/analyze/gui/mainwindow.cpp
index 8d045ca..6837b17 100644
--- a/src/analyze/gui/mainwindow.cpp
+++ b/src/analyze/gui/mainwindow.cpp
@@ -699,9 +699,15 @@ void MainWindow::setupStacks()
chartWidget->updateOnSelected(this);
chartWidget->setFocus(); // to handle keyboard events in the widget
}
- else if (ChartWidget::HelpWindow != nullptr)
- {
- ChartWidget::HelpWindow->hide();
+ else {
+ if (ChartWidget::HelpWindow != nullptr) {
+ ChartWidget::HelpWindow->hide();
+ }
+ const auto histogramWidget = dynamic_cast<HistogramWidget*>(widget);
+ if (histogramWidget) {
+ histogramWidget->updateOnSelected();
+ histogramWidget->setFocus();
+ }
}
#endif
};
@@ -711,7 +717,7 @@ void MainWindow::setupStacks()
m_ui->stacksDock->setVisible(false);
}
-#if defined(QWT_FOUND)
+#ifdef QWT_FOUND
void MainWindow::moveEvent(QMoveEvent *event)
{
if (ChartWidget::HelpWindow != nullptr)
diff --git a/src/analyze/gui/mainwindow.h b/src/analyze/gui/mainwindow.h
index 2f09d10..67751ff 100644
--- a/src/analyze/gui/mainwindow.h
+++ b/src/analyze/gui/mainwindow.h
@@ -50,7 +50,7 @@ public slots:
signals:
void clearData();
-#if defined(QWT_FOUND)
+#ifdef QWT_FOUND
protected:
virtual void moveEvent(QMoveEvent *event) override;
#endif
diff --git a/src/analyze/gui/util.cpp b/src/analyze/gui/util.cpp
index 00ea260..6d896c6 100644
--- a/src/analyze/gui/util.cpp
+++ b/src/analyze/gui/util.cpp
@@ -25,7 +25,15 @@
#include <KFormat>
#endif
-QString Util::formatTime(qint64 ms)
+#ifdef QWT_FOUND
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QMessageBox>
+#endif
+
+namespace Util {
+
+QString formatTime(qint64 ms)
{
if (ms > 60000) {
// minutes
@@ -36,7 +44,7 @@ QString Util::formatTime(qint64 ms)
}
}
-QString Util::formatByteSize(double size, int precision)
+QString formatByteSize(double size, int precision)
{
#ifndef NO_K_LIB
static KFormat format;
@@ -87,7 +95,7 @@ QString Util::formatByteSize(double size, int precision)
#endif
}
-QString Util::wrapLabel(QString label, int maxLineLength, int lastLineExtra,
+QString wrapLabel(QString label, int maxLineLength, int lastLineExtra,
const QString& delimiter)
{
int labelLength = label.size();
@@ -146,3 +154,46 @@ QString Util::wrapLabel(QString label, int maxLineLength, int lastLineExtra,
result += label.toHtmlEscaped();
return result;
}
+
+#ifdef QWT_FOUND
+bool isUnresolvedFunction(const QString &functionName)
+{
+ return functionName.startsWith("<unresolved function>");
+}
+
+bool exportChart(QWidget *parent, QWidget &chartWidget, const QString &chartName)
+{
+ QString selectedFilter;
+ QString saveFilename = QFileDialog::getSaveFileName(parent, "Save Chart As",
+ chartName, "PNG (*.png);; BMP (*.bmp);; JPEG (*.jpg *.jpeg)", &selectedFilter);
+ if (!saveFilename.isEmpty())
+ {
+ QFileInfo fi(saveFilename);
+ if (fi.suffix().isEmpty()) // can be on some platforms
+ {
+ int i = selectedFilter.indexOf("*.");
+ if (i >= 0)
+ {
+ static QRegularExpression delimiters("[ )]");
+ i += 2;
+ int j = selectedFilter.indexOf(delimiters, i);
+ if (j > i)
+ {
+ --i;
+ QString suffix = selectedFilter.mid(i, j - i);
+ saveFilename += suffix;
+ }
+ }
+ }
+ if (chartWidget.grab().save(saveFilename))
+ {
+ return true;
+ }
+ }
+ QMessageBox::warning(parent, "Error",
+ QString("Cannot save the chart to \"%1\".").arg(saveFilename), QMessageBox::Ok);
+ return false;
+}
+#endif
+
+} // namespace Util
diff --git a/src/analyze/gui/util.h b/src/analyze/gui/util.h
index 7f651a0..f2dfaa5 100644
--- a/src/analyze/gui/util.h
+++ b/src/analyze/gui/util.h
@@ -19,9 +19,15 @@
#ifndef UTIL_H
#define UTIL_H
+#include "gui_config.h"
+
#include <qglobal.h>
#include <QString>
+#ifdef QWT_FOUND
+#include <QWidget>
+#endif
+
namespace Util {
QString formatTime(qint64 ms);
@@ -31,6 +37,11 @@ QString formatByteSize(double size, int precision = 1);
QString wrapLabel(QString label, int maxLineLength, int lastLineExtra = 0,
const QString &delimiter = QString("<br>"));
+#ifdef QWT_FOUND
+bool isUnresolvedFunction(const QString &functionName);
+
+bool exportChart(QWidget *parent, QWidget &chartWidget, const QString &chartName);
+#endif
}
#endif // UTIL_H