mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 00:31:02 +08:00
# [UI] Styles and refactoring
This commit is contained in:
parent
91b2a4e609
commit
983085157e
@ -42,6 +42,8 @@ if (Qt5Widgets_FOUND)
|
||||
graphics_slider_area.cpp
|
||||
main_window.h
|
||||
main_window.cpp
|
||||
round_progress_widget.h
|
||||
round_progress_widget.cpp
|
||||
timer.h
|
||||
timer.cpp
|
||||
thread_pool.h
|
||||
|
@ -93,8 +93,8 @@ const qreal MAX_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT, 45); // ~23000
|
||||
const qreal BASE_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT_INV, 25); // ~0.003
|
||||
|
||||
EASY_CONSTEXPR QRgb BACKGROUND_1 = 0xffe4e4ec;
|
||||
EASY_CONSTEXPR QRgb BACKGROUND_2 = ::profiler::colors::White;
|
||||
EASY_CONSTEXPR QRgb TIMELINE_BACKGROUND = 0x20000000 | (::profiler::colors::Grey800 & 0x00ffffff);// 0x20303030;
|
||||
EASY_CONSTEXPR QRgb BACKGROUND_2 = profiler::colors::White;
|
||||
EASY_CONSTEXPR QRgb TIMELINE_BACKGROUND = 0x20000000 | (profiler::colors::Grey800 & 0x00ffffff);// 0x20303030;
|
||||
EASY_CONSTEXPR QRgb TIMELINE_BORDER = 0xffa8a0a0;
|
||||
|
||||
EASY_CONSTEXPR int IDLE_TIMER_INTERVAL = 200; // 5Hz
|
||||
@ -284,7 +284,7 @@ void TimelineIndicatorItem::paint(QPainter* _painter, const QStyleOptionGraphics
|
||||
|
||||
BlocksGraphicsView::BlocksGraphicsView(QWidget* _parent)
|
||||
: Parent(_parent)
|
||||
, m_beginTime(::std::numeric_limits<decltype(m_beginTime)>::max())
|
||||
, m_beginTime(std::numeric_limits<decltype(m_beginTime)>::max())
|
||||
, m_sceneWidth(0)
|
||||
, m_scale(1)
|
||||
, m_offset(0)
|
||||
@ -380,7 +380,7 @@ void BlocksGraphicsView::clear()
|
||||
m_items.clear();
|
||||
m_selectedBlocks.clear();
|
||||
|
||||
m_beginTime = ::std::numeric_limits<decltype(m_beginTime)>::max(); // reset begin time
|
||||
m_beginTime = std::numeric_limits<decltype(m_beginTime)>::max(); // reset begin time
|
||||
m_scale = 1; // scale back to initial 100% scale
|
||||
m_timelineStep = 1;
|
||||
m_offset = 0; // scroll back to the beginning of the scene
|
||||
@ -448,7 +448,7 @@ void BlocksGraphicsView::notifyVisibleRegionPosChange(qreal _pos)
|
||||
notifyVisibleRegionPosChange();
|
||||
}
|
||||
|
||||
void BlocksGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocksTree)
|
||||
void BlocksGraphicsView::setTree(const profiler::thread_blocks_tree_t& _blocksTree)
|
||||
{
|
||||
// clear scene
|
||||
clear();
|
||||
@ -464,8 +464,8 @@ void BlocksGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocks
|
||||
// calculate scene size and fill it with items
|
||||
|
||||
// Calculating start and end time
|
||||
::profiler::timestamp_t finish = 0, busyTime = 0;
|
||||
::profiler::thread_id_t longestTree = 0, mainTree = 0;
|
||||
profiler::timestamp_t finish = 0, busyTime = 0;
|
||||
profiler::thread_id_t longestTree = 0, mainTree = 0;
|
||||
for (const auto& threadTree : _blocksTree)
|
||||
{
|
||||
const auto& t = threadTree.second;
|
||||
@ -476,12 +476,12 @@ void BlocksGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocks
|
||||
if (!t.children.empty())
|
||||
timestart = easyBlocksTree(t.children.front()).node->begin();
|
||||
if (!t.sync.empty())
|
||||
timestart = ::std::min(timestart, easyBlocksTree(t.sync.front()).node->begin());
|
||||
timestart = std::min(timestart, easyBlocksTree(t.sync.front()).node->begin());
|
||||
|
||||
if (!t.children.empty())
|
||||
timefinish = easyBlocksTree(t.children.back()).node->end();
|
||||
if (!t.sync.empty())
|
||||
timefinish = ::std::max(timefinish, easyBlocksTree(t.sync.back()).node->end());
|
||||
timefinish = std::max(timefinish, easyBlocksTree(t.sync.back()).node->end());
|
||||
|
||||
if (m_beginTime > timestart)
|
||||
m_beginTime = timestart;
|
||||
@ -500,15 +500,15 @@ void BlocksGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocks
|
||||
|
||||
const decltype(m_beginTime) additional_offset = (finish - m_beginTime) / 20; // Additional 5% before first block and after last block
|
||||
finish += additional_offset;
|
||||
m_beginTime -= ::std::min(m_beginTime, additional_offset);
|
||||
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;
|
||||
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) {
|
||||
sorted_roots.emplace_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;
|
||||
});
|
||||
|
||||
@ -519,7 +519,7 @@ void BlocksGraphicsView::setTree(const ::profiler::thread_blocks_tree_t& _blocks
|
||||
m_items.reserve(_blocksTree.size());
|
||||
qreal y = EASY_GLOBALS.size.timeline_height;
|
||||
const GraphicsBlockItem *longestItem = nullptr, *mainThreadItem = nullptr;
|
||||
for (const ::profiler::BlocksTreeRoot& t : sorted_roots)
|
||||
for (const profiler::BlocksTreeRoot& t : sorted_roots)
|
||||
{
|
||||
if (m_items.size() == 0xff)
|
||||
{
|
||||
@ -635,7 +635,7 @@ bool BlocksGraphicsView::getSelectionRegionForSaving(profiler::timestamp_t& _beg
|
||||
return true;
|
||||
}
|
||||
|
||||
qreal BlocksGraphicsView::setTree(GraphicsBlockItem* _item, const ::profiler::BlocksTree::children_t& _children, qreal& _height, uint32_t& _maxDepthChild, qreal _y, short _level)
|
||||
qreal BlocksGraphicsView::setTree(GraphicsBlockItem* _item, const profiler::BlocksTree::children_t& _children, qreal& _height, uint32_t& _maxDepthChild, qreal _y, short _level)
|
||||
{
|
||||
if (_children.empty())
|
||||
{
|
||||
@ -1063,7 +1063,7 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
|
||||
}
|
||||
|
||||
const ::profiler_gui::EasyBlock* selectedBlock = nullptr;
|
||||
::profiler::thread_id_t selectedBlockThread = 0;
|
||||
profiler::thread_id_t selectedBlockThread = 0;
|
||||
const auto previouslySelectedBlock = EASY_GLOBALS.selected_block;
|
||||
if (m_mouseButtons & Qt::LeftButton)
|
||||
{
|
||||
@ -1096,7 +1096,7 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
|
||||
// Try to select one of item blocks
|
||||
for (auto item : m_items)
|
||||
{
|
||||
::profiler::block_index_t i = ~0U;
|
||||
profiler::block_index_t i = ~0U;
|
||||
auto block = item->intersect(mouseClickPos, i);
|
||||
if (block != nullptr)
|
||||
{
|
||||
@ -1558,7 +1558,7 @@ void BlocksGraphicsView::initMode()
|
||||
setTree(EASY_GLOBALS.profiler_blocks);
|
||||
});
|
||||
|
||||
connect(globalSignals, &GlobalSignals::selectedBlockIdChanged, [this](::profiler::block_id_t)
|
||||
connect(globalSignals, &GlobalSignals::selectedBlockIdChanged, [this](profiler::block_id_t)
|
||||
{
|
||||
if (profiler_gui::is_max(EASY_GLOBALS.selected_block_id))
|
||||
{
|
||||
@ -1747,7 +1747,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
lay->addWidget(new QLabel("Thread:", widget), row, 0, Qt::AlignRight);
|
||||
|
||||
const char* process_name = "";
|
||||
::profiler::thread_id_t tid = 0;
|
||||
profiler::thread_id_t tid = 0;
|
||||
if (EASY_GLOBALS.version < ::profiler_gui::V130)
|
||||
{
|
||||
tid = cse->tree.node->id();
|
||||
@ -1797,10 +1797,10 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
|
||||
lay->addWidget(new QLabel("Thread", widget), row + 1, 1, Qt::AlignHCenter);
|
||||
|
||||
auto percent = ::profiler_gui::percentReal(duration, item->root()->profiled_time);
|
||||
auto percent = ::profiler_gui::percentReal(duration, item->root().profiled_time);
|
||||
lay->addWidget(new QLabel(0.005 < percent && percent < 0.5001 ? QString::number(percent, 'f', 2) : QString::number(static_cast<int>(0.5 + percent)), widget), row + 2, 1, Qt::AlignHCenter);
|
||||
|
||||
lay->addWidget(new QLabel(QString::number(::profiler_gui::percent(itemBlock.per_thread_stats->total_duration, item->root()->profiled_time)), widget), row + 3, 1, Qt::AlignHCenter);
|
||||
lay->addWidget(new QLabel(QString::number(::profiler_gui::percent(itemBlock.per_thread_stats->total_duration, item->root().profiled_time)), widget), row + 3, 1, Qt::AlignHCenter);
|
||||
|
||||
lay->addWidget(new QLabel(QString::number(itemBlock.per_thread_stats->calls_number), widget), row + 4, 1, Qt::AlignHCenter);
|
||||
|
||||
@ -1826,7 +1826,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
break;
|
||||
}
|
||||
|
||||
::profiler::block_index_t i = ~0U;
|
||||
profiler::block_index_t i = ~0U;
|
||||
auto block = item->intersect(pos, i);
|
||||
if (block != nullptr)
|
||||
{
|
||||
@ -1855,7 +1855,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
int row = 0;
|
||||
switch (itemDesc.type())
|
||||
{
|
||||
case ::profiler::BlockType::Block:
|
||||
case profiler::BlockType::Block:
|
||||
{
|
||||
const auto name = *itemBlock.node->name() != 0 ? itemBlock.node->name() : itemDesc.name();
|
||||
|
||||
@ -1870,7 +1870,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
widget), row, 1, 1, 3, Qt::AlignLeft);
|
||||
++row;
|
||||
|
||||
::profiler::timestamp_t children_duration = 0;
|
||||
profiler::timestamp_t children_duration = 0;
|
||||
for (auto child : itemBlock.children)
|
||||
children_duration += easyBlock(child).tree.node->duration();
|
||||
|
||||
@ -1888,7 +1888,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
break;
|
||||
}
|
||||
|
||||
case ::profiler::BlockType::Event:
|
||||
case profiler::BlockType::Event:
|
||||
{
|
||||
const auto name = *itemBlock.node->name() != 0 ? itemBlock.node->name() : itemDesc.name();
|
||||
|
||||
@ -1902,7 +1902,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
break;
|
||||
}
|
||||
|
||||
case ::profiler::BlockType::Value:
|
||||
case profiler::BlockType::Value:
|
||||
{
|
||||
lay->addWidget(new BoldLabel("Arbitrary Value", widget), row, 0, 1, 2, Qt::AlignHCenter);
|
||||
++row;
|
||||
@ -1931,7 +1931,7 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
|
||||
if (itemBlock.per_thread_stats != nullptr)
|
||||
{
|
||||
if (itemDesc.type() == ::profiler::BlockType::Block)
|
||||
if (itemDesc.type() == profiler::BlockType::Block)
|
||||
{
|
||||
const auto duration = itemBlock.node->duration();
|
||||
|
||||
@ -1941,29 +1941,30 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
|
||||
// Calculate idle/active time
|
||||
{
|
||||
auto threadRoot = item->root();
|
||||
const auto& threadRoot = item->root();
|
||||
|
||||
::profiler::block_index_t ind = 0;
|
||||
auto it = ::std::lower_bound(threadRoot->sync.begin(), threadRoot->sync.end(), itemBlock.node->begin(), [](::profiler::block_index_t _cs_index, ::profiler::timestamp_t _val)
|
||||
profiler::block_index_t ind = 0;
|
||||
auto it = std::lower_bound(threadRoot.sync.begin(), threadRoot.sync.end(), itemBlock.node->begin(),
|
||||
[](profiler::block_index_t _cs_index, profiler::timestamp_t _val)
|
||||
{
|
||||
return EASY_GLOBALS.gui_blocks[_cs_index].tree.node->begin() < _val;
|
||||
});
|
||||
|
||||
if (it != threadRoot->sync.end())
|
||||
if (it != threadRoot.sync.end())
|
||||
{
|
||||
ind = static_cast<::profiler::block_index_t>(it - threadRoot->sync.begin());
|
||||
ind = static_cast<profiler::block_index_t>(it - threadRoot.sync.begin());
|
||||
if (ind > 0)
|
||||
--ind;
|
||||
}
|
||||
else
|
||||
{
|
||||
ind = static_cast<::profiler::block_index_t>(threadRoot->sync.size());
|
||||
ind = static_cast<profiler::block_index_t>(threadRoot.sync.size());
|
||||
}
|
||||
|
||||
::profiler::timestamp_t idleTime = 0;
|
||||
for (auto ncs = static_cast<::profiler::block_index_t>(threadRoot->sync.size()); ind < ncs; ++ind)
|
||||
profiler::timestamp_t idleTime = 0;
|
||||
for (auto ncs = static_cast<profiler::block_index_t>(threadRoot.sync.size()); ind < ncs; ++ind)
|
||||
{
|
||||
auto cs_index = threadRoot->sync[ind];
|
||||
auto cs_index = threadRoot.sync[ind];
|
||||
const auto cs = EASY_GLOBALS.gui_blocks[cs_index].tree.node;
|
||||
|
||||
if (cs->begin() > itemBlock.node->end())
|
||||
@ -1989,12 +1990,12 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
|
||||
lay->addWidget(new QLabel("Thread", widget), row + 1, 1, Qt::AlignHCenter);
|
||||
|
||||
auto percent = ::profiler_gui::percentReal(duration, item->root()->profiled_time);
|
||||
auto percent = ::profiler_gui::percentReal(duration, item->root().profiled_time);
|
||||
lay->addWidget(new QLabel(0.005 < percent && percent < 0.5001 ? QString::number(percent, 'f', 2) : QString::number(static_cast<int>(0.5 + percent)), widget), row + 2, 1, Qt::AlignHCenter);
|
||||
|
||||
lay->addWidget(new QLabel(QString::number(::profiler_gui::percent(itemBlock.per_thread_stats->total_duration, item->root()->profiled_time)), widget), row + 3, 1, Qt::AlignHCenter);
|
||||
lay->addWidget(new QLabel(QString::number(::profiler_gui::percent(itemBlock.per_thread_stats->total_duration, item->root().profiled_time)), widget), row + 3, 1, Qt::AlignHCenter);
|
||||
|
||||
lay->addWidget(new QLabel(QString::number(::profiler_gui::percent(itemBlock.per_thread_stats->total_duration - itemBlock.per_thread_stats->total_children_duration, item->root()->profiled_time)), widget), row + 4, 1, Qt::AlignHCenter);
|
||||
lay->addWidget(new QLabel(QString::number(::profiler_gui::percent(itemBlock.per_thread_stats->total_duration - itemBlock.per_thread_stats->total_children_duration, item->root().profiled_time)), widget), row + 4, 1, Qt::AlignHCenter);
|
||||
|
||||
lay->addWidget(new QLabel(QString::number(itemBlock.per_thread_stats->calls_number), widget), row + 5, 1, Qt::AlignHCenter);
|
||||
|
||||
@ -2067,10 +2068,10 @@ void BlocksGraphicsView::onIdleTimeout()
|
||||
|
||||
auto br = m_popupWidget->rect();
|
||||
if (scenePos.y() + br.height() > m_visibleSceneRect.bottom())
|
||||
scenePos.setY(::std::max(scenePos.y() - br.height(), m_visibleSceneRect.top()));
|
||||
scenePos.setY(std::max(scenePos.y() - br.height(), m_visibleSceneRect.top()));
|
||||
|
||||
if (scenePos.x() + br.width() > m_visibleSceneRect.right())
|
||||
scenePos.setX(::std::max(scenePos.x() - br.width(), m_visibleSceneRect.left()));
|
||||
scenePos.setX(std::max(scenePos.x() - br.width(), m_visibleSceneRect.left()));
|
||||
|
||||
if ((scenePos - prevPos).manhattanLength() != 0)
|
||||
m_popupWidget->move(mapToGlobal(mapFromScene(scenePos)));
|
||||
@ -2109,7 +2110,7 @@ void BlocksGraphicsView::onHierarchyFlagChange(bool)
|
||||
}
|
||||
}
|
||||
|
||||
void BlocksGraphicsView::onSelectedThreadChange(::profiler::thread_id_t _id)
|
||||
void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t _id)
|
||||
{
|
||||
if (m_pScrollbar == nullptr || m_pScrollbar->hystThread() == _id)
|
||||
{
|
||||
@ -2414,7 +2415,7 @@ ThreadNamesWidget::ThreadNamesWidget(BlocksGraphicsView* _view, int _additionalH
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setFixedWidth(m_maxLength);
|
||||
|
||||
connect(&EASY_GLOBALS.events, &::profiler_gui::GlobalSignals::selectedThreadChanged, [this](::profiler::thread_id_t){ repaintScene(); });
|
||||
connect(&EASY_GLOBALS.events, &::profiler_gui::GlobalSignals::selectedThreadChanged, [this](profiler::thread_id_t){ repaintScene(); });
|
||||
connect(&EASY_GLOBALS.events, &::profiler_gui::GlobalSignals::allDataGoingToBeDeleted, this, &This::clear);
|
||||
|
||||
connect(m_view, &BlocksGraphicsView::treeChanged, this, &This::onTreeChange);
|
||||
@ -2477,7 +2478,7 @@ void ThreadNamesWidget::onTreeChange()
|
||||
qreal maxLength = 100;
|
||||
const auto& graphicsItems = m_view->getItems();
|
||||
for (auto graphicsItem : graphicsItems)
|
||||
maxLength = ::std::max(maxLength, (10 + fm.width(graphicsItem->threadName())) * ::profiler_gui::FONT_METRICS_FACTOR);
|
||||
maxLength = std::max(maxLength, (10 + fm.width(graphicsItem->threadName())) * ::profiler_gui::FONT_METRICS_FACTOR);
|
||||
|
||||
auto vbar = verticalScrollBar();
|
||||
auto viewBar = m_view->verticalScrollBar();
|
||||
@ -2582,8 +2583,8 @@ void ThreadNamesWidget::onIdleTimeout()
|
||||
lay->addWidget(new BoldLabel(intersectingItem->threadName(), widget), row, 0, 1, 2, Qt::AlignHCenter);
|
||||
++row;
|
||||
|
||||
::profiler::timestamp_t duration = 0;
|
||||
const auto& root = *intersectingItem->root();
|
||||
profiler::timestamp_t duration = 0;
|
||||
const auto& root = intersectingItem->root();
|
||||
if (!root.children.empty())
|
||||
duration = easyBlock(root.children.back()).tree.node->end() - easyBlock(root.children.front()).tree.node->begin();
|
||||
|
||||
@ -2649,10 +2650,10 @@ void ThreadNamesWidget::onIdleTimeout()
|
||||
}
|
||||
|
||||
if (scenePos.y() + br.height() > visibleSceneRect.bottom())
|
||||
scenePos.setY(::std::max(scenePos.y() - br.height(), visibleSceneRect.top()));
|
||||
scenePos.setY(std::max(scenePos.y() - br.height(), visibleSceneRect.top()));
|
||||
|
||||
if (scenePos.x() + br.width() > visibleSceneRect.right())
|
||||
scenePos.setX(::std::max(scenePos.x() - br.width(), visibleSceneRect.left()));
|
||||
scenePos.setX(std::max(scenePos.x() - br.width(), visibleSceneRect.left()));
|
||||
|
||||
m_popupWidget->setPos(scenePos.x(), scenePos.y() - visibleSceneRect.top());
|
||||
}
|
||||
|
@ -64,23 +64,25 @@
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QActionGroup>
|
||||
#include <QHeaderView>
|
||||
#include <QApplication>
|
||||
#include <QByteArray>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QSignalBlocker>
|
||||
#include <QSettings>
|
||||
#include <QDebug>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMoveEvent>
|
||||
#include <QProgressDialog>
|
||||
#include <QResizeEvent>
|
||||
#include <QMoveEvent>
|
||||
#include <QLineEdit>
|
||||
#include <QLabel>
|
||||
#include <QScrollBar>
|
||||
#include <QSettings>
|
||||
#include <QSignalBlocker>
|
||||
#include <QToolBar>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include "blocks_tree_widget.h"
|
||||
#include "arbitrary_value_tooltip.h"
|
||||
#include "round_progress_widget.h"
|
||||
#include "globals.h"
|
||||
#include "thread_pool.h"
|
||||
|
||||
@ -139,6 +141,7 @@ BlocksTreeWidget::BlocksTreeWidget(QWidget* _parent)
|
||||
, m_mode(TreeMode::Plain)
|
||||
, m_bLocked(false)
|
||||
, m_bSilentExpandCollapse(false)
|
||||
, m_bInitialized(false)
|
||||
{
|
||||
installEventFilter(this);
|
||||
memset(m_columnsHiddenStatus, 0, sizeof(m_columnsHiddenStatus));
|
||||
@ -254,9 +257,10 @@ BlocksTreeWidget::BlocksTreeWidget(QWidget* _parent)
|
||||
}
|
||||
}
|
||||
|
||||
m_hintLabel = new QLabel("Use Right Mouse Button on the Diagram to build a hierarchy...\nPress and hold, move, release", this);
|
||||
m_hintLabel = new QLabel("Use Right Mouse Button on the Diagram to build a hierarchy...\n"
|
||||
"Press and hold the button >> Move mouse >> Release the button", this);
|
||||
m_hintLabel->setObjectName(QStringLiteral("BlocksTreeWidget_HintLabel"));
|
||||
m_hintLabel->setAlignment(Qt::AlignCenter);
|
||||
m_hintLabel->setStyleSheet("QLabel { color: gray; font: 12pt; }");
|
||||
|
||||
QTimer::singleShot(1500, this, &This::alignProgressBar);
|
||||
|
||||
@ -273,9 +277,14 @@ BlocksTreeWidget::~BlocksTreeWidget()
|
||||
|
||||
bool BlocksTreeWidget::eventFilter(QObject* _object, QEvent* _event)
|
||||
{
|
||||
if (_object == this)
|
||||
if (_object != this)
|
||||
return false;
|
||||
|
||||
const auto eventType = _event->type();
|
||||
switch (eventType)
|
||||
{
|
||||
if (_event->type() == QEvent::MouseMove || _event->type() == QEvent::HoverMove)
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::HoverMove:
|
||||
{
|
||||
if (m_idleTimer.isActive())
|
||||
m_idleTimer.stop();
|
||||
@ -298,7 +307,23 @@ bool BlocksTreeWidget::eventFilter(QObject* _object, QEvent* _event)
|
||||
}
|
||||
|
||||
m_idleTimer.start();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::Show:
|
||||
{
|
||||
if (!m_bInitialized)
|
||||
{
|
||||
EASY_CONSTEXPR int Margins = 20;
|
||||
setMinimumSize(m_hintLabel->width() + Margins, m_hintLabel->height() + header()->height() + Margins);
|
||||
m_bInitialized = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -801,13 +826,18 @@ void BlocksTreeWidget::moveEvent(QMoveEvent* _event)
|
||||
|
||||
void BlocksTreeWidget::alignProgressBar()
|
||||
{
|
||||
auto center = rect().center();
|
||||
auto pos = mapToGlobal(center);
|
||||
const auto scrollbarHeight = verticalScrollBar()->isVisible() ? verticalScrollBar()->height() : 0;
|
||||
const auto center = rect().adjusted(0, header()->height(), 0, -scrollbarHeight - 6).center();
|
||||
|
||||
if (m_progress != nullptr)
|
||||
m_progress->move(pos.x() - (m_progress->width() >> 1), pos.y() - (m_progress->height() >> 1));
|
||||
{
|
||||
const auto pos = center;//mapToGlobal(center);
|
||||
m_progress->move(pos.x() - (m_progress->width() >> 1),
|
||||
std::max(pos.y() - (m_progress->height() >> 1), header()->height()));
|
||||
}
|
||||
|
||||
m_hintLabel->move(center.x() - (m_hintLabel->width() >> 1), std::max(center.y() - (m_hintLabel->height() >> 1), header()->height()));
|
||||
m_hintLabel->move(center.x() - (m_hintLabel->width() >> 1),
|
||||
std::max(center.y() - (m_hintLabel->height() >> 1), header()->height()));
|
||||
}
|
||||
|
||||
void BlocksTreeWidget::destroyProgressDialog()
|
||||
@ -824,9 +854,9 @@ void BlocksTreeWidget::createProgressDialog()
|
||||
{
|
||||
destroyProgressDialog();
|
||||
|
||||
m_progress = new QProgressDialog("Building blocks hierarchy...", "", 0, 100, this, Qt::FramelessWindowHint);
|
||||
m_progress = new RoundProgressDialog("Building blocks hierarchy...", this);
|
||||
m_progress->setWindowFlags(Qt::FramelessWindowHint);
|
||||
m_progress->setAttribute(Qt::WA_TranslucentBackground);
|
||||
m_progress->setCancelButton(nullptr);
|
||||
m_progress->setValue(0);
|
||||
m_progress->show();
|
||||
|
||||
@ -981,8 +1011,7 @@ void BlocksTreeWidget::onItemCollapse(QTreeWidgetItem* _item)
|
||||
|
||||
void BlocksTreeWidget::onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem* _previous)
|
||||
{
|
||||
if (_previous != nullptr)
|
||||
static_cast<TreeWidgetItem*>(_previous)->setBold(false);
|
||||
(void)_previous;
|
||||
|
||||
if (_item == nullptr)
|
||||
{
|
||||
@ -992,7 +1021,6 @@ void BlocksTreeWidget::onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetIt
|
||||
else
|
||||
{
|
||||
auto item = static_cast<TreeWidgetItem*>(_item);
|
||||
item->setBold(true);
|
||||
|
||||
EASY_GLOBALS.selected_block = item->block_index();
|
||||
if (EASY_GLOBALS.selected_block < EASY_GLOBALS.gui_blocks.size())
|
||||
@ -1044,10 +1072,6 @@ void BlocksTreeWidget::onSelectedBlockChange(uint32_t _block_index)
|
||||
#endif
|
||||
}
|
||||
|
||||
auto previous = static_cast<TreeWidgetItem*>(currentItem());
|
||||
if (previous != nullptr)
|
||||
previous->setBold(false);
|
||||
|
||||
if (item != nullptr)
|
||||
{
|
||||
//const QSignalBlocker b(this);
|
||||
@ -1074,8 +1098,6 @@ void BlocksTreeWidget::onSelectedBlockChange(uint32_t _block_index)
|
||||
resizeColumnsToContents();
|
||||
connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
|
||||
}
|
||||
|
||||
item->setBold(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -91,12 +91,13 @@ protected:
|
||||
QString m_lastSearch;
|
||||
QTreeWidgetItem* m_lastFound;
|
||||
::profiler::timestamp_t m_beginTime;
|
||||
class QProgressDialog* m_progress;
|
||||
class RoundProgressDialog* m_progress;
|
||||
class QLabel* m_hintLabel;
|
||||
class ArbitraryValueToolTip* m_valueTooltip;
|
||||
TreeMode m_mode;
|
||||
bool m_bLocked;
|
||||
bool m_bSilentExpandCollapse;
|
||||
bool m_bInitialized;
|
||||
char m_columnsHiddenStatus[COL_COLUMNS_NUMBER];
|
||||
|
||||
public:
|
||||
|
@ -110,7 +110,7 @@ struct EasyBlock Q_DECL_FINAL
|
||||
|
||||
EasyBlock() = default;
|
||||
|
||||
EasyBlock(EasyBlock&& that)
|
||||
EasyBlock(EasyBlock&& that) EASY_NOEXCEPT
|
||||
: tree(::std::move(that.tree))
|
||||
#ifdef EASY_TREE_WIDGET__USE_VECTOR
|
||||
, tree_item(that.tree_item)
|
||||
@ -126,21 +126,19 @@ struct EasyBlock Q_DECL_FINAL
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef ::std::vector<EasyBlockItem> EasyItems;
|
||||
typedef ::std::vector<EasyBlock> EasyBlocks;
|
||||
using EasyItems = ::std::vector<EasyBlockItem>;
|
||||
using EasyBlocks = ::std::vector<EasyBlock>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct EasySelectedBlock Q_DECL_FINAL
|
||||
{
|
||||
const ::profiler::BlocksTreeRoot* root;
|
||||
::profiler::block_index_t tree;
|
||||
const ::profiler::BlocksTreeRoot* root = nullptr;
|
||||
::profiler::block_index_t tree = 0xffffffff;
|
||||
|
||||
EasySelectedBlock() : root(nullptr), tree(0xffffffff)
|
||||
{
|
||||
}
|
||||
EasySelectedBlock() = default;
|
||||
|
||||
EasySelectedBlock(const ::profiler::BlocksTreeRoot* _root, const ::profiler::block_index_t _tree)
|
||||
EasySelectedBlock(const ::profiler::BlocksTreeRoot* _root, const ::profiler::block_index_t _tree) EASY_NOEXCEPT
|
||||
: root(_root)
|
||||
, tree(_tree)
|
||||
{
|
||||
|
@ -105,8 +105,8 @@ const QPen HIGHLIGHTER_PEN = ([]() -> QPen { QPen p(profiler::colors::Black); p.
|
||||
|
||||
GraphicsBlockItem::GraphicsBlockItem(uint8_t _index, const profiler::BlocksTreeRoot& _root)
|
||||
: QGraphicsItem(nullptr)
|
||||
, m_thread(_root)
|
||||
, m_threadName(::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, _root, EASY_GLOBALS.hex_thread_id))
|
||||
, m_pRoot(&_root)
|
||||
, m_index(_index)
|
||||
{
|
||||
}
|
||||
@ -117,7 +117,7 @@ GraphicsBlockItem::~GraphicsBlockItem()
|
||||
|
||||
void GraphicsBlockItem::validateName()
|
||||
{
|
||||
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, *m_pRoot, EASY_GLOBALS.hex_thread_id);
|
||||
m_threadName = ::profiler_gui::decoratedThreadName(EASY_GLOBALS.use_decorated_thread_name, m_thread, EASY_GLOBALS.hex_thread_id);
|
||||
}
|
||||
|
||||
const BlocksGraphicsView* GraphicsBlockItem::view() const
|
||||
@ -453,7 +453,7 @@ void GraphicsBlockItem::paintChildren(const float _minWidth, const int _narrowSi
|
||||
void GraphicsBlockItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*, QWidget*)
|
||||
{
|
||||
const bool gotItems = !m_levels.empty() && !m_levels.front().empty();
|
||||
const bool gotSync = !m_pRoot->sync.empty();
|
||||
const bool gotSync = !m_thread.sync.empty();
|
||||
|
||||
if (!gotItems && !gotSync)
|
||||
{
|
||||
@ -963,21 +963,21 @@ void GraphicsBlockItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
|
||||
if (gotSync)
|
||||
{
|
||||
const auto sceneView = view();
|
||||
auto firstSync = ::std::lower_bound(m_pRoot->sync.begin(), m_pRoot->sync.end(), p.sceneLeft, [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
auto firstSync = ::std::lower_bound(m_thread.sync.begin(), m_thread.sync.end(), p.sceneLeft, [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
{
|
||||
return sceneView->time2position(easyBlocksTree(_index).node->begin()) < _value;
|
||||
});
|
||||
|
||||
if (firstSync != m_pRoot->sync.end())
|
||||
if (firstSync != m_thread.sync.end())
|
||||
{
|
||||
if (firstSync != m_pRoot->sync.begin())
|
||||
if (firstSync != m_thread.sync.begin())
|
||||
--firstSync;
|
||||
}
|
||||
else if (!m_pRoot->sync.empty())
|
||||
else if (!m_thread.sync.empty())
|
||||
{
|
||||
firstSync = m_pRoot->sync.begin() + m_pRoot->sync.size() - 1;
|
||||
firstSync = m_thread.sync.begin() + m_thread.sync.size() - 1;
|
||||
}
|
||||
//firstSync = m_pRoot->sync.begin();
|
||||
//firstSync = m_thread.sync.begin();
|
||||
|
||||
p.previousColor = 0;
|
||||
qreal prevRight = -1e100;
|
||||
@ -986,7 +986,7 @@ void GraphicsBlockItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
|
||||
{
|
||||
_painter->setPen(BORDERS_COLOR);
|
||||
|
||||
for (auto it = firstSync, end = m_pRoot->sync.end(); it != end; ++it)
|
||||
for (auto it = firstSync, end = m_thread.sync.end(); it != end; ++it)
|
||||
{
|
||||
const auto& item = easyBlocksTree(*it);
|
||||
auto left = sceneView->time2position(item.node->begin());
|
||||
@ -1039,22 +1039,22 @@ void GraphicsBlockItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
|
||||
|
||||
|
||||
|
||||
if (EASY_GLOBALS.enable_event_markers && !m_pRoot->events.empty())
|
||||
if (EASY_GLOBALS.enable_event_markers && !m_thread.events.empty())
|
||||
{
|
||||
const auto sceneView = view();
|
||||
auto first = ::std::lower_bound(m_pRoot->events.begin(), m_pRoot->events.end(), p.offset, [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
auto first = ::std::lower_bound(m_thread.events.begin(), m_thread.events.end(), p.offset, [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
{
|
||||
return sceneView->time2position(easyBlocksTree(_index).node->begin()) < _value;
|
||||
});
|
||||
|
||||
if (first != m_pRoot->events.end())
|
||||
if (first != m_thread.events.end())
|
||||
{
|
||||
if (first != m_pRoot->events.begin())
|
||||
if (first != m_thread.events.begin())
|
||||
--first;
|
||||
}
|
||||
else if (!m_pRoot->events.empty())
|
||||
else if (!m_thread.events.empty())
|
||||
{
|
||||
first = m_pRoot->events.begin() + m_pRoot->events.size() - 1;
|
||||
first = m_thread.events.begin() + m_thread.events.size() - 1;
|
||||
}
|
||||
|
||||
p.previousColor = 0;
|
||||
@ -1064,7 +1064,7 @@ void GraphicsBlockItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
|
||||
{
|
||||
_painter->setPen(BORDERS_COLOR);
|
||||
|
||||
for (auto it = first, end = m_pRoot->events.end(); it != end; ++it)
|
||||
for (auto it = first, end = m_thread.events.end(); it != end; ++it)
|
||||
{
|
||||
const auto& item = easyBlocksTree(*it);
|
||||
auto left = sceneView->time2position(item.node->begin());
|
||||
@ -1115,9 +1115,9 @@ void GraphicsBlockItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const ::profiler::BlocksTreeRoot* GraphicsBlockItem::root() const
|
||||
const profiler::BlocksTreeRoot& GraphicsBlockItem::root() const
|
||||
{
|
||||
return m_pRoot;
|
||||
return m_thread;
|
||||
}
|
||||
|
||||
const QString& GraphicsBlockItem::threadName() const
|
||||
@ -1173,7 +1173,7 @@ void GraphicsBlockItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tre
|
||||
continue;
|
||||
}
|
||||
|
||||
_blocks.emplace_back(m_pRoot, item.block);
|
||||
_blocks.emplace_back(&m_thread, item.block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1206,31 +1206,31 @@ const ::profiler_gui::EasyBlock* GraphicsBlockItem::intersect(const QPointF& _po
|
||||
{
|
||||
// The Y position is out of blocks range
|
||||
|
||||
if (EASY_GLOBALS.enable_event_markers && !m_pRoot->events.empty())
|
||||
if (EASY_GLOBALS.enable_event_markers && !m_thread.events.empty())
|
||||
{
|
||||
// If event indicators are enabled then try to intersect with one of event indicators
|
||||
|
||||
const auto& sceneView = view();
|
||||
auto first = ::std::lower_bound(m_pRoot->events.begin(), m_pRoot->events.end(), _pos.x(), [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
auto first = ::std::lower_bound(m_thread.events.begin(), m_thread.events.end(), _pos.x(), [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
{
|
||||
return sceneView->time2position(easyBlocksTree(_index).node->begin()) < _value;
|
||||
});
|
||||
|
||||
if (first != m_pRoot->events.end())
|
||||
if (first != m_thread.events.end())
|
||||
{
|
||||
if (first != m_pRoot->events.begin())
|
||||
if (first != m_thread.events.begin())
|
||||
--first;
|
||||
}
|
||||
else if (!m_pRoot->events.empty())
|
||||
else if (!m_thread.events.empty())
|
||||
{
|
||||
first = m_pRoot->events.begin() + m_pRoot->events.size() - 1;
|
||||
first = m_thread.events.begin() + m_thread.events.size() - 1;
|
||||
}
|
||||
|
||||
const auto MIN_WIDTH = EASY_GLOBALS.enable_zero_length ? 0.f : 0.25f;
|
||||
const auto currentScale = sceneView->scale();
|
||||
const auto dw = 5. / currentScale;
|
||||
|
||||
for (auto it = first, end = m_pRoot->events.end(); it != end; ++it)
|
||||
for (auto it = first, end = m_thread.events.end(); it != end; ++it)
|
||||
{
|
||||
_blockIndex = *it;
|
||||
const auto& item = easyBlock(_blockIndex);
|
||||
@ -1354,7 +1354,7 @@ const ::profiler_gui::EasyBlock* GraphicsBlockItem::intersect(const QPointF& _po
|
||||
|
||||
const ::profiler_gui::EasyBlock* GraphicsBlockItem::intersectEvent(const QPointF& _pos) const
|
||||
{
|
||||
if (m_pRoot->sync.empty())
|
||||
if (m_thread.sync.empty())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -1372,18 +1372,18 @@ const ::profiler_gui::EasyBlock* GraphicsBlockItem::intersectEvent(const QPointF
|
||||
}
|
||||
|
||||
const auto sceneView = view();
|
||||
auto firstSync = ::std::lower_bound(m_pRoot->sync.begin(), m_pRoot->sync.end(), _pos.x(), [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
auto firstSync = ::std::lower_bound(m_thread.sync.begin(), m_thread.sync.end(), _pos.x(), [&sceneView](::profiler::block_index_t _index, qreal _value)
|
||||
{
|
||||
return sceneView->time2position(easyBlocksTree(_index).node->begin()) < _value;
|
||||
});
|
||||
|
||||
if (firstSync == m_pRoot->sync.end())
|
||||
firstSync = m_pRoot->sync.begin() + m_pRoot->sync.size() - 1;
|
||||
else if (firstSync != m_pRoot->sync.begin())
|
||||
if (firstSync == m_thread.sync.end())
|
||||
firstSync = m_thread.sync.begin() + m_thread.sync.size() - 1;
|
||||
else if (firstSync != m_thread.sync.begin())
|
||||
--firstSync;
|
||||
|
||||
const auto dw = 4. / view()->scale();
|
||||
for (auto it = firstSync, end = m_pRoot->sync.end(); it != end; ++it)
|
||||
for (auto it = firstSync, end = m_thread.sync.end(); it != end; ++it)
|
||||
{
|
||||
const auto& item = easyBlock(*it);
|
||||
|
||||
@ -1417,7 +1417,7 @@ void GraphicsBlockItem::setBoundingRect(const QRectF& _rect)
|
||||
|
||||
::profiler::thread_id_t GraphicsBlockItem::threadId() const
|
||||
{
|
||||
return m_pRoot->thread_id;
|
||||
return m_thread.thread_id;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -74,19 +74,20 @@ class GraphicsBlockItem : public QGraphicsItem
|
||||
using RightBounds = std::vector<qreal>;
|
||||
using Sublevels = std::vector<Children>;
|
||||
|
||||
const profiler::BlocksTreeRoot& m_thread; ///< Reference to the root profiler block (thread block). Used by ProfTreeWidget to restore hierarchy.
|
||||
|
||||
DrawIndexes m_levelsIndexes; ///< Indexes of first item on each level from which we must start painting
|
||||
RightBounds m_rightBounds; ///<
|
||||
Sublevels m_levels; ///< Arrays of items for each level
|
||||
|
||||
QRectF m_boundingRect; ///< boundingRect (see QGraphicsItem)
|
||||
QString m_threadName; ///<
|
||||
const ::profiler::BlocksTreeRoot* m_pRoot; ///< Pointer to the root profiler block (thread block). Used by ProfTreeWidget to restore hierarchy.
|
||||
uint8_t m_index; ///< This item's index in the list of items of BlocksGraphicsView
|
||||
|
||||
public:
|
||||
|
||||
explicit GraphicsBlockItem(uint8_t _index, const::profiler::BlocksTreeRoot& _root);
|
||||
virtual ~GraphicsBlockItem();
|
||||
explicit GraphicsBlockItem(uint8_t _index, const profiler::BlocksTreeRoot& _root);
|
||||
~GraphicsBlockItem() override;
|
||||
|
||||
// Public virtual methods
|
||||
|
||||
@ -100,7 +101,7 @@ public:
|
||||
|
||||
void validateName();
|
||||
|
||||
const ::profiler::BlocksTreeRoot* root() const;
|
||||
const profiler::BlocksTreeRoot& root() const;
|
||||
const QString& threadName() const;
|
||||
|
||||
QRect getRect() const;
|
||||
|
301
profiler_gui/round_progress_widget.cpp
Normal file
301
profiler_gui/round_progress_widget.cpp
Normal file
@ -0,0 +1,301 @@
|
||||
/************************************************************************
|
||||
* file name : round_progress_widget.cpp
|
||||
* ----------------- :
|
||||
* creation time : 2018/05/17
|
||||
* author : Victor Zarubkin
|
||||
* email : v.s.zarubkin@gmail.com
|
||||
* ----------------- :
|
||||
* description : The file contains implementation of RoundProgressWidget.
|
||||
* ----------------- :
|
||||
* license : Lightweight profiler library for c++
|
||||
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||
* :
|
||||
* : Licensed under either of
|
||||
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||
* : * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* : at your option.
|
||||
* :
|
||||
* : The MIT License
|
||||
* :
|
||||
* : Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* : of this software and associated documentation files (the "Software"), to deal
|
||||
* : in the Software without restriction, including without limitation the rights
|
||||
* : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* : of the Software, and to permit persons to whom the Software is furnished
|
||||
* : to do so, subject to the following conditions:
|
||||
* :
|
||||
* : The above copyright notice and this permission notice shall be included in all
|
||||
* : copies or substantial portions of the Software.
|
||||
* :
|
||||
* : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* : USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
* :
|
||||
* : The Apache License, Version 2.0 (the "License")
|
||||
* :
|
||||
* : You may not use this file except in compliance with the License.
|
||||
* : You may obtain a copy of the License at
|
||||
* :
|
||||
* : http://www.apache.org/licenses/LICENSE-2.0
|
||||
* :
|
||||
* : Unless required by applicable law or agreed to in writing, software
|
||||
* : distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* : See the License for the specific language governing permissions and
|
||||
* : limitations under the License.
|
||||
************************************************************************/
|
||||
|
||||
#include "round_progress_widget.h"
|
||||
#include <math.h>
|
||||
#include <easy/utility.h>
|
||||
#include <QFontMetrics>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef max
|
||||
# undef max
|
||||
#endif
|
||||
|
||||
RoundProgressIndicator::RoundProgressIndicator(QWidget* parent)
|
||||
: Parent(parent)
|
||||
, m_text("0%")
|
||||
, m_background(Qt::transparent)
|
||||
, m_color(Qt::green)
|
||||
, m_value(0)
|
||||
{
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
}
|
||||
|
||||
RoundProgressIndicator::~RoundProgressIndicator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int RoundProgressIndicator::value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::setValue(int value)
|
||||
{
|
||||
m_value = static_cast<int8_t>(estd::clamp(0, value, 100));
|
||||
m_text = QString("%1%").arg(m_value);
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::reset()
|
||||
{
|
||||
m_value = 0;
|
||||
m_text = "0%";
|
||||
update();
|
||||
}
|
||||
|
||||
QColor RoundProgressIndicator::background() const
|
||||
{
|
||||
return m_background;
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::setBackground(QColor color)
|
||||
{
|
||||
m_background = std::move(color);
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::setBackground(QString color)
|
||||
{
|
||||
m_background.setNamedColor(color);
|
||||
update();
|
||||
}
|
||||
|
||||
QColor RoundProgressIndicator::color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::setColor(QColor color)
|
||||
{
|
||||
m_color = std::move(color);
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::setColor(QString color)
|
||||
{
|
||||
m_color.setNamedColor(color);
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::showEvent(QShowEvent* event)
|
||||
{
|
||||
Parent::showEvent(event);
|
||||
|
||||
const QFontMetrics fm(font());
|
||||
const QString text = QStringLiteral("100%");
|
||||
const int size = std::max(fm.width(text), fm.height()) + 4 * 4;
|
||||
|
||||
setFixedSize(size, size);
|
||||
}
|
||||
|
||||
void RoundProgressIndicator::paintEvent(QPaintEvent* /*event*/)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
|
||||
const auto r = rect().adjusted(4, 4, -4, -4);
|
||||
auto p = painter.pen();
|
||||
|
||||
// Draw circle
|
||||
p.setWidth(4);
|
||||
p.setColor(m_background);
|
||||
painter.setPen(p);
|
||||
painter.drawArc(r, 0, 360 * 16);
|
||||
|
||||
p.setColor(m_color);
|
||||
painter.setPen(p);
|
||||
painter.drawArc(r, 90 * 16, -1 * static_cast<int>(m_value) * 16 * 360 / 100);
|
||||
|
||||
// Draw text
|
||||
p.setWidth(1);
|
||||
p.setColor(palette().foreground().color());
|
||||
painter.setPen(p);
|
||||
painter.drawText(r, Qt::AlignCenter, m_text);
|
||||
}
|
||||
|
||||
RoundProgressWidget::RoundProgressWidget(QWidget* parent)
|
||||
: RoundProgressWidget(QString(), parent)
|
||||
{
|
||||
}
|
||||
|
||||
RoundProgressWidget::RoundProgressWidget(const QString& title, QWidget* parent)
|
||||
: Parent(parent)
|
||||
, m_title(new QLabel(title, this))
|
||||
, m_indicatorWrapper(new QWidget(this))
|
||||
, m_indicator(new RoundProgressIndicator(this))
|
||||
, m_titlePosition(RoundProgressWidget::Top)
|
||||
{
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
m_indicatorWrapper->setWindowFlags(Qt::FramelessWindowHint);
|
||||
m_indicatorWrapper->setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
auto wlay = new QHBoxLayout(m_indicatorWrapper);
|
||||
wlay->setContentsMargins(0, 0, 0, 0);
|
||||
wlay->addWidget(m_indicator, 0, Qt::AlignCenter);
|
||||
|
||||
auto lay = new QVBoxLayout(this);
|
||||
lay->addWidget(m_title);
|
||||
lay->addWidget(m_indicatorWrapper);
|
||||
}
|
||||
|
||||
RoundProgressWidget::~RoundProgressWidget()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RoundProgressWidget::setTitle(const QString& title)
|
||||
{
|
||||
m_title->setText(title);
|
||||
}
|
||||
|
||||
int RoundProgressWidget::value() const
|
||||
{
|
||||
return m_indicator->value();
|
||||
}
|
||||
|
||||
void RoundProgressWidget::setValue(int value)
|
||||
{
|
||||
const auto prev = m_indicator->value();
|
||||
const auto newValue = static_cast<int8_t>(estd::clamp(0, value, 100));
|
||||
if (prev == newValue)
|
||||
return;
|
||||
|
||||
m_indicator->setValue(newValue);
|
||||
const auto v = m_indicator->value();
|
||||
|
||||
emit valueChanged(v);
|
||||
|
||||
if (v == 100)
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void RoundProgressWidget::reset()
|
||||
{
|
||||
m_indicator->reset();
|
||||
}
|
||||
|
||||
RoundProgressWidget::TitlePosition RoundProgressWidget::titlePosition() const
|
||||
{
|
||||
return m_titlePosition;
|
||||
}
|
||||
|
||||
void RoundProgressWidget::setTitlePosition(TitlePosition pos)
|
||||
{
|
||||
const auto prev = m_titlePosition;
|
||||
if (prev == pos)
|
||||
return;
|
||||
|
||||
m_titlePosition = pos;
|
||||
|
||||
auto lay = static_cast<QVBoxLayout*>(layout());
|
||||
if (pos == RoundProgressWidget::Top)
|
||||
{
|
||||
lay->removeWidget(m_indicatorWrapper);
|
||||
lay->removeWidget(m_title);
|
||||
|
||||
lay->addWidget(m_title);
|
||||
lay->addWidget(m_indicatorWrapper);
|
||||
}
|
||||
else
|
||||
{
|
||||
lay->removeWidget(m_title);
|
||||
lay->removeWidget(m_indicator);
|
||||
|
||||
lay->addWidget(m_indicator);
|
||||
lay->addWidget(m_title);
|
||||
}
|
||||
|
||||
emit titlePositionChanged();
|
||||
}
|
||||
|
||||
bool RoundProgressWidget::isTopTitlePosition() const
|
||||
{
|
||||
return m_titlePosition == RoundProgressWidget::Top;
|
||||
}
|
||||
|
||||
void RoundProgressWidget::setTopTitlePosition(bool isTop)
|
||||
{
|
||||
setTitlePosition(isTop ? RoundProgressWidget::Top : RoundProgressWidget::Bottom);
|
||||
}
|
||||
|
||||
RoundProgressDialog::RoundProgressDialog(const QString& title, QWidget* parent)
|
||||
: Parent(parent)
|
||||
, m_progress(new RoundProgressWidget(title, this))
|
||||
{
|
||||
auto lay = new QVBoxLayout(this);
|
||||
lay->addWidget(m_progress);
|
||||
}
|
||||
|
||||
RoundProgressDialog::~RoundProgressDialog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RoundProgressDialog::showEvent(QShowEvent* event)
|
||||
{
|
||||
Parent::showEvent(event);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void RoundProgressDialog::setValue(int value)
|
||||
{
|
||||
m_progress->setValue(value);
|
||||
if (value == 100)
|
||||
hide();
|
||||
}
|
174
profiler_gui/round_progress_widget.h
Normal file
174
profiler_gui/round_progress_widget.h
Normal file
@ -0,0 +1,174 @@
|
||||
/************************************************************************
|
||||
* file name : round_progress_widget.h
|
||||
* ----------------- :
|
||||
* creation time : 2018/05/17
|
||||
* author : Victor Zarubkin
|
||||
* email : v.s.zarubkin@gmail.com
|
||||
* ----------------- :
|
||||
* description : The file contains declaration of RoundProgressWidget.
|
||||
* ----------------- :
|
||||
* license : Lightweight profiler library for c++
|
||||
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||
* :
|
||||
* : Licensed under either of
|
||||
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||
* : * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
* : at your option.
|
||||
* :
|
||||
* : The MIT License
|
||||
* :
|
||||
* : Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* : of this software and associated documentation files (the "Software"), to deal
|
||||
* : in the Software without restriction, including without limitation the rights
|
||||
* : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* : of the Software, and to permit persons to whom the Software is furnished
|
||||
* : to do so, subject to the following conditions:
|
||||
* :
|
||||
* : The above copyright notice and this permission notice shall be included in all
|
||||
* : copies or substantial portions of the Software.
|
||||
* :
|
||||
* : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
* : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* : USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
* :
|
||||
* : The Apache License, Version 2.0 (the "License")
|
||||
* :
|
||||
* : You may not use this file except in compliance with the License.
|
||||
* : You may obtain a copy of the License at
|
||||
* :
|
||||
* : http://www.apache.org/licenses/LICENSE-2.0
|
||||
* :
|
||||
* : Unless required by applicable law or agreed to in writing, software
|
||||
* : distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* : See the License for the specific language governing permissions and
|
||||
* : limitations under the License.
|
||||
************************************************************************/
|
||||
|
||||
#ifndef ROUND_PROGRESS_WIDGET_H
|
||||
#define ROUND_PROGRESS_WIDGET_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <QColor>
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
|
||||
class RoundProgressIndicator : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Parent = QWidget;
|
||||
using This = RoundProgressIndicator;
|
||||
|
||||
QString m_text;
|
||||
QColor m_background;
|
||||
QColor m_color;
|
||||
int8_t m_value;
|
||||
|
||||
public:
|
||||
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor);
|
||||
Q_PROPERTY(QColor background READ background WRITE setBackground);
|
||||
|
||||
explicit RoundProgressIndicator(QWidget* parent = nullptr);
|
||||
~RoundProgressIndicator() override;
|
||||
|
||||
int value() const;
|
||||
void setValue(int value);
|
||||
void reset();
|
||||
|
||||
QColor background() const;
|
||||
QColor color() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void setBackground(QColor color);
|
||||
void setBackground(QString color);
|
||||
void setColor(QColor color);
|
||||
void setColor(QString color);
|
||||
|
||||
protected:
|
||||
|
||||
void showEvent(QShowEvent* event) override;
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
}; // end of class RoundProgressIndicator.
|
||||
|
||||
class RoundProgressWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Parent = QWidget;
|
||||
using This = RoundProgressWidget;
|
||||
|
||||
public:
|
||||
|
||||
Q_PROPERTY(bool topTitlePosition READ isTopTitlePosition WRITE setTopTitlePosition NOTIFY titlePositionChanged);
|
||||
|
||||
enum TitlePosition : int8_t
|
||||
{
|
||||
Top = 0,
|
||||
Bottom,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
class QLabel* m_title;
|
||||
QWidget* m_indicatorWrapper;
|
||||
RoundProgressIndicator* m_indicator;
|
||||
TitlePosition m_titlePosition;
|
||||
|
||||
public:
|
||||
|
||||
explicit RoundProgressWidget(QWidget* parent = nullptr);
|
||||
explicit RoundProgressWidget(const QString& title, QWidget* parent = nullptr);
|
||||
~RoundProgressWidget() override;
|
||||
|
||||
void setTitle(const QString& title);
|
||||
int value() const;
|
||||
TitlePosition titlePosition() const;
|
||||
bool isTopTitlePosition() const;
|
||||
|
||||
public slots:
|
||||
|
||||
void setValue(int value);
|
||||
void reset();
|
||||
void setTitlePosition(TitlePosition pos);
|
||||
void setTopTitlePosition(bool isTop);
|
||||
|
||||
signals:
|
||||
|
||||
void valueChanged(int value);
|
||||
void finished();
|
||||
void titlePositionChanged();
|
||||
|
||||
}; // end of class RoundProgressWidget.
|
||||
|
||||
class RoundProgressDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Parent = QDialog;
|
||||
using This = RoundProgressDialog;
|
||||
|
||||
RoundProgressWidget* m_progress;
|
||||
|
||||
public:
|
||||
|
||||
explicit RoundProgressDialog(const QString& title, QWidget* parent = nullptr);
|
||||
~RoundProgressDialog() override;
|
||||
|
||||
protected:
|
||||
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
||||
public slots:
|
||||
|
||||
void setValue(int value);
|
||||
|
||||
}; // end of RoundProgressDialog.
|
||||
|
||||
#endif // ROUND_PROGRESS_WIDGET_H
|
@ -183,16 +183,6 @@ QVariant TreeWidgetItem::data(int _column, int _role) const
|
||||
{
|
||||
if (_column == COL_NAME)
|
||||
{
|
||||
if (_role == Qt::SizeHintRole)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const float k = m_font.bold() ? 1.2f : 1.f;
|
||||
#else
|
||||
const float k = m_font.bold() ? 1.15f : 1.f;
|
||||
#endif
|
||||
return QSize(static_cast<int>(QFontMetrics(m_font).width(text(COL_NAME)) * k) + 20, 26);
|
||||
}
|
||||
|
||||
if (_role == BlockColorRole)
|
||||
{
|
||||
if (parent() != nullptr || m_bMain)
|
||||
@ -203,9 +193,6 @@ QVariant TreeWidgetItem::data(int _column, int _role) const
|
||||
|
||||
switch (_role)
|
||||
{
|
||||
case Qt::FontRole:
|
||||
return m_font;
|
||||
|
||||
case Qt::ForegroundRole:
|
||||
return m_bMain ? QVariant::fromValue(QColor::fromRgb(profiler_gui::SELECTED_THREAD_FOREGROUND)) : QVariant();
|
||||
|
||||
@ -331,11 +318,6 @@ void TreeWidgetItem::expandAll()
|
||||
guiBlock().expanded = true;
|
||||
}
|
||||
|
||||
void TreeWidgetItem::setBold(bool _bold)
|
||||
{
|
||||
m_font.setBold(_bold);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TreeWidgetItemDelegate::TreeWidgetItemDelegate(QTreeWidget* parent) : QStyledItemDelegate(parent), m_treeWidget(parent)
|
||||
@ -350,7 +332,7 @@ TreeWidgetItemDelegate::~TreeWidgetItemDelegate()
|
||||
|
||||
void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
auto brushData = m_treeWidget->model()->data(index, BlockColorRole);
|
||||
const auto brushData = m_treeWidget->model()->data(index, BlockColorRole);
|
||||
if (brushData.isNull())
|
||||
{
|
||||
// Draw item as usual
|
||||
@ -364,7 +346,7 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
|
||||
{
|
||||
// Draw selection background for selected row
|
||||
painter->save();
|
||||
painter->setBrush(QColor::fromRgba(0xCC98DE98));
|
||||
painter->setBrush(m_treeWidget->palette().highlight());
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRect(QRect(option.rect.left(), option.rect.top(), colorBlockSize, option.rect.height()));
|
||||
painter->restore();
|
||||
@ -382,15 +364,16 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
|
||||
painter->save();
|
||||
|
||||
// Draw color marker with block color
|
||||
const auto brush = m_treeWidget->model()->data(index, Qt::UserRole + 1).value<QBrush>();
|
||||
const auto brush = brushData.value<QBrush>();
|
||||
painter->setBrush(brush);
|
||||
painter->setPen(profiler_gui::SYSTEM_BORDER_COLOR);
|
||||
painter->setPen(QColor::fromRgb(profiler::colors::Grey600));
|
||||
painter->drawRect(QRect(option.rect.left(), option.rect.top() + (colorBlockRest >> 1),
|
||||
colorBlockSize, option.rect.height() - colorBlockRest));
|
||||
|
||||
// Draw line under tree indicator
|
||||
const auto bottomLeft = opt.rect.bottomLeft();
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->setPen(profiler_gui::SYSTEM_BORDER_COLOR);
|
||||
painter->drawLine(QPoint(bottomLeft.x() - colorBlockSize, bottomLeft.y()), bottomLeft);
|
||||
|
||||
painter->restore();
|
||||
|
@ -118,7 +118,6 @@ class TreeWidgetItem : public QTreeWidgetItem
|
||||
using Parent = QTreeWidgetItem;
|
||||
using This = TreeWidgetItem;
|
||||
|
||||
QFont m_font;
|
||||
const profiler::block_index_t m_block;
|
||||
QRgb m_customBGColor;
|
||||
std::bitset<17> m_bHasToolTip;
|
||||
@ -126,7 +125,9 @@ class TreeWidgetItem : public QTreeWidgetItem
|
||||
|
||||
public:
|
||||
|
||||
explicit TreeWidgetItem(const profiler::block_index_t _treeBlock = profiler_gui::numeric_max<decltype(m_block)>(), Parent* _parent = nullptr);
|
||||
explicit TreeWidgetItem(const profiler::block_index_t _treeBlock = profiler_gui::numeric_max<decltype(m_block)>()
|
||||
, Parent* _parent = nullptr);
|
||||
|
||||
~TreeWidgetItem() override;
|
||||
|
||||
bool operator < (const Parent& _other) const override;
|
||||
@ -156,8 +157,6 @@ public:
|
||||
|
||||
void expandAll();
|
||||
|
||||
void setBold(bool _bold);
|
||||
|
||||
private:
|
||||
|
||||
void setHasToolTip(int _column);
|
||||
|
@ -301,7 +301,7 @@ void TreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _beginTim
|
||||
const auto endTime = gui_block.tree.node->end();
|
||||
if (startTime > _right || endTime < _left)
|
||||
{
|
||||
setProgress((90 * ++i) / total);
|
||||
setProgress((95 * ++i) / total);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -502,7 +502,7 @@ void TreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _beginTim
|
||||
delete item;
|
||||
}
|
||||
|
||||
setProgress((90 * ++i) / total);
|
||||
setProgress((95 * ++i) / total);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
@ -526,7 +526,7 @@ void TreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _beginTim
|
||||
delete item;
|
||||
}
|
||||
|
||||
setProgress(90 + (10 * ++i) / total);
|
||||
setProgress(95 + (5 * ++i) / total);
|
||||
}
|
||||
|
||||
setDone();
|
||||
|
@ -122,6 +122,7 @@ private:
|
||||
|
||||
void setTreeInternal1(profiler::timestamp_t& _beginTime, const unsigned int _blocksNumber, const profiler::thread_blocks_tree_t& _blocksTree, 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 _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, TreeWidgetItem* _parent, TreeWidgetItem* _frame, profiler::timestamp_t _left, profiler::timestamp_t _right, bool _strict, profiler::timestamp_t& _duration, 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, TreeWidgetItem* _parent, TreeWidgetItem* _frame, profiler::timestamp_t _left, profiler::timestamp_t _right, bool _strict, profiler::timestamp_t& _duration, bool _addZeroBlocks, ::profiler_gui::TimeUnits _units);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user