0
0
mirror of https://github.com/yse/easy_profiler.git synced 2025-01-14 00:27:55 +08:00

(GraphicsScrollbar) Added mini-map which shows duration of blocks relative to each other;

(GraphicsScrollbar) Also added displaying of chronometer item position in graphics scrollbar.
This commit is contained in:
Victor Zarubkin 2016-08-03 00:06:36 +03:00
parent aa7996c1c5
commit 4db8d4fbb6
6 changed files with 258 additions and 83 deletions

View File

@ -90,39 +90,6 @@ QRgb BG2()
//////////////////////////////////////////////////////////////////////////
void ProfBlockItem::setRect(qreal _x, float _y, float _w, float _h) {
x = _x;
y = _y;
w = _w;
h = _h;
}
qreal ProfBlockItem::left() const {
return x;
}
float ProfBlockItem::top() const {
return y;
}
float ProfBlockItem::width() const {
return w;
}
float ProfBlockItem::height() const {
return h;
}
qreal ProfBlockItem::right() const {
return x + w;
}
float ProfBlockItem::bottom() const {
return y + h;
}
//////////////////////////////////////////////////////////////////////////
ProfGraphicsItem::ProfGraphicsItem() : ProfGraphicsItem(false)
{
}
@ -518,6 +485,7 @@ size_t ProfGraphicsItem::addItem(unsigned short _level, ProfBlockItem&& _item)
ProfChronometerItem::ProfChronometerItem() : QGraphicsItem(), m_left(0), m_right(0), m_font(QFont("CourierNew", 16, 2))
{
setZValue(10);
}
ProfChronometerItem::~ProfChronometerItem()
@ -771,6 +739,7 @@ void ProfGraphicsView::test(size_t _frames_number, size_t _total_items_number_es
// Create required number of items
size_t total_items = 0;
qreal maxX = 0;
const ProfGraphicsItem* longestItem = nullptr;
for (int i = 0; i < _rows; ++i)
{
auto item = thread_items[i];
@ -809,6 +778,7 @@ void ProfGraphicsView::test(size_t _frames_number, size_t _total_items_number_es
if (maxX < x)
{
maxX = x;
longestItem = item;
}
}
@ -822,11 +792,11 @@ void ProfGraphicsView::test(size_t _frames_number, size_t _total_items_number_es
m_offset = 0;
updateVisibleSceneRect();
setScrollbar(m_pScrollbar);
m_pScrollbar->setMinimapFrom(longestItem->items(0));
// Create new chronometer item (previous item was destroyed by scene on scene()->clear()).
// It will be shown on mouse right button click.
m_chronometerItem = new ProfChronometerItem();
m_chronometerItem->setZValue(10);
m_chronometerItem->setBoundingRect(scene()->sceneRect());
m_chronometerItem->hide();
scene()->addItem(m_chronometerItem);
@ -877,6 +847,8 @@ void ProfGraphicsView::setTree(const thread_blocks_tree_t& _blocksTree)
// Calculating start and end time
::profiler::timestamp_t finish = 0;
const BlocksTree* longestTree = nullptr;
const ProfGraphicsItem* longestItem = nullptr;
for (const auto& threadTree : _blocksTree)
{
const auto timestart = threadTree.second.children.front().node->block()->getBegin();
@ -890,6 +862,7 @@ void ProfGraphicsView::setTree(const thread_blocks_tree_t& _blocksTree)
if (finish < timefinish)
{
finish = timefinish;
longestTree = &threadTree.second;
}
}
@ -912,6 +885,11 @@ void ProfGraphicsView::setTree(const thread_blocks_tree_t& _blocksTree)
scene()->addItem(item);
y += h + ROW_SPACING;
if (longestTree == &threadTree.second)
{
longestItem = item;
}
}
// Calculating scene rect
@ -927,11 +905,11 @@ void ProfGraphicsView::setTree(const thread_blocks_tree_t& _blocksTree)
// Center view on the beginning of the scene
updateVisibleSceneRect();
setScrollbar(m_pScrollbar);
m_pScrollbar->setMinimapFrom(longestItem->items(0));
// Create new chronometer item (previous item was destroyed by scene on scene()->clear()).
// It will be shown on mouse right button click.
m_chronometerItem = new ProfChronometerItem();
m_chronometerItem->setZValue(10);
m_chronometerItem->setBoundingRect(scene()->sceneRect());
m_chronometerItem->hide();
scene()->addItem(m_chronometerItem);
@ -1028,6 +1006,8 @@ void ProfGraphicsView::setScrollbar(GraphicsHorizontalScrollbar* _scrollbar)
}
m_pScrollbar = _scrollbar;
m_pScrollbar->setMinimapFrom(nullptr);
m_pScrollbar->hideChrono();
m_pScrollbar->setRange(0, scene()->width());
m_pScrollbar->setSliderWidth(m_visibleSceneRect.width());
m_pScrollbar->setValue(0);
@ -1126,6 +1106,7 @@ void ProfGraphicsView::mousePressEvent(QMouseEvent* _event)
const auto mouseX = m_offset + mapToScene(_event->pos()).x() / m_scale;
m_chronometerItem->setLeftRight(mouseX, mouseX);
m_chronometerItem->hide();
m_pScrollbar->hideChrono();
}
_event->accept();
@ -1147,6 +1128,7 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
if (m_chronometerItem->isVisible() && m_chronometerItem->width() < 1e-6)
{
m_chronometerItem->hide();
m_pScrollbar->hideChrono();
}
if (!m_selectedBlocks.empty())
@ -1222,9 +1204,12 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
}
}
m_pScrollbar->setChronoPos(m_chronometerItem->left(), m_chronometerItem->right());
if (!m_chronometerItem->isVisible() && m_chronometerItem->width() > 1e-6)
{
m_chronometerItem->show();
m_pScrollbar->showChrono();
}
needUpdate = true;

