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

(GUI) Added an option to display thread ids in HEX mode;

* (GUI) Fixed problem with searching selected blocks in histogram when selecting block from BlocksList widget
This commit is contained in:
Victor Zarubkin 2017-06-05 21:26:10 +03:00
parent 65ac892e32
commit 089fcf1e31
11 changed files with 221 additions and 189 deletions

View File

@ -1368,21 +1368,8 @@ void EasyGraphicsView::initMode()
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();
});
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::threadNameDecorationChanged, this, &This::onThreadViewChanged);
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::hexThreadIdChanged, this, &This::onThreadViewChanged);
connect(globalSignals, &::profiler_gui::EasyGlobalSignals::blocksTreeModeChanged, [this]()
{
@ -1393,6 +1380,24 @@ void EasyGraphicsView::initMode()
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsView::onThreadViewChanged()
{
if (m_bEmpty)
return;
for (auto item : m_items)
item->validateName();
emit treeChanged();
updateVisibleSceneRect();
onHierarchyFlagChange(EASY_GLOBALS.only_current_thread_hierarchy);
repaintScene();
}
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsView::onScrollbarValueChange(int)
{
if (!m_bUpdatingRect && !m_bEmpty)
@ -1675,7 +1680,14 @@ void EasyGraphicsView::onIdleTimeout()
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->addWidget(new QLabel(QString("%1 %2").arg(cse->tree.node->id()).arg(it->second.name()), widget), row, 1, 1, 2, Qt::AlignLeft);
{
if (EASY_GLOBALS.hex_thread_id)
lay->addWidget(new QLabel(QString("0x%1 %2").arg(cse->tree.node->id(), 0, 16).arg(it->second.name()), widget), row, 1, 1, 2, Qt::AlignLeft);
else
lay->addWidget(new QLabel(QString("%1 %2").arg(cse->tree.node->id()).arg(it->second.name()), widget), row, 1, 1, 2, Qt::AlignLeft);
}
else if (EASY_GLOBALS.hex_thread_id)
lay->addWidget(new QLabel(QString("0x%1").arg(cse->tree.node->id(), 0, 16), widget), row, 1, 1, 2, Qt::AlignLeft);
else
lay->addWidget(new QLabel(QString::number(cse->tree.node->id()), widget), row, 1, 1, 2, Qt::AlignLeft);
++row;

View File

@ -222,6 +222,7 @@ private slots:
void onSelectedThreadChange(::profiler::thread_id_t _id);
void onSelectedBlockChange(unsigned int _block_index);
void onRefreshRequired();
void onThreadViewChanged();
public:

View File

@ -96,7 +96,7 @@ 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_threadName(::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, _root, EASY_GLOBALS.hex_thread_id))
, m_pRoot(&_root)
, m_index(_index)
{
@ -108,7 +108,7 @@ EasyGraphicsItem::~EasyGraphicsItem()
void EasyGraphicsItem::validateName()
{
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, *m_pRoot);
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, *m_pRoot, EASY_GLOBALS.hex_thread_id);
}
const EasyGraphicsView* EasyGraphicsItem::view() const

View File

@ -253,6 +253,7 @@ EasyHistogramItem::EasyHistogramItem() : Parent(nullptr)
, m_workerImageScale(1)
, m_workerTopDuration(0)
, m_workerBottomDuration(0)
, m_blockTotalDuraion(0)
, m_timer(::std::bind(&This::onTimeout, this))
, m_boundaryTimer([this](){ updateImage(); }, true)
, m_pProfilerThread(nullptr)
@ -749,26 +750,15 @@ void EasyHistogramItem::paintById(QPainter* _painter)
_painter->setPen(Qt::black);
rect.setRect(0, bottom + 2, width, widget->defaultFontHeight());
const auto* item = !::profiler_gui::is_max(EASY_GLOBALS.selected_block) ? &easyBlock(EASY_GLOBALS.selected_block) : (!m_selectedBlocks.empty() ? &easyBlock(m_selectedBlocks.front()) : nullptr);
if (item != nullptr)
if (!m_selectedBlocks.empty())
{
const auto name = *item->tree.node->name() != 0 ? item->tree.node->name() : easyDescriptor(item->tree.node->id()).name();
if (item->tree.per_thread_stats != nullptr)
{
_painter->drawText(rect, Qt::AlignHCenter | Qt::TextDontClip, QString("%1 | %2 | %3 calls | %4% of thread profiled time").arg(m_threadName).arg(::profiler_gui::toUnicode(name))
.arg(item->tree.per_thread_stats->calls_number)
.arg(m_threadProfiledTime ? QString::number(100. * (double)item->tree.per_thread_stats->total_duration / (double)m_threadProfiledTime, 'f', 2) : QString("100")));
}
else
{
_painter->drawText(rect, Qt::AlignHCenter | Qt::TextDontClip, QString("%1 | %2 | %3 calls").arg(m_threadName).arg(::profiler_gui::toUnicode(name))
.arg(m_selectedBlocks.size()));
}
_painter->drawText(rect, Qt::AlignHCenter | Qt::TextDontClip, QString("%1 | %2 | %3 calls | %4% of thread profiled time")
.arg(m_threadName).arg(m_blockName).arg(m_selectedBlocks.size())
.arg(m_threadProfiledTime ? QString::number(100. * (double)m_blockTotalDuraion / (double)m_threadProfiledTime, 'f', 2) : QString("100")));
}
else
{
_painter->drawText(rect, Qt::AlignHCenter | Qt::TextDontClip, QString("%1 | %2 | %3 calls").arg(m_threadName).arg(::profiler_gui::toUnicode(easyDescriptor(m_blockId).name()))
.arg(m_selectedBlocks.size()));
_painter->drawText(rect, Qt::AlignHCenter | Qt::TextDontClip, QString("%1 | %2 | 0 calls").arg(m_threadName).arg(m_blockName));
}
_painter->drawText(rect, Qt::AlignLeft, bindMode ? " MODE: zoom" : " MODE: overview");
@ -803,13 +793,16 @@ void EasyHistogramItem::setSource(::profiler::thread_id_t _thread_id, const ::pr
if (m_workerThread.joinable())
m_workerThread.join();
m_blockName.clear();
m_blockTotalDuraion = 0;
delete m_workerImage;
m_workerImage = nullptr;
m_imageOriginUpdate = m_imageOrigin = 0;
m_imageScaleUpdate = m_imageScale = 1;
m_selectedBlocks.clear();
::profiler::BlocksTree::children_t().swap(m_selectedBlocks);
{ ::profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
m_bPermitImageUpdate = false;
m_regime = Hist_Pointer;
@ -826,7 +819,7 @@ void EasyHistogramItem::setSource(::profiler::thread_id_t _thread_id, const ::pr
else
{
const auto& root = EASY_GLOBALS.profiler_blocks[_thread_id];
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root);
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root, EASY_GLOBALS.hex_thread_id);
if (root.children.empty())
m_threadDuration = 0;
@ -918,9 +911,6 @@ void EasyHistogramItem::setSource(::profiler::thread_id_t _thread_id, ::profiler
m_bPermitImageUpdate = false; // Set to false because m_workerThread have to parse input data first. This will be set to true when m_workerThread finish - see onTimeout()
m_regime = Hist_Id;
m_pSource = nullptr;
m_topDurationStr.clear();
m_bottomDurationStr.clear();
m_timer.stop();
m_boundaryTimer.stop();
@ -929,138 +919,173 @@ void EasyHistogramItem::setSource(::profiler::thread_id_t _thread_id, ::profiler
if (m_workerThread.joinable())
m_workerThread.join();
m_pSource = nullptr;
m_topDurationStr.clear();
m_bottomDurationStr.clear();
m_blockName.clear();
m_blockTotalDuraion = 0;
delete m_workerImage;
m_workerImage = nullptr;
m_imageOriginUpdate = m_imageOrigin = 0;
m_imageScaleUpdate = m_imageScale = 1;
m_selectedBlocks.clear();
::profiler::BlocksTree::children_t().swap(m_selectedBlocks);
{ ::profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
m_threadId = _thread_id;
m_blockId = _block_id;
if (m_threadId != 0 && !::profiler_gui::is_max(m_blockId))
{
m_blockName = ::profiler_gui::toUnicode(easyDescriptor(m_blockId).name());
const auto& root = EASY_GLOBALS.profiler_blocks[_thread_id];
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root);
if (root.children.empty())
m_threadDuration = 0;
else
m_threadDuration = easyBlock(root.children.back()).tree.node->end() - easyBlock(root.children.front()).tree.node->begin();
m_threadProfiledTime = root.profiled_time;
m_threadWaitTime = root.wait_time;
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, root, EASY_GLOBALS.hex_thread_id);
m_pProfilerThread = &root;
m_timeUnits = EASY_GLOBALS.time_units;
m_bReady.store(false, ::std::memory_order_release);
m_workerThread = ::std::thread([this](decltype(root) profiler_thread)
if (root.children.empty())
{
typedef ::std::vector<::std::pair<::profiler::block_index_t, ::profiler::block_index_t> > Stack;
m_threadDuration = 0;
m_threadProfiledTime = 0;
m_threadWaitTime = 0;
m_maxDuration = 0;
m_minDuration = 1e30;
//const auto& profiler_thread = EASY_GLOBALS.profiler_blocks[m_threadId];
Stack stack;
stack.reserve(profiler_thread.depth);
m_topDuration = m_maxDuration = 0;
m_bottomDuration = m_minDuration = 1e30;
for (auto frame : profiler_thread.children)
m_bPermitImageUpdate = true;
m_bReady.store(true, ::std::memory_order_release);
}
else
{
m_threadDuration = easyBlock(root.children.back()).tree.node->end() - easyBlock(root.children.front()).tree.node->begin();
m_threadProfiledTime = root.profiled_time;
m_threadWaitTime = root.wait_time;
m_bReady.store(false, ::std::memory_order_release);
m_workerThread = ::std::thread([this](decltype(root) profiler_thread, ::profiler::block_index_t selected_block)
{
const auto& frame_block = easyBlock(frame).tree;
if (frame_block.node->id() == m_blockId)
typedef ::std::vector<::std::pair<::profiler::block_index_t, ::profiler::block_index_t> > Stack;
m_maxDuration = 0;
m_minDuration = 1e30;
//const auto& profiler_thread = EASY_GLOBALS.profiler_blocks[m_threadId];
Stack stack;
stack.reserve(profiler_thread.depth);
const bool has_selected_block = !::profiler_gui::is_max(selected_block);
for (auto frame : profiler_thread.children)
{
m_selectedBlocks.push_back(frame);
const auto& frame_block = easyBlock(frame).tree;
if (frame_block.node->id() == m_blockId || (!has_selected_block && m_blockId == easyDescriptor(frame_block.node->id()).id()))
{
m_selectedBlocks.push_back(frame);
const auto w = frame_block.node->duration();
if (w > m_maxDuration)
m_maxDuration = w;
const auto w = frame_block.node->duration();
if (w > m_maxDuration)
m_maxDuration = w;
if (w < m_minDuration)
m_minDuration = w;
}
if (w < m_minDuration)
m_minDuration = w;
stack.push_back(::std::make_pair(frame, 0U));
while (!stack.empty())
{
if (m_bReady.load(::std::memory_order_acquire))
return;
m_blockTotalDuraion += w;
}
auto& top = stack.back();
const auto& top_children = easyBlock(top.first).tree.children;
const auto stack_size = stack.size();
for (auto end = top_children.size(); top.second < end; ++top.second)
stack.push_back(::std::make_pair(frame, 0U));
while (!stack.empty())
{
if (m_bReady.load(::std::memory_order_acquire))
return;
const auto child_index = top_children[top.second];
const auto& child = easyBlock(child_index).tree;
if (child.node->id() == m_blockId)
auto& top = stack.back();
const auto& top_children = easyBlock(top.first).tree.children;
const auto stack_size = stack.size();
for (auto end = top_children.size(); top.second < end; ++top.second)
{
m_selectedBlocks.push_back(child_index);
if (m_bReady.load(::std::memory_order_acquire))
return;
const auto w = child.node->duration();
if (w > m_maxDuration)
m_maxDuration = w;
if (w < m_minDuration)
m_minDuration = w;
const auto child_index = top_children[top.second];
const auto& child = easyBlock(child_index).tree;
if (child.node->id() == m_blockId || (!has_selected_block && m_blockId == easyDescriptor(child.node->id()).id()))
{
m_selectedBlocks.push_back(child_index);
const auto w = child.node->duration();
if (w > m_maxDuration)
m_maxDuration = w;
if (w < m_minDuration)
m_minDuration = w;
m_blockTotalDuraion += w;
}
if (!child.children.empty())
{
++top.second;
stack.push_back(::std::make_pair(child_index, 0U));
break;
}
}
if (!child.children.empty())
if (stack_size == stack.size())
{
++top.second;
stack.push_back(::std::make_pair(child_index, 0U));
break;
stack.pop_back();
}
}
if (stack_size == stack.size())
{
stack.pop_back();
}
}
}
if (m_selectedBlocks.empty())
{
m_topDurationStr.clear();
m_bottomDurationStr.clear();
}
else
{
m_maxDuration *= 1e-3;
m_minDuration *= 1e-3;
if ((m_maxDuration - m_minDuration) < 1e-3)
if (m_selectedBlocks.empty())
{
if (m_minDuration > 0.1)
m_topDurationStr.clear();
m_bottomDurationStr.clear();
}
else
{
if (has_selected_block)
{
m_minDuration -= 0.1;
const auto& item = easyBlock(selected_block).tree;
if (*item.node->name() != 0)
m_blockName = ::profiler_gui::toUnicode(item.node->name());
}
else
m_maxDuration *= 1e-3;
m_minDuration *= 1e-3;
if ((m_maxDuration - m_minDuration) < 1e-3)
{
m_maxDuration = 0.1;
m_minDuration = 0;
if (m_minDuration > 0.1)
{
m_minDuration -= 0.1;
}
else
{
m_maxDuration = 0.1;
m_minDuration = 0;
}
}
m_topDurationStr = ::profiler_gui::timeStringReal(m_timeUnits, m_maxDuration, 3);
m_bottomDurationStr = ::profiler_gui::timeStringReal(m_timeUnits, m_minDuration, 3);
}
m_topDurationStr = ::profiler_gui::timeStringReal(m_timeUnits, m_maxDuration, 3);
m_bottomDurationStr = ::profiler_gui::timeStringReal(m_timeUnits, m_minDuration, 3);
}
m_topDuration = m_maxDuration;
m_bottomDuration = m_minDuration;
m_topDuration = m_maxDuration;
m_bottomDuration = m_minDuration;
m_bReady.store(true, ::std::memory_order_release);
m_bReady.store(true, ::std::memory_order_release);
}, std::ref(root), EASY_GLOBALS.selected_block);
}, std::ref(root));
m_timeouts = 3;
m_timer.start(WORKER_THREAD_CHECK_INTERVAL);
}
m_timeouts = 3;
m_timer.start(WORKER_THREAD_CHECK_INTERVAL);
show();
}
else
@ -1077,7 +1102,7 @@ void EasyHistogramItem::validateName()
{
if (m_threadName.isEmpty())
return;
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.profiler_blocks[m_threadId]);
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.profiler_blocks[m_threadId], EASY_GLOBALS.hex_thread_id);
}
//////////////////////////////////////////////////////////////////////////
@ -1712,14 +1737,8 @@ EasyGraphicsScrollbar::EasyGraphicsScrollbar(QWidget* _parent)
m_histogramItem->onModeChanged();
});
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::threadNameDecorationChanged, [this]()
{
if (m_histogramItem->isVisible())
{
m_histogramItem->validateName();
scene()->update();
}
});
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::threadNameDecorationChanged, this, &This::onThreadViewChanged);
connect(&EASY_GLOBALS.events, &::profiler_gui::EasyGlobalSignals::hexThreadIdChanged, this, &This::onThreadViewChanged);
centerOn(0, 0);
}
@ -1731,6 +1750,17 @@ EasyGraphicsScrollbar::~EasyGraphicsScrollbar()
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsScrollbar::onThreadViewChanged()
{
if (m_histogramItem->isVisible())
{
m_histogramItem->validateName();
scene()->update();
}
}
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsScrollbar::clear()
{
setHistogramSource(0, nullptr);
@ -2003,54 +2033,6 @@ void EasyGraphicsScrollbar::resizeEvent(QResizeEvent* _event)
m_histogramItem->updateImage();
}
//////////////////////////////////////////////////////////////////////////
/*
void EasyGraphicsScrollbar::contextMenuEvent(QContextMenuEvent* _event)
{
if (EASY_GLOBALS.profiler_blocks.empty())
{
return;
}
QMenu menu;
for (const auto& it : EASY_GLOBALS.profiler_blocks)
{
QString label;
if (it.second.got_name())
label = ::std::move(QString("%1 Thread %2").arg(it.second.name()).arg(it.first));
else
label = ::std::move(QString("Thread %1").arg(it.first));
auto action = new QAction(label, nullptr);
action->setData(it.first);
action->setCheckable(true);
action->setChecked(it.first == EASY_GLOBALS.selected_thread);
connect(action, &QAction::triggered, this, &This::onThreadActionClicked);
menu.addAction(action);
}
menu.exec(QCursor::pos());
_event->accept();
}
*/
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsScrollbar::onThreadActionClicked(bool)
{
auto action = qobject_cast<QAction*>(sender());
if (action == nullptr)
return;
const auto thread_id = action->data().toUInt();
if (thread_id != EASY_GLOBALS.selected_thread)
{
EASY_GLOBALS.selected_thread = thread_id;
emit EASY_GLOBALS.events.selectedThreadChanged(thread_id);
}
}
//////////////////////////////////////////////////////////////////////////
void EasyGraphicsScrollbar::onWindowWidthChange(qreal _width)

