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

(profiler_gui) Reading file (MainWindow) and building blocks hierarchy (TreeWidget) in separate threads + displaying read progress;

(profiler_gui) Moving sources into separate files;
(profiler_gui) Rename Prof* classes into Easy*;
(EasyGraphicsView) Optimized performance by not painting items which were not expanded in TreeWidget. While there are no range selected for TreeWidget, only top-level blocks are painted on scene.
This commit is contained in:
Victor Zarubkin 2016-08-18 23:26:41 +03:00
parent 197a585307
commit 8f30948105
21 changed files with 2208 additions and 1552 deletions

View File

@ -23,6 +23,7 @@ along with this program.If not, see <http://www.gnu.org/licenses/>.
#include <map>
#include <vector>
#include <atomic>
#include "profiler/profiler.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -288,6 +289,13 @@ namespace profiler {
m_data = _data;
}
void swap(SerializedData& other)
{
auto temp = other.m_data;
other.m_data = m_data;
m_data = temp;
}
private:
SerializedData(const SerializedData&) = delete;
@ -300,9 +308,13 @@ namespace profiler {
} // END of namespace profiler.
extern "C"{
unsigned int PROFILER_API fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics = false);
unsigned int PROFILER_API fillTreesFromFile(::std::atomic<int>& progress, const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics = false);
}
inline unsigned int fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics = false) {
::std::atomic<int> progress = ATOMIC_VAR_INIT(0);
return fillTreesFromFile(progress, filename, serialized_blocks, threaded_trees, gather_statistics);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -22,6 +22,10 @@ add_executable(${PROJECT_NAME}
graphics_scrollbar.cpp
main_window.h
main_window.cpp
tree_widget_item.h
tree_widget_item.cpp
tree_widget_loader.h
tree_widget_loader.cpp
#treemodel.h
#treemodel.cpp
#treeitem.h

View File

@ -25,10 +25,12 @@
* license : TODO: add license text
************************************************************************/
#include <QGraphicsScene>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QScrollBar>
#include <QGridLayout>
#include <QFont>
#include <QFontMetrics>
#include <QDebug>
#include <math.h>
@ -64,6 +66,8 @@ const unsigned int TEST_PROGRESSION_BASE = 4;
const int FLICKER_INTERVAL = 16; // 60Hz
const auto CHRONOMETER_FONT = QFont("CourierNew", 16, 2);
//////////////////////////////////////////////////////////////////////////
auto const sign = [](int _value) { return _value < 0 ? -1 : 1; };
@ -81,27 +85,25 @@ inline T logn(T _value)
//////////////////////////////////////////////////////////////////////////
ProfGraphicsItem::ProfGraphicsItem(unsigned char _index, bool _test) : QGraphicsItem(nullptr), m_bTest(_test), m_pRoot(nullptr), m_index(_index)
EasyGraphicsItem::EasyGraphicsItem(unsigned char _index, const::profiler::BlocksTreeRoot* _root)
: QGraphicsItem(nullptr)
, m_pRoot(_root)
, m_index(_index)
{
}
ProfGraphicsItem::ProfGraphicsItem(unsigned char _index, const::profiler::BlocksTreeRoot* _root) : ProfGraphicsItem(_index, false)
{
m_pRoot = _root;
}
ProfGraphicsItem::~ProfGraphicsItem()
EasyGraphicsItem::~EasyGraphicsItem()
{
}
const ProfGraphicsView* ProfGraphicsItem::view() const
const EasyGraphicsView* EasyGraphicsItem::view() const
{
return static_cast<const ProfGraphicsView*>(scene()->parent());
return static_cast<const EasyGraphicsView*>(scene()->parent());
}
//////////////////////////////////////////////////////////////////////////
QRectF ProfGraphicsItem::boundingRect() const
QRectF EasyGraphicsItem::boundingRect() const
{
//const auto sceneView = view();
//return QRectF(m_boundingRect.left() - sceneView->offset() / sceneView->scale(), m_boundingRect.top(), m_boundingRect.width() * sceneView->scale(), m_boundingRect.height());
@ -110,7 +112,7 @@ QRectF ProfGraphicsItem::boundingRect() const
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
if (m_levels.empty() || m_levels.front().empty())
{
@ -177,6 +179,10 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
previousPenStyle = Qt::SolidLine;
_painter->setPen(BORDERS_COLOR);
}
else
{
_painter->setPen(Qt::NoPen);
}
@ -187,7 +193,6 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
auto& level = m_levels[l];
const short next_level = l + 1;
char state = 1;
//bool changebrush = false;
const auto top = levelY(l);
for (unsigned int i = m_levelsIndexes[l], end = static_cast<unsigned int>(level.size()); i < end; ++i)
@ -207,8 +212,10 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
continue;
}
qreal x = 0;
int h = 0, flags = 0;
auto w = ::std::max(item.width() * currentScale, 1.0);
if (w < 20)
if (w < 20 || !::profiler_gui::EASY_GLOBALS.gui_blocks[item.block->block_index].expanded)
{
// Items which width is less than 20 will be painted as big rectangles which are hiding it's children
if (item.left() > sceneRight)
@ -217,20 +224,11 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
break;
}
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);
//}
x = item.left() * currentScale - dx;
h = item.totalHeight;
bool changepen = false;
if (!m_bTest && item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
if (item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
{
selectedItemsWasPainted = true;
changepen = true;
@ -291,9 +289,13 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
m_levels[next_level][item.children_begin].state = -1;
}
if (w < 20)
continue;
}
flags = Qt::AlignCenter;
}
else
{
if (next_level < levelsNumber && item.children_begin != MAX_CHILD_INDEX)
{
if (m_levelsIndexes[next_level] == MAX_CHILD_INDEX)
@ -312,15 +314,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
break;
}
//if (changebrush)
//{
// changebrush = false;
// previousColor = item.color;
// brush = QBrush(previousColor);
// _painter->setBrush(brush);
//} else
if (!m_bTest && item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
if (item.block->block_index == ::profiler_gui::EASY_GLOBALS.selected_block)
{
selectedItemsWasPainted = true;
QPen pen(Qt::SolidLine);
@ -351,10 +345,14 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
// Draw rectangle
const auto x = item.left() * currentScale - dx;
x = item.left() * currentScale - dx;
h = GRAPHICS_ROW_SIZE;
rect.setRect(x, top, w, GRAPHICS_ROW_SIZE);
_painter->drawRect(rect);
flags = item.width() < 1 ? 0 : Qt::AlignHCenter;
}
// Draw text-----------------------------------
// calculating text coordinates
auto xtext = x;
@ -366,7 +364,12 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
xtext = sceneLeft * currentScale - dx;
}
rect.setRect(xtext + 1, top, w - 1, GRAPHICS_ROW_SIZE);
if (item.right() > sceneRight)
{
w -= (item.right() - sceneRight) * currentScale;
}
rect.setRect(xtext + 1, top, w - 1, h);
// text will be painted with inverse color
auto textColor = 0x00ffffff - previousColor;
@ -374,16 +377,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_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, ::profiler_gui::toUnicode(item.block->node->getName()));
}
_painter->drawText(rect, flags, ::profiler_gui::toUnicode(item.block->node->getName()));
// restore previous pen color
if (previousPenStyle == Qt::NoPen)
@ -394,7 +388,7 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
}
if (!selectedItemsWasPainted && !m_bTest && ::profiler_gui::EASY_GLOBALS.selected_block < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
if (!selectedItemsWasPainted && ::profiler_gui::EASY_GLOBALS.selected_block < ::profiler_gui::EASY_GLOBALS.gui_blocks.size())
{
const auto& guiblock = ::profiler_gui::EASY_GLOBALS.gui_blocks[::profiler_gui::EASY_GLOBALS.selected_block];
if (guiblock.graphics_item == m_index)
@ -407,11 +401,50 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
pen.setWidth(2);
_painter->setPen(pen);
brush.setColor(previousColor);
brush.setColor(SELECTED_ITEM_COLOR);
_painter->setBrush(brush);
rect.setRect(item.left() * currentScale - dx, levelY(guiblock.graphics_item_level), ::std::max(item.width() * currentScale, 1.0), item.totalHeight);
auto top = levelY(guiblock.graphics_item_level);
auto x = item.left() * currentScale - dx;
auto w = ::std::max(item.width() * currentScale, 1.0);
rect.setRect(x, top, w, item.totalHeight);
_painter->drawRect(rect);
if (w > 20)
{
// Draw text-----------------------------------
// calculating text coordinates
auto xtext = x;
if (item.left() < sceneLeft)
{
// if item left border is out of screen then attach text to the left border of the screen
// to ensure text is always visible for items presenting on the screen.
w += (item.left() - sceneLeft) * currentScale;
xtext = sceneLeft * currentScale - dx;
}
if (item.right() > sceneRight)
{
w -= (item.right() - sceneRight) * currentScale;
}
rect.setRect(xtext + 1, top, w - 1, item.totalHeight);
// text will be painted with inverse color
auto textColor = 0x00ffffff - previousColor;
if (textColor == previousColor) textColor = 0;
_painter->setPen(textColor);
// drawing text
_painter->drawText(rect, Qt::AlignCenter, ::profiler_gui::toUnicode(item.block->node->getName()));
// 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~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
}
}
}
@ -419,14 +452,16 @@ void ProfGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->restore();
}
QRect ProfGraphicsItem::getRect() const
//////////////////////////////////////////////////////////////////////////
QRect EasyGraphicsItem::getRect() const
{
return view()->mapFromScene(m_boundingRect).boundingRect();
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::TreeBlocks& _blocks) const
void EasyGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::TreeBlocks& _blocks) const
{
//if (m_bTest)
//{
@ -476,7 +511,7 @@ void ProfGraphicsItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tree
//////////////////////////////////////////////////////////////////////////
const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF& _pos) const
const ::profiler_gui::ProfBlockItem* EasyGraphicsItem::intersect(const QPointF& _pos) const
{
if (m_levels.empty() || m_levels.front().empty())
{
@ -544,7 +579,7 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
}
const auto w = item.width() * currentScale;
if (i == levelIndex || w < 20)
if (i == levelIndex || w < 20 || !::profiler_gui::EASY_GLOBALS.gui_blocks[item.block->block_index].expanded)
{
return &item;
}
@ -599,36 +634,36 @@ const ::profiler_gui::ProfBlockItem* ProfGraphicsItem::intersect(const QPointF&
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
void EasyGraphicsItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
{
m_boundingRect.setRect(x, y, w, h);
}
void ProfGraphicsItem::setBoundingRect(const QRectF& _rect)
void EasyGraphicsItem::setBoundingRect(const QRectF& _rect)
{
m_boundingRect = _rect;
}
//////////////////////////////////////////////////////////////////////////
::profiler::thread_id_t ProfGraphicsItem::threadId() const
::profiler::thread_id_t EasyGraphicsItem::threadId() const
{
return m_pRoot->thread_id;
}
//////////////////////////////////////////////////////////////////////////
unsigned char ProfGraphicsItem::levels() const
unsigned char EasyGraphicsItem::levels() const
{
return static_cast<unsigned char>(m_levels.size());
}
float ProfGraphicsItem::levelY(unsigned char _level) const
float EasyGraphicsItem::levelY(unsigned char _level) const
{
return y() + static_cast<int>(_level) * static_cast<int>(GRAPHICS_ROW_SIZE_FULL);
}
void ProfGraphicsItem::setLevels(unsigned char _levels)
void EasyGraphicsItem::setLevels(unsigned char _levels)
{
typedef decltype(m_levelsIndexes) IndexesT;
static const auto MAX_CHILD_INDEX = ::profiler_gui::numeric_max<IndexesT::value_type>();
@ -637,29 +672,29 @@ void ProfGraphicsItem::setLevels(unsigned char _levels)
m_levelsIndexes.resize(_levels, MAX_CHILD_INDEX);
}
void ProfGraphicsItem::reserve(unsigned char _level, unsigned int _items)
void EasyGraphicsItem::reserve(unsigned char _level, unsigned int _items)
{
m_levels[_level].reserve(_items);
}
//////////////////////////////////////////////////////////////////////////
const ProfGraphicsItem::Children& ProfGraphicsItem::items(unsigned char _level) const
const EasyGraphicsItem::Children& EasyGraphicsItem::items(unsigned char _level) const
{
return m_levels[_level];
}
const ::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned char _level, unsigned int _index) const
const ::profiler_gui::ProfBlockItem& EasyGraphicsItem::getItem(unsigned char _level, unsigned int _index) const
{
return m_levels[_level][_index];
}
::profiler_gui::ProfBlockItem& ProfGraphicsItem::getItem(unsigned char _level, unsigned int _index)
::profiler_gui::ProfBlockItem& EasyGraphicsItem::getItem(unsigned char _level, unsigned int _index)
{
return m_levels[_level][_index];
}
unsigned int ProfGraphicsItem::addItem(unsigned char _level)
unsigned int EasyGraphicsItem::addItem(unsigned char _level)
{
m_levels[_level].emplace_back();
return static_cast<unsigned int>(m_levels[_level].size() - 1);
@ -667,22 +702,29 @@ unsigned int ProfGraphicsItem::addItem(unsigned char _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), m_bHover(false)
EasyChronometerItem::EasyChronometerItem(bool _main)
: QGraphicsItem()
, m_color(CHRONOMETER_COLOR)
, m_left(0)
, m_right(0)
, m_bMain(_main)
, m_bReverse(false)
, m_bHoverIndicator(false)
{
//setZValue(_main ? 10 : 9);
m_indicator.reserve(3);
}
ProfChronometerItem::~ProfChronometerItem()
EasyChronometerItem::~EasyChronometerItem()
{
}
QRectF ProfChronometerItem::boundingRect() const
QRectF EasyChronometerItem::boundingRect() const
{
return m_boundingRect;
}
void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
void EasyChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
const auto sceneView = view();
const auto currentScale = sceneView->scale();
@ -699,7 +741,7 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
if (m_bMain)
{
const int size = m_bHover ? 12 : 10;
const int size = m_bHoverIndicator ? 12 : 10;
auto vcenter = visibleSceneRect.top() + visibleSceneRect.height() * 0.5;
auto color = QColor::fromRgb(m_color.rgb());
auto pen = _painter->pen();
@ -723,7 +765,7 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
_painter->save();
_painter->setTransform(QTransform::fromTranslate(-x(), -y()), true);
_painter->setBrush(m_bHover ? QColor::fromRgb(0xffff0000) : color);
_painter->setBrush(m_bHoverIndicator ? QColor::fromRgb(0xffff0000) : color);
_painter->setPen(pen);
_painter->drawPolygon(m_indicator);
_painter->restore();
@ -737,7 +779,7 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
selectedInterval = units2microseconds(selectedInterval);
const QString text = ::profiler_gui::timeStringReal(selectedInterval); // Displayed text
const auto textRect = QFontMetrics(m_font).boundingRect(text); // Calculate displayed text boundingRect
const auto textRect = QFontMetrics(CHRONOMETER_FONT).boundingRect(text); // Calculate displayed text boundingRect
const auto rgb = m_color.rgb() & 0x00ffffff;
@ -764,7 +806,7 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
// draw text
_painter->setCompositionMode(QPainter::CompositionMode_Difference); // This lets the text to be visible on every background
_painter->setPen(0xffffffff - rgb);
_painter->setFont(m_font);
_painter->setFont(CHRONOMETER_FONT);
if (m_left < sceneLeft)
{
@ -789,14 +831,12 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
return;
}
sceneLeft -= offset;
sceneRight -= offset;
if (rect.right() + textRect.width() < sceneRight)
if (m_right + textRect.width() < sceneRight)
{
// Text will be drawed to the right of rectangle
_painter->drawText(QPointF(rect.right(), rect.top() + rect.height() * 0.5 + textRect.height() * 0.33), text);
}
else if (rect.left() - textRect.width() > sceneLeft)
else if (m_left - textRect.width() > sceneLeft)
{
// Text will be drawed to the left of rectangle
_painter->drawText(QPointF(rect.left() - textRect.width(), rect.top() + rect.height() * 0.5 + textRect.height() * 0.33), text);
@ -811,7 +851,7 @@ void ProfChronometerItem::paint(QPainter* _painter, const QStyleOptionGraphicsIt
// END Paint!~~~~~~~~~~~~~~~~~~~~~~
}
bool ProfChronometerItem::contains(const QPointF& _pos) const
bool EasyChronometerItem::contains(const QPointF& _pos) const
{
const auto sceneView = view();
const auto clickX = (_pos.x() - sceneView->offset()) * sceneView->scale() - x();
@ -820,22 +860,22 @@ bool ProfChronometerItem::contains(const QPointF& _pos) const
return false;
}
void ProfChronometerItem::setColor(const QColor& _color)
void EasyChronometerItem::setColor(const QColor& _color)
{
m_color = _color;
}
void ProfChronometerItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
void EasyChronometerItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
{
m_boundingRect.setRect(x, y, w, h);
}
void ProfChronometerItem::setBoundingRect(const QRectF& _rect)
void EasyChronometerItem::setBoundingRect(const QRectF& _rect)
{
m_boundingRect = _rect;
}
void ProfChronometerItem::setLeftRight(qreal _left, qreal _right)
void EasyChronometerItem::setLeftRight(qreal _left, qreal _right)
{
if (_left < _right)
{
@ -849,26 +889,26 @@ void ProfChronometerItem::setLeftRight(qreal _left, qreal _right)
}
}
void ProfChronometerItem::setReverse(bool _reverse)
void EasyChronometerItem::setReverse(bool _reverse)
{
m_bReverse = _reverse;
}
void ProfChronometerItem::setHover(bool _hover)
void EasyChronometerItem::setHover(bool _hover)
{
m_bHover = _hover;
m_bHoverIndicator = _hover;
}
const ProfGraphicsView* ProfChronometerItem::view() const
const EasyGraphicsView* EasyChronometerItem::view() const
{
return static_cast<const ProfGraphicsView*>(scene()->parent());
return static_cast<const EasyGraphicsView*>(scene()->parent());
}
//////////////////////////////////////////////////////////////////////////
void ProfBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
void EasyBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
const auto sceneView = static_cast<const ProfGraphicsView*>(scene()->parent());
const auto sceneView = static_cast<const EasyGraphicsView*>(scene()->parent());
const auto visibleSceneRect = sceneView->visibleSceneRect();
const auto currentScale = sceneView->scale();
const auto offset = sceneView->offset();
@ -940,9 +980,9 @@ void ProfBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsIte
//////////////////////////////////////////////////////////////////////////
void ProfTimelineIndicatorItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
void EasyTimelineIndicatorItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
const auto sceneView = static_cast<const ProfGraphicsView*>(scene()->parent());
const auto sceneView = static_cast<const EasyGraphicsView*>(scene()->parent());
const auto visibleSceneRect = sceneView->visibleSceneRect();
const auto step = sceneView->timelineStep() * sceneView->scale();
const QString text = ::profiler_gui::timeStringInt(units2microseconds(sceneView->timelineStep())); // Displayed text
@ -966,7 +1006,7 @@ void ProfTimelineIndicatorItem::paint(QPainter* _painter, const QStyleOptionGrap
//////////////////////////////////////////////////////////////////////////
ProfGraphicsView::ProfGraphicsView(QWidget* _parent)
EasyGraphicsView::EasyGraphicsView(QWidget* _parent)
: QGraphicsView(_parent)
, m_beginTime(::std::numeric_limits<decltype(m_beginTime)>::max())
, m_scale(1)
@ -979,7 +1019,7 @@ ProfGraphicsView::ProfGraphicsView(QWidget* _parent)
, m_flickerSpeedY(0)
, m_bDoubleClick(false)
, m_bUpdatingRect(false)
, m_bTest(false)
//, m_bTest(false)
, m_bEmpty(true)
{
initMode();
@ -987,15 +1027,15 @@ ProfGraphicsView::ProfGraphicsView(QWidget* _parent)
updateVisibleSceneRect();
}
ProfGraphicsView::~ProfGraphicsView()
EasyGraphicsView::~EasyGraphicsView()
{
}
//////////////////////////////////////////////////////////////////////////
ProfChronometerItem* ProfGraphicsView::createChronometer(bool _main)
EasyChronometerItem* EasyGraphicsView::createChronometer(bool _main)
{
auto chronoItem = new ProfChronometerItem(_main);
auto chronoItem = new EasyChronometerItem(_main);
chronoItem->setColor(_main ? CHRONOMETER_COLOR : CHRONOMETER_COLOR2);
chronoItem->setBoundingRect(scene()->sceneRect());
chronoItem->hide();
@ -1006,7 +1046,7 @@ ProfChronometerItem* ProfGraphicsView::createChronometer(bool _main)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, unsigned int _childrenNumber, unsigned int& _total_items)
/*void EasyGraphicsView::fillTestChildren(EasyGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, unsigned int _childrenNumber, unsigned int& _total_items)
{
unsigned int nchildren = _childrenNumber;
_childrenNumber = TEST_PROGRESSION_BASE;
@ -1041,7 +1081,7 @@ void ProfGraphicsView::fillTestChildren(ProfGraphicsItem* _item, const int _maxl
}
}
void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_items_number_estimate, unsigned char _rows)
void EasyGraphicsView::test(unsigned int _frames_number, unsigned int _total_items_number_estimate, unsigned char _rows)
{
static const qreal X_BEGIN = 50;
static const qreal Y_BEGIN = 0;
@ -1055,14 +1095,14 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
const auto first_level_children_count = static_cast<unsigned int>(static_cast<double>(children_per_frame) * (1.0 - TEST_PROGRESSION_BASE) / (1.0 - pow(TEST_PROGRESSION_BASE, max_depth)) + 0.5);
auto bgItem = new ProfBackgroundItem();
auto bgItem = new EasyBackgroundItem();
scene()->addItem(bgItem);
::std::vector<ProfGraphicsItem*> thread_items(_rows);
::std::vector<EasyGraphicsItem*> thread_items(_rows);
for (unsigned char i = 0; i < _rows; ++i)
{
auto item = new ProfGraphicsItem(i, true);
auto item = new EasyGraphicsItem(i, true);
thread_items[i] = item;
item->setPos(0, Y_BEGIN + i * (max_depth * GRAPHICS_ROW_SIZE_FULL + THREADS_ROW_SPACING * 5));
@ -1087,7 +1127,7 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
// Create required number of items
unsigned int total_items = 0;
qreal maxX = 0;
const ProfGraphicsItem* longestItem = nullptr;
const EasyGraphicsItem* longestItem = nullptr;
for (unsigned char i = 0; i < _rows; ++i)
{
auto item = thread_items[i];
@ -1150,7 +1190,7 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
m_chronometerItem = createChronometer(true);
bgItem->setBoundingRect(scene()->sceneRect());
auto indicator = new ProfTimelineIndicatorItem();
auto indicator = new EasyTimelineIndicatorItem();
indicator->setBoundingRect(scene()->sceneRect());
scene()->addItem(indicator);
@ -1159,11 +1199,11 @@ void ProfGraphicsView::test(unsigned int _frames_number, unsigned int _total_ite
m_bEmpty = false;
scaleTo(BASE_SCALE);
}
}*/
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::clearSilent()
void EasyGraphicsView::clearSilent()
{
const QSignalBlocker blocker(this), sceneBlocker(scene()); // block all scene signals (otherwise clear() would be extremely slow!)
@ -1183,14 +1223,14 @@ void ProfGraphicsView::clearSilent()
m_offset = 0; // scroll back to the beginning of the scene
// Reset necessary flags
m_bTest = false;
//m_bTest = false;
m_bEmpty = true;
// notify ProfTreeWidget that selection was reset
emit intervalChanged(m_selectedBlocks, m_beginTime, 0, 0, false);
}
void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTree)
void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTree)
{
// clear scene
clearSilent();
@ -1200,7 +1240,7 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
return;
}
auto bgItem = new ProfBackgroundItem();
auto bgItem = new EasyBackgroundItem();
scene()->addItem(bgItem);
// set new blocks tree
@ -1209,7 +1249,7 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
// Calculating start and end time
::profiler::timestamp_t finish = 0;
const ::profiler::BlocksTree* longestTree = nullptr;
const ProfGraphicsItem* longestItem = nullptr;
const EasyGraphicsItem* longestItem = nullptr;
for (const auto& threadTree : _blocksTree)
{
const auto& tree = threadTree.second.tree;
@ -1236,7 +1276,7 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
// fill scene with new items
const auto& tree = threadTree.second.tree;
qreal h = 0, x = time2position(tree.children.front().node->block()->getBegin());
auto item = new ProfGraphicsItem(static_cast<unsigned char>(m_items.size()), &threadTree.second);
auto item = new EasyGraphicsItem(static_cast<unsigned char>(m_items.size()), &threadTree.second);
item->setLevels(tree.depth);
item->setPos(0, y);
@ -1255,7 +1295,7 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
if (m_items.size() == 0xff)
{
qWarning() << "Maximum threads number (255 threads) exceeded! See ProfGraphicsView::setTree() : " << __LINE__ << " in file " << __FILE__;
qWarning() << "Maximum threads number (255 threads) exceeded! See EasyGraphicsView::setTree() : " << __LINE__ << " in file " << __FILE__;
break;
}
}
@ -1283,23 +1323,23 @@ void ProfGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
m_chronometerItem = createChronometer(true);
bgItem->setBoundingRect(0, 0, endX, y);
auto indicator = new ProfTimelineIndicatorItem();
auto indicator = new EasyTimelineIndicatorItem();
indicator->setBoundingRect(0, 0, endX, y);
scene()->addItem(indicator);
// Setting flags
m_bTest = false;
//m_bTest = false;
m_bEmpty = false;
scaleTo(BASE_SCALE);
}
const ProfGraphicsView::Items &ProfGraphicsView::getItems() const
const EasyGraphicsView::Items &EasyGraphicsView::getItems() const
{
return m_items;
}
qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
qreal EasyGraphicsView::setTree(EasyGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level)
{
static const qreal MIN_DURATION = 0.25;
@ -1364,7 +1404,7 @@ qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::Block
else if (!child.children.empty() && !warned)
{
warned = true;
qWarning() << "Maximum blocks depth (255) exceeded! See ProfGraphicsView::setTree() : " << __LINE__ << " in file " << __FILE__;
qWarning() << "Maximum blocks depth (255) exceeded! See EasyGraphicsView::setTree() : " << __LINE__ << " in file " << __FILE__;
}
if (duration < children_duration)
@ -1394,11 +1434,11 @@ qreal ProfGraphicsView::setTree(ProfGraphicsItem* _item, const ::profiler::Block
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::setScrollbar(ProfGraphicsScrollbar* _scrollbar)
void EasyGraphicsView::setScrollbar(EasyGraphicsScrollbar* _scrollbar)
{
if (m_pScrollbar)
{
disconnect(m_pScrollbar, &ProfGraphicsScrollbar::valueChanged, this, &This::onGraphicsScrollbarValueChange);
disconnect(m_pScrollbar, &EasyGraphicsScrollbar::valueChanged, this, &This::onGraphicsScrollbarValueChange);
}
m_pScrollbar = _scrollbar;
@ -1407,7 +1447,7 @@ void ProfGraphicsView::setScrollbar(ProfGraphicsScrollbar* _scrollbar)
m_pScrollbar->setRange(0, scene()->width());
m_pScrollbar->setSliderWidth(m_visibleSceneRect.width());
m_pScrollbar->setValue(0);
connect(m_pScrollbar, &ProfGraphicsScrollbar::valueChanged, this, &This::onGraphicsScrollbarValueChange);
connect(m_pScrollbar, &EasyGraphicsScrollbar::valueChanged, this, &This::onGraphicsScrollbarValueChange);
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
emit ::profiler_gui::EASY_GLOBALS.events.selectedThreadChanged(0);
@ -1415,7 +1455,7 @@ void ProfGraphicsView::setScrollbar(ProfGraphicsScrollbar* _scrollbar)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::updateVisibleSceneRect()
void EasyGraphicsView::updateVisibleSceneRect()
{
m_visibleSceneRect = mapToScene(rect()).boundingRect();
@ -1424,7 +1464,7 @@ void ProfGraphicsView::updateVisibleSceneRect()
m_visibleSceneRect.setWidth(m_visibleSceneRect.width() - vbar->width() - 2);
}
void ProfGraphicsView::updateTimelineStep(qreal _windowWidth)
void EasyGraphicsView::updateTimelineStep(qreal _windowWidth)
{
const auto time = units2microseconds(_windowWidth);
if (time < 100)
@ -1445,14 +1485,14 @@ void ProfGraphicsView::updateTimelineStep(qreal _windowWidth)
m_timelineStep = microseconds2units(m_timelineStep);
}
void ProfGraphicsView::updateScene()
void EasyGraphicsView::updateScene()
{
scene()->update(m_visibleSceneRect);
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::scaleTo(qreal _scale)
void EasyGraphicsView::scaleTo(qreal _scale)
{
if (m_bEmpty)
{
@ -1472,7 +1512,7 @@ void ProfGraphicsView::scaleTo(qreal _scale)
updateScene();
}
void ProfGraphicsView::wheelEvent(QWheelEvent* _event)
void EasyGraphicsView::wheelEvent(QWheelEvent* _event)
{
if (m_bEmpty)
{
@ -1511,7 +1551,7 @@ void ProfGraphicsView::wheelEvent(QWheelEvent* _event)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::mousePressEvent(QMouseEvent* _event)
void EasyGraphicsView::mousePressEvent(QMouseEvent* _event)
{
if (m_bEmpty)
{
@ -1534,7 +1574,7 @@ void ProfGraphicsView::mousePressEvent(QMouseEvent* _event)
_event->accept();
}
void ProfGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
void EasyGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
{
if (m_bEmpty)
{
@ -1559,7 +1599,7 @@ void ProfGraphicsView::mouseDoubleClickEvent(QMouseEvent* _event)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
{
if (m_bEmpty)
{
@ -1583,7 +1623,7 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
m_selectedBlocks.clear();
}
if (!m_bTest && m_chronometerItem->isVisible())
if (m_chronometerItem->isVisible())
{
//printf("INTERVAL: {%lf, %lf} ms\n", m_chronometerItem->left(), m_chronometerItem->right());
@ -1605,7 +1645,7 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
{
m_chronometerItemAux->hide();
}
else if (m_chronometerItem->isVisible() && m_chronometerItem->hover())
else if (m_chronometerItem->isVisible() && m_chronometerItem->hoverIndicator())
{
// Jump to selected zone
clicked = true;
@ -1613,7 +1653,7 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
m_pScrollbar->setValue(m_chronometerItem->left() + m_chronometerItem->width() * 0.5 - m_pScrollbar->sliderHalfWidth());
}
if (!clicked && m_mouseMovePath.manhattanLength() < 5 && !m_bTest)
if (!clicked && m_mouseMovePath.manhattanLength() < 5)
{
// Handle Click
@ -1659,7 +1699,7 @@ void ProfGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
//////////////////////////////////////////////////////////////////////////
bool ProfGraphicsView::moveChrono(ProfChronometerItem* _chronometerItem, qreal _mouseX)
bool EasyGraphicsView::moveChrono(EasyChronometerItem* _chronometerItem, qreal _mouseX)
{
if (_chronometerItem->reverse())
{
@ -1695,7 +1735,7 @@ bool ProfGraphicsView::moveChrono(ProfChronometerItem* _chronometerItem, qreal _
return false;
}
void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
void EasyGraphicsView::mouseMoveEvent(QMouseEvent* _event)
{
if (m_bEmpty || (m_mouseButtons == 0 && !m_chronometerItem->isVisible()))
{
@ -1764,9 +1804,9 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
if (m_chronometerItem->isVisible())
{
auto prevValue = m_chronometerItem->hover();
auto prevValue = m_chronometerItem->hoverIndicator();
m_chronometerItem->setHover(m_chronometerItem->contains(mouseScenePos));
needUpdate = needUpdate || (prevValue != m_chronometerItem->hover());
needUpdate = needUpdate || (prevValue != m_chronometerItem->hoverIndicator());
}
if (needUpdate)
@ -1779,7 +1819,7 @@ void ProfGraphicsView::mouseMoveEvent(QMouseEvent* _event)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::resizeEvent(QResizeEvent* _event)
void EasyGraphicsView::resizeEvent(QResizeEvent* _event)
{
QGraphicsView::resizeEvent(_event);
updateVisibleSceneRect(); // Update scene visible rect only once
@ -1788,7 +1828,7 @@ void ProfGraphicsView::resizeEvent(QResizeEvent* _event)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::initMode()
void EasyGraphicsView::initMode()
{
// TODO: find mode with least number of bugs :)
// There are always some display bugs...
@ -1801,19 +1841,20 @@ void ProfGraphicsView::initMode()
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
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);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedBlockChanged, this, &This::onSelectedBlockChange);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::itemsExpandStateChanged, this, &This::onItemsEspandStateChange);
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::onScrollbarValueChange(int)
void EasyGraphicsView::onScrollbarValueChange(int)
{
if (!m_bUpdatingRect && !m_bEmpty)
updateVisibleSceneRect();
}
void ProfGraphicsView::onGraphicsScrollbarValueChange(qreal _value)
void EasyGraphicsView::onGraphicsScrollbarValueChange(qreal _value)
{
if (!m_bEmpty)
{
@ -1828,7 +1869,7 @@ void ProfGraphicsView::onGraphicsScrollbarValueChange(qreal _value)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::onFlickerTimeout()
void EasyGraphicsView::onFlickerTimeout()
{
if (m_mouseButtons & Qt::LeftButton)
{
@ -1865,9 +1906,9 @@ void ProfGraphicsView::onFlickerTimeout()
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::onSelectedThreadChange(::profiler::thread_id_t _id)
void EasyGraphicsView::onSelectedThreadChange(::profiler::thread_id_t _id)
{
if (m_pScrollbar == nullptr || m_pScrollbar->minimapThread() == _id || m_bTest)
if (m_pScrollbar == nullptr || m_pScrollbar->minimapThread() == _id)
{
return;
}
@ -1894,7 +1935,7 @@ void ProfGraphicsView::onSelectedThreadChange(::profiler::thread_id_t _id)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsView::onSelectedBlockChange(unsigned int _block_index)
void EasyGraphicsView::onSelectedBlockChange(unsigned int _block_index)
{
if (!m_bUpdatingRect)
{
@ -1921,16 +1962,26 @@ void ProfGraphicsView::onSelectedBlockChange(unsigned int _block_index)
//////////////////////////////////////////////////////////////////////////
ProfGraphicsViewWidget::ProfGraphicsViewWidget(QWidget* _parent)
void EasyGraphicsView::onItemsEspandStateChange()
{
if (!m_bUpdatingRect)
{
updateScene();
}
}
//////////////////////////////////////////////////////////////////////////
EasyGraphicsViewWidget::EasyGraphicsViewWidget(QWidget* _parent)
: QWidget(_parent)
, m_scrollbar(new ProfGraphicsScrollbar(nullptr))
, m_view(new ProfGraphicsView(nullptr))
//, m_threadWidget(new ProfThreadViewWidget(this,m_view))
, m_scrollbar(new EasyGraphicsScrollbar(nullptr))
, m_view(new EasyGraphicsView(nullptr))
//, m_threadWidget(new EasyThreadViewWidget(this,m_view))
{
initWidget();
}
void ProfGraphicsViewWidget::initWidget()
void EasyGraphicsViewWidget::initWidget()
{
auto lay = new QGridLayout(this);
lay->setContentsMargins(1, 0, 1, 0);
@ -1944,12 +1995,12 @@ void ProfGraphicsViewWidget::initWidget()
m_view->setScrollbar(m_scrollbar);
}
ProfGraphicsViewWidget::~ProfGraphicsViewWidget()
EasyGraphicsViewWidget::~EasyGraphicsViewWidget()
{
}
ProfGraphicsView* ProfGraphicsViewWidget::view()
EasyGraphicsView* EasyGraphicsViewWidget::view()
{
return m_view;
}
@ -1957,7 +2008,7 @@ ProfGraphicsView* ProfGraphicsViewWidget::view()
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
ProfThreadViewWidget::ProfThreadViewWidget(QWidget *parent, ProfGraphicsView* view):QWidget(parent),
EasyThreadViewWidget::EasyThreadViewWidget(QWidget *parent, EasyGraphicsView* view):QWidget(parent),
m_view(view)
, m_label(new QLabel("",this))
{
@ -1967,15 +2018,15 @@ ProfThreadViewWidget::ProfThreadViewWidget(QWidget *parent, ProfGraphicsView* vi
//m_layout->addWidget(m_label);
//setLayout(m_layout);
//show();
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::ProfGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
connect(&::profiler_gui::EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::selectedThreadChanged, this, &This::onSelectedThreadChange);
}
ProfThreadViewWidget::~ProfThreadViewWidget()
EasyThreadViewWidget::~EasyThreadViewWidget()
{
}
void ProfThreadViewWidget::onSelectedThreadChange(::profiler::thread_id_t _id)
void EasyThreadViewWidget::onSelectedThreadChange(::profiler::thread_id_t _id)
{
/*
auto threadName = ::profiler_gui::EASY_GLOBALS.profiler_blocks[::profiler_gui::EASY_GLOBALS.selected_thread].thread_name;

View File

@ -21,13 +21,11 @@
* license : TODO: add license text
************************************************************************/
#ifndef MY____GRAPHICS___VIEW_H
#define MY____GRAPHICS___VIEW_H
#ifndef EASY__GRAPHICS_VIEW__H_
#define EASY__GRAPHICS_VIEW__H_
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QFont>
#include <QPoint>
#include <QTimer>
#include <QLabel>
@ -40,7 +38,7 @@
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsView;
class EasyGraphicsView;
//////////////////////////////////////////////////////////////////////////
@ -58,7 +56,7 @@ inline qreal microseconds2units(qreal _value)
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsItem : public QGraphicsItem
class EasyGraphicsItem : public QGraphicsItem
{
typedef ::profiler_gui::ProfItems Children;
typedef ::std::vector<unsigned int> DrawIndexes;
@ -69,14 +67,12 @@ class ProfGraphicsItem : public QGraphicsItem
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.
const bool m_bTest; ///< If true then we are running test()
unsigned char m_index; ///< This item's index in the list of items of ProfGraphicsView
unsigned char m_index; ///< This item's index in the list of items of EasyGraphicsView
public:
ProfGraphicsItem(unsigned char _index, bool _test);
ProfGraphicsItem(unsigned char _index, const::profiler::BlocksTreeRoot* _root);
virtual ~ProfGraphicsItem();
EasyGraphicsItem(unsigned char _index, const::profiler::BlocksTreeRoot* _root);
virtual ~EasyGraphicsItem();
// Public virtual methods
@ -150,38 +146,37 @@ public:
private:
///< Returns pointer to the ProfGraphicsView widget.
const ProfGraphicsView* view() const;
///< Returns pointer to the EasyGraphicsView widget.
const EasyGraphicsView* view() const;
public:
// Public inline methods
///< Returns this item's index in the list of graphics items of ProfGraphicsView
///< Returns this item's index in the list of graphics items of EasyGraphicsView
inline unsigned char index() const
{
return m_index;
}
}; // END of class ProfGraphicsItem.
}; // END of class EasyGraphicsItem.
//////////////////////////////////////////////////////////////////////////
class ProfChronometerItem : public QGraphicsItem
class EasyChronometerItem : public QGraphicsItem
{
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
bool m_bReverse; ///<
bool m_bHoverIndicator; ///< Mouse hover above indicator
public:
ProfChronometerItem(bool _main = true);
virtual ~ProfChronometerItem();
EasyChronometerItem(bool _main = true);
virtual ~EasyChronometerItem();
// Public virtual methods
@ -205,9 +200,9 @@ public:
bool contains(const QPointF& _pos) const;
inline bool hover() const
inline bool hoverIndicator() const
{
return m_bHover;
return m_bHoverIndicator;
}
inline bool reverse() const
@ -232,10 +227,10 @@ public:
private:
///< Returns pointer to the ProfGraphicsView widget.
const ProfGraphicsView* view() const;
///< Returns pointer to the EasyGraphicsView widget.
const EasyGraphicsView* view() const;
}; // END of class ProfChronometerItem.
}; // END of class EasyChronometerItem.
//////////////////////////////////////////////////////////////////////////
@ -251,24 +246,24 @@ public: \
void setBoundingRect(const QRectF& _rect) { m_boundingRect = _rect; } \
}
EASY_QGRAPHICSITEM(ProfBackgroundItem);
EASY_QGRAPHICSITEM(ProfTimelineIndicatorItem);
EASY_QGRAPHICSITEM(EasyBackgroundItem);
EASY_QGRAPHICSITEM(EasyTimelineIndicatorItem);
#undef EASY_QGRAPHICSITEM
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsView : public QGraphicsView
class EasyGraphicsView : public QGraphicsView
{
Q_OBJECT
private:
typedef ProfGraphicsView This;
typedef ::std::vector<ProfGraphicsItem*> Items;
typedef EasyGraphicsView This;
typedef ::std::vector<EasyGraphicsItem*> Items;
Items m_items; ///< Array of all ProfGraphicsItem items
::profiler_gui::TreeBlocks m_selectedBlocks; ///< Array of items which were selected by selection zone (ProfChronometerItem)
Items m_items; ///< Array of all EasyGraphicsItem items
::profiler_gui::TreeBlocks m_selectedBlocks; ///< Array of items which were selected by selection zone (EasyChronometerItem)
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.
@ -278,20 +273,19 @@ private:
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.
EasyGraphicsScrollbar* m_pScrollbar; ///< Pointer to the graphics scrollbar widget
EasyChronometerItem* m_chronometerItem; ///< Pointer to the EasyChronometerItem 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.
EasyChronometerItem* m_chronometerItemAux; ///< Pointer to the EasyChronometerItem 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
public:
ProfGraphicsView(QWidget* _parent = nullptr);
virtual ~ProfGraphicsView();
EasyGraphicsView(QWidget* _parent = nullptr);
virtual ~EasyGraphicsView();
// Public virtual methods
@ -306,10 +300,9 @@ public:
// Public non-virtual methods
void setScrollbar(ProfGraphicsScrollbar* _scrollbar);
void setScrollbar(EasyGraphicsScrollbar* _scrollbar);
void clearSilent();
void test(unsigned int _frames_number, unsigned int _total_items_number_estimate, unsigned char _rows);
void setTree(const ::profiler::thread_blocks_tree_t& _blocksTree);
const Items& getItems() const;
@ -324,15 +317,14 @@ private:
// Private non-virtual methods
ProfChronometerItem* createChronometer(bool _main = true);
bool moveChrono(ProfChronometerItem* _chronometerItem, qreal _mouseX);
EasyChronometerItem* createChronometer(bool _main = true);
bool moveChrono(EasyChronometerItem* _chronometerItem, qreal _mouseX);
void initMode();
void updateVisibleSceneRect();
void updateTimelineStep(qreal _windowWidth);
void updateScene();
void scaleTo(qreal _scale);
qreal setTree(ProfGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level);
void fillTestChildren(ProfGraphicsItem* _item, const int _maxlevel, int _level, qreal _x, unsigned int _childrenNumber, unsigned int& _total_items);
qreal setTree(EasyGraphicsItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, qreal _y, short _level);
private slots:
@ -343,6 +335,7 @@ private slots:
void onFlickerTimeout();
void onSelectedThreadChange(::profiler::thread_id_t _id);
void onSelectedBlockChange(unsigned int _block_index);
void onItemsEspandStateChange();
public:
@ -384,53 +377,53 @@ private:
//return PROF_FROM_MILLISECONDS(_pos);
}
}; // END of class ProfGraphicsView.
}; // END of class EasyGraphicsView.
class ProfThreadViewWidget : public QWidget
//////////////////////////////////////////////////////////////////////////
class EasyThreadViewWidget : public QWidget
{
Q_OBJECT
private:
ProfGraphicsView* m_view;
EasyGraphicsView* m_view;
QLabel* m_label;
typedef ProfThreadViewWidget This;
typedef EasyThreadViewWidget This;
QHBoxLayout *m_layout;
public:
ProfThreadViewWidget(QWidget *parent, ProfGraphicsView* view);
virtual ~ProfThreadViewWidget();
EasyThreadViewWidget(QWidget *parent, EasyGraphicsView* view);
virtual ~EasyThreadViewWidget();
public slots:
void onSelectedThreadChange(::profiler::thread_id_t _id);
};
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsViewWidget : public QWidget
class EasyGraphicsViewWidget : public QWidget
{
Q_OBJECT
private:
ProfGraphicsView* m_view;
ProfGraphicsScrollbar* m_scrollbar;
//ProfThreadViewWidget* m_threadWidget;
EasyGraphicsView* m_view;
EasyGraphicsScrollbar* m_scrollbar;
//EasyThreadViewWidget* m_threadWidget;
public:
ProfGraphicsViewWidget(QWidget* _parent = nullptr);
virtual ~ProfGraphicsViewWidget();
EasyGraphicsViewWidget(QWidget* _parent = nullptr);
virtual ~EasyGraphicsViewWidget();
ProfGraphicsView* view();
EasyGraphicsView* view();
private:
void initWidget();
}; // END of class ProfGraphicsViewWidget.
}; // END of class EasyGraphicsViewWidget.
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#endif // MY____GRAPHICS___VIEW_H
#endif // EASY__GRAPHICS_VIEW__H_

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of TreeWidget and it's auxiliary classes
* : for displyaing easy_profiler blocks tree.
* description : The file contains declaration of EasyTreeWidget and it's auxiliary classes
* : for displyaing EasyProfiler blocks tree.
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: moved sources from tree_view.h
* : and renamed classes from My* to Prof*.
@ -17,66 +17,20 @@
* :
* : * 2016/06/29 Victor Zarubkin: Added clearSilent() method.
* :
* : *
* : * 2016/08/18 Victor Zarubkin: Added loading blocks hierarchy in separate thread;
* : Moved sources of TreeWidgetItem into tree_widget_item.h/.cpp
* ----------------- :
* license : TODO: add license text
************************************************************************/
#ifndef MY____TREE___VIEW_H
#define MY____TREE___VIEW_H
#ifndef EASY__TREE_WIDGET__H_
#define EASY__TREE_WIDGET__H_
#include <QTreeWidget>
#include <QAction>
#include <stdlib.h>
#include <unordered_map>
#include <vector>
#include <QTimer>
#include "tree_widget_loader.h"
#include "profiler/reader.h"
#include "common_types.h"
//////////////////////////////////////////////////////////////////////////
class ProfTreeWidgetItem : public QTreeWidgetItem
{
typedef QTreeWidgetItem Parent;
typedef ProfTreeWidgetItem This;
const ::profiler::BlocksTree* m_block;
QRgb m_customBGColor;
QRgb m_customTextColor;
public:
using Parent::setBackgroundColor;
using Parent::setTextColor;
ProfTreeWidgetItem(const ::profiler::BlocksTree* _treeBlock, Parent* _parent = nullptr);
virtual ~ProfTreeWidgetItem();
bool operator < (const Parent& _other) const override;
public:
const ::profiler::BlocksTree* block() const;
::profiler::timestamp_t duration() const;
::profiler::timestamp_t selfDuration() const;
void setTimeSmart(int _column, const ::profiler::timestamp_t& _time, const QString& _prefix = "");
void setTimeMs(int _column, const ::profiler::timestamp_t& _time);
void setTimeMs(int _column, const ::profiler::timestamp_t& _time, const QString& _prefix);
void setBackgroundColor(QRgb _color);
void setTextColor(QRgb _color);
void colorize(bool _colorize);
void collapseAll();
void expandAll();
}; // END of class ProfTreeWidgetItem.
//////////////////////////////////////////////////////////////////////////
@ -90,38 +44,40 @@ public: \
connect(this, &QAction::triggered, this, &ClassName::onToggle); } \
ClassName(const QString& _label, DataType _item) : QAction(_label, nullptr), m_item(_item) { \
connect(this, &QAction::triggered, this, &ClassName::onToggle); } \
virtual ~ClassName() {}\
virtual ~ClassName() {} \
private: \
void onToggle(bool) { emit clicked(m_item); }
DECLARE_QACTION(ProfItemAction, unsigned int) signals: void clicked(unsigned int _item); };
DECLARE_QACTION(ProfHideShowColumnAction, int) signals: void clicked(int _item); };
DECLARE_QACTION(EasyItemAction, unsigned int) signals: void clicked(unsigned int _item); };
DECLARE_QACTION(EasyHideShowColumnAction, int) signals: void clicked(int _item); };
#undef DECLARE_QACTION
//////////////////////////////////////////////////////////////////////////
class ProfTreeWidget : public QTreeWidget
class EasyTreeWidget : public QTreeWidget
{
Q_OBJECT
typedef QTreeWidget Parent;
typedef ProfTreeWidget This;
typedef EasyTreeWidget This;
protected:
typedef ::std::vector<ProfTreeWidgetItem*> Items;
typedef ::std::unordered_map<::profiler::thread_id_t, ProfTreeWidgetItem*, ::profiler_gui::do_no_hash<::profiler::thread_id_t>::hasher_t> RootsMap;
EasyTreeWidgetLoader m_hierarchyBuilder;
Items m_items;
RootsMap m_roots;
::profiler_gui::TreeBlocks m_inputBlocks;
QTimer m_fillTimer;
::profiler::timestamp_t m_beginTime;
class QProgressDialog* m_progress;
bool m_bColorRows;
bool m_bLocked;
public:
ProfTreeWidget(QWidget* _parent = nullptr);
virtual ~ProfTreeWidget();
EasyTreeWidget(QWidget* _parent = nullptr);
virtual ~EasyTreeWidget();
void clearSilent(bool _global = false);
@ -133,13 +89,9 @@ public slots:
protected:
size_t setTreeInternal(const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree);
size_t setTreeInternal(const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict);
size_t setTreeInternal(const ::profiler::BlocksTree::children_t& _children, ProfTreeWidgetItem* _parent, ProfTreeWidgetItem* _frame, ProfTreeWidgetItem* _thread, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration);
void contextMenuEvent(QContextMenuEvent* _event) override;
void resizeEvent(QResizeEvent* _event) override;
void moveEvent(QMoveEvent* _event) override;
private slots:
@ -153,7 +105,8 @@ private slots:
void onExpandAllChildrenClicked(bool);
void onItemExpand(QTreeWidgetItem*);
void onItemExpand(QTreeWidgetItem* _item);
void onItemCollapse(QTreeWidgetItem* _item);
void onColorizeRowsTriggered(bool _colorize);
@ -165,13 +118,16 @@ private slots:
void onHideShowColumn(int _column);
void onFillTimerTimeout();
protected:
void loadSettings();
void saveSettings();
void alignProgressBar();
}; // END of class ProfTreeWidget.
}; // END of class EasyTreeWidget.
//////////////////////////////////////////////////////////////////////////
#endif // MY____TREE___VIEW_H
#endif // EASY__TREE_WIDGET__H_

View File

@ -24,13 +24,13 @@
namespace profiler_gui {
ProfGlobals& ProfGlobals::instance()
EasyGlobals& EasyGlobals::instance()
{
static ProfGlobals globals;
static EasyGlobals globals;
return globals;
}
ProfGlobals::ProfGlobals()
EasyGlobals::EasyGlobals()
: selected_thread(0)
, selected_block(-1)
, draw_graphics_items_borders(true)

View File

@ -28,11 +28,6 @@
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsItem;
class ProfTreeWidgetItem;
//////////////////////////////////////////////////////////////////////////
namespace profiler_gui {
const QString ORGANAZATION_NAME = "EasyProfiler";
@ -45,16 +40,17 @@ namespace profiler_gui {
//////////////////////////////////////////////////////////////////////////
#pragma pack(push, 1)
struct ProfBlock final
struct EasyBlock final
{
unsigned int tree_item;
unsigned int graphics_item_index;
unsigned char graphics_item_level;
unsigned char graphics_item;
bool expanded;
};
#pragma pack(pop)
typedef ::std::vector<ProfBlock> ProfBlocks;
typedef ::std::vector<EasyBlock> EasyBlocks;
template <class T>
inline auto toUnicode(const T& _inputString) -> decltype(QTextCodec::codecForLocale()->toUnicode(_inputString))
@ -64,13 +60,13 @@ namespace profiler_gui {
//////////////////////////////////////////////////////////////////////////
struct ProfGlobals final
struct EasyGlobals final
{
static ProfGlobals& instance();
static EasyGlobals& instance();
ProfGlobalSignals events; ///< Global signals
EasyGlobalSignals events; ///< Global signals
::profiler::thread_blocks_tree_t profiler_blocks; ///< Profiler blocks tree loaded from file
ProfBlocks gui_blocks; ///< Profiler graphics blocks builded by GUI
EasyBlocks gui_blocks; ///< Profiler graphics blocks builded by GUI
::profiler::thread_id_t selected_thread; ///< Current selected thread id
unsigned int selected_block; ///< Current selected profiler block index
bool draw_graphics_items_borders; ///< Draw borders for graphics blocks or not
@ -78,10 +74,10 @@ namespace profiler_gui {
private:
ProfGlobals();
EasyGlobals();
};
#ifndef IGNORE_GLOBALS_DECLARATION
static ProfGlobals& EASY_GLOBALS = ProfGlobals::instance();
static EasyGlobals& EASY_GLOBALS = EasyGlobals::instance();
#endif
//////////////////////////////////////////////////////////////////////////

View File

@ -6,7 +6,7 @@
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of ProfGlobalSignals QObject class.
* description : The file contains implementation of EasyGlobalSignals QObject class.
* ----------------- :
* change log : * 2016/08/08 Sergey Yagovtsev: moved sources from globals.cpp
* :
@ -22,11 +22,11 @@
namespace profiler_gui {
ProfGlobalSignals::ProfGlobalSignals() : QObject()
EasyGlobalSignals::EasyGlobalSignals() : QObject()
{
}
ProfGlobalSignals::~ProfGlobalSignals()
EasyGlobalSignals::~EasyGlobalSignals()
{
}

View File

@ -5,21 +5,24 @@
#include "profiler/profiler.h"
namespace profiler_gui {
class ProfGlobalSignals final : public QObject
class EasyGlobalSignals final : public QObject
{
Q_OBJECT
public:
ProfGlobalSignals();
virtual ~ProfGlobalSignals();
EasyGlobalSignals();
virtual ~EasyGlobalSignals();
signals:
void selectedThreadChanged(::profiler::thread_id_t _id);
void selectedBlockChanged(unsigned int _block_index);
};
void itemsExpandStateChanged();
}
}; // END of class EasyGlobalSignals.
} // END of namespace profiler_gui.
#endif // GLOBALS_QOBJECTS_H

View File

@ -16,6 +16,7 @@
************************************************************************/
#include <algorithm>
#include <QGraphicsScene>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QResizeEvent>
@ -41,33 +42,33 @@ auto const clamp = [](qreal _minValue, qreal _value, qreal _maxValue)
//////////////////////////////////////////////////////////////////////////
ProfGraphicsSliderItem::ProfGraphicsSliderItem(bool _main) : Parent(), m_halfwidth(0)
EasyGraphicsSliderItem::EasyGraphicsSliderItem(bool _main) : Parent(), m_halfwidth(0)
{
m_leftIndicator.reserve(3);
m_rightIndicator.reserve(3);
const auto vcenter = DEFAULT_TOP + (_main ? INDICATOR_SIZE : DEFAULT_HEIGHT - INDICATOR_SIZE);
m_leftIndicator.push_back(QPointF(-INDICATOR_SIZE, vcenter - INDICATOR_SIZE));
m_leftIndicator.push_back(QPointF(0, vcenter));
m_leftIndicator.push_back(QPointF(-INDICATOR_SIZE, vcenter + INDICATOR_SIZE));
m_rightIndicator.push_back(QPointF(INDICATOR_SIZE, vcenter - INDICATOR_SIZE));
m_rightIndicator.push_back(QPointF(0, vcenter));
m_rightIndicator.push_back(QPointF(INDICATOR_SIZE, vcenter + INDICATOR_SIZE));
// m_leftIndicator.reserve(3);
// m_rightIndicator.reserve(3);
//
// const auto vcenter = DEFAULT_TOP + (_main ? INDICATOR_SIZE : DEFAULT_HEIGHT - INDICATOR_SIZE);
// m_leftIndicator.push_back(QPointF(-INDICATOR_SIZE, vcenter - INDICATOR_SIZE));
// m_leftIndicator.push_back(QPointF(0, vcenter));
// m_leftIndicator.push_back(QPointF(-INDICATOR_SIZE, vcenter + INDICATOR_SIZE));
//
// m_rightIndicator.push_back(QPointF(INDICATOR_SIZE, vcenter - INDICATOR_SIZE));
// m_rightIndicator.push_back(QPointF(0, vcenter));
// m_rightIndicator.push_back(QPointF(INDICATOR_SIZE, vcenter + INDICATOR_SIZE));
setWidth(1);
setBrush(Qt::SolidPattern);
}
ProfGraphicsSliderItem::~ProfGraphicsSliderItem()
EasyGraphicsSliderItem::~EasyGraphicsSliderItem()
{
}
void ProfGraphicsSliderItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
void EasyGraphicsSliderItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
//Parent::paint(_painter, _option, _widget);
const auto currentScale = static_cast<const ProfGraphicsScrollbar*>(scene()->parent())->getWindowScale();
const auto currentScale = static_cast<const EasyGraphicsScrollbar*>(scene()->parent())->getWindowScale();
const auto br = rect();
qreal w = width() * currentScale;
@ -80,59 +81,67 @@ void ProfGraphicsSliderItem::paint(QPainter* _painter, const QStyleOptionGraphic
}
QRectF r(dx + br.left() * currentScale, br.top(), w, br.height());
const auto r_right = r.right();
const auto r_bottom = r.bottom();
auto b = brush();
_painter->save();
_painter->setTransform(QTransform::fromScale(1.0 / currentScale, 1), true);
_painter->setBrush(brush());
_painter->setBrush(b);
_painter->setPen(Qt::NoPen);
_painter->drawRect(r);
if (w < INDICATOR_SIZE)
{
m_leftIndicator[0].setX(r.left() - INDICATOR_SIZE);
m_leftIndicator[1].setX(r.left());
m_leftIndicator[2].setX(r.left() - INDICATOR_SIZE);
// Draw left and right borders
_painter->setPen(QColor::fromRgba(0xe0000000 | b.color().rgb()));
_painter->drawLine(QPointF(r.left(), r.top()), QPointF(r.left(), r_bottom));
_painter->drawLine(QPointF(r_right, r.top()), QPointF(r_right, r_bottom));
const auto r_right = r.right();
m_rightIndicator[0].setX(r_right + INDICATOR_SIZE);
m_rightIndicator[1].setX(r_right);
m_rightIndicator[2].setX(r_right + INDICATOR_SIZE);
_painter->drawPolygon(m_leftIndicator);
_painter->drawPolygon(m_rightIndicator);
}
// // Draw triangle indicators for small slider
// if (w < INDICATOR_SIZE)
// {
// m_leftIndicator[0].setX(r.left() - INDICATOR_SIZE);
// m_leftIndicator[1].setX(r.left());
// m_leftIndicator[2].setX(r.left() - INDICATOR_SIZE);
//
// m_rightIndicator[0].setX(r_right + INDICATOR_SIZE);
// m_rightIndicator[1].setX(r_right);
// m_rightIndicator[2].setX(r_right + INDICATOR_SIZE);
//
// _painter->drawPolygon(m_leftIndicator);
// _painter->drawPolygon(m_rightIndicator);
// }
_painter->restore();
}
qreal ProfGraphicsSliderItem::width() const
qreal EasyGraphicsSliderItem::width() const
{
return m_halfwidth * 2.0;
}
qreal ProfGraphicsSliderItem::halfwidth() const
qreal EasyGraphicsSliderItem::halfwidth() const
{
return m_halfwidth;
}
void ProfGraphicsSliderItem::setWidth(qreal _width)
void EasyGraphicsSliderItem::setWidth(qreal _width)
{
m_halfwidth = _width * 0.5;
setRect(-m_halfwidth, DEFAULT_TOP, _width, DEFAULT_HEIGHT);
}
void ProfGraphicsSliderItem::setHalfwidth(qreal _halfwidth)
void EasyGraphicsSliderItem::setHalfwidth(qreal _halfwidth)
{
m_halfwidth = _halfwidth;
setRect(-m_halfwidth, DEFAULT_TOP, m_halfwidth * 2.0, DEFAULT_HEIGHT);
}
void ProfGraphicsSliderItem::setColor(QRgb _color)
void EasyGraphicsSliderItem::setColor(QRgb _color)
{
setColor(QColor::fromRgba(_color));
}
void ProfGraphicsSliderItem::setColor(const QColor& _color)
void EasyGraphicsSliderItem::setColor(const QColor& _color)
{
auto b = brush();
b.setColor(_color);
@ -141,29 +150,29 @@ void ProfGraphicsSliderItem::setColor(const QColor& _color)
//////////////////////////////////////////////////////////////////////////
ProfMinimapItem::ProfMinimapItem() : Parent(), m_pSource(nullptr), m_maxDuration(0), m_minDuration(0), m_threadId(0)
EasyMinimapItem::EasyMinimapItem() : Parent(), m_pSource(nullptr), m_maxDuration(0), m_minDuration(0), m_threadId(0)
{
}
ProfMinimapItem::~ProfMinimapItem()
EasyMinimapItem::~EasyMinimapItem()
{
}
QRectF ProfMinimapItem::boundingRect() const
QRectF EasyMinimapItem::boundingRect() const
{
return m_boundingRect;
}
void ProfMinimapItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
void EasyMinimapItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget)
{
if (m_pSource == nullptr)
{
return;
}
const auto currentScale = static_cast<const ProfGraphicsScrollbar*>(scene()->parent())->getWindowScale();
const auto currentScale = static_cast<const EasyGraphicsScrollbar*>(scene()->parent())->getWindowScale();
const auto bottom = m_boundingRect.bottom();
const auto coeff = m_boundingRect.height() / (m_maxDuration - m_minDuration);
const auto heightRevert = 1.0 / m_boundingRect.height();
@ -204,17 +213,17 @@ void ProfMinimapItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->restore();
}
::profiler::thread_id_t ProfMinimapItem::threadId() const
::profiler::thread_id_t EasyMinimapItem::threadId() const
{
return m_threadId;
}
void ProfMinimapItem::setBoundingRect(const QRectF& _rect)
void EasyMinimapItem::setBoundingRect(const QRectF& _rect)
{
m_boundingRect = _rect;
}
void ProfMinimapItem::setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items)
void EasyMinimapItem::setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items)
{
m_pSource = _items;
m_threadId = _thread_id;
@ -258,7 +267,7 @@ void ProfMinimapItem::setSource(::profiler::thread_id_t _thread_id, const ::prof
//////////////////////////////////////////////////////////////////////////
ProfGraphicsScrollbar::ProfGraphicsScrollbar(QWidget* _parent)
EasyGraphicsScrollbar::EasyGraphicsScrollbar(QWidget* _parent)
: Parent(_parent)
, m_minimumValue(0)
, m_maximumValue(500)
@ -287,20 +296,20 @@ ProfGraphicsScrollbar::ProfGraphicsScrollbar(QWidget* _parent)
selfScene->setSceneRect(0, DEFAULT_TOP, 500, DEFAULT_HEIGHT);
setScene(selfScene);
m_slider = new ProfGraphicsSliderItem(true);
m_slider = new EasyGraphicsSliderItem(true);
m_slider->setPos(0, 0);
m_slider->setZValue(5);
m_slider->setColor(0x80e00000);
m_slider->setColor(0x40c0c0c0);
selfScene->addItem(m_slider);
m_chronometerIndicator = new ProfGraphicsSliderItem(false);
m_chronometerIndicator = new EasyGraphicsSliderItem(false);
m_chronometerIndicator->setPos(0, 0);
m_chronometerIndicator->setZValue(10);
m_chronometerIndicator->setColor(0x40000000 | ::profiler_gui::CHRONOMETER_COLOR.rgba());
selfScene->addItem(m_chronometerIndicator);
m_chronometerIndicator->hide();
m_minimap = new ProfMinimapItem();
m_minimap = new EasyMinimapItem();
m_minimap->setPos(0, 0);
m_minimap->setBoundingRect(selfScene->sceneRect());
selfScene->addItem(m_minimap);
@ -309,63 +318,63 @@ ProfGraphicsScrollbar::ProfGraphicsScrollbar(QWidget* _parent)
centerOn(0, 0);
}
ProfGraphicsScrollbar::~ProfGraphicsScrollbar()
EasyGraphicsScrollbar::~EasyGraphicsScrollbar()
{
}
//////////////////////////////////////////////////////////////////////////
qreal ProfGraphicsScrollbar::getWindowScale() const
qreal EasyGraphicsScrollbar::getWindowScale() const
{
return m_windowScale;
}
::profiler::thread_id_t ProfGraphicsScrollbar::minimapThread() const
::profiler::thread_id_t EasyGraphicsScrollbar::minimapThread() const
{
return m_minimap->threadId();
}
qreal ProfGraphicsScrollbar::minimum() const
qreal EasyGraphicsScrollbar::minimum() const
{
return m_minimumValue;
}
qreal ProfGraphicsScrollbar::maximum() const
qreal EasyGraphicsScrollbar::maximum() const
{
return m_maximumValue;
}
qreal ProfGraphicsScrollbar::range() const
qreal EasyGraphicsScrollbar::range() const
{
return m_maximumValue - m_minimumValue;
}
qreal ProfGraphicsScrollbar::value() const
qreal EasyGraphicsScrollbar::value() const
{
return m_value;
}
qreal ProfGraphicsScrollbar::sliderWidth() const
qreal EasyGraphicsScrollbar::sliderWidth() const
{
return m_slider->width();
}
qreal ProfGraphicsScrollbar::sliderHalfWidth() const
qreal EasyGraphicsScrollbar::sliderHalfWidth() const
{
return m_slider->halfwidth();
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::setValue(qreal _value)
void EasyGraphicsScrollbar::setValue(qreal _value)
{
m_value = clamp(m_minimumValue, _value, ::std::max(m_minimumValue, m_maximumValue - m_slider->width()));
m_slider->setX(m_value + m_slider->halfwidth());
emit valueChanged(m_value);
}
void ProfGraphicsScrollbar::setRange(qreal _minValue, qreal _maxValue)
void EasyGraphicsScrollbar::setRange(qreal _minValue, qreal _maxValue)
{
const auto oldRange = range();
const auto oldValue = oldRange < 1e-3 ? 0.0 : m_value / oldRange;
@ -380,7 +389,7 @@ void ProfGraphicsScrollbar::setRange(qreal _minValue, qreal _maxValue)
onWindowWidthChange(width());
}
void ProfGraphicsScrollbar::setSliderWidth(qreal _width)
void EasyGraphicsScrollbar::setSliderWidth(qreal _width)
{
m_slider->setWidth(_width);
setValue(m_value);
@ -388,25 +397,25 @@ void ProfGraphicsScrollbar::setSliderWidth(qreal _width)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::setChronoPos(qreal _left, qreal _right)
void EasyGraphicsScrollbar::setChronoPos(qreal _left, qreal _right)
{
m_chronometerIndicator->setWidth(_right - _left);
m_chronometerIndicator->setX(_left + m_chronometerIndicator->halfwidth());
}
void ProfGraphicsScrollbar::showChrono()
void EasyGraphicsScrollbar::showChrono()
{
m_chronometerIndicator->show();
}
void ProfGraphicsScrollbar::hideChrono()
void EasyGraphicsScrollbar::hideChrono()
{
m_chronometerIndicator->hide();
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::setMinimapFrom(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items)
void EasyGraphicsScrollbar::setMinimapFrom(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items)
{
m_minimap->setSource(_thread_id, _items);
scene()->update();
@ -414,7 +423,7 @@ void ProfGraphicsScrollbar::setMinimapFrom(::profiler::thread_id_t _thread_id, c
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::mousePressEvent(QMouseEvent* _event)
void EasyGraphicsScrollbar::mousePressEvent(QMouseEvent* _event)
{
m_mouseButtons = _event->buttons();
@ -429,7 +438,7 @@ void ProfGraphicsScrollbar::mousePressEvent(QMouseEvent* _event)
//QGraphicsView::mousePressEvent(_event);
}
void ProfGraphicsScrollbar::mouseReleaseEvent(QMouseEvent* _event)
void EasyGraphicsScrollbar::mouseReleaseEvent(QMouseEvent* _event)
{
m_mouseButtons = _event->buttons();
m_bScrolling = false;
@ -437,7 +446,7 @@ void ProfGraphicsScrollbar::mouseReleaseEvent(QMouseEvent* _event)
//QGraphicsView::mouseReleaseEvent(_event);
}
void ProfGraphicsScrollbar::mouseMoveEvent(QMouseEvent* _event)
void EasyGraphicsScrollbar::mouseMoveEvent(QMouseEvent* _event)
{
if (m_mouseButtons & Qt::LeftButton)
{
@ -452,14 +461,14 @@ void ProfGraphicsScrollbar::mouseMoveEvent(QMouseEvent* _event)
}
}
void ProfGraphicsScrollbar::resizeEvent(QResizeEvent* _event)
void EasyGraphicsScrollbar::resizeEvent(QResizeEvent* _event)
{
onWindowWidthChange(_event->size().width());
}
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
void EasyGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
{
if (::profiler_gui::EASY_GLOBALS.profiler_blocks.empty())
{
@ -480,10 +489,10 @@ void ProfGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
label = ::std::move(QString("Thread %1").arg(it.first));
}
auto action = new ProfIdAction(label, it.first);
auto action = new EasyIdAction(label, it.first);
action->setCheckable(true);
action->setChecked(it.first == ::profiler_gui::EASY_GLOBALS.selected_thread);
connect(action, &ProfIdAction::clicked, this, &This::onThreadActionClicked);
connect(action, &EasyIdAction::clicked, this, &This::onThreadActionClicked);
menu.addAction(action);
}
@ -494,7 +503,7 @@ void ProfGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::onThreadActionClicked(::profiler::thread_id_t _id)
void EasyGraphicsScrollbar::onThreadActionClicked(::profiler::thread_id_t _id)
{
if (_id != m_minimap->threadId())
{
@ -505,7 +514,7 @@ void ProfGraphicsScrollbar::onThreadActionClicked(::profiler::thread_id_t _id)
//////////////////////////////////////////////////////////////////////////
void ProfGraphicsScrollbar::onWindowWidthChange(qreal _width)
void EasyGraphicsScrollbar::onWindowWidthChange(qreal _width)
{
const auto oldScale = m_windowScale;
const auto scrollingRange = range();

View File

@ -15,33 +15,32 @@
* license : TODO: add license text
************************************************************************/
#ifndef EASY_PROFILER__GRAPHICS_SCROLLBAR__H
#define EASY_PROFILER__GRAPHICS_SCROLLBAR__H
#ifndef EASY__GRAPHICS_SCROLLBAR__H
#define EASY__GRAPHICS_SCROLLBAR__H
#include <stdlib.h>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QAction>
#include <QPolygonF>
//#include <QPolygonF>
#include "common_types.h"
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsSliderItem : public QGraphicsRectItem
class EasyGraphicsSliderItem : public QGraphicsRectItem
{
typedef QGraphicsRectItem Parent;
typedef ProfGraphicsSliderItem This;
typedef EasyGraphicsSliderItem This;
private:
QPolygonF m_leftIndicator, m_rightIndicator;
//QPolygonF m_leftIndicator, m_rightIndicator;
qreal m_halfwidth;
public:
ProfGraphicsSliderItem(bool _main);
virtual ~ProfGraphicsSliderItem();
EasyGraphicsSliderItem(bool _main);
virtual ~EasyGraphicsSliderItem();
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
@ -54,14 +53,14 @@ public:
void setColor(QRgb _color);
void setColor(const QColor& _color);
}; // END of class ProfGraphicsSliderItem.
}; // END of class EasyGraphicsSliderItem.
//////////////////////////////////////////////////////////////////////////
class ProfMinimapItem : public QGraphicsItem
class EasyMinimapItem : public QGraphicsItem
{
typedef QGraphicsItem Parent;
typedef ProfMinimapItem This;
typedef EasyMinimapItem This;
QRectF m_boundingRect;
qreal m_maxDuration;
@ -71,8 +70,8 @@ class ProfMinimapItem : public QGraphicsItem
public:
ProfMinimapItem();
virtual ~ProfMinimapItem();
EasyMinimapItem();
virtual ~EasyMinimapItem();
// Public virtual methods
@ -89,34 +88,34 @@ public:
void setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::ProfItems* _items);
}; // END of class ProfMinimapItem.
}; // END of class EasyMinimapItem.
//////////////////////////////////////////////////////////////////////////
class ProfIdAction : public QAction
class EasyIdAction : public QAction
{
Q_OBJECT
private:
typedef QAction Parent;
typedef ProfIdAction This;
typedef EasyIdAction This;
::profiler::thread_id_t m_id;
public:
ProfIdAction(const QString& _label, ::profiler::thread_id_t _id) : Parent(_label, nullptr), m_id(_id)
EasyIdAction(const QString& _label, ::profiler::thread_id_t _id) : Parent(_label, nullptr), m_id(_id)
{
connect(this, &Parent::triggered, this, &This::onToggle);
}
ProfIdAction(const char* _label, ::profiler::thread_id_t _id) : Parent(_label, nullptr), m_id(_id)
EasyIdAction(const char* _label, ::profiler::thread_id_t _id) : Parent(_label, nullptr), m_id(_id)
{
connect(this, &Parent::triggered, this, &This::onToggle);
}
virtual ~ProfIdAction()
virtual ~EasyIdAction()
{
}
@ -134,14 +133,14 @@ signals:
//////////////////////////////////////////////////////////////////////////
class ProfGraphicsScrollbar : public QGraphicsView
class EasyGraphicsScrollbar : public QGraphicsView
{
Q_OBJECT
private:
typedef QGraphicsView Parent;
typedef ProfGraphicsScrollbar This;
typedef EasyGraphicsScrollbar This;
qreal m_minimumValue;
qreal m_maximumValue;
@ -149,15 +148,15 @@ private:
qreal m_windowScale;
QPoint m_mousePressPos;
Qt::MouseButtons m_mouseButtons;
ProfGraphicsSliderItem* m_slider;
ProfGraphicsSliderItem* m_chronometerIndicator;
ProfMinimapItem* m_minimap;
EasyGraphicsSliderItem* m_slider;
EasyGraphicsSliderItem* m_chronometerIndicator;
EasyMinimapItem* m_minimap;
bool m_bScrolling;
public:
ProfGraphicsScrollbar(QWidget* _parent = nullptr);
virtual ~ProfGraphicsScrollbar();
EasyGraphicsScrollbar(QWidget* _parent = nullptr);
virtual ~EasyGraphicsScrollbar();
// Public virtual methods
@ -205,8 +204,8 @@ private slots:
void onThreadActionClicked(::profiler::thread_id_t _id);
void onWindowWidthChange(qreal _width);
}; // END of class ProfGraphicsScrollbar.
}; // END of class EasyGraphicsScrollbar.
//////////////////////////////////////////////////////////////////////////
#endif // EASY_PROFILER__GRAPHICS_SCROLLBAR__H
#endif // EASY__GRAPHICS_SCROLLBAR__H

View File

@ -37,7 +37,7 @@ int main(int argc, char **argv)
auto now = ::std::chrono::duration_cast<std::chrono::seconds>(::std::chrono::system_clock::now().time_since_epoch()).count() >> 1;
srand((unsigned int)now);
ProfMainWindow window;
EasyMainWindow window;
window.show();
return app.exec();

View File

@ -10,7 +10,7 @@
* ----------------- :
* change log : * 2016/06/26 Victor Zarubkin: Initial commit.
* :
* : * 2016/06/27 Victor Zarubkin: Passing blocks number to ProfTreeWidget::setTree().
* : * 2016/06/27 Victor Zarubkin: Passing blocks number to EasyTreeWidget::setTree().
* :
* : * 2016/06/29 Victor Zarubkin: Added menu with tests.
* :
@ -30,29 +30,31 @@
#include <QCoreApplication>
#include <QCloseEvent>
#include <QSettings>
#include <QTextCodec>
#include <QProgressDialog>
#include "main_window.h"
#include "blocks_tree_widget.h"
#include "blocks_graphics_view.h"
#include "globals.h"
#include <QTextCodec>
//////////////////////////////////////////////////////////////////////////
ProfMainWindow::ProfMainWindow() : QMainWindow(), m_treeWidget(nullptr), m_graphicsView(nullptr)
EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsView(nullptr), m_progress(nullptr)
{
setObjectName("ProfilerGUI_MainWindow");
setWindowTitle("easy_profiler reader");
setWindowTitle("EasyProfiler Reader v0.2.0");
setDockNestingEnabled(true);
resize(800, 600);
setStatusBar(new QStatusBar());
auto graphicsView = new ProfGraphicsViewWidget();
auto graphicsView = new EasyGraphicsViewWidget();
m_graphicsView = new QDockWidget("Blocks diagram");
m_graphicsView->setMinimumHeight(50);
m_graphicsView->setAllowedAreas(Qt::AllDockWidgetAreas);
m_graphicsView->setWidget(graphicsView);
auto treeWidget = new ProfTreeWidget();
auto treeWidget = new EasyTreeWidget();
m_treeWidget = new QDockWidget("Blocks hierarchy");
m_treeWidget->setMinimumHeight(50);
m_treeWidget->setAllowedAreas(Qt::AllDockWidgetAreas);
@ -70,9 +72,6 @@ ProfMainWindow::ProfMainWindow() : QMainWindow(), m_treeWidget(nullptr), m_graph
auto actionExit = new QAction("Exit", nullptr);
connect(actionExit, &QAction::triggered, this, &This::onExitClicked);
auto actionTestView = new QAction("Test viewport", nullptr);
connect(actionTestView, &QAction::triggered, this, &This::onTestViewportClicked);
auto menu = new QMenu("File");
menu->addAction(actionOpen);
menu->addAction(actionReload);
@ -80,10 +79,6 @@ ProfMainWindow::ProfMainWindow() : QMainWindow(), m_treeWidget(nullptr), m_graph
menu->addAction(actionExit);
menuBar()->addMenu(menu);
menu = new QMenu("Tests");
menu->addAction(actionTestView);
menuBar()->addMenu(menu);
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
settings.beginGroup("main");
@ -113,15 +108,27 @@ ProfMainWindow::ProfMainWindow() : QMainWindow(), m_treeWidget(nullptr), m_graph
}
encodingMenu->addAction(action);
connect(action, &QAction::triggered, this, &This::onEncodingChanged);
}
menu->addSeparator();
auto actionBorders = menu->addAction("Draw items' borders");
actionBorders->setCheckable(true);
actionBorders->setChecked(::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders);
connect(actionBorders, &QAction::triggered, this, &This::onDrawBordersChanged);
menuBar()->addMenu(menu);
connect(graphicsView->view(), &ProfGraphicsView::intervalChanged, treeWidget, &ProfTreeWidget::setTreeBlocks);
connect(graphicsView->view(), &EasyGraphicsView::intervalChanged, treeWidget, &EasyTreeWidget::setTreeBlocks);
connect(&m_readerTimer, &QTimer::timeout, this, &This::onFileReaderTimeout);
loadSettings();
m_progress = new QProgressDialog("Loading file...", "Cancel", 0, 100, this);
m_progress->setWindowTitle("EasyProfiler");
m_progress->setModal(true);
m_progress->hide();
connect(m_progress, &QProgressDialog::canceled, this, &This::onFileReaderCancel);
if(QCoreApplication::arguments().size() > 1)
{
auto opened_filename = QCoreApplication::arguments().at(1).toStdString();
@ -129,13 +136,14 @@ ProfMainWindow::ProfMainWindow() : QMainWindow(), m_treeWidget(nullptr), m_graph
}
}
ProfMainWindow::~ProfMainWindow()
EasyMainWindow::~EasyMainWindow()
{
delete m_progress;
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::onOpenFileClicked(bool)
void EasyMainWindow::onOpenFileClicked(bool)
{
auto filename = QFileDialog::getOpenFileName(this, "Open profiler log", m_lastFile.c_str(), "Profiler Log File (*.prof);;All Files (*.*)");
loadFile(filename.toStdString());
@ -143,85 +151,53 @@ void ProfMainWindow::onOpenFileClicked(bool)
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::loadFile(const std::string& stdfilename)
void EasyMainWindow::loadFile(const std::string& stdfilename)
{
::profiler::SerializedData data;
::profiler::thread_blocks_tree_t prof_blocks;
auto nblocks = fillTreesFromFile(stdfilename.c_str(), data, prof_blocks, true);
m_progress->setValue(0);
m_progress->show();
m_readerTimer.start(20);
m_reader.load(stdfilename);
if (nblocks != 0)
{
static_cast<ProfTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
m_lastFile = stdfilename;
m_serializedData = ::std::move(data);
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
::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);
for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
static_cast<ProfGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
}
// ::profiler::SerializedData data;
// ::profiler::thread_blocks_tree_t prof_blocks;
// auto nblocks = fillTreesFromFile(stdfilename.c_str(), data, prof_blocks, true);
//
// if (nblocks != 0)
// {
// static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
//
// m_lastFile = stdfilename;
// m_serializedData = ::std::move(data);
// ::profiler_gui::EASY_GLOBALS.selected_thread = 0;
// ::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
// ::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::EasyBlock) * nblocks);
// for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
//
// static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
// }
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::onReloadFileClicked(bool)
void EasyMainWindow::onReloadFileClicked(bool)
{
if (m_lastFile.empty())
{
return;
}
::profiler::SerializedData data;
::profiler::thread_blocks_tree_t prof_blocks;
auto nblocks = fillTreesFromFile(m_lastFile.c_str(), data, prof_blocks, true);
if (nblocks != 0)
{
static_cast<ProfTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
m_serializedData = ::std::move(data);
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
::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);
for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
static_cast<ProfGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
}
loadFile(m_lastFile);
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::onExitClicked(bool)
void EasyMainWindow::onExitClicked(bool)
{
close();
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::onTestViewportClicked(bool)
{
static_cast<ProfTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
auto view = static_cast<ProfGraphicsViewWidget*>(m_graphicsView->widget())->view();
view->clearSilent();
m_serializedData.clear();
::profiler_gui::EASY_GLOBALS.gui_blocks.clear();
::profiler_gui::EASY_GLOBALS.profiler_blocks.clear();
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
//view->test(18000, 40000000, 2);
view->test(100, 9000, 1);
}
void ProfMainWindow::onEncodingChanged(bool)
void EasyMainWindow::onEncodingChanged(bool)
{
auto _sender = qobject_cast<QAction*>(sender());
auto name = _sender->text();
@ -229,17 +205,22 @@ void ProfMainWindow::onEncodingChanged(bool)
QTextCodec::setCodecForLocale(codec);
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::closeEvent(QCloseEvent* close_event)
void EasyMainWindow::onDrawBordersChanged(bool _checked)
{
saveSettings();
QMainWindow::closeEvent(close_event);
::profiler_gui::EASY_GLOBALS.draw_graphics_items_borders = _checked;
}
//////////////////////////////////////////////////////////////////////////
void ProfMainWindow::loadSettings()
void EasyMainWindow::closeEvent(QCloseEvent* close_event)
{
saveSettings();
Parent::closeEvent(close_event);
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::loadSettings()
{
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
settings.beginGroup("main");
@ -259,7 +240,7 @@ void ProfMainWindow::loadSettings()
settings.endGroup();
}
void ProfMainWindow::saveSettings()
void EasyMainWindow::saveSettings()
{
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
settings.beginGroup("main");
@ -272,3 +253,111 @@ void ProfMainWindow::saveSettings()
}
//////////////////////////////////////////////////////////////////////////
void EasyMainWindow::onFileReaderTimeout()
{
if (m_reader.done())
{
auto nblocks = m_reader.size();
if (nblocks != 0)
{
static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
::profiler::SerializedData data;
::profiler::thread_blocks_tree_t prof_blocks;
::std::string stdfilename;
m_reader.get(data, prof_blocks, stdfilename);
m_lastFile = ::std::move(stdfilename);
m_serializedData = ::std::move(data);
::profiler_gui::EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block);
::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::EasyBlock) * nblocks);
for (auto& guiblock : ::profiler_gui::EASY_GLOBALS.gui_blocks) ::profiler_gui::set_max(guiblock.tree_item);
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->view()->setTree(::profiler_gui::EASY_GLOBALS.profiler_blocks);
}
m_reader.interrupt();
m_readerTimer.stop();
m_progress->setValue(100);
m_progress->hide();
}
else
{
m_progress->setValue(m_reader.progress());
}
}
void EasyMainWindow::onFileReaderCancel()
{
m_readerTimer.stop();
m_reader.interrupt();
m_progress->hide();
}
//////////////////////////////////////////////////////////////////////////
EasyFileReader::EasyFileReader()
{
}
EasyFileReader::~EasyFileReader()
{
interrupt();
}
bool EasyFileReader::done() const
{
return m_bDone.load();
}
int EasyFileReader::progress() const
{
return m_progress.load();
}
unsigned int EasyFileReader::size() const
{
return m_size.load();
}
void EasyFileReader::load(const ::std::string& _filename)
{
interrupt();
m_filename = _filename;
m_thread = ::std::move(::std::thread([](::std::atomic_bool& isDone, ::std::atomic<unsigned int>& blocks_number, ::std::atomic<int>& progress, const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::thread_blocks_tree_t& threaded_trees) {
blocks_number.store(fillTreesFromFile(progress, filename, serialized_blocks, threaded_trees, true));
isDone.store(true);
}, ::std::ref(m_bDone), ::std::ref(m_size), ::std::ref(m_progress), m_filename.c_str(), ::std::ref(m_serializedData), ::std::ref(m_blocksTree)));
}
void EasyFileReader::interrupt()
{
m_progress.store(-100);
if (m_thread.joinable())
m_thread.join();
m_bDone.store(false);
m_progress.store(0);
m_size.store(0);
m_serializedData.clear();
m_blocksTree.clear();
}
void EasyFileReader::get(::profiler::SerializedData& _data, ::profiler::thread_blocks_tree_t& _tree, ::std::string& _filename)
{
if (done())
{
m_serializedData.swap(_data);
m_blocksTree.swap(_tree);
m_filename.swap(_filename);
}
}
//////////////////////////////////////////////////////////////////////////

View File

@ -17,33 +17,67 @@
#ifndef EASY_PROFILER_GUI__MAIN_WINDOW__H
#define EASY_PROFILER_GUI__MAIN_WINDOW__H
#include <QMainWindow>
#include <string>
#include <thread>
#include <atomic>
#include <QMainWindow>
#include <QTimer>
#include "profiler/reader.h"
//////////////////////////////////////////////////////////////////////////
class ProfTreeWidget;
class ProfGraphicsView;
class QDockWidget;
class ProfMainWindow : public QMainWindow
//////////////////////////////////////////////////////////////////////////
class EasyFileReader final
{
::profiler::SerializedData m_serializedData; ///<
::profiler::thread_blocks_tree_t m_blocksTree; ///<
::std::string m_filename; ///<
::std::thread m_thread; ///<
::std::atomic_bool m_bDone; ///<
::std::atomic<int> m_progress; ///<
::std::atomic<unsigned int> m_size; ///<
public:
EasyFileReader();
~EasyFileReader();
bool done() const;
int progress() const;
unsigned int size() const;
void load(const ::std::string& _filename);
void interrupt();
void get(::profiler::SerializedData& _data, ::profiler::thread_blocks_tree_t& _tree, ::std::string& _filename);
}; // END of class EasyFileReader.
//////////////////////////////////////////////////////////////////////////
class EasyMainWindow : public QMainWindow
{
Q_OBJECT
protected:
typedef ProfMainWindow This;
typedef EasyMainWindow This;
typedef QMainWindow Parent;
::std::string m_lastFile;
QDockWidget* m_treeWidget;
QDockWidget* m_graphicsView;
class QProgressDialog* m_progress;
QTimer m_readerTimer;
::profiler::SerializedData m_serializedData;
EasyFileReader m_reader;
public:
ProfMainWindow();
virtual ~ProfMainWindow();
EasyMainWindow();
virtual ~EasyMainWindow();
// Public virtual methods
@ -54,8 +88,10 @@ protected slots:
void onOpenFileClicked(bool);
void onReloadFileClicked(bool);
void onExitClicked(bool);
void onTestViewportClicked(bool);
void onEncodingChanged(bool);
void onDrawBordersChanged(bool);
void onFileReaderTimeout();
void onFileReaderCancel();
private:
@ -66,7 +102,7 @@ private:
void loadSettings();
void saveSettings();
}; // END of class ProfMainWindow.
}; // END of class EasyMainWindow.
//////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,190 @@
/************************************************************************
* file name : tree_widget_item.cpp
* ----------------- :
* creation time : 2016/08/18
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of EasyTreeWidgetItem.
* ----------------- :
* change log : * 2016/08/18 Victor Zarubkin: Moved sources from blocks_tree_widget.cpp
* : and renamed classes from Prof* to Easy*.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#include "tree_widget_item.h"
#include "globals.h"
//////////////////////////////////////////////////////////////////////////
EasyTreeWidgetItem::EasyTreeWidgetItem(const ::profiler::BlocksTree* _treeBlock, Parent* _parent)
: Parent(_parent)
, m_block(_treeBlock)
, m_customBGColor(0)
, m_customTextColor(0)
{
}
EasyTreeWidgetItem::~EasyTreeWidgetItem()
{
}
bool EasyTreeWidgetItem::operator < (const Parent& _other) const
{
const auto col = treeWidget()->sortColumn();
switch (col)
{
//case COL_UNKNOWN:
case COL_NAME:
{
if (parent() == nullptr)
return false; // Do not sort topLevelItems by name
return Parent::operator < (_other);
}
case COL_NCALLS_PER_THREAD:
case COL_NCALLS_PER_PARENT:
case COL_NCALLS_PER_FRAME:
{
return data(col, Qt::UserRole).toUInt() < _other.data(col, Qt::UserRole).toUInt();
}
case COL_SELF_DURATION_PERCENT:
case COL_PERCENT_PER_PARENT:
case COL_PERCENT_PER_FRAME:
case COL_PERCENT_SUM_PER_PARENT:
case COL_PERCENT_SUM_PER_FRAME:
case COL_PERCENT_SUM_PER_THREAD:
{
return data(col, Qt::UserRole).toInt() < _other.data(col, Qt::UserRole).toInt();
}
default:
{
// durations min, max, average
return data(col, Qt::UserRole).toULongLong() < _other.data(col, Qt::UserRole).toULongLong();
}
}
return false;
}
const ::profiler::BlocksTree* EasyTreeWidgetItem::block() const
{
return m_block;
}
::profiler::timestamp_t EasyTreeWidgetItem::duration() const
{
if (m_block->node)
return m_block->node->block()->duration();
return data(COL_DURATION, Qt::UserRole).toULongLong();
}
::profiler::timestamp_t EasyTreeWidgetItem::selfDuration() const
{
return data(COL_SELF_DURATION, Qt::UserRole).toULongLong();
}
void EasyTreeWidgetItem::setTimeSmart(int _column, const ::profiler::timestamp_t& _time, const QString& _prefix)
{
const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time);
setData(_column, Qt::UserRole, (quint64)nanosecondsTime);
setToolTip(_column, QString("%1 ns").arg(nanosecondsTime));
if (_time < 1e3)
{
setText(_column, QString("%1%2 ns").arg(_prefix).arg(nanosecondsTime));
}
else if (_time < 1e6)
{
setText(_column, QString("%1%2 us").arg(_prefix).arg(double(nanosecondsTime) * 1e-3, 0, 'f', 3));
}
else if (_time < 1e9)
{
setText(_column, QString("%1%2 ms").arg(_prefix).arg(double(nanosecondsTime) * 1e-6, 0, 'f', 3));
}
else
{
setText(_column, QString("%1%2 s").arg(_prefix).arg(double(nanosecondsTime) * 1e-9, 0, 'f', 3));
}
}
void EasyTreeWidgetItem::setTimeMs(int _column, const ::profiler::timestamp_t& _time)
{
const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time);
setData(_column, Qt::UserRole, (quint64)nanosecondsTime);
setToolTip(_column, QString("%1 ns").arg(nanosecondsTime));
setText(_column, QString::number(double(nanosecondsTime) * 1e-6, 'g', 9));
}
void EasyTreeWidgetItem::setTimeMs(int _column, const ::profiler::timestamp_t& _time, const QString& _prefix)
{
const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time);
setData(_column, Qt::UserRole, (quint64)nanosecondsTime);
setToolTip(_column, QString("%1 ns").arg(nanosecondsTime));
setText(_column, QString("%1%2").arg(_prefix).arg(double(nanosecondsTime) * 1e-6, 0, 'g', 9));
}
void EasyTreeWidgetItem::setBackgroundColor(QRgb _color)
{
m_customBGColor = _color;
}
void EasyTreeWidgetItem::setTextColor(QRgb _color)
{
m_customTextColor = _color;
}
void EasyTreeWidgetItem::colorize(bool _colorize)
{
if (_colorize)
{
for (int i = 0; i < COL_COLUMNS_NUMBER; ++i)
{
setBackground(i, QColor::fromRgb(m_customBGColor));
setForeground(i, QColor::fromRgb(m_customTextColor));
}
}
else
{
const QBrush nobrush;
for (int i = 0; i < COL_COLUMNS_NUMBER; ++i)
{
setBackground(i, nobrush);
setForeground(i, nobrush);
}
}
}
void EasyTreeWidgetItem::collapseAll()
{
for (int i = 0, childrenNumber = childCount(); i < childrenNumber; ++i)
{
static_cast<EasyTreeWidgetItem*>(child(i))->collapseAll();
}
setExpanded(false);
::profiler_gui::EASY_GLOBALS.gui_blocks[m_block->block_index].expanded = false;
}
void EasyTreeWidgetItem::expandAll()
{
for (int i = 0, childrenNumber = childCount(); i < childrenNumber; ++i)
{
static_cast<EasyTreeWidgetItem*>(child(i))->expandAll();
}
setExpanded(true);
::profiler_gui::EASY_GLOBALS.gui_blocks[m_block->block_index].expanded = true;
}
//////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,118 @@
/************************************************************************
* file name : tree_widget_item.h
* ----------------- :
* creation time : 2016/08/18
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of EasyTreeWidgetItem
* : for displyaing EasyProfiler blocks tree.
* ----------------- :
* change log : * 2016/08/18 Victor Zarubkin: moved sources from blocks_tree_widget.h
* : and renamed classes from Prof* to Easy*.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#ifndef EASY__TREE_WIDGET_ITEM__H_
#define EASY__TREE_WIDGET_ITEM__H_
#include <stdlib.h>
#include <QTreeWidget>
#include "profiler/reader.h"
#include "common_types.h"
//////////////////////////////////////////////////////////////////////////
enum EasyColumnsIndexes
{
COL_UNKNOWN = -1,
COL_NAME = 0,
COL_BEGIN,
COL_DURATION,
COL_SELF_DURATION,
COL_DURATION_SUM_PER_PARENT,
COL_DURATION_SUM_PER_FRAME,
COL_DURATION_SUM_PER_THREAD,
COL_SELF_DURATION_PERCENT,
COL_PERCENT_PER_PARENT,
COL_PERCENT_PER_FRAME,
COL_PERCENT_SUM_PER_PARENT,
COL_PERCENT_SUM_PER_FRAME,
COL_PERCENT_SUM_PER_THREAD,
COL_END,
COL_MIN_PER_FRAME,
COL_MAX_PER_FRAME,
COL_AVERAGE_PER_FRAME,
COL_NCALLS_PER_FRAME,
COL_MIN_PER_THREAD,
COL_MAX_PER_THREAD,
COL_AVERAGE_PER_THREAD,
COL_NCALLS_PER_THREAD,
COL_MIN_PER_PARENT,
COL_MAX_PER_PARENT,
COL_AVERAGE_PER_PARENT,
COL_NCALLS_PER_PARENT,
COL_COLUMNS_NUMBER
};
//////////////////////////////////////////////////////////////////////////
class EasyTreeWidgetItem : public QTreeWidgetItem
{
typedef QTreeWidgetItem Parent;
typedef EasyTreeWidgetItem This;
const ::profiler::BlocksTree* m_block;
QRgb m_customBGColor;
QRgb m_customTextColor;
public:
using Parent::setBackgroundColor;
using Parent::setTextColor;
EasyTreeWidgetItem(const ::profiler::BlocksTree* _treeBlock, Parent* _parent = nullptr);
virtual ~EasyTreeWidgetItem();
bool operator < (const Parent& _other) const override;
public:
const ::profiler::BlocksTree* block() const;
::profiler::timestamp_t duration() const;
::profiler::timestamp_t selfDuration() const;
void setTimeSmart(int _column, const ::profiler::timestamp_t& _time, const QString& _prefix = "");
void setTimeMs(int _column, const ::profiler::timestamp_t& _time);
void setTimeMs(int _column, const ::profiler::timestamp_t& _time, const QString& _prefix);
void setBackgroundColor(QRgb _color);
void setTextColor(QRgb _color);
void colorize(bool _colorize);
void collapseAll();
void expandAll();
}; // END of class EasyTreeWidgetItem.
//////////////////////////////////////////////////////////////////////////
#endif // EASY__TREE_WIDGET_ITEM__H_

View File

@ -0,0 +1,584 @@
/************************************************************************
* file name : tree_widget_loader.h
* ----------------- :
* creation time : 2016/08/18
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of EasyTreeWidgetLoader which aim is
* : to load EasyProfiler blocks hierarchy in separate thread.
* ----------------- :
* change log : * 2016/08/18 Victor Zarubkin: moved sources from blocks_tree_widget.h/.cpp
* : and renamed Prof* to Easy*.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#include "tree_widget_loader.h"
#include "tree_widget_item.h"
#include "globals.h"
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
//////////////////////////////////////////////////////////////////////////
EasyTreeWidgetLoader::EasyTreeWidgetLoader() : m_bDone(ATOMIC_VAR_INIT(false)), m_bInterrupt(ATOMIC_VAR_INIT(false)), m_progress(ATOMIC_VAR_INIT(0))
{
}
EasyTreeWidgetLoader::~EasyTreeWidgetLoader()
{
interrupt();
}
bool EasyTreeWidgetLoader::done() const
{
return m_bDone.load();
}
void EasyTreeWidgetLoader::setDone()
{
m_bDone.store(true);
//m_progress.store(100);
}
void EasyTreeWidgetLoader::setProgress(int _progress)
{
m_progress.store(_progress);
}
bool EasyTreeWidgetLoader::interrupted() const
{
return m_bInterrupt.load();
}
int EasyTreeWidgetLoader::progress() const
{
return m_progress.load();
}
void EasyTreeWidgetLoader::takeTopLevelItems(ThreadedItems& _output)
{
if (done())
{
_output = ::std::move(m_topLevelItems);
m_topLevelItems.clear();
}
}
void EasyTreeWidgetLoader::takeItems(Items& _output)
{
if (done())
{
_output = ::std::move(m_items);
m_items.clear();
}
}
void EasyTreeWidgetLoader::interrupt()
{
m_bInterrupt.store(true);
if (m_thread.joinable())
m_thread.join();
m_bInterrupt.store(false);
m_bDone.store(false);
m_progress.store(0);
for (auto item : m_topLevelItems)
{
//qDeleteAll(item.second->takeChildren());
delete item.second;
}
m_items.clear();
m_topLevelItems.clear();
}
void EasyTreeWidgetLoader::fillTree(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows)
{
interrupt();
m_thread = ::std::move(::std::thread(&FillTreeClass<EasyTreeWidgetLoader>::setTreeInternal1, ::std::ref(*this), ::std::ref(m_items), ::std::ref(m_topLevelItems), ::std::ref(_beginTime), _blocksNumber, ::std::ref(_blocksTree), _colorizeRows));
}
void EasyTreeWidgetLoader::fillTreeBlocks(const::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _beginTime, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows)
{
interrupt();
m_thread = ::std::move(::std::thread(&FillTreeClass<EasyTreeWidgetLoader>::setTreeInternal2, ::std::ref(*this), ::std::ref(m_items), ::std::ref(m_topLevelItems), _beginTime, ::std::ref(_blocks), _left, _right, _strict, _colorizeRows));
}
//////////////////////////////////////////////////////////////////////////
template <class T>
void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, ::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows)
{
_items.reserve(_blocksNumber + _blocksTree.size()); // _blocksNumber does not include Thread root blocks
::profiler::timestamp_t finishtime = 0;
for (const auto& threadTree : _blocksTree)
{
const auto node_block = threadTree.second.tree.children.front().node->block();
const auto startTime = node_block->getBegin();
const auto endTime = node_block->getEnd();
if (_beginTime > startTime)
_beginTime = startTime;
if (finishtime < endTime)
finishtime = endTime;
}
//const QSignalBlocker b(this);
int i = 0;
const int total = static_cast<int>(_blocksTree.size());
for (const auto& threadTree : _blocksTree)
{
if (_safelocker.interrupted())
break;
auto& block = threadTree.second.tree;
auto item = new EasyTreeWidgetItem(&block);
if (threadTree.second.thread_name && threadTree.second.thread_name[0] != 0)
{
item->setText(COL_NAME, QString("%1 Thread %2").arg(threadTree.second.thread_name).arg(threadTree.first));
}
else
{
item->setText(COL_NAME, QString("Thread %1").arg(threadTree.first));
}
::profiler::timestamp_t duration = 0;
if (!block.children.empty())
{
duration = block.children.back().node->block()->getEnd() - block.children.front().node->block()->getBegin();
}
item->setTimeSmart(COL_DURATION, duration);
item->setBackgroundColor(::profiler_gui::SELECTED_THREAD_BACKGROUND);
item->setTextColor(::profiler_gui::SELECTED_THREAD_FOREGROUND);
_items.push_back(item);
// TODO: Optimize children duration calculation (it must be calculated before setTreeInternal now)
::profiler::timestamp_t children_duration = 0;
for (const auto& child : block.children)
children_duration += child.node->block()->duration();
item->setTimeSmart(COL_SELF_DURATION, children_duration);
children_duration = 0;
const auto children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, block.children, item, nullptr, item, _beginTime, finishtime + 1000000000ULL, false, children_duration, _colorizeRows);
if (children_items_number > 0)
{
//total_items += children_items_number + 1;
//addTopLevelItem(item);
//m_roots[threadTree.first] = item;
_topLevelItems.emplace_back(threadTree.first, item);
}
else
{
_items.pop_back();
delete item;
}
_safelocker.setProgress((100 * ++i) / total);
}
_safelocker.setDone();
//return total_items;
}
//////////////////////////////////////////////////////////////////////////
auto calculateTotalChildrenNumber(const ::profiler::BlocksTree* _tree) -> decltype(_tree->children.size())
{
auto children_number = _tree->children.size();
for (const auto& child : _tree->children)
children_number += calculateTotalChildrenNumber(&child);
return children_number;
}
template <class T>
void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows)
{
//size_t blocksNumber = 0;
//for (const auto& block : _blocks)
// blocksNumber += calculateTotalChildrenNumber(block.tree);
// //blocksNumber += block.tree->total_children_number;
//m_items.reserve(blocksNumber + _blocks.size()); // blocksNumber does not include root blocks
RootsMap threadsMap;
int i = 0, total = static_cast<int>(_blocks.size());
//const QSignalBlocker b(this);
for (const auto& block : _blocks)
{
if (_safelocker.interrupted())
break;
const auto startTime = block.tree->node->block()->getBegin();
const auto endTime = block.tree->node->block()->getEnd();
if (startTime > _right || endTime < _left)
{
_safelocker.setProgress((90 * ++i) / total);
continue;
}
::profiler::timestamp_t duration = 0;
EasyTreeWidgetItem* thread_item = nullptr;
auto thread_item_it = threadsMap.find(block.root->thread_id);
if (thread_item_it != threadsMap.end())
{
thread_item = thread_item_it->second;
}
else
{
thread_item = new EasyTreeWidgetItem(&block.root->tree);
if (block.root->thread_name && block.root->thread_name[0] != 0)
{
thread_item->setText(COL_NAME, QString("%1 Thread %2").arg(block.root->thread_name).arg(block.root->thread_id));
}
else
{
thread_item->setText(COL_NAME, QString("Thread %1").arg(block.root->thread_id));
}
if (!block.root->tree.children.empty())
{
duration = block.root->tree.children.back().node->block()->getEnd() - block.root->tree.children.front().node->block()->getBegin();
}
thread_item->setTimeSmart(COL_DURATION, duration);
thread_item->setBackgroundColor(::profiler_gui::SELECTED_THREAD_BACKGROUND);
thread_item->setTextColor(::profiler_gui::SELECTED_THREAD_FOREGROUND);
// Calculate clean duration (sum of all children durations)
::profiler::timestamp_t children_duration = 0;
for (const auto& child : block.root->tree.children)
children_duration += child.node->block()->duration();
thread_item->setTimeSmart(COL_SELF_DURATION, children_duration);
threadsMap.insert(::std::make_pair(block.root->thread_id, thread_item));
}
auto item = new EasyTreeWidgetItem(block.tree, thread_item);
duration = endTime - startTime;
item->setText(COL_NAME, ::profiler_gui::toUnicode(block.tree->node->getName()));
item->setTimeSmart(COL_DURATION, duration);
item->setTimeMs(COL_BEGIN, startTime - _beginTime);
item->setTimeMs(COL_END, endTime - _beginTime);
item->setData(COL_PERCENT_PER_PARENT, Qt::UserRole, 0);
item->setText(COL_PERCENT_PER_PARENT, "");
item->setData(COL_PERCENT_PER_FRAME, Qt::UserRole, 0);
item->setText(COL_PERCENT_PER_FRAME, "");
if (block.tree->per_thread_stats != nullptr) // if there is per_thread_stats then there are other stats also
{
const auto& per_thread_stats = block.tree->per_thread_stats;
const auto& per_parent_stats = block.tree->per_parent_stats;
const auto& per_frame_stats = block.tree->per_frame_stats;
if (per_thread_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_THREAD, per_thread_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_THREAD, per_thread_stats->max_duration, "max ");
item->setTimeSmart(COL_AVERAGE_PER_THREAD, per_thread_stats->average_duration());
item->setTimeSmart(COL_DURATION_SUM_PER_THREAD, per_thread_stats->total_duration);
}
item->setData(COL_NCALLS_PER_THREAD, Qt::UserRole, per_thread_stats->calls_number);
item->setText(COL_NCALLS_PER_THREAD, QString::number(per_thread_stats->calls_number));
auto percentage_per_thread = static_cast<int>(0.5 + 100. * static_cast<double>(per_thread_stats->total_duration) / static_cast<double>(thread_item->selfDuration()));
item->setData(COL_PERCENT_SUM_PER_THREAD, Qt::UserRole, percentage_per_thread);
item->setText(COL_PERCENT_SUM_PER_THREAD, QString::number(percentage_per_thread));
if (per_parent_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_PARENT, per_parent_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_PARENT, per_parent_stats->max_duration, "max ");
item->setTimeSmart(COL_AVERAGE_PER_PARENT, per_parent_stats->average_duration());
item->setTimeSmart(COL_DURATION_SUM_PER_PARENT, per_parent_stats->total_duration);
}
item->setData(COL_NCALLS_PER_PARENT, Qt::UserRole, per_parent_stats->calls_number);
item->setText(COL_NCALLS_PER_PARENT, QString::number(per_parent_stats->calls_number));
if (per_frame_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_FRAME, per_frame_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_FRAME, per_frame_stats->max_duration, "max ");
item->setTimeSmart(COL_AVERAGE_PER_FRAME, per_frame_stats->average_duration());
item->setTimeSmart(COL_DURATION_SUM_PER_FRAME, per_frame_stats->total_duration);
}
item->setData(COL_NCALLS_PER_FRAME, Qt::UserRole, per_frame_stats->calls_number);
item->setText(COL_NCALLS_PER_FRAME, QString::number(per_frame_stats->calls_number));
}
else
{
item->setData(COL_PERCENT_SUM_PER_THREAD, Qt::UserRole, 0);
item->setText(COL_PERCENT_SUM_PER_THREAD, "");
}
const auto color = block.tree->node->block()->getColor();
const auto bgColor = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color));
const auto fgColor = 0x00ffffff - bgColor;
item->setBackgroundColor(bgColor);
item->setTextColor(fgColor);
auto item_index = static_cast<unsigned int>(_items.size());
_items.push_back(item);
size_t children_items_number = 0;
::profiler::timestamp_t children_duration = 0;
if (!block.tree->children.empty())
{
children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, block.tree->children, item, item, thread_item, _left, _right, _strict, children_duration, _colorizeRows);
if (_safelocker.interrupted())
break;
}
int percentage = 100;
auto self_duration = duration - children_duration;
if (children_duration > 0 && duration > 0)
{
percentage = static_cast<int>(0.5 + 100. * static_cast<double>(self_duration) / static_cast<double>(duration));
}
item->setTimeSmart(COL_SELF_DURATION, self_duration);
item->setData(COL_SELF_DURATION_PERCENT, Qt::UserRole, percentage);
item->setText(COL_SELF_DURATION_PERCENT, QString::number(percentage));
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
{
//total_items += children_items_number + 1;
::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].tree_item = item_index;
if (_colorizeRows)
{
item->colorize(_colorizeRows);
}
}
else
{
_items.pop_back();
delete item;
}
_safelocker.setProgress((90 * ++i) / total);
}
i = 0;
total = static_cast<int>(threadsMap.size());
for (auto& it : threadsMap)
{
auto item = it.second;
if (item->childCount() > 0)
{
//addTopLevelItem(item);
//m_roots[it.first] = item;
_items.push_back(item);
_topLevelItems.emplace_back(it.first, item);
//++total_items;
}
else
{
delete item;
}
_safelocker.setProgress(90 + (10 * ++i) / total);
}
_safelocker.setDone();
//return total_items;
}
template <class T>
size_t FillTreeClass<T>::setTreeInternal(T& _safelocker, Items& _items, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, EasyTreeWidgetItem* _thread, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows)
{
size_t total_items = 0;
for (const auto& child : _children)
{
if (_safelocker.interrupted())
break;
const auto startTime = child.node->block()->getBegin();
const auto endTime = child.node->block()->getEnd();
const auto duration = endTime - startTime;
_duration += duration;
if (startTime > _right || endTime < _left)
{
continue;
}
auto item = new EasyTreeWidgetItem(&child, _parent);
item->setText(COL_NAME, ::profiler_gui::toUnicode(child.node->getName()));
item->setTimeSmart(COL_DURATION, duration);
item->setTimeMs(COL_BEGIN, startTime - _beginTime);
item->setTimeMs(COL_END, endTime - _beginTime);
item->setData(COL_PERCENT_SUM_PER_THREAD, Qt::UserRole, 0);
if (child.per_thread_stats != nullptr) // if there is per_thread_stats then there are other stats also
{
const auto& per_thread_stats = child.per_thread_stats;
const auto& per_parent_stats = child.per_parent_stats;
const auto& per_frame_stats = child.per_frame_stats;
auto percentage = duration == 0 ? 0 : static_cast<int>(0.5 + 100. * static_cast<double>(duration) / static_cast<double>(_parent->duration()));
auto percentage_sum = static_cast<int>(0.5 + 100. * static_cast<double>(per_parent_stats->total_duration) / static_cast<double>(_parent->duration()));
item->setData(COL_PERCENT_PER_PARENT, Qt::UserRole, percentage);
item->setText(COL_PERCENT_PER_PARENT, QString::number(percentage));
item->setData(COL_PERCENT_SUM_PER_PARENT, Qt::UserRole, percentage_sum);
item->setText(COL_PERCENT_SUM_PER_PARENT, QString::number(percentage_sum));
if (_frame != nullptr)
{
if (_parent != _frame)
{
percentage = duration == 0 ? 0 : static_cast<int>(0.5 + 100. * static_cast<double>(duration) / static_cast<double>(_frame->duration()));
percentage_sum = static_cast<int>(0.5 + 100. * static_cast<double>(per_frame_stats->total_duration) / static_cast<double>(_frame->duration()));
}
item->setData(COL_PERCENT_PER_FRAME, Qt::UserRole, percentage);
item->setText(COL_PERCENT_PER_FRAME, QString::number(percentage));
item->setData(COL_PERCENT_SUM_PER_FRAME, Qt::UserRole, percentage_sum);
item->setText(COL_PERCENT_SUM_PER_FRAME, QString::number(percentage_sum));
}
else
{
item->setData(COL_PERCENT_PER_FRAME, Qt::UserRole, 0);
item->setText(COL_PERCENT_PER_FRAME, "");
item->setData(COL_PERCENT_SUM_PER_FRAME, Qt::UserRole, 0);
item->setText(COL_PERCENT_SUM_PER_FRAME, "");
}
if (per_thread_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_THREAD, per_thread_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_THREAD, per_thread_stats->max_duration, "max ");
item->setTimeSmart(COL_AVERAGE_PER_THREAD, per_thread_stats->average_duration());
item->setTimeSmart(COL_DURATION_SUM_PER_THREAD, per_thread_stats->total_duration);
}
item->setData(COL_NCALLS_PER_THREAD, Qt::UserRole, per_thread_stats->calls_number);
item->setText(COL_NCALLS_PER_THREAD, QString::number(per_thread_stats->calls_number));
if (_thread)
{
auto percentage_per_thread = static_cast<int>(0.5 + 100. * static_cast<double>(per_thread_stats->total_duration) / static_cast<double>(_thread->selfDuration()));
item->setData(COL_PERCENT_SUM_PER_THREAD, Qt::UserRole, percentage_per_thread);
item->setText(COL_PERCENT_SUM_PER_THREAD, QString::number(percentage_per_thread));
}
if (per_parent_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_PARENT, per_parent_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_PARENT, per_parent_stats->max_duration, "max ");
item->setTimeSmart(COL_AVERAGE_PER_PARENT, per_parent_stats->average_duration());
item->setTimeSmart(COL_DURATION_SUM_PER_PARENT, per_parent_stats->total_duration);
}
item->setData(COL_NCALLS_PER_PARENT, Qt::UserRole, per_parent_stats->calls_number);
item->setText(COL_NCALLS_PER_PARENT, QString::number(per_parent_stats->calls_number));
if (per_frame_stats->calls_number > 1 || !::profiler_gui::EASY_GLOBALS.display_only_relevant_stats)
{
item->setTimeSmart(COL_MIN_PER_FRAME, per_frame_stats->min_duration, "min ");
item->setTimeSmart(COL_MAX_PER_FRAME, per_frame_stats->max_duration, "max ");
item->setTimeSmart(COL_AVERAGE_PER_FRAME, per_frame_stats->average_duration());
item->setTimeSmart(COL_DURATION_SUM_PER_FRAME, per_frame_stats->total_duration);
}
item->setData(COL_NCALLS_PER_FRAME, Qt::UserRole, per_frame_stats->calls_number);
item->setText(COL_NCALLS_PER_FRAME, QString::number(per_frame_stats->calls_number));
}
else
{
item->setData(COL_PERCENT_PER_PARENT, Qt::UserRole, 0);
item->setText(COL_PERCENT_PER_PARENT, "");
item->setData(COL_PERCENT_SUM_PER_PARENT, Qt::UserRole, 0);
item->setText(COL_PERCENT_SUM_PER_PARENT, "");
item->setData(COL_PERCENT_SUM_PER_THREAD, Qt::UserRole, 0);
item->setText(COL_PERCENT_SUM_PER_THREAD, "");
}
const auto color = child.node->block()->getColor();
const auto bgColor = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color));
const auto fgColor = 0x00ffffff - bgColor;
item->setBackgroundColor(bgColor);
item->setTextColor(fgColor);
auto item_index = static_cast<unsigned int>(_items.size());
_items.push_back(item);
size_t children_items_number = 0;
::profiler::timestamp_t children_duration = 0;
if (!child.children.empty())
{
children_items_number = FillTreeClass<T>::setTreeInternal(_safelocker, _items, _beginTime, child.children, item, _frame ? _frame : item, _thread, _left, _right, _strict, children_duration, _colorizeRows);
if (_safelocker.interrupted())
break;
}
int percentage = 100;
auto self_duration = duration - children_duration;
if (children_duration > 0 && duration > 0)
{
percentage = static_cast<int>(0.5 + 100. * static_cast<double>(self_duration) / static_cast<double>(duration));
}
item->setTimeSmart(COL_SELF_DURATION, self_duration);
item->setData(COL_SELF_DURATION_PERCENT, Qt::UserRole, percentage);
item->setText(COL_SELF_DURATION_PERCENT, QString::number(percentage));
if (children_items_number > 0 || !_strict || (startTime >= _left && endTime <= _right))
{
total_items += children_items_number + 1;
::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].tree_item = item_index;
if (_colorizeRows)
{
item->colorize(_colorizeRows);
}
}
else
{
_items.pop_back();
delete item;
}
}
return total_items;
}
//////////////////////////////////////////////////////////////////////////
template struct FillTreeClass<EasyTreeWidgetLoader>;
template struct FillTreeClass<StubLocker>;
//////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,90 @@
/************************************************************************
* file name : tree_widget_loader.h
* ----------------- :
* creation time : 2016/08/18
* copyright : (c) 2016 Victor Zarubkin
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of EasyTreeWidgetLoader which aim is
* : to load EasyProfiler blocks hierarchy in separate thread.
* ----------------- :
* change log : * 2016/08/18 Victor Zarubkin: moved sources from blocks_tree_widget.h/.cpp
* : and renamed Prof* to Easy*.
* :
* : *
* ----------------- :
* license : TODO: add license text
************************************************************************/
#ifndef EASY__TREE_WIDGET_LOADER__H_
#define EASY__TREE_WIDGET_LOADER__H_
#include <stdlib.h>
#include <vector>
#include <thread>
#include <atomic>
#include "profiler/reader.h"
#include "common_types.h"
//////////////////////////////////////////////////////////////////////////
class EasyTreeWidgetItem;
typedef ::std::vector<EasyTreeWidgetItem*> Items;
typedef ::std::vector<::std::pair<::profiler::thread_id_t, EasyTreeWidgetItem*> > ThreadedItems;
typedef ::std::unordered_map<::profiler::thread_id_t, EasyTreeWidgetItem*, ::profiler_gui::do_no_hash<::profiler::thread_id_t>::hasher_t> RootsMap;
//////////////////////////////////////////////////////////////////////////
class EasyTreeWidgetLoader final
{
ThreadedItems m_topLevelItems; ///<
Items m_items; ///<
::std::thread m_thread; ///<
::std::atomic_bool m_bDone; ///<
::std::atomic_bool m_bInterrupt; ///<
::std::atomic<int> m_progress; ///<
public:
EasyTreeWidgetLoader();
~EasyTreeWidgetLoader();
bool interrupted() const;
int progress() const;
bool done() const;
void takeTopLevelItems(ThreadedItems& _output);
void takeItems(Items& _output);
void interrupt();
void fillTree(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows);
void fillTreeBlocks(const::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _beginTime, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows);
void setDone();
void setProgress(int _progress);
}; // END of class EasyTreeWidgetLoader.
//////////////////////////////////////////////////////////////////////////
template <class T>
struct FillTreeClass final
{
static void setTreeInternal1(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, ::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows);
static void setTreeInternal2(T& _safelocker, Items& _items, ThreadedItems& _topLevelItems, const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows);
static size_t setTreeInternal(T& _safelocker, Items& _items, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, EasyTreeWidgetItem* _thread, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows);
};
//////////////////////////////////////////////////////////////////////////
struct StubLocker final
{
void setDone() {}
bool interrupted() const { return false; }
void setProgress(int) {}
};
//////////////////////////////////////////////////////////////////////////
#endif // EASY__TREE_WIDGET_LOADER__H_

View File

@ -79,7 +79,7 @@ void calcBrain(){
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(profiler::colors::Blue);
double* intarray = new double[OBJECTS];
for (int i = 0; i < OBJECTS; ++i)
intarray[i] = calcSubbrain(double(i)) + double(i * 180 / 3);
intarray[i] = calcSubbrain(i) + double(i * 180 / 3);
delete[] intarray;
//std::this_thread::sleep_for(std::chrono::milliseconds(3));
}
@ -137,6 +137,7 @@ void loadingResourcesThread(){
for(int i = 0; i < RESOURCE_LOADING_COUNT; i++){
loadingResources();
PROFILER_ADD_EVENT_GROUPED("Resources Loading!",profiler::colors::Cyan);
localSleep(1200000);
//std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
@ -147,7 +148,7 @@ void modellingThread(){
PROFILER_SET_THREAD_NAME("Modelling")
for (int i = 0; i < RENDER_SPEPS; i++){
modellingStep();
localSleep(300000);
localSleep(1200000);
//std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
@ -158,7 +159,7 @@ void renderThread(){
PROFILER_SET_THREAD_NAME("Render")
for (int i = 0; i < MODELLING_STEPS; i++){
frame();
localSleep(300000);
localSleep(1200000);
//std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}

View File

@ -221,14 +221,16 @@ typedef ::std::map<::profiler::thread_id_t, StatsMap> PerThreadStats;
extern "C"{
unsigned int fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics)
unsigned int fillTreesFromFile(::std::atomic<int>& progress, const char* filename, ::profiler::SerializedData& serialized_blocks, ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics)
{
PROFILER_BEGIN_FUNCTION_BLOCK_GROUPED(::profiler::colors::Cyan)
::std::ifstream inFile(filename, ::std::fstream::binary);
progress.store(0);
if (!inFile.is_open())
{
progress.store(100);
return 0;
}
@ -239,6 +241,7 @@ extern "C"{
inFile.read((char*)&memory_size, sizeof(uint64_t));
if (memory_size == 0)
{
progress.store(100);
return 0;
}
@ -346,6 +349,17 @@ extern "C"{
current.per_thread_stats = update_statistics(per_thread_statistics, current);
}
if (progress.load() < 0)
break;
progress.store(static_cast<int>(90 * i / memory_size));
}
if (progress.load() < 0)
{
progress.store(100);
serialized_blocks.clear();
threaded_trees.clear();
return 0;
}
PROFILER_BEGIN_BLOCK_GROUPED("Gather statistics for roots", ::profiler::colors::Purple)
@ -382,13 +396,16 @@ extern "C"{
}, ::std::ref(root))));
}
int j = 0, n = static_cast<int>(statistics_threads.size());
for (auto& t : statistics_threads)
{
t.join();
progress.store(90 + (10 * ++j) / n);
}
}
else
{
int j = 0, n = static_cast<int>(threaded_trees.size());
for (auto& it : threaded_trees)
{
auto& root = it.second;
@ -402,11 +419,14 @@ extern "C"{
}
++root.tree.depth;
progress.store(90 + (10 * ++j) / n);
}
}
PROFILER_END_BLOCK
// No need to delete BlockStatistics instances - they will be deleted inside BlocksTree destructors
progress.store(100);
return blocks_counter;
}
}