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

Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Victor Zarubkin 2016-08-08 23:11:27 +03:00
commit c6fb0bfeb9
12 changed files with 578 additions and 534 deletions

View File

@ -17,6 +17,7 @@ add_executable(${PROJECT_NAME}
blocks_tree_widget.cpp
globals.h
globals.cpp
globals_qobjects.cpp
graphics_scrollbar.h
graphics_scrollbar.cpp
main_window.h

View File

@ -1,28 +1,28 @@
/************************************************************************
* file name : blocks_graphics_view.cpp
* ----------------- :
* creation time : 2016/06/26
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of GraphicsScene and GraphicsView and
* : it's auxiliary classes for displyaing easy_profiler blocks tree.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: Moved sources from graphics_view.h
* : and renamed classes from My* to Prof*.
* :
* : * 2016/06/27 Victor Zarubkin: Added text shifting relatively to it's parent item.
* : Disabled border lines painting because of vertical lines painting bug.
* : Changed height of blocks. Variable thread-block height.
* :
* : * 2016/06/29 Victor Zarubkin: Highly optimized painting performance and memory consumption.
* :
* : * 2016/06/30 Victor Zarubkin: Replaced doubles with floats (in ProfBlockItem) for less memory consumption.
* :
* : *
* ----------------- :
* license : TODO: add license text
/************************************************************************
* file name : blocks_graphics_view.cpp
* ----------------- :
* creation time : 2016/06/26
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of GraphicsScene and GraphicsView and
* : it's auxiliary classes for displyaing easy_profiler blocks tree.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: Moved sources from graphics_view.h
* : and renamed classes from My* to Prof*.
* :
* : * 2016/06/27 Victor Zarubkin: Added text shifting relatively to it's parent item.
* : Disabled border lines painting because of vertical lines painting bug.
* : Changed height of blocks. Variable thread-block height.
* :
* : * 2016/06/29 Victor Zarubkin: Highly optimized painting performance and memory consumption.
* :
* : * 2016/06/30 Victor Zarubkin: Replaced doubles with floats (in ProfBlockItem) for less memory consumption.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#include <QWheelEvent>
@ -34,6 +34,8 @@
#include <algorithm>
#include "blocks_graphics_view.h"
#include "globals.h"
using namespace profiler_gui;
//////////////////////////////////////////////////////////////////////////
@ -110,9 +112,9 @@ ProfGraphicsItem::~ProfGraphicsItem()
{
}
const ProfGraphicsView* ProfGraphicsItem::view() const
{
return static_cast<const ProfGraphicsView*>(scene()->parent());
const ProfGraphicsView* ProfGraphicsItem::view() const
{
return static_cast<const ProfGraphicsView*>(scene()->parent());
}
//////////////////////////////////////////////////////////////////////////
@ -243,15 +245,15 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
const auto x = item.left() * currentScale - dx;
//if (previousColor != item.color)
//{
// changebrush = true;
// previousColor = item.color;
// QLinearGradient gradient(x - dx, item.top(), x - dx, item.top() + item.totalHeight);
// gradient.setColorAt(0, item.color);
// gradient.setColorAt(1, 0x00ffffff);
// brush = QBrush(gradient);
// _painter->setBrush(brush);
//if (previousColor != item.color)
//{
// changebrush = true;
// previousColor = item.color;
// QLinearGradient gradient(x - dx, item.top(), x - dx, item.top() + item.totalHeight);
// gradient.setColorAt(0, item.color);
// gradient.setColorAt(1, 0x00ffffff);
// brush = QBrush(gradient);
// _painter->setBrush(brush);
//}
bool changepen = false;
@ -264,18 +266,18 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
pen.setWidth(2);
_painter->setPen(pen);
previousColor = SELECTED_ITEM_COLOR;
brush.setColor(previousColor);
previousColor = SELECTED_ITEM_COLOR;
brush.setColor(previousColor);
_painter->setBrush(brush);
}
else
{
if (previousColor != item.color)
{
// Set background color brush for rectangle
previousColor = item.color;
brush.setColor(previousColor);
_painter->setBrush(brush);
if (previousColor != item.color)
{
// Set background color brush for rectangle
previousColor = item.color;
brush.setColor(previousColor);
_painter->setBrush(brush);
}
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders)
@ -304,24 +306,24 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (changepen)
{
if (previousPenStyle == Qt::NoPen)
_painter->setPen(Qt::NoPen);
else
_painter->setPen(BORDERS_COLOR); // restore pen for rectangle painting
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
m_levels[next_level][item.children_begin].state = -1;
}
if (next_level < levelsNumber && item.children_begin != NEGATIVE_ONE)
{
// Mark that we would not paint children of current item
m_levels[next_level][item.children_begin].state = -1;
}
continue;
}
if (next_level < levelsNumber && item.children_begin != -1)
if (next_level < levelsNumber && item.children_begin != NEGATIVE_ONE)
{
if (m_levelsIndexes[next_level] == -1)
if (m_levelsIndexes[next_level] == NEGATIVE_ONE)
{
// Mark first potentially visible child item on next sublevel
m_levelsIndexes[next_level] = item.children_begin;
@ -340,11 +342,11 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
//if (changebrush)
//{
// changebrush = false;
// previousColor = item.color;
// brush = QBrush(previousColor);
// previousColor = item.color;
// brush = QBrush(previousColor);
// _painter->setBrush(brush);
//} else
//} else
if (!m_bTest && item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
{
selectedItemsWasPainted = true;
@ -353,18 +355,18 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
pen.setWidth(2);
_painter->setPen(pen);
previousColor = SELECTED_ITEM_COLOR;
brush.setColor(previousColor);
previousColor = SELECTED_ITEM_COLOR;
brush.setColor(previousColor);
_painter->setBrush(brush);
}
}
else
{
if (previousColor != item.color)
{
// Set background color brush for rectangle
previousColor = item.color;
brush.setColor(previousColor);
_painter->setBrush(brush);
if (previousColor != item.color)
{
// Set background color brush for rectangle
previousColor = item.color;
brush.setColor(previousColor);
_painter->setBrush(brush);
}
if (::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders && previousPenStyle != Qt::SolidLine)
@ -372,16 +374,16 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
// Restore pen for item which is wide enough to paint borders
previousPenStyle = Qt::SolidLine;
_painter->setPen(BORDERS_COLOR);
}
}
// Draw rectangle
const auto x = item.left() * currentScale - dx;
rect.setRect(x, item.top(), w, item.height());
_painter->drawRect(rect);
// Draw text-----------------------------------
// calculating text coordinates
}
}
// Draw rectangle
const auto x = item.left() * currentScale - dx;
rect.setRect(x, item.top(), w, item.height());
_painter->drawRect(rect);
// Draw text-----------------------------------
// calculating text coordinates
auto xtext = x;
if (item.left() < sceneLeft)
{
@ -391,31 +393,31 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
xtext = sceneLeft * currentScale - dx;
}
rect.setRect(xtext + 1, item.top(), w - 1, item.height());
// text will be painted with inverse color
auto textColor = 0x00ffffff - previousColor;
if (textColor == previousColor) textColor = 0;
_painter->setPen(textColor);
// drawing text
if (m_bTest)
{
char text[128] = {0};
sprintf(text, "ITEM_%u", i);
_painter->drawText(rect, 0, text);
}
else
{
_painter->drawText(rect, 0, item.block->node->getBlockName());
}
// 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~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rect.setRect(xtext + 1, item.top(), w - 1, item.height());
// text will be painted with inverse color
auto textColor = 0x00ffffff - previousColor;
if (textColor == previousColor) textColor = 0;
_painter->setPen(textColor);
// drawing text
if (m_bTest)
{
char text[128] = {0};
sprintf(text, "ITEM_%u", i);
_painter->drawText(rect, 0, text);
}
else
{
_painter->drawText(rect, 0, item.block->node->getBlockName());
}
// 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~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
}
@ -448,10 +450,10 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
void ProfGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::TreeBlocks& _blocks) const
{
//if (m_bTest)
//{
// return;
//}
//if (m_bTest)
//{
// return;
//}
// Search for first visible top-level item
auto& level0 = m_levels.front();
@ -568,7 +570,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
return &item;
}
if (item.children_begin == -1)
if (item.children_begin == NEGATIVE_ONE)
{
if (itemIndex != 0)
{
@ -578,7 +580,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
--j;
const auto& item2 = level[j];
if (item2.children_begin != -1)
if (item2.children_begin != NEGATIVE_ONE)
{
firstItem = item2.children_begin;
break;
@ -600,7 +602,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
for (auto j = itemIndex + 1; j < size; ++j)
{
const auto& item2 = level[j];
if (item2.children_begin != -1)
if (item2.children_begin != NEGATIVE_ONE)
{
lastItem = item2.children_begin;
break;
@ -649,40 +651,40 @@ unsigned short ProfGraphicsItem::levels() const
return static_cast<unsigned short>(m_levels.size());
}
void ProfGraphicsItem::setLevels(unsigned short _levels)
{
m_levels.resize(_levels);
m_levelsIndexes.resize(_levels, -1);
}
void ProfGraphicsItem::reserve(unsigned short _level, unsigned int _items)
{
m_levels[_level].reserve(_items);
}
//////////////////////////////////////////////////////////////////////////
const ProfGraphicsItem::Children& ProfGraphicsItem::items(unsigned short _level) const
{
return m_levels[_level];
}
const ::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned short _level, unsigned int _index) const
{
return m_levels[_level][_index];
}
::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned short _level, unsigned int _index)
{
return m_levels[_level][_index];
}
unsigned int ProfGraphicsItem::addItem(unsigned short _level)
{
m_levels[_level].emplace_back();
return static_cast<unsigned int>(m_levels[_level].size() - 1);
}
void ProfGraphicsItem::setLevels(unsigned short _levels)
{
m_levels.resize(_levels);
m_levelsIndexes.resize(_levels, -1);
}
void ProfGraphicsItem::reserve(unsigned short _level, unsigned int _items)
{
m_levels[_level].reserve(_items);
}
//////////////////////////////////////////////////////////////////////////
const ProfGraphicsItem::Children& ProfGraphicsItem::items(unsigned short _level) const
{
return m_levels[_level];
}
const ::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned short _level, unsigned int _index) const
{
return m_levels[_level][_index];
}
::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned short _level, unsigned int _index)
{
return m_levels[_level][_index];
}
unsigned int ProfGraphicsItem::addItem(unsigned short _level)
{
m_levels[_level].emplace_back();
return static_cast<unsigned int>(m_levels[_level].size() - 1);
}
//////////////////////////////////////////////////////////////////////////
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)
@ -1131,13 +1133,13 @@ void ProfGraphicsView::clearSilent()
void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTree)
{
// clear scene
clearSilent();
if (_blocksTree.empty())
{
return;
}
clearSilent();
if (_blocksTree.empty())
{
return;
}
// set new blocks tree
// calculate scene size and fill it with items
@ -1201,7 +1203,7 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
}
// Center view on the beginning of the scene
updateVisibleSceneRect();
updateVisibleSceneRect();
setScrollbar(m_pScrollbar);
if (longestItem != nullptr)
@ -1407,19 +1409,19 @@ void ProfGraphicsView::mousePressEvent(QMouseEvent* _event)
return;
}
m_mouseButtons = _event->buttons();
m_mousePressPos = _event->pos();
if (m_mouseButtons & Qt::RightButton)
{
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
m_chronometerItem->setLeftRight(mouseX, mouseX);
m_chronometerItem->setReverse(false);
m_chronometerItem->hide();
m_pScrollbar->hideChrono();
}
_event->accept();
m_mouseButtons = _event->buttons();
m_mousePressPos = _event->pos();
if (m_mouseButtons & Qt::RightButton)
{
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
m_chronometerItem->setLeftRight(mouseX, mouseX);
m_chronometerItem->setReverse(false);
m_chronometerItem->hide();
m_pScrollbar->hideChrono();
}
_event->accept();
}
void ProfGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
@ -1434,12 +1436,12 @@ void ProfGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
m_mousePressPos = _event->pos();
m_bDoubleClick = true;
if (m_mouseButtons & Qt::LeftButton)
{
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
m_chronometerItemAux->setLeftRight(mouseX, mouseX);
m_chronometerItemAux->setReverse(false);
m_chronometerItemAux->hide();
if (m_mouseButtons & Qt::LeftButton)
{
const auto mouseX = m_offset + mapToScene(m_mousePressPos).x() / m_scale;
m_chronometerItemAux->setLeftRight(mouseX, mouseX);
m_chronometerItemAux->setReverse(false);
m_chronometerItemAux->hide();
}
_event->accept();
@ -1454,130 +1456,130 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
_event->accept();
return;
}
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();
}
if (!m_selectedBlocks.empty())
{
changedSelection = true;
m_selectedBlocks.clear();
}
if (!m_bTest && m_chronometerItem->isVisible())
{
//printf("INTERVAL: {%lf, %lf} ms\n", m_chronometerItem->left(), m_chronometerItem->right());
for (auto item : m_items)
{
item->getBlocks(m_chronometerItem->left(), m_chronometerItem->right(), m_selectedBlocks);
}
if (!m_selectedBlocks.empty())
{
changedSelection = true;
}
}
}
if (m_mouseButtons & Qt::LeftButton)
{
if (m_chronometerItemAux->isVisible() && m_chronometerItemAux->width() < 1e-6)
{
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)
{
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_chronometerItem->left()), position2time(m_chronometerItem->right()), m_chronometerItem->reverse());
}
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();
}
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();
}
if (!m_selectedBlocks.empty())
{
changedSelection = true;
m_selectedBlocks.clear();
}
if (!m_bTest && m_chronometerItem->isVisible())
{
//printf("INTERVAL: {%lf, %lf} ms\n", m_chronometerItem->left(), m_chronometerItem->right());
for (auto item : m_items)
{
item->getBlocks(m_chronometerItem->left(), m_chronometerItem->right(), m_selectedBlocks);
}
if (!m_selectedBlocks.empty())
{
changedSelection = true;
}
}
}
if (m_mouseButtons & Qt::LeftButton)
{
if (m_chronometerItemAux->isVisible() && m_chronometerItemAux->width() < 1e-6)
{
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)
{
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_chronometerItem->left()), position2time(m_chronometerItem->right()), m_chronometerItem->reverse());
}
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();
}
}
//////////////////////////////////////////////////////////////////////////
bool ProfGraphicsView::moveChrono(ProfChronometerItem* _chronometerItem, qreal _mouseX)
{
if (_chronometerItem->reverse())
{
if (_mouseX > _chronometerItem->right())
{
_chronometerItem->setReverse(false);
_chronometerItem->setLeftRight(_chronometerItem->right(), _mouseX);
}
else
{
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->right());
}
}
else
{
if (_mouseX < _chronometerItem->left())
{
_chronometerItem->setReverse(true);
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->left());
}
else
{
_chronometerItem->setLeftRight(_chronometerItem->left(), _mouseX);
}
}
if (!_chronometerItem->isVisible() && _chronometerItem->width() > 1e-6)
{
_chronometerItem->show();
return true;
if (_chronometerItem->reverse())
{
if (_mouseX > _chronometerItem->right())
{
_chronometerItem->setReverse(false);
_chronometerItem->setLeftRight(_chronometerItem->right(), _mouseX);
}
else
{
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->right());
}
}
else
{
if (_mouseX < _chronometerItem->left())
{
_chronometerItem->setReverse(true);
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->left());
}
else
{
_chronometerItem->setLeftRight(_chronometerItem->left(), _mouseX);
}
}
if (!_chronometerItem->isVisible() && _chronometerItem->width() > 1e-6)
{
_chronometerItem->show();
return true;
}
return false;
@ -1592,8 +1594,8 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
}
bool needUpdate = false;
const auto pos = _event->pos();
const auto delta = pos - m_mousePressPos;
const auto pos = _event->pos();
const auto delta = pos - m_mousePressPos;
m_mousePressPos = pos;
if (m_mouseButtons != 0)
@ -1602,66 +1604,67 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
m_mouseMovePath.setY(m_mouseMovePath.y() + ::std::abs(delta.y()));
}
auto mouseScenePos = mapToScene(m_mousePressPos);
auto mouseScenePos = mapToScene(m_mousePressPos);
mouseScenePos.setX(m_offset + mouseScenePos.x() / m_scale);
if (m_mouseButtons & Qt::RightButton)
{
bool showItem = moveChrono(m_chronometerItem, mouseScenePos.x());
m_pScrollbar->setChronoPos(m_chronometerItem->left(), m_chronometerItem->right());
if (showItem)
{
m_pScrollbar->showChrono();
}
needUpdate = true;
if (m_mouseButtons & Qt::RightButton)
{
bool showItem = moveChrono(m_chronometerItem, mouseScenePos.x());
m_pScrollbar->setChronoPos(m_chronometerItem->left(), m_chronometerItem->right());
if (showItem)
{
m_pScrollbar->showChrono();
}
needUpdate = true;
}
if (m_mouseButtons & Qt::LeftButton)
{
if (m_bDoubleClick)
{
moveChrono(m_chronometerItemAux, mouseScenePos.x());
}
else
{
auto vbar = verticalScrollBar();
m_bUpdatingRect = true; // Block scrollbars from updating scene rect to make it possible to do it only once
vbar->setValue(vbar->value() - delta.y()); m_pScrollbar->setValue(m_pScrollbar->value() - delta.x() / m_scale);
m_bUpdatingRect = false;
// Seems like an ugly stub, but QSignalBlocker is also a bad decision
// because if scrollbar does not emit valueChanged signal then viewport does not move
updateVisibleSceneRect(); // Update scene visible rect only once
// Update flicker speed
m_flickerSpeedX += delta.x() >> 1;
m_flickerSpeedY += delta.y() >> 1;
if (!m_flickerTimer.isActive())
{
// If flicker timer is not started, then start it
m_flickerTimer.start(FLICKER_INTERVAL);
}
}
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
}
_event->accept();
if (m_mouseButtons & Qt::LeftButton)
{
if (m_bDoubleClick)
{
moveChrono(m_chronometerItemAux, mouseScenePos.x());
}
else
{
auto vbar = verticalScrollBar();
m_bUpdatingRect = true; // Block scrollbars from updating scene rect to make it possible to do it only once
vbar->setValue(vbar->value() - delta.y());
m_pScrollbar->setValue(m_pScrollbar->value() - delta.x() / m_scale);
m_bUpdatingRect = false;
// Seems like an ugly stub, but QSignalBlocker is also a bad decision
// because if scrollbar does not emit valueChanged signal then viewport does not move
updateVisibleSceneRect(); // Update scene visible rect only once
// Update flicker speed
m_flickerSpeedX += delta.x() >> 1;
m_flickerSpeedY += delta.y() >> 1;
if (!m_flickerTimer.isActive())
{
// If flicker timer is not started, then start it
m_flickerTimer.start(FLICKER_INTERVAL);
}
}
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
}
_event->accept();
}
//////////////////////////////////////////////////////////////////////////
@ -1729,13 +1732,13 @@ void ProfGraphicsView::onFlickerTimeout()
auto vbar = verticalScrollBar();
m_bUpdatingRect = true; // Block scrollbars from updating scene rect to make it possible to do it only once
m_pScrollbar->setValue(m_pScrollbar->value() - m_flickerSpeedX / m_scale);
vbar->setValue(vbar->value() - m_flickerSpeedY);
m_bUpdatingRect = false;
// Seems like an ugly stub, but QSignalBlocker is also a bad decision
// because if scrollbar does not emit valueChanged signal then viewport does not move
m_bUpdatingRect = true; // Block scrollbars from updating scene rect to make it possible to do it only once
m_pScrollbar->setValue(m_pScrollbar->value() - m_flickerSpeedX / m_scale);
vbar->setValue(vbar->value() - m_flickerSpeedY);
m_bUpdatingRect = false;
// Seems like an ugly stub, but QSignalBlocker is also a bad decision
// because if scrollbar does not emit valueChanged signal then viewport does not move
updateVisibleSceneRect(); // Update scene visible rect only once
updateScene(); // repaint scene
@ -1792,7 +1795,7 @@ void ProfGraphicsView::onSelectedBlockChange(unsigned int _block_index)
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_flickerSpeedX = m_flickerSpeedY = 0;
m_pScrollbar->setValue(item.left() + item.width() * 0.5 - m_pScrollbar->sliderHalfWidth());
}

View File

@ -1,24 +1,24 @@
/************************************************************************
* file name : blocks_graphics_view.h
* ----------------- :
* creation time : 2016/06/26
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of GraphicsScene and GraphicsView and
* : it's auxiliary classes for displyaing easy_profiler blocks tree.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: moved sources from graphics_view.h
* : and renamed classes from My* to Prof*.
* :
* : * 2016/06/29 Victor Zarubkin: Highly optimized painting performance and memory consumption.
* :
* : * 2016/06/30 Victor Zarubkin: Replaced doubles with floats (in ProfBlockItem) for less memory consumption.
* :
* : *
* ----------------- :
* license : TODO: add license text
/************************************************************************
* file name : blocks_graphics_view.h
* ----------------- :
* creation time : 2016/06/26
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of GraphicsScene and GraphicsView and
* : it's auxiliary classes for displyaing easy_profiler blocks tree.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: moved sources from graphics_view.h
* : and renamed classes from My* to Prof*.
* :
* : * 2016/06/29 Victor Zarubkin: Highly optimized painting performance and memory consumption.
* :
* : * 2016/06/30 Victor Zarubkin: Replaced doubles with floats (in ProfBlockItem) for less memory consumption.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#ifndef MY____GRAPHICS___VIEW_H
@ -34,7 +34,6 @@
#include "graphics_scrollbar.h"
#include "profiler/reader.h"
#include "common_types.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@ -86,53 +85,53 @@ public:
\note Must be set before doing anything else.
\param _levels Desired number of levels */
void setLevels(unsigned short _levels);
/** \brief Reserves memory for desired number of items on specified level.
\param _level Index of the level
\param _items Desired number of items on this level */
void reserve(unsigned short _level, unsigned int _items);
/**\brief Returns reference to the array of items of specified level.
\param _level Index of the level */
const Children& items(unsigned short _level) const;
/**\brief Returns reference to the item with required index on specified level.
\param _level Index of the level
\param _index Index of required item */
const ::profiler_gui::ProfBlockItem& getItem(unsigned short _level, unsigned int _index) const;
/**\brief Returns reference to the item with required index on specified level.
\param _level Index of the level
\param _index Index of required item */
::profiler_gui::ProfBlockItem& getItem(unsigned short _level, unsigned int _index);
/** \brief Adds new item to required level.
\param _level Index of the level
\retval Index of the new created item */
unsigned int addItem(unsigned short _level);
/** \brief Finds top-level blocks which are intersects with required selection zone.
\note Found blocks will be added into the array of selected blocks.
\param _left Left bound of the selection zone
\param _right Right bound of the selection zone
\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.
const ProfGraphicsView* view() const;
void setLevels(unsigned short _levels);
/** \brief Reserves memory for desired number of items on specified level.
\param _level Index of the level
\param _items Desired number of items on this level */
void reserve(unsigned short _level, unsigned int _items);
/**\brief Returns reference to the array of items of specified level.
\param _level Index of the level */
const Children& items(unsigned short _level) const;
/**\brief Returns reference to the item with required index on specified level.
\param _level Index of the level
\param _index Index of required item */
const ::profiler_gui::ProfBlockItem& getItem(unsigned short _level, unsigned int _index) const;
/**\brief Returns reference to the item with required index on specified level.
\param _level Index of the level
\param _index Index of required item */
::profiler_gui::ProfBlockItem& getItem(unsigned short _level, unsigned int _index);
/** \brief Adds new item to required level.
\param _level Index of the level
\retval Index of the new created item */
unsigned int addItem(unsigned short _level);
/** \brief Finds top-level blocks which are intersects with required selection zone.
\note Found blocks will be added into the array of selected blocks.
\param _left Left bound of the selection zone
\param _right Right bound of the selection zone
\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.
const ProfGraphicsView* view() const;
}; // END of class ProfGraphicsItem.

View File

@ -31,6 +31,7 @@
#include <QSettings>
#include <QTextCodec>
#include "blocks_tree_widget.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////
@ -834,7 +835,7 @@ void ProfTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
case COL_MAX_PER_PARENT:
case COL_MAX_PER_FRAME:
{
unsigned int i = -1;
unsigned int i = NEGATIVE_ONE;
switch (col)
{
case COL_MIN_PER_THREAD: i = item->block()->per_thread_stats->min_duration_block; break;
@ -845,7 +846,7 @@ void ProfTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
case COL_MAX_PER_FRAME: i = item->block()->per_frame_stats->max_duration_block; break;
}
if (i != -1)
if (i != NEGATIVE_ONE)
{
menu.addSeparator();
itemAction = new ProfItemAction("Jump to such item", i);

View File

@ -32,7 +32,6 @@
#include <vector>
#include "profiler/reader.h"
#include "common_types.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////

View File

@ -1,35 +1,29 @@
/************************************************************************
* file name : globals.cpp
* ----------------- :
* creation time : 2016/08/03
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of global constants and variables for profiler gui.
* ----------------- :
* change log : * 2016/08/03 Victor Zarubkin: initial commit.
* :
* : *
* ----------------- :
* license : TODO: add license text
/************************************************************************
* file name : globals.cpp
* ----------------- :
* creation time : 2016/08/03
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of global constants and variables for profiler gui.
* ----------------- :
* change log : * 2016/08/03 Victor Zarubkin: initial commit.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#define IGNORE_GLOBALS_DECLARATION
#include "globals.h"
#undef IGNORE_GLOBALS_DECLARATION
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
namespace profiler_gui {
ProfGlobalSignals::ProfGlobalSignals() : QObject()
{
}
ProfGlobalSignals::~ProfGlobalSignals()
{
}
ProfGlobals& ProfGlobals::instance()
{
static ProfGlobals globals;

View File

@ -1,18 +1,18 @@
/************************************************************************
* file name : globals.h
* ----------------- :
* creation time : 2016/08/03
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of global constants and variables for profiler gui.
* ----------------- :
* change log : * 2016/08/03 Victor Zarubkin: initial commit.
* :
* : *
* ----------------- :
* license : TODO: add license text
/************************************************************************
* file name : globals.h
* ----------------- :
* creation time : 2016/08/03
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of global constants and variables for profiler gui.
* ----------------- :
* change log : * 2016/08/03 Victor Zarubkin: initial commit.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#ifndef EASY_PROFILER__GUI_GLOBALS_H
@ -22,6 +22,7 @@
#include <QObject>
#include <QColor>
#include "common_types.h"
#include "globals_qobjects.h"
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@ -29,6 +30,8 @@
class ProfGraphicsItem;
class ProfTreeWidgetItem;
const unsigned int NEGATIVE_ONE = std::numeric_limits<unsigned int>::max();
//////////////////////////////////////////////////////////////////////////
namespace profiler_gui {
@ -43,23 +46,6 @@ namespace profiler_gui {
//////////////////////////////////////////////////////////////////////////
class ProfGlobalSignals final : public QObject
{
Q_OBJECT
public:
ProfGlobalSignals();
virtual ~ProfGlobalSignals();
signals:
void selectedThreadChanged(::profiler::thread_id_t _id);
void selectedBlockChanged(unsigned int _block_index);
};
//////////////////////////////////////////////////////////////////////////
struct ProfBlock final
{
ProfGraphicsItem* graphics_item;
@ -87,9 +73,9 @@ namespace profiler_gui {
ProfGlobals();
};
#ifndef IGNORE_GLOBALS_DECLARATION
static ProfGlobals& EASY_GLOBALS = ProfGlobals::instance();
#endif
//////////////////////////////////////////////////////////////////////////
} // END of namespace profiler_gui.

View File

@ -0,0 +1,35 @@
/************************************************************************
* file name : globals_qobjects.cpp
* ----------------- :
* creation time : 2016/08/08
* copyright : (c) 2016 Victor Zarubkin, Sergey Yagovtsev
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of ProfGlobalSignals QObject class.
* ----------------- :
* change log : * 2016/08/08 Sergey Yagovtsev: moved sources from globals.cpp
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#include "globals_qobjects.h"
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
namespace profiler_gui {
ProfGlobalSignals::ProfGlobalSignals() : QObject()
{
}
ProfGlobalSignals::~ProfGlobalSignals()
{
}
} // END of namespace profiler_gui.
//////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,25 @@
#ifndef GLOBALS_QOBJECTS_H
#define GLOBALS_QOBJECTS_H
#include <QObject>
#include "profiler/profiler.h"
namespace profiler_gui {
class ProfGlobalSignals final : public QObject
{
Q_OBJECT
public:
ProfGlobalSignals();
virtual ~ProfGlobalSignals();
signals:
void selectedThreadChanged(::profiler::thread_id_t _id);
void selectedBlockChanged(unsigned int _block_index);
};
}
#endif // GLOBALS_QOBJECTS_H

View File

@ -22,6 +22,7 @@
#include <QContextMenuEvent>
#include <QMenu>
#include "graphics_scrollbar.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////
@ -170,12 +171,12 @@ void ProfMinimapItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
//const auto color = ::profiler_gui::toRgb(col * 255, (1.0 - col) * 255, 0); // item.color;
const auto color = 0x00ffffff & QColor::fromHsvF((1.0 - col) * 0.35, 0.85, 0.85).rgb();
if (previousColor != color)
{
// Set background color brush for rectangle
previousColor = color;
brush.setColor(QColor::fromRgba(0xc0000000 | color));
_painter->setBrush(brush);
if (previousColor != color)
{
// Set background color brush for rectangle
previousColor = color;
brush.setColor(QColor::fromRgba(0xc0000000 | color));
_painter->setBrush(brush);
}
rect.setRect(item.left() * currentScale, bottom - h, ::std::max(item.width() * currentScale, 1.0), h);

View File

@ -24,7 +24,6 @@
#include <QGraphicsRectItem>
#include <QAction>
#include "common_types.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////

View File

@ -1,24 +1,24 @@
/************************************************************************
* file name : main_window.cpp
* ----------------- :
* creation time : 2016/06/26
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of MainWindow for easy_profiler GUI.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: Initial commit.
* :
* : * 2016/06/27 Victor Zarubkin: Passing blocks number to ProfTreeWidget::setTree().
* :
* : * 2016/06/29 Victor Zarubkin: Added menu with tests.
* :
* : * 2016/06/30 Sergey Yagovtsev: Open file by command line argument
* :
* : *
* ----------------- :
* license : TODO: add license text
/************************************************************************
* file name : main_window.cpp
* ----------------- :
* creation time : 2016/06/26
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of MainWindow for easy_profiler GUI.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: Initial commit.
* :
* : * 2016/06/27 Victor Zarubkin: Passing blocks number to ProfTreeWidget::setTree().
* :
* : * 2016/06/29 Victor Zarubkin: Added menu with tests.
* :
* : * 2016/06/30 Sergey Yagovtsev: Open file by command line argument
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#include <QStatusBar>
@ -27,12 +27,13 @@
#include <QAction>
#include <QMenu>
#include <QMenuBar>
#include <QCoreApplication>
#include <QCloseEvent>
#include <QSettings>
#include <QCoreApplication>
#include <QCloseEvent>
#include <QSettings>
#include "main_window.h"
#include "blocks_tree_widget.h"
#include "blocks_graphics_view.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////
@ -82,17 +83,17 @@ ProfMainWindow::ProfMainWindow() : QMainWindow(), m_treeWidget(nullptr), m_graph
menu = new QMenu("Tests");
menu->addAction(actionTestView);
menuBar()->addMenu(menu);
connect(graphicsView->view(), &ProfGraphicsView::intervalChanged, treeWidget, &ProfTreeWidget::setTreeBlocks);
loadSettings();
if(QCoreApplication::arguments().size() > 1)
{
auto opened_filename = QCoreApplication::arguments().at(1).toStdString();
loadFile(opened_filename);
connect(graphicsView->view(), &ProfGraphicsView::intervalChanged, treeWidget, &ProfTreeWidget::setTreeBlocks);
loadSettings();
if(QCoreApplication::arguments().size() > 1)
{
auto opened_filename = QCoreApplication::arguments().at(1).toStdString();
loadFile(opened_filename);
}
}
}
ProfMainWindow::~ProfMainWindow()
{
@ -103,13 +104,13 @@ ProfMainWindow::~ProfMainWindow()
void ProfMainWindow::onOpenFileClicked(bool)
{
auto filename = QFileDialog::getOpenFileName(this, "Open profiler log", m_lastFile.c_str(), "Profiler Log File (*.prof);;All Files (*.*)");
loadFile(filename.toStdString());
}
loadFile(filename.toStdString());
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::loadFile(const std::string& stdfilename)
{
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::loadFile(const std::string& stdfilename)
{
::profiler::thread_blocks_tree_t prof_blocks;
auto nblocks = fillTreesFromFile(stdfilename.c_str(), prof_blocks, true);
@ -117,8 +118,8 @@ void ProfMainWindow::loadFile(const std::string& stdfilename)
{
static_cast<ProfTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
m_lastFile = stdfilename;
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
m_lastFile = stdfilename;
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::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);