Reduces memory consumption when the flame graph is not being displayed.
#include <QGraphicsScene>
#include <QStyleOption>
#include <QGraphicsView>
-#include <QGraphicsItem>
+#include <QGraphicsRectItem>
#include <QWheelEvent>
#include <QEvent>
#include <QToolTip>
#include <KLocalizedString>
#include <KColorScheme>
+class FrameGraphicsItem : public QGraphicsRectItem
+{
+public:
+ FrameGraphicsItem(const quint64 cost, const QString& function, FrameGraphicsItem* parent = nullptr);
+
+ quint64 cost() const;
+ void setCost(quint64 cost);
+ QString function() const;
+
+ void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override;
+
+protected:
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
+ void showToolTip() const;
+
+private:
+ quint64 m_cost;
+ QString m_function;
+ bool m_isHovered;
+};
+
FrameGraphicsItem::FrameGraphicsItem(const quint64 cost, const QString& function, FrameGraphicsItem* parent)
: QGraphicsRectItem(parent)
, m_cost(cost)
}
}
+FrameGraphicsItem* parseData(const QVector<RowData>& topDownData)
+{
+ double totalCost = 0;
+ foreach(const auto& frame, topDownData) {
+ totalCost += frame.allocations;
+ }
+
+ KColorScheme scheme(QPalette::Active);
+ const QPen pen(scheme.foreground().color());
+
+ auto rootItem = new FrameGraphicsItem(totalCost, i18n("%1 allocations in total", totalCost));
+ rootItem->setBrush(scheme.background());
+ rootItem->setPen(pen);
+ toGraphicsItems(topDownData, rootItem);
+ return rootItem;
+}
+
}
FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags)
return ret;
}
+void FlameGraph::showEvent(QShowEvent* event)
+{
+ setData(parseData(m_topDownData));
+ QWidget::showEvent(event);
+}
+
+void FlameGraph::hideEvent(QHideEvent* event)
+{
+ setData(nullptr);
+ QWidget::hideEvent(event);
+}
+
+void FlameGraph::setTopDownData(const TreeData& topDownData)
+{
+ m_topDownData = topDownData;
+ if (isVisible()) {
+ setData(parseData(topDownData));
+ }
+}
+
void FlameGraph::setData(FrameGraphicsItem* rootItem)
{
m_scene->clear();
m_rootItem = rootItem;
m_selectedItem = rootItem;
+ if (!rootItem) {
+ return;
+ }
+
// layouting needs a root item with a given height, the rest will be overwritten later
rootItem->setRect(0, 0, 800, m_view->fontMetrics().height() + 4);
m_scene->addItem(rootItem);
}
}
-FrameGraphicsItem* FlameGraph::parseData(const QVector<RowData>& topDownData)
-{
- double totalCost = 0;
- foreach(const auto& frame, topDownData) {
- totalCost += frame.allocations;
- }
-
- KColorScheme scheme(QPalette::Active);
- const QPen pen(scheme.foreground().color());
-
- auto rootItem = new FrameGraphicsItem(totalCost, i18n("%1 allocations in total", totalCost));
- rootItem->setBrush(scheme.background());
- rootItem->setPen(pen);
- toGraphicsItems(topDownData, rootItem);
- return rootItem;
-}
-
void FlameGraph::selectItem(FrameGraphicsItem* item)
{
if (!item) {
#define FLAMEGRAPH_H
#include <QWidget>
-#include <QGraphicsRectItem>
#include "treemodel.h"
class QGraphicsScene;
class QGraphicsView;
-class FrameGraphicsItem : public QGraphicsRectItem
-{
-public:
- FrameGraphicsItem(const quint64 cost, const QString& function, FrameGraphicsItem* parent = nullptr);
-
- quint64 cost() const;
- void setCost(quint64 cost);
- QString function() const;
-
- void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override;
-
-protected:
- void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
- void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
- void showToolTip() const;
-
-private:
- quint64 m_cost;
- QString m_function;
- bool m_isHovered;
-};
+class FrameGraphicsItem;
class FlameGraph : public QWidget
{
FlameGraph(QWidget* parent = nullptr, Qt::WindowFlags flags = 0);
~FlameGraph();
- void setData(FrameGraphicsItem* rootFrame);
- // called from background thread
- static FrameGraphicsItem* parseData(const QVector<RowData>& topDownData);
+ void setTopDownData(const TreeData& topDownData);
protected:
bool eventFilter(QObject* object, QEvent* event) override;
+ void showEvent(QShowEvent* event) override;
+ void hideEvent(QHideEvent* event) override;
private:
+ void setData(FrameGraphicsItem* rootItem);
void selectItem(FrameGraphicsItem* item);
+ TreeData m_topDownData;
+
QGraphicsScene* m_scene;
QGraphicsView* m_view;
FrameGraphicsItem* m_rootItem;
allocationsModel, &ChartModel::resetData);
connect(m_parser, &Parser::summaryAvailable,
m_ui->summary, &QLabel::setText);
- connect(m_parser, &Parser::flameGraphDataAvailable,
- m_ui->flameGraphTab, &FlameGraph::setData);
+ connect(m_parser, &Parser::topDownDataAvailable,
+ m_ui->flameGraphTab, &FlameGraph::setTopDownData);
connect(m_parser, &Parser::finished,
this, [&] { m_ui->pages->setCurrentWidget(m_ui->resultsPage); });
#include <QDebug>
#include "../accumulatedtracedata.h"
-#include "flamegraph.h"
#include <vector>
#include <memory>
emit bottomUpDataAvailable(mergedAllocations);
const auto topDownData = toTopDownData(mergedAllocations);
emit topDownDataAvailable(topDownData);
- // TODO: do this on-demand when the flame graph is shown for the first time
- emit flameGraphDataAvailable(FlameGraph::parseData(topDownData));
}) << make_job([this, data, stdPath]() {
// this mutates data, and thus anything running in parallel must
// not access data
#include "treemodel.h"
#include "chartmodel.h"
-class FrameGraphicsItem;
-
class Parser : public QObject
{
Q_OBJECT
void consumedChartDataAvailable(const ChartData& data);
void allocationsChartDataAvailable(const ChartData& data);
void allocatedChartDataAvailable(const ChartData& data);
- void flameGraphDataAvailable(FrameGraphicsItem* rootItem);
void finished();
};