View File

@ -157,9 +157,11 @@ class EasyHistogramItem : public QGraphicsItem
qreal m_workerImageScale;
qreal m_workerTopDuration;
qreal m_workerBottomDuration;
::profiler::timestamp_t m_blockTotalDuraion;
QString m_topDurationStr;
QString m_bottomDurationStr;
QString m_threadName;
QString m_blockName;
::profiler::BlocksTree::children_t m_selectedBlocks;
QImage m_mainImage;
EasyQTimer m_timer;
@ -270,7 +272,6 @@ public:
void mouseMoveEvent(QMouseEvent* _event) override;
void wheelEvent(QWheelEvent* _event) override;
void resizeEvent(QResizeEvent* _event) override;
//void contextMenuEvent(QContextMenuEvent* _event) override;
void dragEnterEvent(QDragEnterEvent*) override {}
@ -325,7 +326,7 @@ signals:
private slots:
void onThreadActionClicked(bool);
void onThreadViewChanged();
void onWindowWidthChange(qreal _width);
}; // END of class EasyGraphicsScrollbar.

View File

@ -84,6 +84,7 @@ namespace profiler_gui {
, connected(false)
, fps_enabled(true)
, use_decorated_thread_name(false)
, hex_thread_id(false)
, enable_event_markers(true)
, enable_statistics(true)
, enable_zero_length(true)

View File

@ -101,29 +101,47 @@ namespace profiler_gui {
//////////////////////////////////////////////////////////////////////////
inline QString decoratedThreadName(bool _use_decorated_thread_name, const::profiler::BlocksTreeRoot& _root, const QString& _unicodeThreadWord)
inline QString decoratedThreadName(bool _use_decorated_thread_name, const::profiler::BlocksTreeRoot& _root, const QString& _unicodeThreadWord, bool _hex = false)
{
if (_root.got_name())
{
QString rootname(toUnicode(_root.name()));
if (!_use_decorated_thread_name || rootname.contains(_unicodeThreadWord, Qt::CaseInsensitive))
{
if (_hex)
return QString("%1 0x%2").arg(rootname).arg(_root.thread_id, 0, 16);
return QString("%1 %2").arg(rootname).arg(_root.thread_id);
}
if (_hex)
return QString("%1 Thread 0x%2").arg(rootname).arg(_root.thread_id, 0, 16);
return QString("%1 Thread %2").arg(rootname).arg(_root.thread_id);
}
if (_hex)
return QString("Thread 0x%1").arg(_root.thread_id, 0, 16);
return QString("Thread %1").arg(_root.thread_id);
}
inline QString decoratedThreadName(bool _use_decorated_thread_name, const ::profiler::BlocksTreeRoot& _root)
inline QString decoratedThreadName(bool _use_decorated_thread_name, const ::profiler::BlocksTreeRoot& _root, bool _hex = false)
{
if (_root.got_name())
{
QString rootname(toUnicode(_root.name()));
if (!_use_decorated_thread_name || rootname.contains(toUnicode("thread"), Qt::CaseInsensitive))
{
if (_hex)
return QString("%1 0x%2").arg(rootname).arg(_root.thread_id, 0, 16);
return QString("%1 %2").arg(rootname).arg(_root.thread_id);
}
if (_hex)
return QString("%1 Thread 0x%2").arg(rootname).arg(_root.thread_id, 0, 16);
return QString("%1 Thread %2").arg(rootname).arg(_root.thread_id);
}
if (_hex)
return QString("Thread 0x%1").arg(_root.thread_id, 0, 16);
return QString("Thread %1").arg(_root.thread_id);
}
@ -163,6 +181,7 @@ namespace profiler_gui {
bool connected; ///< Is connected to source (to be able to capture profiling information)
bool fps_enabled; ///< Is FPS Monitor enabled
bool use_decorated_thread_name; ///< Add "Thread" to the name of each thread (if there is no one)
bool hex_thread_id; ///< Use hex view for thread-id instead of decimal
bool enable_event_markers; ///< 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

@ -82,6 +82,7 @@ namespace profiler_gui {
void autoAdjustHistogramChanged();
void hierarchyFlagChanged(bool);
void threadNameDecorationChanged();
void hexThreadIdChanged();
void refreshRequired();
void blocksTreeModeChanged();

View File

@ -385,6 +385,16 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_lastAddress("localhost"), m_lastP
emit EASY_GLOBALS.events.threadNameDecorationChanged();
});
action = submenu->addAction("Display hex thread id");
action->setToolTip("Display hex thread id instead of decimal.");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.hex_thread_id);
connect(action, &QAction::triggered, [this](bool _checked)
{
EASY_GLOBALS.hex_thread_id = _checked;
emit EASY_GLOBALS.events.hexThreadIdChanged();
});
submenu->addSeparator();
auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true);
@ -1264,6 +1274,10 @@ void EasyMainWindow::loadSettings()
if (!flag.isNull())
EASY_GLOBALS.use_decorated_thread_name = flag.toBool();
flag = settings.value("hex_thread_id");
if (!flag.isNull())
EASY_GLOBALS.hex_thread_id = flag.toBool();
flag = settings.value("fps_timer_interval");
if (!flag.isNull())
EASY_GLOBALS.fps_timer_interval = flag.toInt();
@ -1334,6 +1348,7 @@ void EasyMainWindow::saveSettingsAndGeometry()
settings.setValue("enable_event_indicators", EASY_GLOBALS.enable_event_markers);
settings.setValue("auto_adjust_histogram_height", EASY_GLOBALS.auto_adjust_histogram_height);
settings.setValue("use_decorated_thread_name", EASY_GLOBALS.use_decorated_thread_name);
settings.setValue("hex_thread_id", EASY_GLOBALS.hex_thread_id);
settings.setValue("enable_statistics", EASY_GLOBALS.enable_statistics);
settings.setValue("fps_timer_interval", EASY_GLOBALS.fps_timer_interval);
settings.setValue("max_fps_history", EASY_GLOBALS.max_fps_history);

