From 58c23536604bb82b25cd76e50fb6befbcbabc4c0 Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Sun, 29 May 2016 19:39:51 +0200 Subject: [PATCH] Make it possible to go back/forward in flamegraph via keyboard. We keep a simple list of items around that got selected and use that when the user presses the standard back/forward keys to reset the view state accordingly. --- gui/flamegraph.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++----- gui/flamegraph.h | 9 +++++++-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/gui/flamegraph.cpp b/gui/flamegraph.cpp index f98f07b..eda8f8a 100644 --- a/gui/flamegraph.cpp +++ b/gui/flamegraph.cpp @@ -334,7 +334,6 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags) , m_view(new QGraphicsView(this)) , m_displayLabel(new QLabel) , m_rootItem(nullptr) - , m_selectedItem(nullptr) , m_minRootWidth(0) { qRegisterMetaType(); @@ -400,6 +399,21 @@ FlameGraph::FlameGraph(QWidget* parent, Qt::WindowFlags flags) layout()->addWidget(controls); layout()->addWidget(m_view); layout()->addWidget(m_displayLabel); + + { + auto action = new QAction(tr("back"), this); + action->setShortcuts({QKeySequence::Back, Qt::Key_Backspace}); + connect(action, &QAction::triggered, + this, &FlameGraph::navigateBack); + addAction(action); + } + { + auto action = new QAction(tr("forward"), this); + action->setShortcuts(QKeySequence::Forward); + connect(action, &QAction::triggered, + this, &FlameGraph::navigateForward); + addAction(action); + } } FlameGraph::~FlameGraph() = default; @@ -411,7 +425,15 @@ bool FlameGraph::eventFilter(QObject* object, QEvent* event) if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent* mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton) { - selectItem(static_cast(m_view->itemAt(mouseEvent->pos()))); + auto item = static_cast(m_view->itemAt(mouseEvent->pos())); + if (item && item != m_selectionHistory.at(m_selectedItem)) { + selectItem(item); + if (m_selectedItem != m_selectionHistory.size() - 1) { + m_selectionHistory.remove(m_selectedItem + 1, m_selectionHistory.size() - m_selectedItem - 1); + } + m_selectedItem = m_selectionHistory.size(); + m_selectionHistory.push_back(item); + } } } else if (event->type() == QEvent::MouseMove) { QMouseEvent* mouseEvent = static_cast(event); @@ -427,7 +449,7 @@ bool FlameGraph::eventFilter(QObject* object, QEvent* event) if (!m_rootItem) { showData(); } else { - selectItem(m_selectedItem); + selectItem(m_selectionHistory.at(m_selectedItem)); } } else if (event->type() == QEvent::Hide) { setData(nullptr); @@ -473,7 +495,9 @@ void FlameGraph::setData(FrameGraphicsItem* rootItem) { m_scene->clear(); m_rootItem = rootItem; - m_selectedItem = rootItem; + m_selectionHistory.clear(); + m_selectionHistory.push_back(rootItem); + m_selectedItem = 0; if (!rootItem) { auto text = m_scene->addText(i18n("generating flame graph...")); m_view->centerOn(text); @@ -519,6 +543,20 @@ void FlameGraph::selectItem(FrameGraphicsItem* item) // and make sure it's visible m_view->centerOn(item); +} - m_selectedItem = item; +void FlameGraph::navigateBack() +{ + if (m_selectedItem > 0) { + --m_selectedItem; + } + selectItem(m_selectionHistory.at(m_selectedItem)); +} + +void FlameGraph::navigateForward() +{ + if ((m_selectedItem + 1) < m_selectionHistory.size()) { + ++m_selectedItem; + } + selectItem(m_selectionHistory.at(m_selectedItem)); } diff --git a/gui/flamegraph.h b/gui/flamegraph.h index 02bc3e1..355b070 100644 --- a/gui/flamegraph.h +++ b/gui/flamegraph.h @@ -21,6 +21,8 @@ #define FLAMEGRAPH_H #include +#include + #include "treemodel.h" class QGraphicsScene; @@ -49,6 +51,8 @@ private slots: void setData(FrameGraphicsItem* rootItem); private: + void navigateBack(); + void navigateForward(); void showData(); void selectItem(FrameGraphicsItem* item); @@ -60,8 +64,9 @@ private: QGraphicsView* m_view; QLabel* m_displayLabel; FrameGraphicsItem* m_rootItem; - FrameGraphicsItem* m_selectedItem; - int m_minRootWidth; + QVector m_selectionHistory; + int m_selectedItem = -1; + int m_minRootWidth = 0; bool m_showBottomUpData = false; // cost threshold in percent, items below that value will not be shown double m_costThreshold = 0.1; -- 2.7.4