0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-26 16:11:02 +08:00

(ProfGraphicsView) Selecting items on scene;

(ProfGraphicsView) Clickable indicators of ProfChronometerItem;
(ProfTreeWidget) Jump to items on scene from ProfTreeWidget;
(profiler GUI) Fixed typos and warnings;
This commit is contained in:
Victor Zarubkin 2016-08-08 22:17:56 +03:00
parent 00602398fb
commit f0f82c01e2
8 changed files with 390 additions and 93 deletions

View File

@ -157,7 +157,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
// Search for first visible top-level item
auto& level0 = m_levels[0];
auto& level0 = m_levels.front();
auto first = ::std::lower_bound(level0.begin(), level0.end(), sceneLeft, [](const ::profiler_gui::ProfBlockItem& _item, qreal _value)
{
return _item.left() < _value;
@ -261,7 +261,16 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setBrush(brush);
}
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders)
bool changepen = false;
if (!m_bTest && item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
{
changepen = true;
QPen pen(Qt::SolidLine);
pen.setColor(Qt::red);
pen.setWidth(2);
_painter->setPen(pen);
}
else if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders)
{
if (w < 3)
{
@ -284,6 +293,14 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
rect.setRect(x, item.top(), w, item.totalHeight);
_painter->drawRect(rect);
if (changepen)
{
if (previousPenStyle == Qt::NoPen)
_painter->setPen(Qt::NoPen);
else
_painter->setPen(BORDERS_COLOR); // restore pen for rectangle painting
}
if (next_level < levelsNumber && item.children_begin != -1)
{
// Mark that we would not paint children of current item
@ -326,7 +343,14 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setBrush(brush);
}
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders && previousPenStyle != Qt::SolidLine)
if (!m_bTest && item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
{
QPen pen(Qt::SolidLine);
pen.setColor(Qt::red);
pen.setWidth(2);
_painter->setPen(pen);
}
else if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders && previousPenStyle != Qt::SolidLine)
{
// Restore pen for item which is wide enough to paint borders
previousPenStyle = Qt::SolidLine;
@ -370,13 +394,9 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
// restore previous pen color
if (previousPenStyle == Qt::NoPen)
{
_painter->setPen(Qt::NoPen);
}
else
{
_painter->setPen(BORDERS_COLOR); // restore pen for rectangle painting
}
// END Draw text~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
}
@ -394,7 +414,7 @@ void ProfGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tree
//}
// Search for first visible top-level item
auto& level0 = m_levels[0];
auto& level0 = m_levels.front();
auto first = ::std::lower_bound(level0.begin(), level0.end(), _left, [](const ::profiler_gui::ProfBlockItem& _item, qreal _value)
{
return _item.left() < _value;
@ -436,6 +456,128 @@ void ProfGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tree
//////////////////////////////////////////////////////////////////////////
const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF& _pos) const
{
if (m_levels.empty() || m_levels.front().empty())
{
return nullptr;
}
const auto& level0 = m_levels.front();
const auto top = level0.front().top();
if (top > _pos.y())
{
return nullptr;
}
const auto bottom = top + m_levels.size() * GRAPHICS_ROW_SIZE_FULL;
if (bottom < _pos.y())
{
return nullptr;
}
const unsigned int levelIndex = static_cast<unsigned int>(_pos.y() - top) / GRAPHICS_ROW_SIZE_FULL;
if (levelIndex >= m_levels.size())
{
return nullptr;
}
const auto currentScale = view()->scale();
unsigned int i = 0;
size_t itemIndex = -1;
size_t firstItem = 0, lastItem = static_cast<unsigned int>(level0.size());
while (i <= levelIndex)
{
const auto& level = m_levels[i];
// Search for first visible item
auto first = ::std::lower_bound(level.begin() + firstItem, level.begin() + lastItem, _pos.x(), [](const ::profiler_gui::ProfBlockItem& _item, qreal _value)
{
return _item.left() < _value;
});
if (first != level.end())
{
itemIndex = first - level.begin();
if (itemIndex != 0)
--itemIndex;
}
else
{
itemIndex = level.size() - 1;
}
for (auto size = level.size(); itemIndex < size; ++itemIndex)
{
const auto& item = level[itemIndex];
if (item.left() > _pos.x())
{
return nullptr;
}
if (item.right() < _pos.x())
{
continue;
}
const auto w = item.width() * currentScale;
if (i == levelIndex || w < 20)
{
return &item;
}
if (item.children_begin == -1)
{
if (itemIndex != 0)
{
auto j = itemIndex;
firstItem = 0;
do {
--j;
const auto& item2 = level[j];
if (item2.children_begin != -1)
{
firstItem = item2.children_begin;
break;
}
} while (j != 0);
}
else
{
firstItem = 0;
}
}
else
{
firstItem = item.children_begin;
}
lastItem = m_levels[i + 1].size();
for (auto j = itemIndex + 1; j < size; ++j)
{
const auto& item2 = level[j];
if (item2.children_begin != -1)
{
lastItem = item2.children_begin;
break;
}
}
break;
}
++i;
}
return nullptr;
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsItem::setBackgroundColor(QRgb _color)
{
m_backgroundColor = _color;
@ -503,7 +645,7 @@ unsigned int ProfGraphicsItem::addItem(unsigned short _level)
//////////////////////////////////////////////////////////////////////////
ProfChronometerItem::ProfChronometerItem(bool _main) : QGraphicsItem(), m_font(QFont("CourierNew", 16, 2)), m_color(CHRONOMETER_COLOR), m_left(0), m_right(0), m_bMain(_main), m_bReverse(false)
ProfChronometerItem::ProfChronometerItem(bool _main) : QGraphicsItem(), m_font(QFont("CourierNew", 16, 2)), m_color(CHRONOMETER_COLOR), m_left(0), m_right(0), m_bMain(_main), m_bReverse(false), m_bHover(false)
{
setZValue(10);
m_indicator.reserve(3);
@ -526,34 +668,41 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
const auto visibleSceneRect = sceneView->visibleSceneRect();
auto sceneLeft = offset, sceneRight = offset + visibleSceneRect.width() / currentScale;
if (m_bMain)
m_indicator.clear();
if (m_left > sceneRight || m_right < sceneLeft)
{
// This item is out of screen
if (m_bMain)
{
const int size = m_bHover ? 12 : 10;
auto vcenter = visibleSceneRect.top() + visibleSceneRect.height() * 0.5;
auto color = QColor::fromRgb(m_color.rgb());
auto pen = _painter->pen();
pen.setColor(color);
m_indicator.clear();
if (m_left > sceneRight)
{
sceneRight = (sceneRight - offset) * currentScale;
m_indicator.push_back(QPointF(sceneRight - 10, vcenter - 10));
m_indicator.push_back(QPointF(sceneRight - size, vcenter - size));
m_indicator.push_back(QPointF(sceneRight, vcenter));
m_indicator.push_back(QPointF(sceneRight - 10, vcenter + 10));
m_indicator.push_back(QPointF(sceneRight - size, vcenter + size));
}
else
{
sceneLeft = (sceneLeft - offset) * currentScale;
m_indicator.push_back(QPointF(sceneLeft + 10, vcenter - 10));
m_indicator.push_back(QPointF(sceneLeft + size, vcenter - size));
m_indicator.push_back(QPointF(sceneLeft, vcenter));
m_indicator.push_back(QPointF(sceneLeft + 10, vcenter + 10));
m_indicator.push_back(QPointF(sceneLeft + size, vcenter + size));
}
_painter->save();
_painter->setTransform(QTransform::fromTranslate(-x(), -y()), true);
_painter->setBrush(QColor::fromRgb(m_color.rgb()));
_painter->setPen(Qt::NoPen);
_painter->setBrush(m_bHover ? QColor::fromRgb(0xffff0000) : color);
_painter->setPen(pen);
_painter->drawPolygon(m_indicator);
_painter->restore();
}
@ -637,6 +786,15 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
// END Paint!~~~~~~~~~~~~~~~~~~~~~~
}
bool ProfChronometerItem::contains(const QPointF& _pos) const
{
const auto sceneView = view();
const auto clickX = (_pos.x() - sceneView->offset()) * sceneView->scale() - x();
if (!m_indicator.empty() && m_indicator.containsPoint(QPointF(clickX, _pos.y()), Qt::OddEvenFill))
return true;
return false;
}
void ProfChronometerItem::setColor(const QColor& _color)
{
m_color = _color;
@ -671,6 +829,11 @@ void ProfChronometerItem::setReverse(bool _reverse)
m_bReverse = _reverse;
}
void ProfChronometerItem::setHover(bool _hover)
{
m_bHover = _hover;
}
const ProfGraphicsView* ProfChronometerItem::view() const
{
return static_cast<const ProfGraphicsView*>(scene()->parent());
@ -875,9 +1038,13 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
m_offset = 0;
updateVisibleSceneRect();
setScrollbar(m_pScrollbar);
m_pScrollbar->setMinimapFrom(0, longestItem->items(0));
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
emit ::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(0);
if (longestItem != nullptr)
{
m_pScrollbar->setMinimapFrom(0, longestItem->items(0));
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
emit::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(0);
}
// Create new chronometer item (previous item was destroyed by scene on scene()->clear()).
// It will be shown on mouse right button click.
@ -926,6 +1093,11 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
// clear scene
clearSilent();
if (_blocksTree.empty())
{
return;
}
// set new blocks tree
// calculate scene size and fill it with items
@ -991,9 +1163,13 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
// Center view on the beginning of the scene
updateVisibleSceneRect();
setScrollbar(m_pScrollbar);
m_pScrollbar->setMinimapFrom(longestItem->threadId(), longestItem->items(0));
::profiler_gui::EASY_GLOBALS.selected_thread = longestItem->threadId();
emit ::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(longestItem->threadId());
if (longestItem != nullptr)
{
m_pScrollbar->setMinimapFrom(longestItem->threadId(), longestItem->items(0));
::profiler_gui::EASY_GLOBALS.selected_thread = longestItem->threadId();
emit::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(longestItem->threadId());
}
// Create new chronometer item (previous item was destroyed by scene on scene()->clear()).
// It will be shown on mouse right button click.
@ -1192,15 +1368,11 @@ void ProfGraphicsView::mousePressEvent(QMouseEvent* _event)
}
m_mouseButtons = _event->buttons();
if (m_mouseButtons & Qt::LeftButton)
{
m_mousePressPos = _event->globalPos();
}
m_mousePressPos = _event->pos();
if (m_mouseButtons & Qt::RightButton)
{
const auto mouseX = m_offset + mapToScene(_event->pos()).x() / m_scale;
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
m_chronometerItem->setLeftRight(mouseX, mouseX);
m_chronometerItem->setReverse(false);
m_chronometerItem->hide();
@ -1219,11 +1391,12 @@ void ProfGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
}
m_mouseButtons = _event->buttons();
m_mousePressPos = _event->pos();
m_bDoubleClick = true;
if (m_mouseButtons & Qt::LeftButton)
{
const auto mouseX = m_offset + mapToScene(_event->pos()).x() / m_scale;
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
m_chronometerItemAux->setLeftRight(mouseX, mouseX);
m_chronometerItemAux->setReverse(false);
m_chronometerItemAux->hide();
@ -1242,12 +1415,13 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
return;
}
bool changedSelection = false;
bool changedSelection = false, clicked = false, changedSelectedItem = false;
if (m_mouseButtons & Qt::RightButton)
{
if (m_chronometerItem->isVisible() && m_chronometerItem->width() < 1e-6)
{
m_chronometerItem->hide();
m_chronometerItem->setHover(false);
m_pScrollbar->hideChrono();
}
@ -1279,10 +1453,39 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
{
m_chronometerItemAux->hide();
}
else if (m_chronometerItem->isVisible() && m_chronometerItem->hover())
{
// Jump to selected zone
clicked = true;
m_flickerSpeedX = m_flickerSpeedY = 0;
m_pScrollbar->setValue(m_chronometerItem->left() + m_chronometerItem->width() * 0.5 - m_pScrollbar->sliderHalfWidth());
}
if (!clicked && m_mouseMovePath.manhattanLength() < 5 && !m_bTest)
{
// Handle Click
clicked = true;
auto mouseClickPos = mapToScene(m_mousePressPos);
mouseClickPos.setX(m_offset + mouseClickPos.x() / m_scale);
// Try to select one of item blocks
for (auto item : m_items)
{
auto block = item->intersect(mouseClickPos);
if (block)
{
changedSelectedItem = true;
::profiler_gui::EASY_GLOBALS.selected_block = block->block->block_index;
break;
}
}
}
}
m_bDoubleClick = false;
m_mouseButtons = _event->buttons();
m_mouseMovePath = QPoint();
_event->accept();
if (changedSelection)
@ -1291,6 +1494,15 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
}
m_chronometerItem->setReverse(false);
if (changedSelectedItem)
{
m_bUpdatingRect = true;
emit ::profiler_gui::EASY_GLOBALS.events.selectedBlockChanged(::profiler_gui::EASY_GLOBALS.selected_block);
m_bUpdatingRect = false;
updateScene();
}
}
//////////////////////////////////////////////////////////////////////////
@ -1333,18 +1545,29 @@ bool ProfGraphicsView::moveChrono(ProfChronometerItem* _chronometerItem, qreal _
void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
{
if (m_bEmpty)
if (m_bEmpty || (m_mouseButtons == 0 && !m_chronometerItem->isVisible()))
{
_event->accept();
return;
}
bool needUpdate = false;
const auto pos = _event->pos();
const auto delta = pos - m_mousePressPos;
m_mousePressPos = pos;
if (m_mouseButtons != 0)
{
m_mouseMovePath.setX(m_mouseMovePath.x() + ::std::abs(delta.x()));
m_mouseMovePath.setY(m_mouseMovePath.y() + ::std::abs(delta.y()));
}
auto mouseScenePos = mapToScene(m_mousePressPos);
mouseScenePos.setX(m_offset + mouseScenePos.x() / m_scale);
if (m_mouseButtons & Qt::RightButton)
{
const auto mouseX = m_offset + mapToScene(_event->pos()).x() / m_scale;
bool showItem = moveChrono(m_chronometerItem, mouseX);
bool showItem = moveChrono(m_chronometerItem, mouseScenePos.x());
m_pScrollbar->setChronoPos(m_chronometerItem->left(), m_chronometerItem->right());
if (showItem)
@ -1359,15 +1582,10 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
{
if (m_bDoubleClick)
{
const auto mouseX = m_offset + mapToScene(_event->pos()).x() / m_scale;
moveChrono(m_chronometerItemAux, mouseX);
moveChrono(m_chronometerItemAux, mouseScenePos.x());
}
else
{
const auto pos = _event->globalPos();
const auto delta = pos - m_mousePressPos;
m_mousePressPos = pos;
auto vbar = verticalScrollBar();
m_bUpdatingRect = true; // Block scrollbars from updating scene rect to make it possible to do it only once
@ -1391,6 +1609,13 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
needUpdate = true;
}
if (m_chronometerItem->isVisible())
{
auto prevValue = m_chronometerItem->hover();
m_chronometerItem->setHover(m_chronometerItem->contains(mouseScenePos));
needUpdate = needUpdate || (prevValue != m_chronometerItem->hover());
}
if (needUpdate)
{
updateScene(); // repaint scene
@ -1424,6 +1649,7 @@ void ProfGraphicsView::initMode()
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &This::onScrollbarValueChange);
connect(&m_flickerTimer, &QTimer::timeout, this, &This::onFlickerTimeout);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::ProfGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::ProfGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
}
//////////////////////////////////////////////////////////////////////////
@ -1515,6 +1741,27 @@ void ProfGraphicsView::onSelectedThreadChange(::profiler::thread_id_t _id)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::onSelectedBlockChange(unsigned int _block_index)
{
if (!m_bUpdatingRect)
{
if (_block_index < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
{
// Scroll to item
const auto& guiblock = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index];
const auto& item = guiblock.graphics_item->items(guiblock.graphics_item_level)[guiblock.graphics_item_index];
m_flickerSpeedX = m_flickerSpeedY = 0;
m_pScrollbar->setValue(item.left() + item.width() * 0.5 - m_pScrollbar->sliderHalfWidth());
}
updateScene();
}
}
//////////////////////////////////////////////////////////////////////////
ProfGraphicsViewWidget::ProfGraphicsViewWidget(bool _test)
: QWidget(nullptr)
, m_scrollbar(new ProfGraphicsScrollbar(nullptr))

View File

@ -127,6 +127,8 @@ public:
\param _blocks Reference to the array of selected blocks */
void getBlocks(qreal _left, qreal _right, ::profiler_gui::TreeBlocks& _blocks) const;
const ::profiler_gui::ProfBlockItem* intersect(const QPointF& _pos) const;
private:
///< Returns pointer to the ProfGraphicsView widget.
@ -145,6 +147,7 @@ class ProfChronometerItem : public QGraphicsItem
qreal m_left, m_right; ///< Left and right bounds of the selection zone
bool m_bMain; ///< Is this chronometer main (true, by default)
bool m_bReverse;
bool m_bHover; ///< Mouse hover above indicator
public:
@ -169,6 +172,15 @@ public:
void setReverse(bool _reverse);
void setHover(bool _hover);
bool contains(const QPointF& _pos) const;
inline bool hover() const
{
return m_bHover;
}
inline bool reverse() const
{
return m_bReverse;
@ -215,6 +227,7 @@ private:
qreal m_scale; ///< Current scale
qreal m_offset; ///< Have to use manual offset for all scene content instead of using scrollbars because QScrollBar::value is 32-bit integer :(
QPoint m_mousePressPos; ///< Last mouse global position (used by mousePressEvent and mouseMoveEvent)
QPoint m_mouseMovePath; ///< Mouse move path between press and release of any button
Qt::MouseButtons m_mouseButtons; ///< Pressed mouse buttons
ProfGraphicsScrollbar* m_pScrollbar; ///< Pointer to the graphics scrollbar widget
ProfChronometerItem* m_chronometerItem; ///< Pointer to the ProfChronometerItem which is displayed when you press right mouse button and move mouse left or right. This item is used to select blocks to display in tree widget.
@ -278,6 +291,7 @@ private slots:
void onGraphicsScrollbarValueChange(qreal);
void onFlickerTimeout();
void onSelectedThreadChange(::profiler::thread_id_t _id);
void onSelectedBlockChange(unsigned int _block_index);
public:

View File

@ -252,6 +252,7 @@ ProfTreeWidget::ProfTreeWidget(QWidget* _parent) : Parent(_parent), m_beginTime(
header->setText(COL_DURATION, "Duration");
header->setText(COL_SELF_DURATION, "Self Dur.");
//header->setToolTip(COL_SELF_DURATION, "");
header->setText(COL_DURATION_SUM_PER_PARENT, "Tot. Dur./Parent");
header->setText(COL_DURATION_SUM_PER_FRAME, "Tot. Dur./Frame");
header->setText(COL_DURATION_SUM_PER_THREAD, "Tot. Dur./Thread");
@ -283,6 +284,7 @@ ProfTreeWidget::ProfTreeWidget(QWidget* _parent) : Parent(_parent), m_beginTime(
setHeaderItem(header);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::ProfGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::ProfGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
loadSettings();
}
@ -332,6 +334,7 @@ void ProfTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, ::
resizeColumnToContents(COL_NAME);
connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
onSelectedBlockChange(::profiler_gui::EASY_GLOBALS.selected_block);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -813,30 +816,46 @@ void ProfTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
connect(action, &QAction::triggered, this, &This::onColorizeRowsTriggered);
menu.addAction(action);
if (item != nullptr && col >= 0)
if (item != nullptr)
{
switch (col)
{
case COL_MIN_PER_THREAD:
case COL_MIN_PER_PARENT:
case COL_MIN_PER_FRAME:
{
menu.addSeparator();
auto itemAction = new ProfItemAction("Jump to such item", item);
connect(itemAction, &ProfItemAction::clicked, this, &This::onJumpToMinItemClicked);
menu.addAction(itemAction);
break;
}
auto itemAction = new ProfItemAction("Show this item on scene", item->block()->block_index);
itemAction->setToolTip("Scroll graphics scene to current item in the tree");
connect(itemAction, &ProfItemAction::clicked, this, &This::onJumpToItemClicked);
menu.addAction(itemAction);
case COL_MAX_PER_THREAD:
case COL_MAX_PER_PARENT:
case COL_MAX_PER_FRAME:
if (col >= 0)
{
switch (col)
{
menu.addSeparator();
auto itemAction = new ProfItemAction("Jump to such item", item);
connect(itemAction, &ProfItemAction::clicked, this, &This::onJumpToMaxItemClicked);
menu.addAction(itemAction);
break;
case COL_MIN_PER_THREAD:
case COL_MIN_PER_PARENT:
case COL_MIN_PER_FRAME:
case COL_MAX_PER_THREAD:
case COL_MAX_PER_PARENT:
case COL_MAX_PER_FRAME:
{
unsigned int i = -1;
switch (col)
{
case COL_MIN_PER_THREAD: i = item->block()->per_thread_stats->min_duration_block; break;
case COL_MIN_PER_PARENT: i = item->block()->per_parent_stats->min_duration_block; break;
case COL_MIN_PER_FRAME: i = item->block()->per_frame_stats->min_duration_block; break;
case COL_MAX_PER_THREAD: i = item->block()->per_thread_stats->max_duration_block; break;
case COL_MAX_PER_PARENT: i = item->block()->per_parent_stats->max_duration_block; break;
case COL_MAX_PER_FRAME: i = item->block()->per_frame_stats->max_duration_block; break;
}
if (i != -1)
{
menu.addSeparator();
itemAction = new ProfItemAction("Jump to such item", i);
itemAction->setToolTip("Jump to item with min/max duration (depending on clicked column)");
connect(itemAction, &ProfItemAction::clicked, this, &This::onJumpToItemClicked);
menu.addAction(itemAction);
}
break;
}
}
}
}
@ -862,24 +881,10 @@ void ProfTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ProfTreeWidget::onJumpToMinItemClicked(ProfTreeWidgetItem* _item)
void ProfTreeWidget::onJumpToItemClicked(unsigned int _block_index)
{
auto item = ::profiler_gui::EASY_GLOBALS.gui_blocks[_item->block()->per_thread_stats->min_duration_block].tree_item;
if (item != nullptr)
{
scrollToItem(item, QAbstractItemView::PositionAtCenter);
setCurrentItem(item);
}
}
void ProfTreeWidget::onJumpToMaxItemClicked(ProfTreeWidgetItem* _item)
{
auto item = ::profiler_gui::EASY_GLOBALS.gui_blocks[_item->block()->per_thread_stats->max_duration_block].tree_item;
if (item != nullptr)
{
scrollToItem(item, QAbstractItemView::PositionAtCenter);
setCurrentItem(item);
}
::profiler_gui::EASY_GLOBALS.selected_block = _block_index;
emit ::profiler_gui::EASY_GLOBALS.events.selectedBlockChanged(_block_index);
}
void ProfTreeWidget::onCollapseAllClicked(bool)
@ -958,6 +963,21 @@ void ProfTreeWidget::onSelectedThreadChange(::profiler::thread_id_t _id)
}
}
void ProfTreeWidget::onSelectedBlockChange(unsigned int _block_index)
{
if (_block_index < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
{
auto item = ::profiler_gui::EASY_GLOBALS.gui_blocks[_block_index].tree_item;
if (item != nullptr)
scrollToItem(item, QAbstractItemView::PositionAtCenter);
setCurrentItem(item);
}
else
{
setCurrentItem(nullptr);
}
}
//////////////////////////////////////////////////////////////////////////
void ProfTreeWidget::resizeColumnsToContents()

View File

@ -94,7 +94,7 @@ public: \
private: \
void onToggle(bool) { emit clicked(m_item); }
DECLARE_QACTION(ProfItemAction, ProfTreeWidgetItem*) signals: void clicked(ProfTreeWidgetItem* _item); };
DECLARE_QACTION(ProfItemAction, unsigned int) signals: void clicked(unsigned int _item); };
DECLARE_QACTION(ProfHideShowColumnAction, int) signals: void clicked(int _item); };
#undef DECLARE_QACTION
@ -144,9 +144,7 @@ protected:
private slots:
void onJumpToMinItemClicked(ProfTreeWidgetItem* _item);
void onJumpToMaxItemClicked(ProfTreeWidgetItem* _item);
void onJumpToItemClicked(unsigned int _block_index);
void onCollapseAllClicked(bool);
@ -162,6 +160,8 @@ private slots:
void onSelectedThreadChange(::profiler::thread_id_t _id);
void onSelectedBlockChange(unsigned int _block_index);
void resizeColumnsToContents();
void onHideShowColumn(int _column);

View File

@ -38,7 +38,7 @@ namespace profiler_gui {
ProfGlobals::ProfGlobals()
: selected_thread(0)
, selected_block(0)
, selected_block(-1)
, draw_graphics_items_borders(true)
{

View File

@ -206,21 +206,23 @@ void ProfMinimapItem::setSource(::profiler::thread_id_t _thread_id, const ::prof
{
m_pSource = nullptr;
}
m_maxDuration = 0;
m_minDuration = 1e30;
for (const auto& item : *m_pSource)
else
{
auto w = item.width();
if (w > m_maxDuration)
m_maxDuration = 0;
m_minDuration = 1e30;
for (const auto& item : *m_pSource)
{
m_maxDuration = item.width();
}
auto w = item.width();
if (w < m_minDuration)
{
m_minDuration = w;
if (w > m_maxDuration)
{
m_maxDuration = item.width();
}
if (w < m_minDuration)
{
m_minDuration = w;
}
}
}
}
@ -325,6 +327,16 @@ qreal ProfGraphicsScrollbar::value() const
return m_value;
}
qreal ProfGraphicsScrollbar::sliderWidth() const
{
return m_slider->width();
}
qreal ProfGraphicsScrollbar::sliderHalfWidth() const
{
return m_slider->halfwidth();
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::setValue(qreal _value)

View File

@ -177,6 +177,8 @@ public:
qreal maximum() const;
qreal range() const;
qreal value() const;
qreal sliderWidth() const;
qreal sliderHalfWidth() const;
void setValue(qreal _value);
void setRange(qreal _minValue, qreal _maxValue);

View File

@ -144,6 +144,7 @@ void ProfMainWindow::onReloadFileClicked(bool)
static_cast<ProfTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::EASY_GLOBALS.selected_block = -1;
::profiler_gui::EASY_GLOBALS.profiler_blocks.swap(prof_blocks);
::profiler_gui::EASY_GLOBALS.gui_blocks.resize(nblocks);
memset(::profiler_gui::EASY_GLOBALS.gui_blocks.data(), 0, sizeof(::profiler_gui::ProfBlock) * nblocks);
@ -171,6 +172,7 @@ void ProfMainWindow::onTestViewportClicked(bool)
::profiler_gui::EASY_GLOBALS.gui_blocks.clear();
::profiler_gui::EASY_GLOBALS.profiler_blocks.clear();
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::EASY_GLOBALS.selected_block = -1;
view->test(18000, 40000000, 2);
//view->test(3, 300, 1);