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

(GUI) Added possibility to torn on/off decorated thread names (add/don't add "Thread" word info thread name. Example, "Render" convert to "Render Thread", "WorkerThread" "My thread" will not convert in any way). See Settings->View->Use decorated thread names.

* (GUI) Fixed lagging when painting very long block on large scale.
This commit is contained in:
Victor Zarubkin 2016-12-14 21:47:33 +03:00
parent 0304a55c15
commit eafcb40970
11 changed files with 226 additions and 106 deletions

View File

@ -56,8 +56,6 @@
#include <QGraphicsScene>
#include <QGraphicsProxyWidget>
#include <QFormLayout>
#include <QLabel>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QKeyEvent>
@ -119,6 +117,20 @@ inline T logn(T _value)
//////////////////////////////////////////////////////////////////////////
EasyBoldLabel::EasyBoldLabel(const QString& _text, QWidget* _parent) : QLabel(_text, _parent)
{
auto f = font();
f.setBold(true);
setFont(f);
}
EasyBoldLabel::~EasyBoldLabel()
{
}
//////////////////////////////////////////////////////////////////////////
void EasyBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*, QWidget*)
{
auto const sceneView = static_cast<EasyGraphicsView*>(scene()->parent());
@ -429,11 +441,20 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
m_beginTime -= ::std::min(m_beginTime, additional_offset);
EASY_GLOBALS.begin_time = m_beginTime;
// Sort threads by name
::std::vector<::std::reference_wrapper<const ::profiler::BlocksTreeRoot> > sorted_roots;
sorted_roots.reserve(_blocksTree.size());
for (const auto& threadTree : _blocksTree)
sorted_roots.push_back(threadTree.second);
::std::sort(sorted_roots.begin(), sorted_roots.end(), [](const ::profiler::BlocksTreeRoot& _a, const ::profiler::BlocksTreeRoot& _b) {
return _a.thread_name < _b.thread_name;
});
// Filling scene with items
m_items.reserve(_blocksTree.size());
qreal y = TIMELINE_ROW_SIZE;
const EasyGraphicsItem *longestItem = nullptr, *mainThreadItem = nullptr;
for (const auto& threadTree : _blocksTree)
for (const ::profiler::BlocksTreeRoot& t : sorted_roots)
{
if (m_items.size() == 0xff)
{
@ -441,8 +462,6 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
break;
}
const auto& t = threadTree.second;
// fill scene with new items
qreal h = 0, x = 0;
@ -475,10 +494,10 @@ void EasyGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTr
y += h + ::profiler_gui::THREADS_ROW_SPACING;
if (longestTree == threadTree.first)
if (longestTree == t.thread_id)
longestItem = item;
if (mainTree == threadTree.first)
if (mainTree == t.thread_id)
mainThreadItem = item;
}
@ -1253,6 +1272,22 @@ void EasyGraphicsView::initMode()
m_pScrollbar->setHystogramFrom(EASY_GLOBALS.selected_thread, EASY_GLOBALS.selected_block_id);
onRefreshRequired();
});
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::threadNameDecorationChanged, [this]()
{
if (m_bEmpty)
return;
for (auto item : m_items)
item->validateName();
emit treeChanged();
updateVisibleSceneRect();
onHierarchyFlagChange(EASY_GLOBALS.only_current_thread_hierarchy);
repaintScene();
});
}
//////////////////////////////////////////////////////////////////////////
@ -1371,8 +1406,8 @@ void EasyGraphicsView::onIdleTimeout()
int row = 0;
if (itemDesc.type() == ::profiler::BLOCK_TYPE_BLOCK)
{
lay->addWidget(new QLabel("Block:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new QLabel(name, widget), row, 1, 1, 4, Qt::AlignLeft);
//lay->addWidget(new QLabel("Name:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new EasyBoldLabel(name, widget), row, 0, 1, 5, Qt::AlignHCenter);
++row;
lay->addWidget(new QLabel("Duration:", widget), row, 0, Qt::AlignRight);
@ -1381,7 +1416,10 @@ void EasyGraphicsView::onIdleTimeout()
}
else
{
lay->addWidget(new QLabel("Event:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new EasyBoldLabel("User defined event", widget), row, 0, 1, 2, Qt::AlignHCenter);
++row;
lay->addWidget(new QLabel("Name:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new QLabel(name, widget), row, 1, Qt::AlignLeft);
++row;
}
@ -1396,7 +1434,7 @@ void EasyGraphicsView::onIdleTimeout()
lay->addWidget(new QLabel(::profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, itemBlock.per_thread_stats->average_duration(), 3), widget), row, 1, 1, 3, Qt::AlignLeft);
++row;
lay->addWidget(new QLabel("-------- Statistics --------", widget), row, 0, 1, 5, Qt::AlignHCenter);
lay->addWidget(new EasyBoldLabel("-------- Statistics --------", widget), row, 0, 1, 5, Qt::AlignHCenter);
lay->addWidget(new QLabel("per ", widget), row + 1, 0, Qt::AlignRight);
lay->addWidget(new QLabel("This %:", widget), row + 2, 0, Qt::AlignRight);
lay->addWidget(new QLabel("Sum %:", widget), row + 3, 0, Qt::AlignRight);
@ -1449,7 +1487,7 @@ void EasyGraphicsView::onIdleTimeout()
}
else
{
lay->addWidget(new QLabel("N calls/Thread:", widget), 1, 0, Qt::AlignRight);
lay->addWidget(new QLabel("N calls/Thread:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new QLabel(QString::number(itemBlock.per_thread_stats->calls_number), widget), row, 1, Qt::AlignLeft);
}
}
@ -1464,16 +1502,26 @@ void EasyGraphicsView::onIdleTimeout()
if (cse)
{
auto widget = new QWidget();
auto lay = new QFormLayout(widget);
lay->setLabelAlignment(Qt::AlignRight);
auto lay = new QGridLayout(widget);
int row = 0;
lay->addWidget(new EasyBoldLabel("Context switch event", widget), row, 0, 1, 2, Qt::AlignHCenter);
++row;
lay->addWidget(new QLabel("Thread:", widget), row, 0, Qt::AlignRight);
auto it = EASY_GLOBALS.profiler_blocks.find(cse->tree.node->id());
if (it != EASY_GLOBALS.profiler_blocks.end())
lay->addRow("Thread:", new QLabel(QString("%1 %2").arg(cse->tree.node->id()).arg(it->second.name())));
lay->addWidget(new QLabel(QString("%1 %2").arg(cse->tree.node->id()).arg(it->second.name()), widget), row, 1, Qt::AlignLeft);
else
lay->addRow("Thread:", new QLabel(QString::number(cse->tree.node->id())));
lay->addRow("Process:", new QLabel(cse->tree.node->name()));
lay->addRow("Duration:", new QLabel(::profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, cse->tree.node->duration(), 3)));
lay->addWidget(new QLabel(QString::number(cse->tree.node->id()), widget), row, 1, Qt::AlignLeft);
++row;
lay->addWidget(new QLabel("Process:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new QLabel(cse->tree.node->name(), widget), row, 1, Qt::AlignLeft);
++row;
lay->addWidget(new QLabel("Duration:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new QLabel(::profiler_gui::timeStringRealNs(EASY_GLOBALS.time_units, cse->tree.node->duration(), 3), widget), row, 1, Qt::AlignLeft);
m_csInfoWidget = new QGraphicsProxyWidget();
m_csInfoWidget->setWidget(widget);

View File

@ -60,6 +60,7 @@
#include <QPoint>
#include <QRectF>
#include <QTimer>
#include <QLabel>
#include "easy/reader.h"
#include "common_types.h"
@ -94,6 +95,13 @@ EASY_QGRAPHICSITEM(EasyThreadNameItem);
//////////////////////////////////////////////////////////////////////////
struct EasyBoldLabel : public QLabel {
EasyBoldLabel(const QString& _text, QWidget* _parent = nullptr);
virtual ~EasyBoldLabel();
};
//////////////////////////////////////////////////////////////////////////
class EasyGraphicsView : public QGraphicsView
{
Q_OBJECT

View File

@ -86,28 +86,21 @@ const auto SELECTED_ITEM_FONT = ::profiler_gui::EFont("Helvetica", 10, QFont::Bo
EasyGraphicsItem::EasyGraphicsItem(uint8_t _index, const::profiler::BlocksTreeRoot& _root)
: QGraphicsItem(nullptr)
, m_threadName(::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, _root))
, m_pRoot(&_root)
, m_index(_index)
{
const auto u_thread = ::profiler_gui::toUnicode("thread");
if (_root.got_name())
{
QString rootname(::profiler_gui::toUnicode(_root.name()));
if (rootname.contains(u_thread, Qt::CaseInsensitive))
m_threadName = ::std::move(QString("%1 %2").arg(rootname).arg(_root.thread_id));
else
m_threadName = ::std::move(QString("%1 Thread %2").arg(rootname).arg(_root.thread_id));
}
else
{
m_threadName = ::std::move(QString("Thread %1").arg(_root.thread_id));
}
}
EasyGraphicsItem::~EasyGraphicsItem()
{
}
void EasyGraphicsItem::validateName()
{
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, *m_pRoot);
}
const EasyGraphicsView* EasyGraphicsItem::view() const
{
return static_cast<const EasyGraphicsView*>(scene()->parent());
@ -375,6 +368,25 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->setPen(Qt::NoPen);
}
const auto wprev = w;
decltype(w) dw = 0;
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;
x = sceneLeft * currentScale - dx - 2;
w += 2;
dw = 2;
}
if (item.right() > sceneRight)
{
w -= (item.right() - sceneRight) * currentScale;
w += 2;
dw += 2;
}
if (w < EASY_GLOBALS.blocks_size_min)
w = EASY_GLOBALS.blocks_size_min;
@ -384,13 +396,18 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
prevRight = rect.right() + EASY_GLOBALS.blocks_spacing;
//skip_children(next_level, item.children_begin);
if (w < EASY_GLOBALS.blocks_narrow_size)
if (wprev < EASY_GLOBALS.blocks_narrow_size)
continue;
if (totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE)
flags = Qt::AlignCenter;
else if (!(item.width() < 1))
flags = Qt::AlignHCenter;
if (dw > 1) {
w -= dw;
x += 2;
}
}
else
{
@ -440,6 +457,25 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
if (dh > 0)
h -= dh;
const auto wprev = w;
decltype(w) dw = 0;
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;
x = sceneLeft * currentScale - dx - 2;
w += 2;
dw = 2;
}
if (item.right() > sceneRight)
{
w -= (item.right() - sceneRight) * currentScale;
w += 2;
dw += 2;
}
if (w < EASY_GLOBALS.blocks_size_min)
w = EASY_GLOBALS.blocks_size_min;
@ -447,34 +483,24 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
_painter->drawRect(rect);
prevRight = rect.right() + EASY_GLOBALS.blocks_spacing;
if (w < EASY_GLOBALS.blocks_narrow_size)
if (wprev < EASY_GLOBALS.blocks_narrow_size)
{
dont_skip_children(next_level, item.children_begin, w < narrow_size_half ? BLOCK_ITEM_DO_PAINT_FIRST : BLOCK_ITEM_DO_PAINT);
dont_skip_children(next_level, item.children_begin, wprev < narrow_size_half ? BLOCK_ITEM_DO_PAINT_FIRST : BLOCK_ITEM_DO_PAINT);
continue;
}
dont_skip_children(next_level, item.children_begin, BLOCK_ITEM_DO_PAINT);
if (!(item.width() < 1))
flags = Qt::AlignHCenter;
if (dw > 1) {
w -= dw;
x += 2;
}
}
// 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, h);
rect.setRect(x + 1, top, w - 1, h);
// text will be painted with inverse color
//auto textColor = inverseColor < 0x00808080 ? profiler::colors::Black : profiler::colors::White;
@ -547,28 +573,36 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*
}
auto x = item.left() * currentScale - dx;
decltype(w) dw = 0;
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;
x = sceneLeft * currentScale - dx - 2;
w += 2;
dw = 2;
}
if (item.right() > sceneRight)
{
w -= (item.right() - sceneRight) * currentScale;
w += 2;
dw += 2;
}
rect.setRect(x, top, w, h);
_painter->drawRect(rect);
if (!selectedItemsWasPainted && w > EASY_GLOBALS.blocks_narrow_size)
{
if (dw > 1) {
w -= dw;
x += 2;
}
// 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, h);
rect.setRect(x + 1, top, w - 1, h);
// text will be painted with inverse color
//auto textColor = 0x00ffffff - previousColor;

View File

@ -87,6 +87,8 @@ public:
// Public non-virtual methods
void validateName();
const ::profiler::BlocksTreeRoot* root() const;
const QString& threadName() const;

View File

@ -762,10 +762,7 @@ void EasyHystogramItem::setSource(::profiler::thread_id_t _thread_id, const ::pr
else
{
const auto& root = EASY_GLOBALS.profiler_blocks[_thread_id];
if (root.got_name())
m_threadName = ::std::move(QString("%1 Thread %2").arg(root.name()).arg(_thread_id));
else
m_threadName = ::std::move(QString("Thread %1").arg(_thread_id));
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root);
if (root.children.empty())
m_threadDuration = 0;
@ -813,10 +810,7 @@ void EasyHystogramItem::setSource(::profiler::thread_id_t _thread_id, ::profiler
if (m_threadId != 0 && !::profiler_gui::is_max(m_blockId))
{
const auto& root = EASY_GLOBALS.profiler_blocks[_thread_id];
if (root.got_name())
m_threadName = ::std::move(QString("%1 Thread %2").arg(root.name()).arg(_thread_id));
else
m_threadName = ::std::move(QString("Thread %1").arg(_thread_id));
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root);
if (root.children.empty())
m_threadDuration = 0;
@ -918,6 +912,15 @@ void EasyHystogramItem::setSource(::profiler::thread_id_t _thread_id, ::profiler
//////////////////////////////////////////////////////////////////////////
void EasyHystogramItem::validateName()
{
if (m_threadName.isEmpty())
return;
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.profiler_blocks[m_threadId]);
}
//////////////////////////////////////////////////////////////////////////
void EasyHystogramItem::onTimeout()
{
if (!isVisible())
@ -1189,6 +1192,14 @@ EasyGraphicsScrollbar::EasyGraphicsScrollbar(QWidget* _parent)
scene()->update();
});
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::threadNameDecorationChanged, [this]()
{
if (!m_hystogramItem->isVisible())
return;
m_hystogramItem->validateName();
scene()->update();
});
centerOn(0, 0);
}

View File

@ -178,6 +178,7 @@ public:
void setSource(::profiler::thread_id_t _thread_id, const ::profiler_gui::EasyItems* _items);
void setSource(::profiler::thread_id_t _thread_id, ::profiler::block_id_t _block_id);
void validateName();
void updateImage();
private:

View File

@ -69,6 +69,7 @@ namespace profiler_gui {
, chrono_text_position(ChronoTextPosition_Center)
, time_units(TimeUnits_auto)
, connected(false)
, use_decorated_thread_name(true)
, enable_event_indicators(true)
, enable_statistics(true)
, enable_zero_length(true)

View File

@ -90,6 +90,34 @@ namespace profiler_gui {
//////////////////////////////////////////////////////////////////////////
inline QString decoratedThreadName(bool _use_decorated_thread_name, const::profiler::BlocksTreeRoot& _root, const QString& _unicodeThreadWord)
{
if (_root.got_name())
{
QString rootname(toUnicode(_root.name()));
if (!_use_decorated_thread_name || rootname.contains(_unicodeThreadWord, Qt::CaseInsensitive))
return QString("%1 %2").arg(rootname).arg(_root.thread_id);
return QString("%1 Thread %2").arg(rootname).arg(_root.thread_id);
}
return QString("Thread %1").arg(_root.thread_id);
}
inline QString decoratedThreadName(bool _use_decorated_thread_name, const ::profiler::BlocksTreeRoot& _root)
{
if (_root.got_name())
{
QString rootname(toUnicode(_root.name()));
if (!_use_decorated_thread_name || rootname.contains(toUnicode("thread"), Qt::CaseInsensitive))
return QString("%1 %2").arg(rootname).arg(_root.thread_id);
return QString("%1 Thread %2").arg(rootname).arg(_root.thread_id);
}
return QString("Thread %1").arg(_root.thread_id);
}
//////////////////////////////////////////////////////////////////////////
enum ChronometerTextPosition : int8_t
{
ChronoTextPosition_Center = 0,
@ -119,6 +147,7 @@ namespace profiler_gui {
ChronometerTextPosition chrono_text_position; ///< Selected interval text position
TimeUnits time_units; ///< Units type for time (milliseconds, microseconds, nanoseconds or auto-definition)
bool connected; ///< Is connected to source (to be able to capture profiling information)
bool use_decorated_thread_name; ///< Add "Thread" to the name of each thread (if there is no one)
bool enable_event_indicators; ///< Enable event indicators painting (These are narrow rectangles at the bottom of each thread)
bool enable_statistics; ///< Enable gathering and using statistics (Disable if you want to consume less memory)
bool enable_zero_length; ///< Enable zero length blocks (if true, then such blocks will have width == 1 pixel on each scale)

View File

@ -56,6 +56,7 @@ namespace profiler_gui {
void blocksRefreshRequired(bool);
void timelineMarkerChanged();
void hierarchyFlagChanged(bool);
void threadNameDecorationChanged();
void refreshRequired();
}; // END of class EasyGlobalSignals.

View File

@ -336,6 +336,16 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_lastAddress("localhost"), m_lastP
action->setChecked(EASY_GLOBALS.enable_event_indicators);
connect(action, &QAction::triggered, this, &This::onEventIndicatorsChange);
action = submenu->addAction("Use decorated thread names");
action->setToolTip("Add \'Thread\' word into thread name if there is no one already.\nExamples: \'Render\' will change to \'Render Thread\'\n\'WorkerThread\' will not change.");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.use_decorated_thread_name);
connect(action, &QAction::triggered, [this](bool _checked)
{
EASY_GLOBALS.use_decorated_thread_name = _checked;
emit EASY_GLOBALS.events.threadNameDecorationChanged();
});
submenu->addSeparator();
auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true);
@ -1014,6 +1024,10 @@ void EasyMainWindow::loadSettings()
if (!flag.isNull())
EASY_GLOBALS.enable_event_indicators = flag.toBool();
flag = settings.value("use_decorated_thread_name");
if (!flag.isNull())
EASY_GLOBALS.use_decorated_thread_name = flag.toBool();
flag = settings.value("enable_statistics");
if (!flag.isNull())
EASY_GLOBALS.enable_statistics = flag.toBool();
@ -1070,6 +1084,7 @@ void EasyMainWindow::saveSettingsAndGeometry()
settings.setValue("bind_scene_and_tree_expand_status", EASY_GLOBALS.bind_scene_and_tree_expand_status);
settings.setValue("selecting_block_changes_thread", EASY_GLOBALS.selecting_block_changes_thread);
settings.setValue("enable_event_indicators", EASY_GLOBALS.enable_event_indicators);
settings.setValue("use_decorated_thread_name", EASY_GLOBALS.use_decorated_thread_name);
settings.setValue("enable_statistics", EASY_GLOBALS.enable_statistics);
settings.setValue("encoding", QTextCodec::codecForLocale()->name());

View File

@ -196,22 +196,7 @@ void FillTreeClass<T>::setTreeInternal1(T& _safelocker, Items& _items, ThreadedI
const auto& root = threadTree.second;
auto item = new EasyTreeWidgetItem();
QString threadName;
if (root.got_name())
{
QString rootname(::profiler_gui::toUnicode(root.name()));
if (rootname.contains(u_thread, Qt::CaseInsensitive))
threadName = ::std::move(QString("%1 %2").arg(rootname).arg(root.thread_id));
else
threadName = ::std::move(QString("%1 Thread %2").arg(rootname).arg(root.thread_id));
}
else
{
threadName = ::std::move(QString("Thread %1").arg(root.thread_id));
}
item->setText(COL_NAME, threadName);
item->setText(COL_NAME, ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root, u_thread));
::profiler::timestamp_t duration = 0;
if (!root.children.empty())
@ -296,22 +281,7 @@ void FillTreeClass<T>::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI
else
{
thread_item = new EasyTreeWidgetItem();
QString threadName;
if (block.root->got_name())
{
QString rootname(::profiler_gui::toUnicode(block.root->name()));
if (rootname.contains(u_thread, Qt::CaseInsensitive))
threadName = ::std::move(QString("%1 %2").arg(rootname).arg(block.root->thread_id));
else
threadName = ::std::move(QString("%1 Thread %2").arg(rootname).arg(block.root->thread_id));
}
else
{
threadName = ::std::move(QString("Thread %1").arg(block.root->thread_id));
}
thread_item->setText(COL_NAME, threadName);
thread_item->setText(COL_NAME, ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, *block.root, u_thread));
if (!block.root->children.empty())
duration = blocksTree(block.root->children.back()).node->end() - blocksTree(block.root->children.front()).node->begin();