View File

@ -31,7 +31,6 @@
#include <QPoint>
#include <QTimer>
#include <stdlib.h>
#include <vector>
#include "graphics_scrollbar.h"
#include "profiler/reader.h"
#include "common_types.h"
@ -39,36 +38,11 @@
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
struct ProfBlockItem
{
const BlocksTree* block; ///< Pointer to profiler block
qreal x; ///< x coordinate of the item (this is made qreal=double to avoid mistakes on very wide scene)
float w; ///< Width of the item
float y; ///< y coordinate of the item
float h; ///< Height of the item
QRgb color; ///< Background color of the item
unsigned int children_begin; ///< Index of first child item on the next sublevel
unsigned short totalHeight; ///< Total height of the item including heights of all it's children
char state; ///< 0 = no change, 1 = paint, -1 = do not paint
void setRect(qreal _x, float _y, float _w, float _h);
qreal left() const;
float top() const;
float width() const;
float height() const;
qreal right() const;
float bottom() const;
};
#pragma pack(pop)
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsView;
class ProfGraphicsItem : public QGraphicsItem
{
typedef ::std::vector<ProfBlockItem> Children;
typedef ProfItems Children;
typedef ::std::vector<unsigned int> DrawIndexes;
typedef ::std::vector<Children> Sublevels;

View File

@ -237,6 +237,7 @@ void ProfTreeWidget::setTree(const unsigned int _blocksNumber, const thread_bloc
setSortingEnabled(true);
sortByColumn(COL_BEGIN, Qt::AscendingOrder);
resizeColumnToContents(COL_NAME);
connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
}
@ -252,6 +253,7 @@ void ProfTreeWidget::setTreeBlocks(const TreeBlocks& _blocks, ::profiler::timest
setSortingEnabled(true);
sortByColumn(COL_BEGIN, Qt::AscendingOrder);
resizeColumnToContents(COL_NAME);
connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
}

View File

@ -55,6 +55,39 @@ inline QRgb toRgb(unsigned int _red, unsigned int _green, unsigned int _blue)
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
struct ProfBlockItem
{
const BlocksTree* block; ///< Pointer to profiler block
qreal x; ///< x coordinate of the item (this is made qreal=double to avoid mistakes on very wide scene)
float w; ///< Width of the item
float y; ///< y coordinate of the item
float h; ///< Height of the item
QRgb color; ///< Background color of the item
unsigned int children_begin; ///< Index of first child item on the next sublevel
unsigned short totalHeight; ///< Total height of the item including heights of all it's children
char state; ///< 0 = no change, 1 = paint, -1 = do not paint
inline void setRect(qreal _x, float _y, float _w, float _h) {
x = _x;
y = _y;
w = _w;
h = _h;
}
inline qreal left() const { return x; }
inline float top() const { return y; }
inline float width() const { return w; }
inline float height() const { return h; }
inline qreal right() const { return x + w; }
inline float bottom() const { return y + h; }
};
#pragma pack(pop)
typedef ::std::vector<ProfBlockItem> ProfItems;
//////////////////////////////////////////////////////////////////////////
struct ProfBlock
{
const BlocksTree* thread_tree;

View File

@ -25,6 +25,8 @@
const qreal SCALING_COEFFICIENT = 1.25;
const qreal SCALING_COEFFICIENT_INV = 1.0 / SCALING_COEFFICIENT;
const int DEFAULT_TOP = -40;
const int DEFAULT_HEIGHT = 80;
//////////////////////////////////////////////////////////////////////////
@ -37,7 +39,7 @@ auto const clamp = [](qreal _minValue, qreal _value, qreal _maxValue)
GraphicsHorizontalSlider::GraphicsHorizontalSlider() : Parent(), m_halfwidth(0)
{
setWidth(40);
setWidth(1);
setBrush(Qt::SolidPattern);
}
@ -82,27 +84,119 @@ qreal GraphicsHorizontalSlider::halfwidth() const
void GraphicsHorizontalSlider::setWidth(qreal _width)
{
m_halfwidth = _width * 0.5;
setRect(-m_halfwidth, -10, _width, 20);
setRect(-m_halfwidth, DEFAULT_TOP, _width, DEFAULT_HEIGHT);
}
void GraphicsHorizontalSlider::setHalfwidth(qreal _halfwidth)
{
m_halfwidth = _halfwidth;
setRect(-m_halfwidth, -10, m_halfwidth * 2.0, 20);
setRect(-m_halfwidth, DEFAULT_TOP, m_halfwidth * 2.0, DEFAULT_HEIGHT);
}
void GraphicsHorizontalSlider::setColor(QRgb _color)
{
QColor c(_color);
c.setAlpha((_color & 0xff000000) >> 24);
auto b = brush();
b.setColor(c);
b.setColor(QColor::fromRgba(_color));
setBrush(b);
}
//////////////////////////////////////////////////////////////////////////
MinimapItem::MinimapItem() : Parent(), m_pSource(nullptr), m_maxDuration(0)
{
}
MinimapItem::~MinimapItem()
{
}
QRectF MinimapItem::boundingRect() const
{
return m_boundingRect;
}
void MinimapItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
if (m_pSource == nullptr)
{
return;
}
const auto currentScale = static_cast<const GraphicsHorizontalScrollbar*>(scene()->parent())->getWindowScale();
const auto bottom = m_boundingRect.bottom();
const auto coeff = (m_boundingRect.height() - 5) / m_maxDuration;
QRectF rect;
QBrush brush(Qt::SolidPattern);
QRgb previousColor = 0;
brush.setColor(QColor::fromRgba(0x80808080));
_painter->save();
_painter->setPen(Qt::NoPen);
_painter->setBrush(brush);
_painter->setTransform(QTransform::fromScale(1.0 / currentScale, 1), true);
auto& items = *m_pSource;
for (const auto& item : items)
{
//if (previousColor != item.color)
//{
// // Set background color brush for rectangle
// previousColor = item.color;
// brush.setColor(QColor::fromRgba(0x40000000 | item.color));
// _painter->setBrush(brush);
//}
// Draw rectangle
auto h = 5 + item.width() * coeff;
rect.setRect(item.left() * currentScale, bottom - h, ::std::max(item.width() * currentScale, 1.0), h);
_painter->drawRect(rect);
}
_painter->restore();
}
void MinimapItem::setBoundingRect(const QRectF& _rect)
{
m_boundingRect = _rect;
}
void MinimapItem::setSource(const ProfItems* _items)
{
m_pSource = _items;
if (m_pSource)
{
if (m_pSource->empty())
{
m_pSource = nullptr;
}
m_maxDuration = 0;
for (const auto& item : *m_pSource)
{
if (item.width() > m_maxDuration)
{
m_maxDuration = item.width();
}
}
}
if (m_pSource == nullptr)
{
hide();
}
else
{
show();
}
}
//////////////////////////////////////////////////////////////////////////
GraphicsHorizontalScrollbar::GraphicsHorizontalScrollbar(QWidget* _parent)
: Parent(_parent)
, m_minimumValue(0)
@ -111,6 +205,8 @@ GraphicsHorizontalScrollbar::GraphicsHorizontalScrollbar(QWidget* _parent)
, m_windowScale(1)
, m_mouseButtons(Qt::NoButton)
, m_slider(nullptr)
, m_chronometerIndicator(nullptr)
, m_minimap(nullptr)
, m_bScrolling(false)
{
setCacheMode(QGraphicsView::CacheNone);
@ -121,18 +217,33 @@ GraphicsHorizontalScrollbar::GraphicsHorizontalScrollbar(QWidget* _parent)
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMinimumHeight(20);
setMaximumHeight(20);
setContentsMargins(0, 0, 0, 0);
setMinimumHeight(DEFAULT_HEIGHT + 2);
setMaximumHeight(DEFAULT_HEIGHT + 2);
auto selfScene = new QGraphicsScene(this);
selfScene->setSceneRect(0, -10, 500, 20);
selfScene->setSceneRect(0, DEFAULT_TOP, 500, DEFAULT_HEIGHT);
setScene(selfScene);
m_slider = new GraphicsHorizontalSlider();
m_slider->setPos(10, 0);
m_slider->setColor(0x80e00000);
m_slider->setPos(0, 0);
m_slider->setZValue(5);
m_slider->setColor(0x90e00000);
selfScene->addItem(m_slider);
m_chronometerIndicator = new GraphicsHorizontalSlider();
m_chronometerIndicator->setPos(0, 0);
m_chronometerIndicator->setZValue(10);
m_chronometerIndicator->setColor(0x90404040);
selfScene->addItem(m_chronometerIndicator);
m_chronometerIndicator->hide();
m_minimap = new MinimapItem();
m_minimap->setPos(0, 0);
m_minimap->setBoundingRect(selfScene->sceneRect());
selfScene->addItem(m_minimap);
m_minimap->hide();
centerOn(0, 0);
}
@ -184,7 +295,8 @@ void GraphicsHorizontalScrollbar::setRange(qreal _minValue, qreal _maxValue)
m_minimumValue = _minValue;
m_maximumValue = _maxValue;
scene()->setSceneRect(_minValue, -10, _maxValue - _minValue, 20);
scene()->setSceneRect(_minValue, DEFAULT_TOP, _maxValue - _minValue, DEFAULT_HEIGHT);
m_minimap->setBoundingRect(scene()->sceneRect());
emit rangeChanged();
setValue(_minValue + oldValue * range());
@ -199,6 +311,31 @@ void GraphicsHorizontalScrollbar::setSliderWidth(qreal _width)
//////////////////////////////////////////////////////////////////////////
void GraphicsHorizontalScrollbar::setChronoPos(qreal _left, qreal _right)
{
m_chronometerIndicator->setWidth(_right - _left);
m_chronometerIndicator->setX(_left + m_chronometerIndicator->halfwidth());
}
void GraphicsHorizontalScrollbar::showChrono()
{
m_chronometerIndicator->show();
}
void GraphicsHorizontalScrollbar::hideChrono()
{
m_chronometerIndicator->hide();
}
//////////////////////////////////////////////////////////////////////////
void GraphicsHorizontalScrollbar::setMinimapFrom(const ProfItems* _items)
{
m_minimap->setSource(_items);
}
//////////////////////////////////////////////////////////////////////////
void GraphicsHorizontalScrollbar::mousePressEvent(QMouseEvent* _event)
{
m_mouseButtons = _event->buttons();

View File

@ -22,6 +22,7 @@
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include "common_types.h"
//////////////////////////////////////////////////////////////////////////
@ -53,6 +54,37 @@ public:
//////////////////////////////////////////////////////////////////////////
class MinimapItem : public QGraphicsItem
{
typedef QGraphicsItem Parent;
typedef MinimapItem This;
QRectF m_boundingRect;
qreal m_maxDuration;
const ProfItems* m_pSource;
public:
MinimapItem();
virtual ~MinimapItem();
// Public virtual methods
QRectF boundingRect() const override;
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
public:
// Public non-virtual methods
void setBoundingRect(const QRectF& _rect);
void setSource(const ProfItems* _items);
}; // END of class MinimapItem.
//////////////////////////////////////////////////////////////////////////
class GraphicsHorizontalScrollbar : public QGraphicsView
{
Q_OBJECT
@ -62,14 +94,16 @@ private:
typedef QGraphicsView Parent;
typedef GraphicsHorizontalScrollbar This;
qreal m_minimumValue;
qreal m_maximumValue;
qreal m_value;
qreal m_windowScale;
QPoint m_mousePressPos;
Qt::MouseButtons m_mouseButtons;
GraphicsHorizontalSlider* m_slider;
bool m_bScrolling;
qreal m_minimumValue;
qreal m_maximumValue;
qreal m_value;
qreal m_windowScale;
QPoint m_mousePressPos;
Qt::MouseButtons m_mouseButtons;
GraphicsHorizontalSlider* m_slider;
GraphicsHorizontalSlider* m_chronometerIndicator;
MinimapItem* m_minimap;
bool m_bScrolling;
public:
@ -91,6 +125,16 @@ public:
void setValue(qreal _value);
void setRange(qreal _minValue, qreal _maxValue);
void setSliderWidth(qreal _width);
void setChronoPos(qreal _left, qreal _right);
void showChrono();
void hideChrono();
void setMinimapFrom(const ProfItems* _items);
inline void setMinimapFrom(const ProfItems& _items)
{
setMinimapFrom(&_items);
}
signals: