diff options
author | Alexey Chernobaev <achernobaev@dev.rtsoft.ru> | 2018-03-25 01:48:26 +0300 |
---|---|---|
committer | Alexey Chernobaev <achernobaev@dev.rtsoft.ru> | 2018-03-25 01:48:26 +0300 |
commit | f1d2f7d7dad7a4d8ae6dd8164e4b103a312f04c4 (patch) | |
tree | 0d5f1436dada0a46761ca3d5eb9910b2bfd6581f /src/analyze | |
parent | 62ad2e1d17a8b820a3c104356494c8112b41f12b (diff) | |
download | heaptrack-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.cpp | 81 | ||||
-rw-r--r-- | src/analyze/gui/chartwidget.h | 9 | ||||
-rw-r--r-- | src/analyze/gui/chartwidgetqwtplot.cpp | 32 | ||||
-rw-r--r-- | src/analyze/gui/chartwidgetqwtplot.h | 17 | ||||
-rw-r--r-- | src/analyze/gui/contextmenuqwt.cpp | 2 | ||||
-rw-r--r-- | src/analyze/gui/contextmenuqwt.h | 2 | ||||
-rw-r--r-- | src/analyze/gui/histogrammodel.cpp | 7 | ||||
-rw-r--r-- | src/analyze/gui/histogrammodel.h | 2 | ||||
-rw-r--r-- | src/analyze/gui/histogramwidget.cpp | 51 | ||||
-rw-r--r-- | src/analyze/gui/histogramwidget.h | 20 | ||||
-rw-r--r-- | src/analyze/gui/histogramwidgetqwtplot.cpp | 132 | ||||
-rw-r--r-- | src/analyze/gui/histogramwidgetqwtplot.h | 14 | ||||
-rw-r--r-- | src/analyze/gui/mainwindow.cpp | 14 | ||||
-rw-r--r-- | src/analyze/gui/mainwindow.h | 2 | ||||
-rw-r--r-- | src/analyze/gui/util.cpp | 57 | ||||
-rw-r--r-- | src/analyze/gui/util.h | 11 |
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 |