View File

@ -176,7 +176,7 @@ void EasyTreeWidgetLoader::fillTree(::profiler::timestamp_t& _beginTime, const u
m_mode = _mode;
m_thread = ::std::thread(&EasyTreeWidgetLoader::setTreeInternal1, this,
::std::ref(_beginTime), _blocksNumber, ::std::ref(_blocksTree), _colorizeRows,
EASY_GLOBALS.add_zero_blocks_to_hierarchy, EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.time_units);
EASY_GLOBALS.add_zero_blocks_to_hierarchy, EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.hex_thread_id, EASY_GLOBALS.time_units);
}
void EasyTreeWidgetLoader::fillTreeBlocks(const::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _beginTime, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, EasyTreeMode _mode)
@ -185,12 +185,12 @@ void EasyTreeWidgetLoader::fillTreeBlocks(const::profiler_gui::TreeBlocks& _bloc
m_mode = _mode;
m_thread = ::std::thread(&EasyTreeWidgetLoader::setTreeInternal2, this,
_beginTime, ::std::ref(_blocks), _left, _right, _strict, _colorizeRows,
EASY_GLOBALS.add_zero_blocks_to_hierarchy, EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.time_units);
EASY_GLOBALS.add_zero_blocks_to_hierarchy, EASY_GLOBALS.use_decorated_thread_name, EASY_GLOBALS.hex_thread_id, EASY_GLOBALS.time_units);
}
//////////////////////////////////////////////////////////////////////////
void EasyTreeWidgetLoader::setTreeInternal1(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, ::profiler_gui::TimeUnits _units)
void EasyTreeWidgetLoader::setTreeInternal1(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, bool _hexThreadId, ::profiler_gui::TimeUnits _units)
{
m_items.reserve(_blocksNumber + _blocksTree.size()); // _blocksNumber does not include Thread root blocks
@ -219,7 +219,7 @@ void EasyTreeWidgetLoader::setTreeInternal1(::profiler::timestamp_t& _beginTime,
const auto& root = threadTree.second;
auto item = new EasyTreeWidgetItem();
item->setText(COL_NAME, ::profiler_gui::decoratedThreadName(_decoratedThreadNames, root, u_thread));
item->setText(COL_NAME, ::profiler_gui::decoratedThreadName(_decoratedThreadNames, root, u_thread, _hexThreadId));
::profiler::timestamp_t duration = 0;
if (!root.children.empty())
@ -268,7 +268,7 @@ void EasyTreeWidgetLoader::setTreeInternal1(::profiler::timestamp_t& _beginTime,
typedef ::std::unordered_map<::profiler::thread_id_t, ::profiler::block_index_t, ::profiler_gui::do_no_hash<::profiler::thread_id_t>::hasher_t> BeginEndIndicesMap;
void EasyTreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, ::profiler_gui::TimeUnits _units)
void EasyTreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, bool _hexThreadId, ::profiler_gui::TimeUnits _units)
{
//size_t blocksNumber = 0;
//for (const auto& block : _blocks)
@ -309,7 +309,7 @@ void EasyTreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _begi
else
{
thread_item = new EasyTreeWidgetItem();
thread_item->setText(COL_NAME, ::profiler_gui::decoratedThreadName(_decoratedThreadNames, *block.root, u_thread));
thread_item->setText(COL_NAME, ::profiler_gui::decoratedThreadName(_decoratedThreadNames, *block.root, u_thread, _hexThreadId));
if (!block.root->children.empty())
duration = blocksTree(block.root->children.back()).node->end() - blocksTree(block.root->children.front()).node->begin();

View File

@ -122,8 +122,8 @@ private:
void setDone();
void setProgress(int _progress);
void setTreeInternal1(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, ::profiler_gui::TimeUnits _units);
void setTreeInternal2(const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, ::profiler_gui::TimeUnits _units);
void setTreeInternal1(::profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, bool _hexThreadId, ::profiler_gui::TimeUnits _units);
void setTreeInternal2(const ::profiler::timestamp_t& _beginTime, const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, bool _colorizeRows, bool _addZeroBlocks, bool _decoratedThreadNames, bool _hexThreadId, ::profiler_gui::TimeUnits _units);
size_t setTreeInternal(const ::profiler::BlocksTreeRoot& _threadRoot, ::profiler::block_index_t _firstCswitch, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows, bool _addZeroBlocks, ::profiler_gui::TimeUnits _units);
size_t setTreeInternalPlain(const ::profiler::BlocksTreeRoot& _threadRoot, ::profiler::block_index_t _firstCswitch, const ::profiler::timestamp_t& _beginTime, const ::profiler::BlocksTree::children_t& _children, EasyTreeWidgetItem* _parent, EasyTreeWidgetItem* _frame, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict, ::profiler::timestamp_t& _duration, bool _colorizeRows, bool _addZeroBlocks, ::profiler_gui::TimeUnits _units);