0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 00:31:02 +08:00
easy_profiler/profiler_gui/blocks_graphics_view.h

372 lines
13 KiB
C
Raw Normal View History

2016-06-26 18:56:40 +03:00
/************************************************************************
* 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
2016-06-26 19:06:53 +03:00
* : 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.
* :
2016-06-26 18:56:40 +03:00
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
2016-06-26 18:46:51 +03:00
#ifndef MY____GRAPHICS___VIEW_H
#define MY____GRAPHICS___VIEW_H
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QFont>
#include <QPoint>
#include <QTimer>
2016-06-26 18:46:51 +03:00
#include <stdlib.h>
#include "graphics_scrollbar.h"
2016-06-26 18:46:51 +03:00
#include "profiler/reader.h"
#include "common_types.h"
#include "globals.h"
2016-06-26 18:46:51 +03:00
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
2016-06-26 18:46:51 +03:00
class ProfGraphicsView;
class ProfGraphicsItem : public QGraphicsItem
{
typedef ::profiler_gui::ProfItems Children;
typedef ::std::vector<unsigned int> DrawIndexes;
typedef ::std::vector<Children> Sublevels;
DrawIndexes m_levelsIndexes; ///< Indexes of first item on each level from which we must start painting
Sublevels m_levels; ///< Arrays of items for each level
QRectF m_boundingRect; ///< boundingRect (see QGraphicsItem)
const ::profiler::BlocksTreeRoot* m_pRoot; ///< Pointer to the root profiler block (thread block). Used by ProfTreeWidget to restore hierarchy.
QRgb m_backgroundColor; ///< Background color (to enable AlternateColors behavior like in QTreeWidget)
const bool m_bTest; ///< If true then we are running test()
2016-06-26 18:46:51 +03:00
public:
2016-06-26 18:46:51 +03:00
ProfGraphicsItem();
ProfGraphicsItem(bool _test);
ProfGraphicsItem(const ::profiler::BlocksTreeRoot* _root);
virtual ~ProfGraphicsItem();
// Public virtual methods
QRectF boundingRect() const override;
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
2016-06-26 18:46:51 +03:00
public:
// Public non-virtual methods
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
void setBoundingRect(const QRectF& _rect);
2016-06-26 18:46:51 +03:00
void setBackgroundColor(QRgb _color);
::profiler::thread_id_t threadId() const;
///< Returns number of levels
2016-07-27 21:50:11 +03:00
unsigned short levels() const;
/** \brief Sets number of levels.
\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;
}; // END of class ProfGraphicsItem.
2016-06-26 18:46:51 +03:00
//////////////////////////////////////////////////////////////////////////
2016-06-26 18:46:51 +03:00
class ProfChronometerItem : public QGraphicsItem
2016-06-26 18:46:51 +03:00
{
QFont m_font; ///< Font which is used to draw text
QPolygonF m_indicator; ///< Indicator displayed when this chrono item is out of screen (displaying only for main item)
QRectF m_boundingRect; ///< boundingRect (see QGraphicsItem)
QColor m_color; ///< Color of the item
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:
2016-06-26 18:46:51 +03:00
ProfChronometerItem(bool _main = true);
virtual ~ProfChronometerItem();
// Public virtual methods
QRectF boundingRect() const override;
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
2016-06-26 18:46:51 +03:00
public:
// Public non-virtual methods
void setColor(const QColor& _color);
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
void setBoundingRect(const QRectF& _rect);
void setLeftRight(qreal _left, qreal _right);
2016-06-26 18:46:51 +03:00
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;
}
inline qreal left() const
{
return m_left;
}
inline qreal right() const
{
return m_right;
}
2016-06-26 18:46:51 +03:00
inline qreal width() const
2016-06-26 18:46:51 +03:00
{
return m_right - m_left;
2016-06-26 18:46:51 +03:00
}
private:
2016-06-26 18:46:51 +03:00
///< Returns pointer to the ProfGraphicsView widget.
const ProfGraphicsView* view() const;
}; // END of class ProfChronometerItem.
//////////////////////////////////////////////////////////////////////////
2016-06-26 18:46:51 +03:00
2016-06-26 19:06:53 +03:00
class ProfGraphicsView : public QGraphicsView
2016-06-26 18:46:51 +03:00
{
Q_OBJECT
private:
typedef ProfGraphicsView This;
typedef ::std::vector<ProfGraphicsItem*> Items;
Items m_items; ///< Array of all ProfGraphicsItem items
::profiler_gui::TreeBlocks m_selectedBlocks; ///< Array of items which were selected by selection zone (ProfChronometerItem)
QTimer m_flickerTimer; ///< Timer for flicking behavior
QRectF m_visibleSceneRect; ///< Visible scene rectangle
::profiler::timestamp_t m_beginTime; ///< Begin time of profiler session. Used to reduce values of all begin and end times of profiler blocks.
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.
ProfChronometerItem* m_chronometerItemAux; ///< Pointer to the ProfChronometerItem which is displayed when you double click left mouse button and move mouse left or right. This item is used only to measure time.
int m_flickerSpeedX; ///< Current flicking speed x
int m_flickerSpeedY; ///< Current flicking speed y
bool m_bDoubleClick; ///< Is mouse buttons double clicked
bool m_bUpdatingRect; ///< Stub flag which is used to avoid excess calculations on some scene update (flicking, scaling and so on)
bool m_bTest; ///< Testing flag (true when test() is called)
bool m_bEmpty; ///< Indicates whether scene is empty and has no items
2016-06-26 18:46:51 +03:00
public:
ProfGraphicsView(bool _test = false);
ProfGraphicsView(const ::profiler::thread_blocks_tree_t& _blocksTree);
2016-06-26 19:06:53 +03:00
virtual ~ProfGraphicsView();
2016-06-26 18:46:51 +03:00
// Public virtual methods
void wheelEvent(QWheelEvent* _event) override;
void mousePressEvent(QMouseEvent* _event) override;
void mouseDoubleClickEvent(QMouseEvent* _event) override;
void mouseReleaseEvent(QMouseEvent* _event) override;
void mouseMoveEvent(QMouseEvent* _event) override;
void resizeEvent(QResizeEvent* _event) override;
public:
// Public non-virtual methods
void setScrollbar(ProfGraphicsScrollbar* _scrollbar);
void clearSilent();
void test(unsigned int _frames_number, unsigned int _total_items_number_estimate, int _rows);
void setTree(const ::profiler::thread_blocks_tree_t& _blocksTree);
signals:
// Signals
void intervalChanged(const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _session_begin_time, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict);
private:
// Private non-virtual methods
ProfChronometerItem* createChronometer(bool _main = true);
bool moveChrono(ProfChronometerItem* _chronometerItem, qreal _mouseX);
void initMode();
void updateVisibleSceneRect();
void updateScene();
void scaleTo(qreal _scale);
qreal setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, unsigned short _level);
void fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, qreal _y, unsigned int _childrenNumber, unsigned int& _total_items);
private slots:
// Private Slots
void onScrollbarValueChange(int);
void onGraphicsScrollbarValueChange(qreal);
void onFlickerTimeout();
void onSelectedThreadChange(::profiler::thread_id_t _id);
void onSelectedBlockChange(unsigned int _block_index);
2016-06-26 18:46:51 +03:00
public:
// Public inline methods
inline qreal scale() const
{
return m_scale;
}
inline qreal offset() const
{
return m_offset;
}
inline const QRectF& visibleSceneRect() const
{
return m_visibleSceneRect;
}
private:
// Private inline methods
inline qreal time2position(const profiler::timestamp_t& _time) const
{
return PROF_MICROSECONDS(qreal(_time - m_beginTime));
//return PROF_MILLISECONDS(qreal(_time - m_beginTime));
}
inline ::profiler::timestamp_t position2time(qreal _pos) const
{
return PROF_FROM_MICROSECONDS(_pos);
//return PROF_FROM_MILLISECONDS(_pos);
}
inline qreal to_microseconds(qreal _value) const
{
return _value;
//return _value * 1e-3;
}
inline qreal to_milliseconds(qreal _value) const
{
return _value * 1e3;
//return _value;
}
2016-06-26 19:06:53 +03:00
}; // END of class ProfGraphicsView.
2016-06-26 18:46:51 +03:00
//////////////////////////////////////////////////////////////////////////
2016-06-26 18:46:51 +03:00
class ProfGraphicsViewWidget : public QWidget
{
Q_OBJECT
private:
ProfGraphicsView* m_view;
ProfGraphicsScrollbar* m_scrollbar;
public:
ProfGraphicsViewWidget(bool _test = false);
ProfGraphicsViewWidget(const ::profiler::thread_blocks_tree_t& _blocksTree);
virtual ~ProfGraphicsViewWidget();
ProfGraphicsView* view();
private:
}; // END of class ProfGraphicsViewWidget.
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
2016-06-26 18:46:51 +03:00
#endif // MY____GRAPHICS___VIEW_H