0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-25 23:40:51 +08:00

Big bunch of changes:

* update copyright
* fix css parsing
* fix block name search
* add matching text highlighing for find results
* add calculation of block statistics for selected area
* new action: right-click on a block on "Diagram" selects region using left and right bounds of this block
* other optimizations
This commit is contained in:
Victor Zarubkin 2019-10-20 16:12:37 +03:00
parent d4b414eb73
commit 92a5ca4a75
105 changed files with 3637 additions and 1376 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright (c) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,4 +1,4 @@
Copyright (c) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright (c) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,4 +1,4 @@
Copyright (c) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright (c) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -6,7 +6,7 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of profiling blocks
* :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -16,7 +16,7 @@
* : * 2016/09/17 Victor Zarubkin: added log messages printing.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : This file contains auxiliary profiler macros for different compiler support.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -298,6 +298,7 @@ namespace profiler {
using blocks_t = profiler::BlocksTree::blocks_t;
using thread_blocks_tree_t = std::unordered_map<profiler::thread_id_t, profiler::BlocksTreeRoot, ::estd::hash<profiler::thread_id_t> >;
using block_getter_fn = std::function<const profiler::BlocksTree&(profiler::block_index_t)>;
using stats_map_t = std::unordered_map<profiler::block_id_t, profiler::BlockStatistics*, estd::hash<profiler::block_id_t> >;
//////////////////////////////////////////////////////////////////////////

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of Profile manager and implement access c-function
* :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of Profile manager and implement access c-function
* :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -9,7 +9,7 @@
* : which reads profiler file and fill profiler blocks tree.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -231,7 +231,6 @@ namespace profiler {
//////////////////////////////////////////////////////////////////////////
using StatsMap = std::unordered_map<profiler::block_id_t, profiler::BlockStatistics*, estd::hash<profiler::block_id_t> >;
using IdMap = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
using CsStatsMap = std::unordered_map<profiler::string_with_hash, profiler::BlockStatistics*>;
@ -249,8 +248,14 @@ using CsStatsMap = std::unordered_map<profiler::string_with_hash, profiler::Bloc
automatically receive statistics update.
*/
static profiler::BlockStatistics* update_statistics(StatsMap& _stats_map, const profiler::BlocksTree& _current, profiler::block_index_t _current_index, profiler::block_index_t _parent_index, const profiler::blocks_t& _blocks, bool _calculate_children = true)
{
static profiler::BlockStatistics* update_statistics(
profiler::stats_map_t& _stats_map,
const profiler::BlocksTree& _current,
profiler::block_index_t _current_index,
profiler::block_index_t _parent_index,
const profiler::blocks_t& _blocks,
bool _calculate_children = true
) {
auto duration = _current.node->duration();
//StatsMap::key_type key(_current.node->name());
//auto it = _stats_map.find(key);
@ -359,7 +364,7 @@ static profiler::BlockStatistics* update_statistics(CsStatsMap& _stats_map, cons
//////////////////////////////////////////////////////////////////////////
static void update_statistics_recursive(StatsMap& _stats_map, profiler::BlocksTree& _current, profiler::block_index_t _current_index, profiler::block_index_t _parent_index, profiler::blocks_t& _blocks)
static void update_statistics_recursive(profiler::stats_map_t& _stats_map, profiler::BlocksTree& _current, profiler::block_index_t _current_index, profiler::block_index_t _parent_index, profiler::blocks_t& _blocks)
{
_current.per_frame_stats = update_statistics(_stats_map, _current, _current_index, _parent_index, _blocks, false);
for (auto i : _current.children)
@ -696,7 +701,7 @@ extern "C" PROFILER_API profiler::block_index_t fillTreesFromStream(std::atomic<
}
}
using PerThreadStats = std::unordered_map<profiler::thread_id_t, StatsMap, estd::hash<profiler::thread_id_t> >;
using PerThreadStats = std::unordered_map<profiler::thread_id_t, profiler::stats_map_t, estd::hash<profiler::thread_id_t> >;
PerThreadStats parent_statistics, frame_statistics;
IdMap identification_table;
@ -808,7 +813,7 @@ extern "C" PROFILER_API profiler::block_index_t fillTreesFromStream(std::atomic<
if (inStream.eof())
break;
StatsMap per_thread_statistics;
profiler::stats_map_t per_thread_statistics;
blocks_number_in_thread = 0;
read(inStream, blocks_number_in_thread);

View File

@ -16,7 +16,7 @@ BEGIN
BEGIN
VALUE "CompanyName", "EasySolutions"
VALUE "FileDescription", "Lightweight profiler library for C++"
VALUE "LegalCopyright", "Copyright (C) 2016-2018 Victor Zarubkin, Sergey Yagovtsev"
VALUE "LegalCopyright", "Copyright (C) 2016-2019 Victor Zarubkin, Sergey Yagovtsev"
VALUE "LegalTrademarks1", "All Rights Reserved"
VALUE "LegalTrademarks2", "All Rights Reserved"
VALUE "ProductName", "easy_profiler lib"

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -9,7 +9,7 @@
* : which reads profiler file and fill profiler blocks tree.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -49,6 +49,8 @@ if (Qt5Widgets_FOUND)
main_window.cpp
round_progress_widget.h
round_progress_widget.cpp
text_highlighter.h
text_highlighter.cpp
timer.h
timer.cpp
thread_pool.h

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -1121,7 +1121,7 @@ void ArbitraryValuesChartItem::updateRegularImageAsync(QRectF _boundingRect, qre
{
auto color = profiler_gui::darken(c.color, 0.65f);
if (profiler_gui::alpha(color) < 0xc0)
p.setPen(QColor::fromRgba(profiler::colors::modify_alpha32(0xc0000000, color)));
p.setPen(QColor::fromRgba(profiler::colors::modify_alpha32(color, 0xc0000000)));
else
p.setPen(QColor::fromRgba(color));
p.setBrush(QColor::fromRgba(0xc8ffffff));
@ -1456,7 +1456,7 @@ void ArbitraryValuesChartItem::updateComplexityImageAsync(QRectF _boundingRect,
auto color = profiler_gui::darken(c.color, 0.65f);
if (profiler_gui::alpha(color) < 0xc0)
p.setPen(QColor::fromRgba(profiler::colors::modify_alpha32(0xc0000000, color)));
p.setPen(QColor::fromRgba(profiler::colors::modify_alpha32(color, 0xc0000000)));
else
p.setPen(QColor::fromRgba(color));
p.setBrush(QColor::fromRgba(0xc8ffffff));
@ -1546,12 +1546,14 @@ void ArbitraryValuesChartItem::clear()
m_collections.clear();
m_minValue = m_maxValue = 0;
m_minDuration = m_maxDuration = 0;
setEmpty(true);
}
void ArbitraryValuesChartItem::update(Collections _collections)
{
cancelImageUpdate();
m_collections = std::move(_collections);
setEmpty(m_collections.empty());
updateImage();
}
@ -1866,6 +1868,7 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(bool _isMainWidget, profiler::threa
, m_threadId(_threadId)
, m_blockIndex(_blockIndex)
, m_blockId(_blockId)
, m_bInitialized(false)
, m_bMainWidget(_isMainWidget)
{
m_collectionsTimer.setInterval(100);
@ -1903,12 +1906,12 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(bool _isMainWidget, profiler::threa
auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true);
auto actionRegulatChart = new QAction(QIcon(imagePath("yx-chart")), tr("Regular chart"), actionGroup);
auto actionRegulatChart = new QAction(QIcon(imagePath("yx-chart")), tr("Regular chart [ v(t) ]"), actionGroup);
actionRegulatChart->setCheckable(true);
actionRegulatChart->setChecked(true);
tb->addAction(actionRegulatChart);
auto actionComplexityChart = new QAction(QIcon(imagePath("big-o-chart")), tr("Complexity chart"), actionGroup);
auto actionComplexityChart = new QAction(QIcon(imagePath("big-o-chart")), tr("Complexity chart [ t(v) ]"), actionGroup);
actionComplexityChart->setCheckable(true);
tb->addAction(actionComplexityChart);
@ -1950,6 +1953,8 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(bool _isMainWidget, profiler::threa
connect(globalEvents, &GlobalSignals::selectedBlockIdChanged, this, &This::onSelectedBlockIdChanged);
connect(globalEvents, &GlobalSignals::allDataGoingToBeDeleted, this, &This::clear);
connect(m_treeWidget->header(), &QHeaderView::sectionResized, this, &This::onHeaderSectionResized);
if (_isMainWidget)
{
connect(m_treeWidget, &QTreeWidget::itemDoubleClicked, this, &This::onItemDoubleClicked);
@ -1989,6 +1994,69 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(QWidget* _parent)
m_exportToCsvAction->setEnabled(false);
}
void ArbitraryValuesWidget::showEvent(QShowEvent* event)
{
Parent::showEvent(event);
if (!m_bInitialized)
{
m_columnsMinimumWidth.resize(static_cast<size_t>(ArbitraryColumns::Count), 0);
#if !defined(_WIN32) && !defined(__APPLE__)
const auto padding = px(9);
#else
const auto padding = px(6);
#endif
auto header = m_treeWidget->header();
auto headerItem = m_treeWidget->headerItem();
auto f = header->font();
#if !defined(_WIN32) && !defined(__APPLE__)
f.setBold(true);
#endif
QFontMetrics fm(f);
const auto indicatorSize = header->isSortIndicatorShown() ? px(11) : 0;
for (int i = 0; i < static_cast<int>(m_columnsMinimumWidth.size()); ++i)
{
auto minSize = static_cast<int>(fm.width(headerItem->text(i)) * profiler_gui::FONT_METRICS_FACTOR + padding);
m_columnsMinimumWidth[i] = minSize;
if (header->isSortIndicatorShown() && header->sortIndicatorSection() == i)
{
minSize += indicatorSize;
}
if (header->sectionSize(i) < minSize)
{
header->resizeSection(i, minSize);
}
}
m_bInitialized = true;
}
}
void ArbitraryValuesWidget::onHeaderSectionResized(int logicalIndex, int /*oldSize*/, int newSize)
{
if (logicalIndex >= m_columnsMinimumWidth.size())
{
return;
}
auto header = m_treeWidget->header();
const auto indicatorSize = header->isSortIndicatorShown() && header->sortIndicatorSection() == logicalIndex ? px(11) : 0;
const auto minSize = m_columnsMinimumWidth[logicalIndex] + indicatorSize;
if (!m_bInitialized || newSize >= minSize)
{
return;
}
header->resizeSection(logicalIndex, minSize);
}
ArbitraryTreeWidgetItem* findSimilarItem(QTreeWidgetItem* _parentItem, ArbitraryTreeWidgetItem* _item)
{
const auto index = _item->getSelfIndexInArray();
@ -2583,12 +2651,7 @@ void ArbitraryValuesWidget::onOpenInNewWindowClicked(bool)
auto viewer = new ArbitraryValuesWidget(m_checkedItems, m_treeWidget->currentItem(), m_threadId, m_blockIndex, m_blockId);
#ifdef WIN32
const WindowHeader::Buttons buttons = WindowHeader::AllButtons;
#else
const WindowHeader::Buttons buttons {WindowHeader::MaximizeButton | WindowHeader::CloseButton};
#endif
auto dialog = new Dialog(nullptr, "EasyProfiler", viewer, buttons, QMessageBox::NoButton);
auto dialog = new Dialog(nullptr, "EasyProfiler", viewer, WindowHeader::AllButtons, QMessageBox::NoButton);
dialog->setProperty("stayVisible", true);
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::allDataGoingToBeDeleted, dialog, &QDialog::reject);

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -341,6 +341,7 @@ class ArbitraryValuesWidget : public QWidget
QTimer m_collectionsTimer;
QList<ArbitraryTreeWidgetItem*> m_checkedItems;
std::vector<int> m_columnsMinimumWidth;
class QSplitter* m_splitter;
QTreeWidget* m_treeWidget;
GraphicsChart* m_chart;
@ -353,6 +354,7 @@ class ArbitraryValuesWidget : public QWidget
profiler::thread_id_t m_threadId;
profiler::block_index_t m_blockIndex;
profiler::block_id_t m_blockId;
bool m_bInitialized;
const bool m_bMainWidget;
explicit ArbitraryValuesWidget(bool _isMainWidget, profiler::thread_id_t _threadId
@ -366,6 +368,7 @@ public:
explicit ArbitraryValuesWidget(QWidget* _parent = nullptr);
~ArbitraryValuesWidget() override;
void showEvent(class QShowEvent* event) override;
void contextMenuEvent(QContextMenuEvent*) override { /* ignore context menu event */ }
public slots:
@ -377,6 +380,7 @@ public slots:
private slots:
void onHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
void onSelectedThreadChanged(profiler::thread_id_t);
void onSelectedBlockChanged(uint32_t _block_index);
void onSelectedBlockIdChanged(profiler::block_id_t _id);

View File

@ -9,7 +9,7 @@
* : for displaying arbitrary value in Diagram and Hierarchy widgets.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -9,7 +9,7 @@
* : for displaying arbitrary value in Diagram and Hierarchy widgets.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -24,7 +24,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -500,7 +500,12 @@ bool BackgroundItem::mouseDoubleClick(const QPointF& scenePos)
{
qApp->restoreOverrideCursor();
auto editor = new BookmarkEditor(m_bookmark, false, sceneView->parentWidget());
#ifndef _WIN32
// Ugly workaround for Linux: without show-hide-show you can not drag the window
editor->show();
editor->hide();
#endif
editor->exec();
}
else
{
@ -523,7 +528,12 @@ bool BackgroundItem::mouseDoubleClick(const QPointF& scenePos)
{
qApp->restoreOverrideCursor();
auto editor = new BookmarkEditor(m_bookmark, true, sceneView->parentWidget());
#ifndef _WIN32
// Ugly workaround for Linux: without show-hide-show you can not drag the window
editor->show();
editor->hide();
#endif
editor->exec();
}
}
@ -1528,11 +1538,11 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
const profiler_gui::EasyBlock* selectedBlock = nullptr;
profiler::thread_id_t selectedBlockThread = 0;
const auto previouslySelectedBlock = EASY_GLOBALS.selected_block;
if (m_mouseButtons & Qt::LeftButton)
bool jumpToZone = false;
bool changedSelectionBySelectingItem = false;
const bool leftClickSelect = (m_mouseButtons & Qt::LeftButton) != 0;
if (leftClickSelect)
{
bool clicked = false;
if (m_rulerItem->isVisible() && m_rulerItem->width() < 1e-6)
{
chronoHidden = true;
@ -1542,44 +1552,83 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
else if (m_selectionItem->isVisible() && m_selectionItem->hoverIndicator())
{
// Jump to selected zone
clicked = true;
jumpToZone = true;
m_flickerSpeedX = m_flickerSpeedY = 0;
notifyVisibleRegionPosChange(m_selectionItem->left() + (m_selectionItem->width() - m_visibleRegionWidth) * 0.5);
}
}
if (!clicked && m_mouseMovePath.manhattanLength() < 5 && !m_backgroundItem->contains(scenePos))
const bool rightClickSelect = ((m_mouseButtons & Qt::RightButton) != 0 && !changedSelection);
if ((leftClickSelect || rightClickSelect) && !jumpToZone && m_mouseMovePath.manhattanLength() < 5 && !m_backgroundItem->contains(scenePos))
{
// Handle Click
//clicked = true;
auto mouseClickPos = mapToScene(m_mousePressPos);
if (mouseClickPos.x() >= 0)
{
// Handle Click
mouseClickPos.setX(m_offset + mouseClickPos.x() / m_scale);
//clicked = true;
auto mouseClickPos = mapToScene(m_mousePressPos);
if (mouseClickPos.x() >= 0)
// Try to select one of item blocks
for (auto item : m_items)
{
mouseClickPos.setX(m_offset + mouseClickPos.x() / m_scale);
// Try to select one of item blocks
for (auto item : m_items)
{
profiler::block_index_t i = ~0U;
auto block = item->intersect(mouseClickPos, i);
if (block != nullptr)
{
changedSelectedItem = true;
selectedBlock = block;
selectedBlockThread = item->threadId();
EASY_GLOBALS.selected_block = i;
EASY_GLOBALS.selected_block_id = easyBlock(i).tree.node->id();
break;
}
}
if (!changedSelectedItem && !profiler_gui::is_max(EASY_GLOBALS.selected_block))
profiler::block_index_t i = ~0U;
auto block = item->intersect(mouseClickPos, i);
if (block != nullptr)
{
changedSelectedItem = true;
profiler_gui::set_max(EASY_GLOBALS.selected_block);
profiler_gui::set_max(EASY_GLOBALS.selected_block_id);
selectedBlock = block;
selectedBlockThread = item->threadId();
EASY_GLOBALS.selected_block = i;
EASY_GLOBALS.selected_block_id = block->tree.node->id();
break;
}
}
if (!changedSelectedItem && !profiler_gui::is_max(EASY_GLOBALS.selected_block))
{
changedSelectedItem = true;
profiler_gui::set_max(EASY_GLOBALS.selected_block);
profiler_gui::set_max(EASY_GLOBALS.selected_block_id);
}
}
if (selectedBlock != nullptr && rightClickSelect)
{
if (!m_selectedBlocks.empty())
{
changedSelection = true;
m_selectedBlocks.clear();
}
const auto thread_item = m_items[selectedBlock->graphics_item];
const auto& selectedItem = thread_item->items(selectedBlock->graphics_item_level)[selectedBlock->graphics_item_index];
const auto left = selectedItem.left();
const auto right = selectedItem.right();
for (auto item : m_items)
{
if (!EASY_GLOBALS.only_current_thread_hierarchy || (EASY_GLOBALS.selecting_block_changes_thread && selectedBlockThread == item->threadId()))
{
item->getBlocks(left, right, m_selectedBlocks);
}
}
if (!m_selectedBlocks.empty())
{
changedSelection = true;
m_selectionItem->setLeftRight(left, right);
m_selectionItem->setReverse(true);
m_selectionItem->setStrict(true);
m_selectionItem->show();
m_pScrollbar->setSelectionPos(left, right);
m_pScrollbar->showSelectionIndicator();
emit EASY_GLOBALS.events.rulerVisible(true);
}
changedSelectionBySelectingItem = changedSelection;
}
}
@ -1591,15 +1640,24 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
if (changedSelection)
{
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_selectionItem->left()), position2time(m_selectionItem->right()), m_selectionItem->reverse());
profiler::timestamp_t left=0, right=0;
if (changedSelectionBySelectingItem)
{
left = selectedBlock->tree.node->begin() - m_beginTime;
right = selectedBlock->tree.node->end() - m_beginTime;
}
else
{
left = position2time(m_selectionItem->left());
right = position2time(m_selectionItem->right());
}
emit intervalChanged(m_selectedBlocks, m_beginTime, left, right, m_selectionItem->strict());
}
if (changedSelectedItem)
{
profiler_gui::BoolFlagGuard guard(m_bUpdatingRect, true);
emit EASY_GLOBALS.events.selectedBlockChanged(EASY_GLOBALS.selected_block);
if (EASY_GLOBALS.selecting_block_changes_thread && selectedBlock != nullptr && EASY_GLOBALS.selected_thread != selectedBlockThread)
{
EASY_GLOBALS.selected_thread = selectedBlockThread;
@ -1609,6 +1667,8 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
emit EASY_GLOBALS.events.unlockCharts();
}
emit EASY_GLOBALS.events.selectedBlockChanged(EASY_GLOBALS.selected_block);
if (selectedBlock != nullptr && isDoubleClick)
{
if (!selectedBlock->tree.children.empty())
@ -1641,6 +1701,10 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
repaintScene();
}
else if (jumpToZone)
{
repaintScene();
}
else if (chronoHidden)
{
emit sceneUpdated();
@ -1677,7 +1741,13 @@ void BlocksGraphicsView::addSelectionToHierarchy()
if (changedSelection)
{
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_selectionItem->left()), position2time(m_selectionItem->right()), m_selectionItem->reverse());
emit intervalChanged(
m_selectedBlocks,
m_beginTime,
position2time(m_selectionItem->left()),
position2time(m_selectionItem->right()),
m_selectionItem->strict()
);
}
}
@ -1712,14 +1782,15 @@ void BlocksGraphicsView::onZoomSelection()
repaintScene(); // repaint scene
}
void BlocksGraphicsView::onInspectCurrentView(bool _strict)
void BlocksGraphicsView::onInspectCurrentView(bool strict)
{
if (m_bEmpty)
return;
if (!m_selectionItem->isVisible())
{
m_selectionItem->setReverse(_strict);
m_selectionItem->setReverse(strict);
m_selectionItem->setStrict(strict);
m_selectionItem->setLeftRight(m_offset, m_offset + m_visibleRegionWidth);
m_selectionItem->show();
m_pScrollbar->setSelectionPos(m_selectionItem->left(), m_selectionItem->right());
@ -1737,48 +1808,53 @@ void BlocksGraphicsView::onInspectCurrentView(bool _strict)
//////////////////////////////////////////////////////////////////////////
bool BlocksGraphicsView::moveChrono(GraphicsRulerItem* _chronometerItem, qreal _mouseX)
bool BlocksGraphicsView::moveChrono(GraphicsRulerItem* ruler_item, qreal mouse_x)
{
if (_chronometerItem->reverse())
if (ruler_item->reverse())
{
if (_mouseX > _chronometerItem->right())
if (mouse_x > ruler_item->right())
{
_chronometerItem->setReverse(false);
_chronometerItem->setLeftRight(_chronometerItem->right(), _mouseX);
ruler_item->setReverse(false);
ruler_item->setLeftRight(ruler_item->right(), mouse_x);
if (_chronometerItem->hoverLeft())
if (ruler_item->hoverLeft())
{
_chronometerItem->setHoverLeft(false);
_chronometerItem->setHoverRight(true);
ruler_item->setHoverLeft(false);
ruler_item->setHoverRight(true);
}
}
else
{
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->right());
ruler_item->setLeftRight(mouse_x, ruler_item->right());
}
}
else
{
if (_mouseX < _chronometerItem->left())
if (mouse_x < ruler_item->left())
{
_chronometerItem->setReverse(true);
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->left());
ruler_item->setReverse(true);
ruler_item->setLeftRight(mouse_x, ruler_item->left());
if (_chronometerItem->hoverRight())
if (ruler_item->hoverRight())
{
_chronometerItem->setHoverLeft(true);
_chronometerItem->setHoverRight(false);
ruler_item->setHoverLeft(true);
ruler_item->setHoverRight(false);
}
}
else
{
_chronometerItem->setLeftRight(_chronometerItem->left(), _mouseX);
ruler_item->setLeftRight(ruler_item->left(), mouse_x);
}
}
if (!_chronometerItem->isVisible() && _chronometerItem->width() > 1e-6)
if (!ruler_item->hoverAnyBorder())
{
_chronometerItem->show();
ruler_item->setStrict(ruler_item->reverse());
}
if (!ruler_item->isVisible() && ruler_item->width() > 1e-6)
{
ruler_item->show();
emit EASY_GLOBALS.events.rulerVisible(true);
return true;
}
@ -1786,7 +1862,7 @@ bool BlocksGraphicsView::moveChrono(GraphicsRulerItem* _chronometerItem, qreal _
return false;
}
void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* event)
{
if (needToIgnoreMouseEvent())
return;
@ -1795,26 +1871,26 @@ void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
if (m_bEmpty)
{
_event->accept();
event->accept();
return;
}
auto scenePos = mapToScene(_event->pos());
auto scenePos = mapToScene(event->pos());
scenePos.setX(m_offset + scenePos.x() / m_scale);
if (m_backgroundItem->mouseMove(scenePos))
{
_event->accept();
event->accept();
return;
}
if (m_mouseButtons == 0 && !m_selectionItem->isVisible() && !m_rulerItem->isVisible())
{
_event->accept();
event->accept();
return;
}
bool needUpdate = false;
const auto pos = _event->pos();
const auto pos = event->pos();
const auto delta = pos - m_mousePressPos;
m_mousePressPos = pos;
@ -1851,7 +1927,9 @@ void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
{
auto vbar = verticalScrollBar();
profiler_gui::BoolFlagGuard guard(m_bUpdatingRect, true); // Block scrollbars from updating scene rect to make it possible to do it only once
// Block scrollbars from updating scene rect to make it possible to do it only once
profiler_gui::BoolFlagGuard guard(m_bUpdatingRect, true);
vbar->setValue(vbar->value() - delta.y());
notifyVisibleRegionPosChange(m_offset - delta.x() / m_scale);
guard.restore();
@ -1913,16 +1991,16 @@ void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
repaintScene(); // repaint scene
}
_event->accept();
event->accept();
}
//////////////////////////////////////////////////////////////////////////
void BlocksGraphicsView::keyPressEvent(QKeyEvent* _event)
void BlocksGraphicsView::keyPressEvent(QKeyEvent* event)
{
static const int KeyStep = 100;
const int key = _event->key();
const int key = event->key();
switch (key)
{
@ -1971,14 +2049,14 @@ void BlocksGraphicsView::keyPressEvent(QKeyEvent* _event)
}
m_idleTime = 0;
_event->accept();
event->accept();
}
//////////////////////////////////////////////////////////////////////////
void BlocksGraphicsView::resizeEvent(QResizeEvent* _event)
void BlocksGraphicsView::resizeEvent(QResizeEvent* event)
{
Parent::resizeEvent(_event);
Parent::resizeEvent(event);
const QRectF previousRect = m_visibleSceneRect;
const int vbar_width = updateVisibleSceneRect(); // Update scene visible rect only once
@ -2062,7 +2140,13 @@ void BlocksGraphicsView::initMode()
connect(globalSignals, &profiler_gui::GlobalSignals::blocksTreeModeChanged, [this]()
{
if (!m_selectedBlocks.empty())
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_selectionItem->left()), position2time(m_selectionItem->right()), m_selectionItem->reverse());
emit intervalChanged(
m_selectedBlocks,
m_beginTime,
position2time(m_selectionItem->left()),
position2time(m_selectionItem->right()),
m_selectionItem->strict()
);
});
connect(globalSignals, &profiler_gui::GlobalSignals::chartSliderChanged, this, &This::onGraphicsScrollbarValueChange);
@ -2095,11 +2179,11 @@ void BlocksGraphicsView::onScrollbarValueChange(int)
updateVisibleSceneRect();
}
void BlocksGraphicsView::onGraphicsScrollbarValueChange(qreal _value)
void BlocksGraphicsView::onGraphicsScrollbarValueChange(qreal value)
{
if (!m_bEmpty)
{
m_offset = _value;
m_offset = value;
if (!m_bUpdatingRect)
{
updateVisibleSceneRect();
@ -2184,7 +2268,7 @@ void BlocksGraphicsView::onIdleTimeout()
if (m_popupWidget != nullptr)
return;
if (!window()->isActiveWindow())
if (window() == nullptr || !window()->isActiveWindow())
return;
auto focusWidget = qApp->focusWidget();
@ -2507,7 +2591,7 @@ void BlocksGraphicsView::onIdleTimeout()
lay->addWidget(new QLabel(QString::number(itemBlock.per_frame_stats->calls_number), widget), row + 5, col, Qt::AlignHCenter);
}
if (!profiler_gui::is_max(itemBlock.per_parent_stats->parent_block))// != item->threadId())
if (!profiler_gui::is_max(itemBlock.per_parent_stats->parent_block))
{
++col;
auto parent_duration = easyBlocksTree(itemBlock.per_parent_stats->parent_block).node->duration();
@ -2592,18 +2676,24 @@ void BlocksGraphicsView::onHierarchyFlagChange(bool)
if (changedSelection)
{
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_selectionItem->left()), position2time(m_selectionItem->right()), m_selectionItem->reverse());
emit intervalChanged(
m_selectedBlocks,
m_beginTime,
position2time(m_selectionItem->left()),
position2time(m_selectionItem->right()),
m_selectionItem->strict()
);
}
}
void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t _id)
void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t id)
{
if (m_pScrollbar == nullptr || m_pScrollbar->hystThread() == _id)
if (m_pScrollbar == nullptr || m_pScrollbar->hystThread() == id)
{
return;
}
if (_id == 0)
if (id == 0)
{
m_pScrollbar->setHistogramSource(0, nullptr);
return;
@ -2611,9 +2701,9 @@ void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t _id)
for (auto item : m_items)
{
if (item->threadId() == _id)
if (item->threadId() == id)
{
m_pScrollbar->setHistogramSource(_id, item->items(0));
m_pScrollbar->setHistogramSource(id, item->items(0));
bool changedSelection = false;
if (EASY_GLOBALS.only_current_thread_hierarchy)
@ -2634,7 +2724,13 @@ void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t _id)
if (changedSelection)
{
emit intervalChanged(m_selectedBlocks, m_beginTime, position2time(m_selectionItem->left()), position2time(m_selectionItem->right()), m_selectionItem->reverse());
emit intervalChanged(
m_selectedBlocks,
m_beginTime,
position2time(m_selectionItem->left()),
position2time(m_selectionItem->right()),
m_selectionItem->strict()
);
}
repaintScene();
@ -3007,7 +3103,7 @@ void ThreadNamesWidget::onIdleTimeout()
if (m_popupWidget != nullptr)
return;
if (!window()->isActiveWindow())
if (window() == nullptr || !window()->isActiveWindow())
return;
auto focusWidget = qApp->focusWidget();
@ -3123,7 +3219,7 @@ void ThreadNamesWidget::onIdleTimeout()
m_popupWidget = widget;
if (m_popupWidget != nullptr)
{
auto focusWidget = qApp->focusWidget();
focusWidget = qApp->focusWidget();
m_popupWidget->move(QCursor::pos());
m_popupWidget->show();

View File

@ -20,7 +20,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -236,9 +236,9 @@ public:
void mousePressEvent(QMouseEvent* _event) override;
void mouseDoubleClickEvent(QMouseEvent* _event) override;
void mouseReleaseEvent(QMouseEvent* _event) override;
void mouseMoveEvent(QMouseEvent* _event) override;
void keyPressEvent(QKeyEvent* _event) override;
void resizeEvent(QResizeEvent* _event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
void dragEnterEvent(QDragEnterEvent*) override {}
@ -288,7 +288,7 @@ private:
bool needToIgnoreMouseEvent() const;
GraphicsRulerItem* createRuler(bool _main = true);
bool moveChrono(GraphicsRulerItem* _chronometerItem, qreal _mouseX);
bool moveChrono(GraphicsRulerItem* ruler_item, qreal mouse_x);
void initMode();
int updateVisibleSceneRect();
void updateTimelineStep(qreal _windowWidth);
@ -313,7 +313,7 @@ private slots:
void onFlickerTimeout();
void onIdleTimeout();
void onHierarchyFlagChange(bool _value);
void onSelectedThreadChange(::profiler::thread_id_t _id);
void onSelectedThreadChange(::profiler::thread_id_t id);
void onSelectedBlockChange(unsigned int _block_index);
void onRefreshRequired();
void onThreadViewChanged();

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@
* : Moved sources of TreeWidgetItem into tree_widget_item.h/.cpp
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -95,13 +95,18 @@ protected:
class QLabel* m_hintLabel;
class ArbitraryValueToolTip* m_valueTooltip;
TreeMode m_mode;
int m_lastFoundIndex;
bool m_bLocked;
bool m_bSilentExpandCollapse;
bool m_bCaseSensitiveSearch;
bool m_bInitialized;
char m_columnsHiddenStatus[COL_COLUMNS_NUMBER];
int m_columnsMinimumWidth[COL_COLUMNS_NUMBER];
public:
using Parent::indexFromItem;
explicit BlocksTreeWidget(QWidget* _parent = nullptr);
~BlocksTreeWidget() override;
@ -114,11 +119,22 @@ public:
int findNext(const QString& _str, Qt::MatchFlags _flags);
int findPrev(const QString& _str, Qt::MatchFlags _flags);
void resetSearch(bool repaint = true);
TreeMode mode() const
{
return m_mode;
}
QTreeWidgetItem* lastFoundItem() const;
const QString& searchString() const;
bool caseSensitiveSearch() const;
int lastFoundIndex() const;
public slots:
void setTree(const unsigned int _blocksNumber, const ::profiler::thread_blocks_tree_t& _blocksTree);
void setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, ::profiler::timestamp_t _session_begin_time, ::profiler::timestamp_t _left, ::profiler::timestamp_t _right, bool _strict);
void updateHintLabelOnHover(bool hover);
protected:
@ -127,6 +143,8 @@ protected:
private slots:
void onHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
void onJumpToItemClicked(bool);
void onCollapseAllClicked(bool);
@ -140,6 +158,7 @@ private slots:
void onItemExpand(QTreeWidgetItem* _item);
void onItemCollapse(QTreeWidgetItem* _item);
void onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem*);
void onItemDoubleClicked(QTreeWidgetItem* _item, int _column);
void onSelectedThreadChange(::profiler::thread_id_t _id);
@ -192,6 +211,8 @@ public:
explicit HierarchyWidget(QWidget* _parent = nullptr);
~HierarchyWidget() override;
void enterEvent(QEvent* event) override;
void leaveEvent(QEvent* event) override;
void keyPressEvent(QKeyEvent* _event) override;
void contextMenuEvent(QContextMenuEvent* _event) override;
void dragEnterEvent(QDragEnterEvent*) override {}

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of BookmarkEditor.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -70,7 +70,6 @@ BookmarkEditor::BookmarkEditor(size_t bookmarkIndex, bool isNew, QWidget* parent
{
setAttribute(Qt::WA_DeleteOnClose, true);
setSizeGripEnabled(EASY_GLOBALS.use_custom_window_header);
setModal(true);
const auto& bookmark = EASY_GLOBALS.bookmarks[m_bookmarkIndex];
@ -128,7 +127,7 @@ BookmarkEditor::BookmarkEditor(size_t bookmarkIndex, bool isNew, QWidget* parent
contentLayout->addWidget(m_textEdit, 1);
const WindowHeader::Buttons buttons {WindowHeader::MaximizeButton | WindowHeader::CloseButton};
auto header = new WindowHeader(isNew ? "New bookmark" : "Edit bookmark", buttons, this);
auto header = new WindowHeader(isNew ? "New bookmark" : "Edit bookmark", buttons, *this);
auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(1, 1, 1, 1);
@ -174,10 +173,11 @@ void BookmarkEditor::onColorButtonClicked(bool)
QColorDialog colorDialog(palette.brush(QPalette::Background).color(), this);
colorDialog.exec();
palette.setBrush(QPalette::Background, QBrush(colorDialog.currentColor()));
auto color = colorDialog.currentColor();
palette.setBrush(QPalette::Background, QBrush(color));
m_colorButton->setPalette(palette);
m_colorButton->setStyleSheet(QString("background-color: %1;").arg(colorDialog.currentColor().name()));
m_colorButton->setStyleSheet(QString("background-color: %1;").arg(color.name()));
m_colorButton->style()->unpolish(m_colorButton);
m_colorButton->style()->polish(m_colorButton);
m_colorButton->update();

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of BookmarkEditor.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -96,13 +96,9 @@ struct EasyBlockItem Q_DECL_FINAL
}; // END of struct EasyBlockItem.
//#define EASY_TREE_WIDGET__USE_VECTOR
struct EasyBlock Q_DECL_FINAL
{
::profiler::BlocksTree tree;
#ifdef EASY_TREE_WIDGET__USE_VECTOR
uint32_t tree_item;
#endif
uint32_t graphics_item_index;
uint8_t graphics_item_level;
uint8_t graphics_item;
@ -112,9 +108,6 @@ struct EasyBlock Q_DECL_FINAL
EasyBlock(EasyBlock&& that) EASY_NOEXCEPT
: tree(::std::move(that.tree))
#ifdef EASY_TREE_WIDGET__USE_VECTOR
, tree_item(that.tree_item)
#endif
, graphics_item_index(that.graphics_item_index)
, graphics_item_level(that.graphics_item_level)
, graphics_item(that.graphics_item)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -53,26 +53,31 @@
* : limitations under the License.
************************************************************************/
#include <QMenu>
#include <QAbstractTextDocumentLayout>
#include <QAction>
#include <QActionGroup>
#include <QHeaderView>
#include <QString>
#include <QContextMenuEvent>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QKeyEvent>
#include <QSignalBlocker>
#include <QSettings>
#include <QLabel>
#include <QLineEdit>
#include <QToolBar>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMenu>
#include <QSettings>
#include <QSignalBlocker>
#include <QSplitter>
#include <QVariant>
#include <QString>
#include <QTextDocument>
#include <QTimer>
#include <QToolBar>
#include <QVariant>
#include <QVBoxLayout>
#include "descriptors_tree_widget.h"
#include "arbitrary_value_inspector.h"
#include "globals.h"
#include "arbitrary_value_inspector.h"
#include "text_highlighter.h"
#include "thread_pool.h"
#ifdef max
@ -85,18 +90,6 @@
//////////////////////////////////////////////////////////////////////////
enum DescColumns
{
DESC_COL_FILE_LINE = 0,
DESC_COL_TYPE,
DESC_COL_NAME,
DESC_COL_STATUS,
DESC_COL_COLUMNS_NUMBER
};
//////////////////////////////////////////////////////////////////////////
::profiler::EasyBlockStatus nextStatus(::profiler::EasyBlockStatus _status)
{
switch (_status)
@ -240,10 +233,15 @@ QVariant DescriptorsTreeItem::data(int _column, int _role) const
DescriptorsTreeWidget::DescriptorsTreeWidget(QWidget* _parent)
: Parent(_parent)
, m_lastFound(nullptr)
, m_lastFoundIndex(0)
, m_lastSearchColumn(-1)
, m_searchColumn(DESC_COL_NAME)
, m_bLocked(false)
, m_bCaseSensitiveSearch(false)
, m_bInitialized(false)
{
memset(m_columnsMinimumWidth, 0, sizeof(m_columnsMinimumWidth));
setAutoFillBackground(false);
setAlternatingRowColors(true);
setItemsExpandable(true);
@ -264,8 +262,11 @@ DescriptorsTreeWidget::DescriptorsTreeWidget(QWidget* _parent)
connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
connect(this, &Parent::itemDoubleClicked, this, &This::onDoubleClick);
connect(this, &Parent::currentItemChanged, this, &This::onCurrentItemChange);
connect(header(), &QHeaderView::sectionResized, this, &This::onHeaderSectionResized);
loadSettings();
setItemDelegateForColumn(m_searchColumn, new DescWidgetItemDelegate(this));
}
DescriptorsTreeWidget::~DescriptorsTreeWidget()
@ -279,11 +280,83 @@ DescriptorsTreeWidget::~DescriptorsTreeWidget()
saveSettings();
}
void DescriptorsTreeWidget::showEvent(QShowEvent* event)
{
Parent::showEvent(event);
if (!m_bInitialized)
{
#if !defined(_WIN32) && !defined(__APPLE__)
const auto padding = px(9);
#else
const auto padding = px(6);
#endif
auto header = this->header();
auto headerItem = this->headerItem();
auto f = header->font();
#if !defined(_WIN32) && !defined(__APPLE__)
f.setBold(true);
#endif
QFontMetrics fm(f);
const auto indicatorSize = header->isSortIndicatorShown() ? px(11) : 0;
for (int i = 0; i < DESC_COL_COLUMNS_NUMBER; ++i)
{
auto minSize = static_cast<int>(fm.width(headerItem->text(i)) * profiler_gui::FONT_METRICS_FACTOR + padding);
m_columnsMinimumWidth[i] = minSize;
if (header->isSortIndicatorShown() && header->sortIndicatorSection() == i)
{
minSize += indicatorSize;
}
if (header->sectionSize(i) < minSize)
{
header->resizeSection(i, minSize);
}
}
m_bInitialized = true;
}
}
//////////////////////////////////////////////////////////////////////////
void DescriptorsTreeWidget::resetSearch(bool repaint)
{
if (m_lastSearch.isEmpty())
{
return;
}
m_lastSearchColumn = m_searchColumn;
m_bCaseSensitiveSearch = false;
m_lastSearch.clear();
m_lastFound = nullptr;
m_lastFoundIndex = 0;
if (repaint)
{
viewport()->update();
}
}
void DescriptorsTreeWidget::setSearchColumn(int column)
{
const int prevColumn = m_searchColumn;
m_searchColumn = column;
if (m_searchColumn != prevColumn)
{
auto delegate = itemDelegateForColumn(prevColumn);
setItemDelegateForColumn(prevColumn, nullptr);
delete delegate;
setItemDelegateForColumn(m_searchColumn, new DescWidgetItemDelegate(this));
}
emit searchColumnChanged(column);
}
@ -292,6 +365,26 @@ int DescriptorsTreeWidget::searchColumn() const
return m_searchColumn;
}
QTreeWidgetItem* DescriptorsTreeWidget::lastFoundItem() const
{
return m_lastFound;
}
bool DescriptorsTreeWidget::caseSensitiveSearch() const
{
return m_bCaseSensitiveSearch;
}
const QString& DescriptorsTreeWidget::searchString() const
{
return m_lastSearch;
}
int DescriptorsTreeWidget::lastFoundIndex() const
{
return m_lastFoundIndex;
}
//////////////////////////////////////////////////////////////////////////
void DescriptorsTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
@ -348,10 +441,8 @@ void DescriptorsTreeWidget::clearSilent(bool _global)
const QSignalBlocker b(this);
setSortingEnabled(false);
m_lastFound = nullptr;
m_lastSearch.clear();
resetSearch(false);
m_highlightItems.clear();
m_items.clear();
if (topLevelItemCount() != 0)
@ -464,7 +555,23 @@ void DescriptorsTreeWidget::build()
setSortingEnabled(true);
sortByColumn(DESC_COL_FILE_LINE, Qt::AscendingOrder);
resizeColumnsToContents();
QTimer::singleShot(100, [this](){ onSelectedBlockChange(EASY_GLOBALS.selected_block); });
QTimer::singleShot(100, [this] { onSelectedBlockChange(EASY_GLOBALS.selected_block); });
}
//////////////////////////////////////////////////////////////////////////
void DescriptorsTreeWidget::onHeaderSectionResized(int logicalIndex, int /*oldSize*/, int newSize)
{
const auto indicatorSize = header()->isSortIndicatorShown() && header()->sortIndicatorSection() == logicalIndex ? px(11) : 0;
const auto minSize = m_columnsMinimumWidth[logicalIndex] + indicatorSize;
if (!m_bInitialized || newSize >= minSize)
{
return;
}
header()->resizeSection(logicalIndex, minSize);
}
//////////////////////////////////////////////////////////////////////////
@ -500,20 +607,8 @@ void DescriptorsTreeWidget::onDoubleClick(QTreeWidgetItem* _item, int _column)
void DescriptorsTreeWidget::onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem* _prev)
{
if (_prev != nullptr)
{
auto f = font();
for (int i = 0; i < DESC_COL_STATUS; ++i)
_prev->setFont(i, f);
}
if (_item != nullptr)
{
auto f = font();
f.setBold(true);
for (int i = 0; i < DESC_COL_STATUS; ++i)
_item->setFont(i, f);
if (::profiler_gui::is_max(EASY_GLOBALS.selected_block) && _item->parent() != nullptr)
{
const auto id = static_cast<DescriptorsTreeItem*>(_item)->desc();
@ -598,15 +693,6 @@ void DescriptorsTreeWidget::onSelectedBlockChange(uint32_t _block_index)
//////////////////////////////////////////////////////////////////////////
void DescriptorsTreeWidget::resetHighlight()
{
for (auto item : m_highlightItems) {
for (int i = 0; i < DESC_COL_COLUMNS_NUMBER; ++i)
item->setBackground(i, Qt::NoBrush);
}
m_highlightItems.clear();
}
void DescriptorsTreeWidget::loadSettings()
{
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME);
@ -635,19 +721,20 @@ int DescriptorsTreeWidget::findNext(const QString& _str, Qt::MatchFlags _flags)
{
if (_str.isEmpty())
{
resetHighlight();
m_lastSearchColumn = m_searchColumn;
resetSearch();
return 0;
}
const bool isNewSearch = (m_lastSearchColumn != m_searchColumn || m_lastSearch != _str);
auto itemsList = findItems(_str, Qt::MatchContains | Qt::MatchRecursive | _flags, m_searchColumn);
m_bCaseSensitiveSearch = _flags.testFlag(Qt::MatchCaseSensitive);
if (!isNewSearch)
{
if (!itemsList.empty())
{
bool stop = false;
int i = 0;
decltype(m_lastFound) next = nullptr;
for (auto item : itemsList)
{
@ -658,29 +745,24 @@ int DescriptorsTreeWidget::findNext(const QString& _str, Qt::MatchFlags _flags)
}
stop = item == m_lastFound;
++i;
}
m_lastFound = next == nullptr ? itemsList.front() : next;
m_lastFoundIndex = next == nullptr ? 0 : i;
}
else
{
m_lastFound = nullptr;
m_lastFoundIndex = 0;
}
}
else
{
resetHighlight();
m_lastSearchColumn = m_searchColumn;
m_lastSearch = _str;
m_lastFound = !itemsList.empty() ? itemsList.front() : nullptr;
for (auto item : itemsList)
{
m_highlightItems.push_back(item);
for (int i = 0; i < DESC_COL_COLUMNS_NUMBER; ++i)
item->setBackgroundColor(i, QColor::fromRgba(0x80000000 | (0x00ffffff & ::profiler::colors::Yellow)));
}
m_lastFoundIndex = 0;
}
if (m_lastFound != nullptr)
@ -689,6 +771,8 @@ int DescriptorsTreeWidget::findNext(const QString& _str, Qt::MatchFlags _flags)
setCurrentItem(m_lastFound);
}
viewport()->update();
return itemsList.size();
}
@ -696,48 +780,54 @@ int DescriptorsTreeWidget::findPrev(const QString& _str, Qt::MatchFlags _flags)
{
if (_str.isEmpty())
{
resetHighlight();
m_lastSearchColumn = m_searchColumn;
resetSearch();
return 0;
}
const bool isNewSearch = (m_lastSearchColumn != m_searchColumn || m_lastSearch != _str);
auto itemsList = findItems(_str, Qt::MatchContains | Qt::MatchRecursive | _flags, m_searchColumn);
m_bCaseSensitiveSearch = _flags.testFlag(Qt::MatchCaseSensitive);
if (!isNewSearch)
{
if (!itemsList.empty())
{
int i = 0;
decltype(m_lastFound) prev = nullptr;
for (auto item : itemsList)
{
if (item == m_lastFound)
{
--i;
break;
}
prev = item;
++i;
}
m_lastFound = prev == nullptr ? itemsList.back() : prev;
m_lastFoundIndex = prev == nullptr ? itemsList.length() - 1 : i;
}
else
{
m_lastFound = nullptr;
m_lastFoundIndex = 0;
}
}
else
{
resetHighlight();
m_lastSearchColumn = m_searchColumn;
m_lastSearch = _str;
m_lastFound = !itemsList.empty() ? itemsList.front() : nullptr;
m_highlightItems.reserve(itemsList.size());
for (auto item : itemsList)
if (!itemsList.empty())
{
m_highlightItems.push_back(item);
for (int i = 0; i < DESC_COL_COLUMNS_NUMBER; ++i)
item->setBackgroundColor(i, QColor::fromRgba(0x80000000 | (0x00ffffff & ::profiler::colors::Yellow)));
m_lastFound = itemsList.back();
m_lastFoundIndex = itemsList.length() - 1;
}
else
{
m_lastFound = nullptr;
m_lastFoundIndex = 0;
}
}
@ -747,6 +837,8 @@ int DescriptorsTreeWidget::findPrev(const QString& _str, Qt::MatchFlags _flags)
setCurrentItem(m_lastFound);
}
viewport()->update();
return itemsList.size();
}
@ -757,7 +849,7 @@ BlockDescriptorsWidget::BlockDescriptorsWidget(QWidget* _parent) : Parent(_paren
, m_tree(new DescriptorsTreeWidget(this))
, m_values(new ArbitraryValuesWidget(this))
, m_searchBox(new QLineEdit(this))
, m_foundNumber(new QLabel("0 matches", this))
, m_foundNumber(new QLabel(QStringLiteral("<font color=\"red\">0</font> matches"), this))
, m_searchButton(nullptr)
, m_bCaseSensitiveSearch(false)
{
@ -897,12 +989,24 @@ void BlockDescriptorsWidget::saveSettings()
void BlockDescriptorsWidget::keyPressEvent(QKeyEvent* _event)
{
if (_event->key() == Qt::Key_F3)
switch (_event->key())
{
if (_event->modifiers() & Qt::ShiftModifier)
findPrev(true);
else
findNext(true);
case Qt::Key_F3:
{
if (_event->modifiers() & Qt::ShiftModifier)
findPrev(true);
else
findNext(true);
break;
}
case Qt::Key_Escape:
{
m_searchBox->clear();
break;
}
default: break;
}
_event->accept();
@ -922,7 +1026,7 @@ void BlockDescriptorsWidget::showEvent(QShowEvent* event)
void BlockDescriptorsWidget::build()
{
m_tree->clearSilent(false);
m_foundNumber->setText(QString("0 matches"));
m_foundNumber->setText(QStringLiteral("<font color=\"red\">0</font> matches"));
m_foundNumber->hide();
m_tree->build();
m_values->rebuild();
@ -931,7 +1035,7 @@ void BlockDescriptorsWidget::build()
void BlockDescriptorsWidget::clear()
{
m_tree->clearSilent(true);
m_foundNumber->setText(QString("0 matches"));
m_foundNumber->setText(QStringLiteral("<font color=\"red\">0</font> matches"));
m_foundNumber->hide();
m_values->clear();
}
@ -943,7 +1047,7 @@ ArbitraryValuesWidget* BlockDescriptorsWidget::dataViewer() const
void BlockDescriptorsWidget::onSeachBoxReturnPressed()
{
if (m_searchButton->data().toBool() == true)
if (m_searchButton->data().toBool())
findNext(true);
else
findPrev(true);
@ -952,7 +1056,10 @@ void BlockDescriptorsWidget::onSeachBoxReturnPressed()
void BlockDescriptorsWidget::onSearchBoxTextChanged(const QString& _text)
{
if (_text.isEmpty())
{
m_foundNumber->hide();
m_tree->resetSearch();
}
}
void BlockDescriptorsWidget::onSearchColumnChanged(int column)
@ -989,15 +1096,27 @@ void BlockDescriptorsWidget::findNext(bool)
{
if (m_foundNumber->isVisible())
m_foundNumber->hide();
m_tree->resetSearch();
return;
}
auto matches = m_tree->findNext(text, m_bCaseSensitiveSearch ? Qt::MatchCaseSensitive : Qt::MatchFlags());
if (matches == 1)
m_foundNumber->setText(QString("1 match"));
if (matches == 0)
{
m_foundNumber->setText(QStringLiteral("<font color=\"red\">0</font> matches"));
}
else if (matches == 1)
{
m_foundNumber->setText(QStringLiteral("<font color=\"#f5f5f5\" style=\"background:#e040fb\">&nbsp;1&nbsp;</font> match"));
}
else
m_foundNumber->setText(QString("%1 matches").arg(matches));
{
auto i = m_tree->lastFoundIndex() + 1;
m_foundNumber->setText(QString("<font color=\"#f5f5f5\" style=\"background:#e040fb\">&nbsp;%1&nbsp;</font> of "
"<font style=\"background:#ffeb3b\">&nbsp;%2&nbsp;</font> matches")
.arg(i).arg(matches));
}
if (!m_foundNumber->isVisible())
m_foundNumber->show();
@ -1010,15 +1129,27 @@ void BlockDescriptorsWidget::findPrev(bool)
{
if (m_foundNumber->isVisible())
m_foundNumber->hide();
m_tree->resetSearch();
return;
}
auto matches = m_tree->findPrev(text, m_bCaseSensitiveSearch ? Qt::MatchCaseSensitive : Qt::MatchFlags());
if (matches == 1)
m_foundNumber->setText(QString("1 match"));
if (matches == 0)
{
m_foundNumber->setText(QStringLiteral("<font color=\"red\">0</font> matches"));
}
else if (matches == 1)
{
m_foundNumber->setText(QStringLiteral("<font color=\"#f5f5f5\" style=\"background:#e040fb\">&nbsp;1&nbsp;</font> match"));
}
else
m_foundNumber->setText(QString("%1 matches").arg(matches));
{
auto i = m_tree->lastFoundIndex() + 1;
m_foundNumber->setText(QString("<font color=\"#f5f5f5\" style=\"background:#e040fb\">&nbsp;%1&nbsp;</font> of "
"<font style=\"background:#ffeb3b\">&nbsp;%2&nbsp;</font> matches")
.arg(i).arg(matches));
}
if (!m_foundNumber->isVisible())
m_foundNumber->show();
@ -1029,7 +1160,7 @@ void BlockDescriptorsWidget::findNextFromMenu(bool _checked)
if (!_checked)
return;
if (m_searchButton->data().toBool() == false)
if (!m_searchButton->data().toBool())
{
m_searchButton->setData(true);
m_searchButton->setText(tr("Find next"));
@ -1046,7 +1177,7 @@ void BlockDescriptorsWidget::findPrevFromMenu(bool _checked)
if (!_checked)
return;
if (m_searchButton->data().toBool() == true)
if (m_searchButton->data().toBool())
{
m_searchButton->setData(false);
m_searchButton->setText(tr("Find prev"));
@ -1059,3 +1190,103 @@ void BlockDescriptorsWidget::findPrevFromMenu(bool _checked)
}
//////////////////////////////////////////////////////////////////////////
DescWidgetItemDelegate::DescWidgetItemDelegate(DescriptorsTreeWidget* parent)
: QStyledItemDelegate(parent)
, m_treeWidget(parent)
{
}
DescWidgetItemDelegate::~DescWidgetItemDelegate()
{
}
void DescWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyledItemDelegate::paint(painter, option, index);
highlightMatchingText(painter, option, index);
}
void DescWidgetItemDelegate::highlightMatchingText(
QPainter* painter,
const QStyleOptionViewItem& option,
const QModelIndex& index
) const {
if (m_treeWidget->lastFoundItem() != nullptr && !m_treeWidget->searchString().isEmpty())
{
// Highlight matching word
auto displayData = m_treeWidget->model()->data(index);
if (displayData.canConvert<QString>())
{
const auto text = displayData.toString();
const auto caseSensitivity = m_treeWidget->caseSensitiveSearch() ? Qt::CaseSensitive : Qt::CaseInsensitive;
if (text.contains(m_treeWidget->searchString(), caseSensitivity))
{
auto lastFoundIndex = m_treeWidget->indexFromItem(m_treeWidget->lastFoundItem(), index.column());
highlightMatchingText(
painter,
option,
text,
m_treeWidget->searchString(),
caseSensitivity,
lastFoundIndex == index
);
}
}
}
}
void DescWidgetItemDelegate::highlightMatchingText(
QPainter* painter,
const QStyleOptionViewItem& option,
const QString& text,
const QString& pattern,
Qt::CaseSensitivity caseSensitivity,
bool current
) const {
const auto str = pattern.toStdString();
(void)str;
QTextDocument doc;
doc.setDefaultFont(painter->font());
doc.setTextWidth(option.rect.width());
const auto elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight, std::max(option.rect.width(), 0));
doc.setHtml(elidedText);
TextHighlighter highlighter(
&doc,
painter->pen().color(),
QColor::fromRgb(profiler::colors::Grey100),
pattern,
caseSensitivity,
current
);
painter->save();
#ifdef _WIN32
EASY_CONSTEXPR int fixed_padding_x = -1;
EASY_CONSTEXPR int fixed_padding_y = 0;
#else
EASY_CONSTEXPR int fixed_padding_x = -1;
EASY_CONSTEXPR int fixed_padding_y = -1;
#endif
auto dh = std::max((option.rect.height() - doc.size().height()) * 0.5, 0.);
painter->translate(option.rect.left() + fixed_padding_x, option.rect.top() + dh + fixed_padding_y);
QRect clip(0, 0, option.rect.width(), option.rect.height());
painter->setClipRect(clip);
QAbstractTextDocumentLayout::PaintContext ctx;
ctx.clip = clip;
ctx.palette.setColor(QPalette::Text, Qt::transparent);
doc.documentLayout()->draw(painter, ctx);
painter->restore();
}
//////////////////////////////////////////////////////////////////////////

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -67,6 +67,18 @@
//////////////////////////////////////////////////////////////////////////
enum DescColumns
{
DESC_COL_FILE_LINE = 0,
DESC_COL_TYPE,
DESC_COL_NAME,
DESC_COL_STATUS,
DESC_COL_COLUMNS_NUMBER
};
//////////////////////////////////////////////////////////////////////////
class DescriptorsTreeItem : public QTreeWidgetItem
{
using Parent = QTreeWidgetItem;
@ -121,19 +133,21 @@ class DescriptorsTreeWidget : public QTreeWidget
using This = DescriptorsTreeWidget;
using Items = ::std::vector<DescriptorsTreeItem*>;
using TreeItems = ::std::vector<QTreeWidgetItem*>;
using ExpandedFiles = ::std::unordered_set<::std::string>;
protected:
ExpandedFiles m_expandedFilesTemp;
Items m_items;
TreeItems m_highlightItems;
QString m_lastSearch;
QTreeWidgetItem* m_lastFound;
int m_columnsMinimumWidth[DESC_COL_COLUMNS_NUMBER];
int m_lastFoundIndex;
int m_lastSearchColumn;
int m_searchColumn;
bool m_bLocked;
bool m_bCaseSensitiveSearch;
bool m_bInitialized;
public:
@ -141,17 +155,29 @@ public:
explicit DescriptorsTreeWidget(QWidget* _parent = nullptr);
~DescriptorsTreeWidget() override;
void contextMenuEvent(QContextMenuEvent* _event) override;
void showEvent(class QShowEvent* event) override;
public:
using Parent::indexFromItem;
// Public non-virtual methods
int findNext(const QString& _str, Qt::MatchFlags _flags);
int findPrev(const QString& _str, Qt::MatchFlags _flags);
void resetSearch(bool repaint = true);
void setSearchColumn(int column);
int searchColumn() const;
QTreeWidgetItem* lastFoundItem() const;
const QString& searchString() const;
bool caseSensitiveSearch() const;
int lastFoundIndex() const;
signals:
void searchColumnChanged(int column);
@ -163,6 +189,7 @@ public slots:
private slots:
void onHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
void onBlockStatusChangeClicked(bool);
void onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem* _prev);
void onItemExpand(QTreeWidgetItem* _item);
@ -175,7 +202,6 @@ private:
// Private methods
void resetHighlight();
void loadSettings();
void saveSettings();
@ -243,6 +269,35 @@ private:
}; // END of class BlockDescriptorsWidget.
//////////////////////////////////////////////////////////////////////////
class DescWidgetItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
DescriptorsTreeWidget* m_treeWidget;
public:
explicit DescWidgetItemDelegate(DescriptorsTreeWidget* parent = nullptr);
~DescWidgetItemDelegate() override;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
private:
void highlightMatchingText(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void highlightMatchingText(
QPainter* painter,
const QStyleOptionViewItem& option,
const QString& text,
const QString& pattern,
Qt::CaseSensitivity caseSensitivity,
bool current
) const;
}; // END of class DescWidgetItemDelegate.
//////////////////////////////////////////////////////////////////////////
#endif // EASY_DESCRIPTORS_WIDGET_H

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of Dialog.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -75,7 +75,7 @@ Dialog::Dialog(QWidget* parent, const QString& title, QWidget* content, WindowHe
{
setSizeGripEnabled(EASY_GLOBALS.use_custom_window_header);
m_header = new WindowHeader(title, headerButtons, this);
m_header = new WindowHeader(title, headerButtons, *this);
auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(1, 1, 1, 1);

View File

@ -9,7 +9,7 @@
* : for all dialogs in the application.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -268,11 +268,12 @@ FpsWidget::FpsWidget(QWidget* _parent) : Parent(_parent), m_fpsItem(nullptr)
centerOn(0, 0);
// Dirty hack for QDockWidget stupid initial size policy :(
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
setFixedHeight(10); // Set very small height to enable appropriate minimum height on the application startup
QTimer::singleShot(100, [this]
{
// Now set appropriate minimum height
setMinimumHeight((QFontMetrics(scene()->font()).height() + 3) * 6);
setMinimumHeight((QFontMetrics(scene()->font()).height() + px(3)) * 3);
setMaximumHeight(minimumHeight() * 20);
});
}
@ -294,6 +295,16 @@ void FpsWidget::addPoint(uint32_t _maxFrameTime, uint32_t _avgFrameTime)
scene()->update();
}
QSize FpsWidget::sizeHint() const
{
return QSize(Parent::sizeHint().width(), minimumHeight());
}
QSize FpsWidget::minimumSizeHint() const
{
return QSize(Parent::minimumSizeHint().width(), minimumHeight());
}
void FpsWidget::resizeEvent(QResizeEvent* _event)
{
Parent::resizeEvent(_event);

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -109,6 +109,8 @@ public:
explicit FpsWidget(QWidget* _parent = nullptr);
~FpsWidget() override;
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
void resizeEvent(QResizeEvent* _event) override;
void hideEvent(QHideEvent* _event) override;
void showEvent(QShowEvent* _event) override;

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -59,69 +59,69 @@
namespace profiler_gui {
Globals& Globals::instance()
{
// It's okay even without C++11 "magic statics" feature because first call happens
// on application initialization - there is only one thread and no data races occur.
static Globals globals;
return globals;
}
Globals& Globals::instance()
{
// It's okay even without C++11 "magic statics" feature because first call happens
// on application initialization - there is only one thread and no data races occur.
static Globals globals;
return globals;
}
Globals::Fonts::Fonts()
: default_font(::profiler_gui::EFont("DejaVu Sans", 13))
, background(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Bold))
, ruler(::profiler_gui::EFont("DejaVu Sans", 16, QFont::Bold))
, item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium))
, selected_item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium))
{
Globals::Fonts::Fonts()
: default_font(::profiler_gui::EFont("DejaVu Sans", 13))
, background(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Bold))
, ruler(::profiler_gui::EFont("DejaVu Sans", 16, QFont::Bold))
, item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium))
, selected_item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium))
{
}
}
Globals::Globals()
: theme("default")
, pid(0)
, begin_time(0)
, selected_thread(0U)
, selected_block(::profiler_gui::numeric_max<decltype(selected_block)>())
, selected_block_id(::profiler_gui::numeric_max<decltype(selected_block_id)>())
, version(0)
, frame_time(16700)
, blocks_spacing(0)
, blocks_size_min(2)
, blocks_narrow_size(20)
, max_fps_history(90)
, fps_timer_interval(500)
, fps_widget_line_width(2)
, bookmark_default_color(0)
, chrono_text_position(RulerTextPosition_Top)
, time_units(TimeUnits_ms)
, connected(false)
, has_local_changes(false)
, use_custom_window_header(true)
, is_right_window_header_controls(true)
, fps_enabled(true)
, use_decorated_thread_name(false)
, hex_thread_id(false)
, enable_event_markers(true)
, enable_statistics(true)
, enable_zero_length(true)
, add_zero_blocks_to_hierarchy(false)
, draw_graphics_items_borders(true)
, hide_narrow_children(false)
, hide_minsize_blocks(false)
, display_only_relevant_stats(true)
, collapse_items_on_tree_close(false)
, all_items_expanded_by_default(true)
, only_current_thread_hierarchy(false)
, highlight_blocks_with_same_id(true)
, selecting_block_changes_thread(true)
, auto_adjust_histogram_height(true)
, auto_adjust_chart_height(false)
, display_only_frames_on_histogram(false)
, bind_scene_and_tree_expand_status(true)
{
Globals::Globals()
: theme("default")
, pid(0)
, begin_time(0)
, selected_thread(0U)
, selected_block(::profiler_gui::numeric_max<decltype(selected_block)>())
, selected_block_id(::profiler_gui::numeric_max<decltype(selected_block_id)>())
, version(0)
, frame_time(16700)
, blocks_spacing(0)
, blocks_size_min(2)
, blocks_narrow_size(20)
, max_fps_history(90)
, fps_timer_interval(500)
, fps_widget_line_width(2)
, bookmark_default_color(0)
, chrono_text_position(RulerTextPosition_Top)
, time_units(TimeUnits_ms)
, connected(false)
, has_local_changes(false)
, use_custom_window_header(true)
, is_right_window_header_controls(true)
, fps_enabled(true)
, use_decorated_thread_name(false)
, hex_thread_id(false)
, enable_event_markers(true)
, enable_statistics(true)
, enable_zero_length(true)
, add_zero_blocks_to_hierarchy(false)
, draw_graphics_items_borders(true)
, hide_narrow_children(false)
, hide_minsize_blocks(false)
, display_only_relevant_stats(false)
, collapse_items_on_tree_close(false)
, all_items_expanded_by_default(true)
, only_current_thread_hierarchy(false)
, highlight_blocks_with_same_id(true)
, selecting_block_changes_thread(true)
, auto_adjust_histogram_height(true)
, auto_adjust_chart_height(false)
, display_only_frames_on_histogram(false)
, bind_scene_and_tree_expand_status(true)
{
}
}
} // END of namespace profiler_gui.

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -273,38 +273,38 @@ inline profiler::SerializedBlockDescriptor& easyDescriptor(profiler::block_id_t
return *EASY_GLOBALS.descriptors[i];
}
inline profiler::SerializedBlockDescriptor& easyDescriptor(const profiler::BlocksTree& _block) {
return easyDescriptor(_block.node->id());
inline profiler::SerializedBlockDescriptor& easyDescriptor(const profiler::BlocksTree& block) {
return easyDescriptor(block.node->id());
}
EASY_FORCE_INLINE const profiler::BlocksTree& easyBlocksTree(profiler::block_index_t i) {
return easyBlock(i).tree;
}
EASY_FORCE_INLINE const char* easyBlockName(const profiler::BlocksTree& _block) {
const char* name = _block.node->name();
return *name != 0 ? name : easyDescriptor(_block.node->id()).name();
EASY_FORCE_INLINE const char* easyBlockName(const profiler::BlocksTree& block) {
const char* name = block.node->name();
return *name != 0 ? name : easyDescriptor(block.node->id()).name();
}
EASY_FORCE_INLINE const char* easyBlockName(const profiler::BlocksTree& _block, const profiler::SerializedBlockDescriptor& _desc) {
const char* name = _block.node->name();
return *name != 0 ? name : _desc.name();
EASY_FORCE_INLINE const char* easyBlockName(const profiler::BlocksTree& block, const profiler::SerializedBlockDescriptor& desc) {
const char* name = block.node->name();
return *name != 0 ? name : desc.name();
}
EASY_FORCE_INLINE const char* easyBlockName(profiler::block_index_t i) {
return easyBlockName(easyBlock(i).tree);
}
inline qreal sceneX(profiler::timestamp_t _time) {
return PROF_MICROSECONDS(qreal(_time - EASY_GLOBALS.begin_time));
inline qreal sceneX(profiler::timestamp_t time) {
return PROF_MICROSECONDS(qreal(time - EASY_GLOBALS.begin_time));
}
inline QString imagePath(const QString& _resource) {
return QString(":/images/%1/%2").arg(EASY_GLOBALS.theme).arg(_resource);
inline QString imagePath(const QString& resource_name) {
return QString(":/images/%1/%2").arg(EASY_GLOBALS.theme).arg(resource_name);
}
inline QString imagePath(const char* _resource) {
return QString(":/images/%1/%2").arg(EASY_GLOBALS.theme).arg(_resource);
inline QString imagePath(const char* resource_name) {
return QString(":/images/%1/%2").arg(EASY_GLOBALS.theme).arg(resource_name);
}
inline QSize applicationIconsSize() {

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of GraphicsBlockItem.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -1146,7 +1146,7 @@ void GraphicsBlockItem::getBlocks(qreal _left, qreal _right, ::profiler_gui::Tre
size_t itemIndex = 0;
if (first != level0.end())
{
itemIndex = first - level0.begin();
itemIndex = static_cast<size_t>(std::distance(level0.begin(), first));
if (itemIndex > 0)
itemIndex -= 1;
}

View File

@ -9,7 +9,7 @@
* : used to draw profiler blocks on graphics scene.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of GraphicsImageItem.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -70,6 +70,7 @@ GraphicsImageItem::GraphicsImageItem() : Parent(nullptr)
, m_maxValue(0)
, m_minValue(0)
, m_timer(::std::bind(&This::onTimeout, this))
, m_bEmpty(true)
, m_bPermitImageUpdate(true)
{
m_bReady = false;
@ -97,6 +98,16 @@ void GraphicsImageItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
m_boundingRect.setRect(x, y, w, h);
}
bool GraphicsImageItem::isEmpty() const
{
return m_bEmpty;
}
void GraphicsImageItem::setEmpty(bool empty)
{
m_bEmpty = empty;
}
void GraphicsImageItem::setMousePos(const QPointF& pos)
{
m_mousePos = pos;
@ -173,6 +184,11 @@ bool GraphicsImageItem::cancelImageUpdate()
bool GraphicsImageItem::pickTopValue()
{
if (isEmpty())
{
return false;
}
const auto y = m_mousePos.y();
if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom())
{
@ -187,6 +203,11 @@ bool GraphicsImageItem::pickTopValue()
bool GraphicsImageItem::increaseTopValue()
{
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_topValue < m_maxValue)
{
auto step = 0.05 * (m_maxValue - m_bottomValue);
@ -202,6 +223,11 @@ bool GraphicsImageItem::increaseTopValue()
bool GraphicsImageItem::decreaseTopValue()
{
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_topValue > m_bottomValue)
{
auto step = 0.05 * (m_maxValue - m_bottomValue);
@ -221,6 +247,11 @@ bool GraphicsImageItem::decreaseTopValue()
bool GraphicsImageItem::pickBottomValue()
{
if (isEmpty())
{
return false;
}
const auto y = m_mousePos.y();
if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom())
{
@ -235,6 +266,11 @@ bool GraphicsImageItem::pickBottomValue()
bool GraphicsImageItem::increaseBottomValue()
{
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_bottomValue < m_topValue)
{
auto step = 0.05 * (m_topValue - m_minValue);
@ -254,6 +290,11 @@ bool GraphicsImageItem::increaseBottomValue()
bool GraphicsImageItem::decreaseBottomValue()
{
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_bottomValue > m_minValue)
{
auto step = 0.05 * (m_topValue - m_minValue);
@ -270,7 +311,7 @@ bool GraphicsImageItem::decreaseBottomValue()
void GraphicsImageItem::paintImage(QPainter* _painter)
{
_painter->setPen(Qt::NoPen);
_painter->drawImage(0, m_boundingRect.top(), m_image);
_painter->drawImage(0, static_cast<int>(m_boundingRect.top()), m_image);
}
void GraphicsImageItem::paintImage(QPainter* _painter, qreal _scale, qreal _sceneLeft, qreal _sceneRight,

View File

@ -9,7 +9,7 @@
* : used to display, scroll and zoom QImage on graphics scene.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -80,11 +80,12 @@ protected:
qreal m_bottomValue;
qreal m_maxValue;
qreal m_minValue;
bool m_bEmpty;
std::atomic_bool m_bReady;
private:
Timer m_timer;
Timer m_timer;
bool m_bPermitImageUpdate; ///< Is false when m_workerThread is parsing input dataset (when setSource(_block_id) is called)
public:
@ -111,6 +112,7 @@ protected:
public:
bool isEmpty() const;
void onValueChanged();
void setMousePos(const QPointF& pos);
void setMousePos(qreal x, qreal y);
@ -120,6 +122,7 @@ public:
protected:
void setEmpty(bool empty);
void paintImage(QPainter* _painter);
void paintImage(QPainter* _painter, qreal _scale, qreal _sceneLeft, qreal _sceneRight,
qreal _visibleRegionLeft, qreal _visibleRegionWidth);

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -72,16 +72,17 @@
//////////////////////////////////////////////////////////////////////////
GraphicsRulerItem::GraphicsRulerItem(bool _main)
GraphicsRulerItem::GraphicsRulerItem(bool main)
: Parent()
, m_color(profiler_gui::RULER_COLOR)
, m_left(0)
, m_right(0)
, m_bMain(_main)
, m_bReverse(false)
, m_bHoverIndicator(false)
, m_bHoverLeftBorder(false)
, m_bHoverRightBorder(false)
, m_main(main)
, m_reverse(false)
, m_strict(false)
, m_hover_on_indicator(false)
, m_hover_on_left_border(false)
, m_hover_on_right_border(false)
{
m_indicator.reserve(3);
}
@ -92,10 +93,10 @@ GraphicsRulerItem::~GraphicsRulerItem()
QRectF GraphicsRulerItem::boundingRect() const
{
return m_boundingRect;
return m_bounding_rect;
}
void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem*, QWidget*)
void GraphicsRulerItem::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
{
auto const sceneView = view();
const auto currentScale = sceneView->scale();
@ -103,19 +104,19 @@ void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
const auto visibleSceneRect = sceneView->visibleSceneRect();
auto sceneLeft = offset, sceneRight = offset + visibleSceneRect.width() / currentScale;
if (m_bMain)
if (m_main)
m_indicator.clear();
if (m_left > sceneRight || m_right < sceneLeft)
{
// This item is out of screen
if (m_bMain)
if (m_main)
{
const int size = m_bHoverIndicator ? 12 : 10;
const int size = m_hover_on_indicator ? 12 : 10;
auto vcenter = visibleSceneRect.top() + visibleSceneRect.height() * 0.5;
auto color = QColor::fromRgb(m_color.rgb());
auto pen = _painter->pen();
auto pen = painter->pen();
pen.setColor(color);
m_indicator.clear();
@ -134,19 +135,24 @@ void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
m_indicator.push_back(QPointF(sceneLeft + size, vcenter + size));
}
_painter->save();
_painter->setTransform(QTransform::fromTranslate(-x(), -y()), true);
_painter->setBrush(m_bHoverIndicator ? QColor::fromRgb(0xffff0000) : color);
_painter->setPen(pen);
_painter->drawPolygon(m_indicator);
_painter->restore();
painter->save();
painter->setTransform(QTransform::fromTranslate(-x(), -y()), true);
painter->setBrush(m_hover_on_indicator ? QColor::fromRgb(0xffff0000) : color);
painter->setPen(pen);
painter->drawPolygon(m_indicator);
painter->restore();
}
return;
}
auto selectedInterval = width();
QRectF rect((m_left - offset) * currentScale, visibleSceneRect.top(), ::std::max(selectedInterval * currentScale, 1.0), visibleSceneRect.height());
QRectF rect(
(m_left - offset) * currentScale,
visibleSceneRect.top(),
::std::max(selectedInterval * currentScale, 1.0),
visibleSceneRect.height()
);
selectedInterval = units2microseconds(selectedInterval);
const QString text = profiler_gui::timeStringReal(EASY_GLOBALS.time_units, selectedInterval); // Displayed text
@ -156,10 +162,10 @@ void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
// Paint!--------------------------
_painter->save();
painter->save();
// instead of scrollbar we're using manual offset
_painter->setTransform(QTransform::fromTranslate(-x(), -y()), true);
painter->setTransform(QTransform::fromTranslate(-x(), -y()), true);
if (m_left < sceneLeft)
rect.setLeft(0);
@ -174,87 +180,87 @@ void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
g.setColorAt(0.2, QColor::fromRgba(0x14000000 | rgb));
g.setColorAt(0.8, QColor::fromRgba(0x14000000 | rgb));
g.setColorAt(1, m_color);
_painter->setBrush(g);
_painter->setPen(Qt::NoPen);
_painter->drawRect(rect);
painter->setBrush(g);
painter->setPen(Qt::NoPen);
painter->drawRect(rect);
// draw left and right borders
_painter->setBrush(Qt::NoBrush);
if (m_bMain && !m_bReverse)
painter->setBrush(Qt::NoBrush);
if (m_main && !m_strict)
{
QPen p(QColor::fromRgba(0xd0000000 | rgb));
p.setStyle(Qt::DotLine);
_painter->setPen(p);
painter->setPen(p);
}
else
{
_painter->setPen(QColor::fromRgba(0xd0000000 | rgb));
painter->setPen(QColor::fromRgba(0xd0000000 | rgb));
}
if (m_left > sceneLeft)
{
if (m_bHoverLeftBorder)
if (m_hover_on_left_border)
{
// Set bold if border is hovered
QPen p = _painter->pen();
QPen p = painter->pen();
p.setWidth(3);
_painter->setPen(p);
painter->setPen(p);
}
_painter->drawLine(QPointF(rect.left(), rect.top()), QPointF(rect.left(), rect.bottom()));
painter->drawLine(QPointF(rect.left(), rect.top()), QPointF(rect.left(), rect.bottom()));
}
if (m_right < sceneRight)
{
if (m_bHoverLeftBorder)
if (m_hover_on_left_border)
{
// Restore width
QPen p = _painter->pen();
QPen p = painter->pen();
p.setWidth(1);
_painter->setPen(p);
painter->setPen(p);
}
else if (m_bHoverRightBorder)
else if (m_hover_on_right_border)
{
// Set bold if border is hovered
QPen p = _painter->pen();
QPen p = painter->pen();
p.setWidth(3);
_painter->setPen(p);
painter->setPen(p);
}
_painter->drawLine(QPointF(rect.right(), rect.top()), QPointF(rect.right(), rect.bottom()));
painter->drawLine(QPointF(rect.right(), rect.top()), QPointF(rect.right(), rect.bottom()));
// This is not necessary because another setPen() invoked for draw text
//if (m_bHoverRightBorder)
//if (m_hover_on_right_border)
//{
// // Restore width
// QPen p = _painter->pen();
// QPen p = painter->pen();
// p.setWidth(1);
// _painter->setPen(p);
// painter->setPen(p);
//}
}
// draw text
_painter->setCompositionMode(QPainter::CompositionMode_Difference); // This lets the text to be visible on every background
_painter->setRenderHint(QPainter::TextAntialiasing);
_painter->setPen(0x00ffffff - rgb);
_painter->setFont(EASY_GLOBALS.font.ruler);
painter->setCompositionMode(QPainter::CompositionMode_Difference); // This lets the text to be visible on every background
painter->setRenderHint(QPainter::TextAntialiasing);
painter->setPen(0x00ffffff - rgb);
painter->setFont(EASY_GLOBALS.font.ruler);
int textFlags = 0;
switch (EASY_GLOBALS.chrono_text_position)
{
case profiler_gui::RulerTextPosition_Top:
textFlags = Qt::AlignTop | Qt::AlignHCenter;
if (!m_bMain) rect.setTop(rect.top() + textRect.height() * 0.75);
if (!m_main) rect.setTop(rect.top() + textRect.height() * 0.75);
break;
case profiler_gui::RulerTextPosition_Center:
textFlags = Qt::AlignCenter;
if (!m_bMain) rect.setTop(rect.top() + textRect.height() * 1.5);
if (!m_main) rect.setTop(rect.top() + textRect.height() * 1.5);
break;
case profiler_gui::RulerTextPosition_Bottom:
textFlags = Qt::AlignBottom | Qt::AlignHCenter;
if (!m_bMain) rect.setHeight(rect.height() - textRect.height() * 0.75);
if (!m_main) rect.setHeight(rect.height() - textRect.height() * 0.75);
break;
}
@ -262,8 +268,8 @@ void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
if (textRect_width < rect.width())
{
// Text will be drawed inside rectangle
_painter->drawText(rect, textFlags, text);
_painter->restore();
painter->drawText(rect, textFlags, text);
painter->restore();
return;
}
@ -284,101 +290,107 @@ void GraphicsRulerItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem
}
//else // Text will be drawed inside rectangle
_painter->drawText(rect, textFlags | Qt::TextDontClip, text);
painter->drawText(rect, textFlags | Qt::TextDontClip, text);
_painter->restore();
painter->restore();
// END Paint!~~~~~~~~~~~~~~~~~~~~~~
}
void GraphicsRulerItem::hide()
{
m_bHoverIndicator = false;
m_bHoverLeftBorder = false;
m_bHoverRightBorder = false;
m_bReverse = false;
m_hover_on_indicator = false;
m_hover_on_left_border = false;
m_hover_on_right_border = false;
m_reverse = false;
m_strict = false;
Parent::hide();
}
bool GraphicsRulerItem::indicatorContains(const QPointF& _pos) const
bool GraphicsRulerItem::indicatorContains(const QPointF& pos) const
{
if (m_indicator.empty())
return false;
const auto itemX = toItem(_pos.x());
return m_indicator.containsPoint(QPointF(itemX, _pos.y()), Qt::OddEvenFill);
const auto itemX = toItem(pos.x());
return m_indicator.containsPoint(QPointF(itemX, pos.y()), Qt::OddEvenFill);
}
void GraphicsRulerItem::setHoverLeft(bool _hover)
void GraphicsRulerItem::setHoverLeft(bool hover)
{
m_bHoverLeftBorder = _hover;
m_hover_on_left_border = hover;
}
void GraphicsRulerItem::setHoverRight(bool _hover)
void GraphicsRulerItem::setHoverRight(bool hover)
{
m_bHoverRightBorder = _hover;
m_hover_on_right_border = hover;
}
bool GraphicsRulerItem::hoverLeft(qreal _x) const
bool GraphicsRulerItem::hoverLeft(qreal x) const
{
const auto dx = fabs(_x - m_left) * view()->scale();
const auto dx = fabs(x - m_left) * view()->scale();
return dx < 4;
}
bool GraphicsRulerItem::hoverRight(qreal _x) const
bool GraphicsRulerItem::hoverRight(qreal x) const
{
const auto dx = fabs(_x - m_right) * view()->scale();
const auto dx = fabs(x - m_right) * view()->scale();
return dx < 4;
}
QPointF GraphicsRulerItem::toItem(const QPointF& _pos) const
QPointF GraphicsRulerItem::toItem(const QPointF& pos) const
{
const auto sceneView = view();
return QPointF((_pos.x() - sceneView->offset()) * sceneView->scale() - x(), _pos.y());
return QPointF((pos.x() - sceneView->offset()) * sceneView->scale() - x(), pos.y());
}
qreal GraphicsRulerItem::toItem(qreal _x) const
qreal GraphicsRulerItem::toItem(qreal x) const
{
const auto sceneView = view();
return (_x - sceneView->offset()) * sceneView->scale() - x();
return (x - sceneView->offset()) * sceneView->scale() - this->x();
}
void GraphicsRulerItem::setColor(const QColor& _color)
void GraphicsRulerItem::setColor(const QColor& color)
{
m_color = _color;
m_color = color;
}
void GraphicsRulerItem::setBoundingRect(qreal x, qreal y, qreal w, qreal h)
{
m_boundingRect.setRect(x, y, w, h);
m_bounding_rect.setRect(x, y, w, h);
}
void GraphicsRulerItem::setBoundingRect(const QRectF& _rect)
void GraphicsRulerItem::setBoundingRect(const QRectF& rect)
{
m_boundingRect = _rect;
m_bounding_rect = rect;
}
void GraphicsRulerItem::setLeftRight(qreal _left, qreal _right)
void GraphicsRulerItem::setLeftRight(qreal left, qreal right)
{
if (_left < _right)
if (left < right)
{
m_left = _left;
m_right = _right;
m_left = left;
m_right = right;
}
else
{
m_left = _right;
m_right = _left;
m_left = right;
m_right = left;
}
}
void GraphicsRulerItem::setReverse(bool _reverse)
void GraphicsRulerItem::setReverse(bool reverse)
{
m_bReverse = _reverse;
m_reverse = reverse;
}
void GraphicsRulerItem::setHoverIndicator(bool _hover)
void GraphicsRulerItem::setStrict(bool strict)
{
m_bHoverIndicator = _hover;
m_strict = strict;
}
void GraphicsRulerItem::setHoverIndicator(bool hover)
{
m_hover_on_indicator = hover;
}
const BlocksGraphicsView* GraphicsRulerItem::view() const

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -74,25 +74,26 @@ class GraphicsRulerItem : public QGraphicsItem
typedef QGraphicsItem Parent;
typedef GraphicsRulerItem This;
QPolygonF m_indicator; ///< Indicator displayed when this chrono item is out of screen (displaying only for main item)
QRectF m_boundingRect; ///< boundingRect (see QGraphicsItem)
QColor m_color; ///< Color of the item
qreal m_left, m_right; ///< Left and right bounds of the selection zone
bool m_bMain; ///< Is this chronometer main (true, by default)
bool m_bReverse; ///<
bool m_bHoverIndicator; ///< Mouse hover above indicator
bool m_bHoverLeftBorder;
bool m_bHoverRightBorder;
QPolygonF m_indicator; ///< Indicator displayed when this chrono item is out of screen (displaying only for main item)
QRectF m_bounding_rect; ///< boundingRect (see QGraphicsItem)
QColor m_color; ///< Color of the item
qreal m_left, m_right; ///< Left and right bounds of the selection zone
bool m_main; ///< Is this ruler item main (true, by default)
bool m_reverse; ///<
bool m_strict; ///<
bool m_hover_on_indicator; ///< Mouse hover above indicator
bool m_hover_on_left_border;
bool m_hover_on_right_border;
public:
explicit GraphicsRulerItem(bool _main = true);
explicit GraphicsRulerItem(bool main = true);
virtual ~GraphicsRulerItem();
// Public virtual methods
QRectF boundingRect() const override;
void paint(QPainter* _painter, const QStyleOptionGraphicsItem* _option, QWidget* _widget = nullptr) override;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
public:
@ -100,46 +101,57 @@ public:
void hide();
void setColor(const QColor& _color);
void setColor(const QColor& color);
void setBoundingRect(qreal x, qreal y, qreal w, qreal h);
void setBoundingRect(const QRectF& _rect);
void setBoundingRect(const QRectF& rect);
void setLeftRight(qreal _left, qreal _right);
void setLeftRight(qreal left, qreal right);
void setReverse(bool _reverse);
void setReverse(bool reverse);
void setStrict(bool strict);
void setHoverIndicator(bool _hover);
void setHoverIndicator(bool hover);
bool indicatorContains(const QPointF& _pos) const;
bool indicatorContains(const QPointF& pos) const;
void setHoverLeft(bool _hover);
void setHoverRight(bool _hover);
void setHoverLeft(bool hover);
void setHoverRight(bool hover);
bool hoverLeft(qreal _x) const;
bool hoverRight(qreal _x) const;
bool hoverLeft(qreal x) const;
bool hoverRight(qreal x) const;
QPointF toItem(const QPointF& _pos) const;
qreal toItem(qreal _x) const;
QPointF toItem(const QPointF& pos) const;
qreal toItem(qreal x) const;
inline bool hoverIndicator() const
{
return m_bHoverIndicator;
return m_hover_on_indicator;
}
inline bool hoverLeft() const
{
return m_bHoverLeftBorder;
return m_hover_on_left_border;
}
inline bool hoverRight() const
{
return m_bHoverRightBorder;
return m_hover_on_right_border;
}
inline bool hoverAnyBorder() const
{
return m_hover_on_left_border || m_hover_on_right_border;
}
inline bool reverse() const
{
return m_bReverse;
return m_reverse;
}
inline bool strict() const
{
return m_strict;
}
inline qreal left() const

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -115,6 +115,11 @@ void GraphicsHistogramItem::paint(QPainter* _painter, const QStyleOptionGraphics
void GraphicsHistogramItem::paintMouseIndicator(QPainter* _painter, qreal _top, qreal _bottom, qreal _width, qreal _height, qreal _top_width, qreal _mouse_y, qreal _delta_time, int _font_h)
{
if (isEmpty())
{
return;
}
if (_font_h != 0 && _top < _mouse_y && _mouse_y < _bottom)
{
const int half_font_h = _font_h >> 1;
@ -178,7 +183,7 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
_painter->setPen(profiler_gui::TEXT_COLOR);
_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, bindMode ? " Mode: Zoom" : " Mode: Overview");
if (!m_topDurationStr.isEmpty())
if (!isEmpty() && !m_topDurationStr.isEmpty())
{
if (m_timeUnits != EASY_GLOBALS.time_units)
{
@ -204,7 +209,7 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
paintMouseIndicator(_painter, m_boundingRect.top(), bottom, width, m_boundingRect.height(), top_width, m_mousePos.y(), dtime, font_h);
if (m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
if (!isEmpty() && m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
{
// Draw marker displaying expected frame_time step
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff;
@ -270,7 +275,7 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
_painter->setPen(profiler_gui::TEXT_COLOR);
_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, bindMode ? " Mode: Zoom" : " Mode: Overview");
if (!m_topDurationStr.isEmpty())
if (!isEmpty() && !m_topDurationStr.isEmpty())
{
if (m_timeUnits != EASY_GLOBALS.time_units)
{
@ -296,7 +301,7 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
paintMouseIndicator(_painter, m_boundingRect.top(), bottom, width, m_boundingRect.height(), top_width, m_mousePos.y(), dtime, font_h);
if (m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
if (!isEmpty() && m_bottomValue < EASY_GLOBALS.frame_time && EASY_GLOBALS.frame_time < m_topValue)
{
// Draw marker displaying required frame_time step
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff;
@ -315,20 +320,20 @@ void GraphicsHistogramItem::paintById(QPainter* _painter)
_painter->setPen(profiler_gui::TEXT_COLOR);
rect.setRect(0, bottom + 2, width, font_h);
if (!m_selectedBlocks.empty())
if (!items.empty())
{
if (m_threadProfiledTime != 0)
{
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip,
QString("%1 | %2 | %3 calls | %4% of thread profiled time")
.arg(m_threadName).arg(m_blockName).arg(m_selectedBlocks.size())
.arg(m_threadName).arg(m_blockName).arg(items.size())
.arg(QString::number(100. * (double)m_blockTotalDuraion / (double)m_threadProfiledTime, 'f', 2)));
}
else
{
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip,
QString("%1 | %2 | %3 calls | 100% of thread profiled time")
.arg(m_threadName).arg(m_blockName).arg(m_selectedBlocks.size()));
.arg(m_threadName).arg(m_blockName).arg(items.size()));
}
}
else
@ -380,6 +385,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
m_imageScaleUpdate = m_imageScale = 1;
m_selectedBlocks.clear();
setEmpty(true);
{ profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
setImageUpdatePermitted(false);
@ -464,6 +470,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
m_bottomDurationStr.clear();
}
setEmpty(empty);
setReady(true);
}, m_bReady);
@ -505,6 +512,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
m_imageScaleUpdate = m_imageScale = 1;
m_selectedBlocks.clear();
setEmpty(true);
{ profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
m_threadId = _thread_id;
@ -658,6 +666,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
m_topValue = m_maxValue;
m_bottomValue = m_minValue;
setEmpty(m_selectedBlocks.empty());
setReady(true);
}, m_bReady);
@ -770,7 +779,7 @@ bool GraphicsHistogramItem::decreaseBottomValue()
void GraphicsHistogramItem::pickFrameTime(qreal _y) const
{
if (isImageUpdatePermitted() && m_boundingRect.top() < _y && _y < m_boundingRect.bottom() && !m_topDurationStr.isEmpty())
if (!isEmpty() && isImageUpdatePermitted() && m_boundingRect.top() < _y && _y < m_boundingRect.bottom() && !m_topDurationStr.isEmpty())
{
const auto frame_time = m_bottomValue + (m_topValue - m_bottomValue) * (m_boundingRect.bottom() - _y) / m_boundingRect.height();
EASY_GLOBALS.frame_time = static_cast<decltype(EASY_GLOBALS.frame_time)>(frame_time);

View File

@ -12,7 +12,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/**
Lightweight profiler library for c++
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -51,6 +51,5 @@ default/crop.svg - Icon made by Freepik from www.flaticon.com
default/yx.svg - Icon made by Freepik from www.flaticon.com
default/svg2.svg - Icon made by Freepik from www.flaticon.com
default/svg3.svg - Icon made by Freepik from www.flaticon.com
default/to-fullscreen.svg - Icon made by Freepik from www.flaticon.com
default/to-window.svg - Icon made by Freepik from www.flaticon.com
default/window.svg - Icon made by Freepik from www.flaticon.com

View File

@ -1,9 +1,8 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
<g>
<path fill="#504040" d="M359.277,137.723H152.721c-8.284,0-15,6.716-15,15V359.28c0,8.284,6.716,15,15,15h206.557c8.284,0,15-6.716,15-15V152.723
C374.277,144.439,367.561,137.723,359.277,137.723z M344.278,344.279L344.278,344.279H167.721V167.723h176.557V344.279z"/>
<rect stroke="black" stroke-width="5" stroke-linecap="butt" stroke-linejoin="miter" fill="none" x="38" y="38" width="52" height="52"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 633 B

After

Width:  |  Height:  |  Size: 506 B

View File

@ -8,7 +8,7 @@
* description : Main file for EasyProfiler GUI.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -18,7 +18,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -87,6 +87,7 @@
#include <QPushButton>
#include <QProgressDialog>
#include <QTextCodec>
#include <QPlainTextEdit>
#include <QTextStream>
#include <QToolBar>
#include <QToolButton>
@ -128,7 +129,7 @@ const auto NETWORK_CACHE_FILE = "easy_profiler_stream.cache";
//////////////////////////////////////////////////////////////////////////
inline const QStringList& UI_themes()
static const QStringList& UI_themes()
{
static const QStringList themes {
"default"
@ -150,7 +151,80 @@ inline void clear_stream(std::stringstream& _stream)
#endif
}
inline void loadTheme(const QString& _theme)
static void convertPointSizes(QString& style)
{
// Find font family
const auto fontMatch = QRegularExpression("font-family:\\s*\\\"(.*)\\\"\\s*;").match(style);
const auto fontFamily = fontMatch.hasMatch() ? fontMatch.captured(fontMatch.lastCapturedIndex()) : QString("DejaVu Sans");
//QMessageBox::information(nullptr, "Found font family", fontFamily);
// Calculate point size using current font
const auto pointSizeF = QFontMetricsF(QFont(fontFamily, 100)).height() * 1e-2;
//QMessageBox::information(nullptr, "Point size", QString("100pt = %1\n1pt = %2").arg(pointSizeF * 1e2).arg(pointSizeF));
// Find and convert all sizes from points to pixels
QRegularExpression re("(\\d+\\.?\\d*)ex");
auto it = re.globalMatch(style);
std::vector<QStringList> matches;
{
QSet<QString> uniqueMatches;
while (it.hasNext())
{
const auto match = it.next();
if (!uniqueMatches.contains(match.captured()))
{
uniqueMatches.insert(match.captured());
matches.emplace_back(match.capturedTexts());
}
}
}
for (const auto& capturedTexts : matches)
{
const auto pt = capturedTexts.back().toDouble();
const int pixels = static_cast<int>(lround(pointSizeF * pt));
style.replace(QString(" %1").arg(capturedTexts.front()), QString(" %1px").arg(pixels));
style.replace(QString(":%1").arg(capturedTexts.front()), QString(":%1px").arg(pixels));
}
}
static void replaceOsDependentSettings(QString& style)
{
// Find and convert all OS dependent options
// Example: "/*{lin}font-weight: bold;*/" -> "font-weight: bold;"
#if defined(_WIN32)
QRegularExpression re("/\\*\\{win\\}(.*)\\*/");
#elif defined(__APPLE__)
QRegularExpression re("/\\*\\{mac\\}(.*)\\*/");
#else
QRegularExpression re("/\\*\\{lin\\}(.*)\\*/");
#endif
auto it = re.globalMatch(style);
std::vector<QStringList> matches;
{
QSet<QString> uniqueMatches;
while (it.hasNext())
{
const auto match = it.next();
if (!uniqueMatches.contains(match.captured()))
{
uniqueMatches.insert(match.captured());
matches.emplace_back(match.capturedTexts());
}
}
}
for (const auto& capturedTexts : matches)
{
style.replace(capturedTexts.front(), capturedTexts.back());
}
}
static void loadTheme(const QString& _theme)
{
QFile file(QStringLiteral(":/themes/") + _theme);
if (file.open(QFile::ReadOnly | QFile::Text))
@ -159,41 +233,8 @@ inline void loadTheme(const QString& _theme)
QString style = in.readAll();
if (!style.isEmpty())
{
// Find font family
const auto fontMatch = QRegularExpression("font-family:\\s*\\\"(.*)\\\"\\s*;").match(style);
const auto fontFamily = fontMatch.hasMatch() ? fontMatch.captured(fontMatch.lastCapturedIndex()) : QString("DejaVu Sans");
//QMessageBox::information(nullptr, "Found font family", fontFamily);
// Calculate point size using current font
const auto pointSizeF = QFontMetricsF(QFont(fontFamily, 100)).height() * 1e-2;
//QMessageBox::information(nullptr, "Point size", QString("100pt = %1\n1pt = %2").arg(pointSizeF * 1e2).arg(pointSizeF));
// Find and convert all sizes from points to pixels
QRegularExpression re("(\\d+\\.?\\d*)ex");
auto it = re.globalMatch(style);
std::vector<QStringList> matches;
{
QSet<QString> uniqueMatches;
while (it.hasNext())
{
const auto match = it.next();
if (!uniqueMatches.contains(match.captured()))
{
uniqueMatches.insert(match.captured());
matches.emplace_back(match.capturedTexts());
}
}
}
for (const auto& capturedTexts : matches)
{
const auto pt = capturedTexts.back().toDouble();
const int pixels = static_cast<int>(pointSizeF * pt + 0.5);
//QMessageBox::information(nullptr, "Style-sheet modification", QString("Replacing '%1'\nwith\n'%2px'\n\npt count: %3").arg(capturedTexts.front()).arg(pixels).arg(pt));
style.replace(capturedTexts.front(), QString("%1px").arg(pixels));
}
convertPointSizes(style);
replaceOsDependentSettings(style);
qApp->setStyleSheet(style);
}
}
@ -253,7 +294,7 @@ void MainWindow::configureSizes()
EASY_GLOBALS.font.default_font = w.font();
const QFontMetricsF fm(w.font());
#ifdef WIN32
#ifdef _WIN32
EASY_CONSTEXPR qreal DefaultHeight = 16;
#else
EASY_CONSTEXPR qreal DefaultHeight = 17;
@ -268,7 +309,7 @@ void MainWindow::configureSizes()
size.graphics_row_full = size.graphics_row_height;
size.threads_row_spacing = size.graphics_row_full >> 1;
size.timeline_height = size.font_height + px(10);
size.icon_size = size.font_height + px(11);
size.icon_size = size.font_height + px(5);
const auto fontFamily = w.font().family();
const auto pixelSize = w.font().pixelSize();
@ -543,6 +584,12 @@ MainWindow::MainWindow() : Parent(), m_theme("default"), m_lastAddress("localhos
action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status);
connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange);
action = submenu->addAction("Hide stats for single blocks in tree");
action->setToolTip("If checked then such stats like Min,Max,Avg etc.\nwill not be displayed in stats tree for blocks\nwith number of calls == 1");
action->setCheckable(true);
action->setChecked(EASY_GLOBALS.display_only_relevant_stats);
connect(action, &QAction::triggered, this, &This::onDisplayRelevantStatsChange);
action = submenu->addAction("Selecting block changes current thread");
action->setToolTip("Automatically select thread while selecting a block.\nIf not checked then you will have to select current thread\nmanually double clicking on thread name on a diagram.");
action->setCheckable(true);
@ -1375,6 +1422,11 @@ void MainWindow::onBindExpandStatusChange(bool _checked)
EASY_GLOBALS.bind_scene_and_tree_expand_status = _checked;
}
void MainWindow::onDisplayRelevantStatsChange(bool _checked)
{
EASY_GLOBALS.display_only_relevant_stats = _checked;
}
void MainWindow::onHierarchyFlagChange(bool _checked)
{
EASY_GLOBALS.only_current_thread_hierarchy = _checked;
@ -1467,8 +1519,14 @@ void MainWindow::onEditBlocksClicked(bool)
{
if (m_descTreeDialog.ptr != nullptr)
{
if (m_descTreeDialog.ptr->isMinimized())
{
m_descTreeDialog.ptr->setWindowState((m_descTreeDialog.ptr->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
}
m_descTreeDialog.ptr->raise();
m_descTreeDialog.ptr->setFocus();
return;
}
@ -1647,6 +1705,10 @@ void MainWindow::loadSettings()
if (!flag.isNull())
EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool();
flag = settings.value("display_only_relevant_stats");
if (!flag.isNull())
EASY_GLOBALS.display_only_relevant_stats = flag.toBool();
flag = settings.value("selecting_block_changes_thread");
if (!flag.isNull())
EASY_GLOBALS.selecting_block_changes_thread = flag.toBool();
@ -1779,6 +1841,7 @@ void MainWindow::saveSettingsAndGeometry()
settings.setValue("add_zero_blocks_to_hierarchy", EASY_GLOBALS.add_zero_blocks_to_hierarchy);
settings.setValue("highlight_blocks_with_same_id", EASY_GLOBALS.highlight_blocks_with_same_id);
settings.setValue("bind_scene_and_tree_expand_status", EASY_GLOBALS.bind_scene_and_tree_expand_status);
settings.setValue("display_only_relevant_stats", EASY_GLOBALS.display_only_relevant_stats);
settings.setValue("selecting_block_changes_thread", EASY_GLOBALS.selecting_block_changes_thread);
settings.setValue("enable_event_indicators", EASY_GLOBALS.enable_event_markers);
settings.setValue("auto_adjust_histogram_height", EASY_GLOBALS.auto_adjust_histogram_height);
@ -2106,9 +2169,6 @@ void MainWindow::onLoadingFinish(profiler::block_index_t& _nblocks)
{
auto& guiblock = EASY_GLOBALS.gui_blocks[i];
guiblock.tree = std::move(blocks[i]);
#ifdef EASY_TREE_WIDGET__USE_VECTOR
profiler_gui::set_max(guiblock.tree_item);
#endif
}
m_saveAction->setEnabled(true);
@ -2818,12 +2878,7 @@ void MainWindow::onSelectValue(profiler::thread_id_t _thread_id, uint32_t _value
void DialogWithGeometry::create(QWidget* content, QWidget* parent)
{
#ifdef WIN32
const WindowHeader::Buttons buttons = WindowHeader::AllButtons;
#else
const WindowHeader::Buttons buttons {WindowHeader::MaximizeButton | WindowHeader::CloseButton};
#endif
ptr = new Dialog(parent, EASY_DEFAULT_WINDOW_TITLE, content, buttons, QMessageBox::NoButton);
ptr = new Dialog(parent, EASY_DEFAULT_WINDOW_TITLE, content, WindowHeader::AllButtons, QMessageBox::NoButton);
ptr->setProperty("stayVisible", true);
ptr->setAttribute(Qt::WA_DeleteOnClose, true);
}

View File

@ -11,7 +11,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -337,6 +337,7 @@ protected slots:
void onAllItemsExpandedByDefaultChange(bool);
void onBindExpandStatusChange(bool);
void onHierarchyFlagChange(bool);
void onDisplayRelevantStatsChange(bool);
void onExpandAllClicked(bool);
void onCollapseAllClicked(bool);
void onViewportInfoClicked(bool);

View File

@ -18,7 +18,7 @@ BEGIN
VALUE "CompanyName", "EasySolutions"
VALUE "FileDescription", "EasyProfiler"
VALUE "InternalName", "profiler_gui"
VALUE "LegalCopyright", "Copyright (C) 2016-2018 Victor Zarubkin, Sergey Yagovtsev"
VALUE "LegalCopyright", "Copyright (C) 2016-2019 Victor Zarubkin, Sergey Yagovtsev"
VALUE "LegalTrademarks1", "All Rights Reserved"
VALUE "LegalTrademarks2", "All Rights Reserved"
VALUE "OriginalFilename", "profiler_gui.exe"

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of RoundProgressWidget.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of RoundProgressWidget.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -0,0 +1,104 @@
/************************************************************************
* file name : text_highlighter.cpp
* ----------------- :
* creation time : 2019/10/12
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains implementation of TextHighlighter.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2019 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 "text_highlighter.h"
#include <QColor>
#include <QRegExp>
#include <easy/details/profiler_colors.h>
#include "common_functions.h"
EASY_CONSTEXPR auto HighlightColor = profiler::colors::Yellow;
EASY_CONSTEXPR auto CurrentHighlightColor = profiler::colors::Magenta;
TextHighlighter::TextHighlighter(
QTextDocument* doc,
const QColor& normalTextColor,
const QColor& lightTextColor,
const QString& pattern,
Qt::CaseSensitivity caseSensitivity,
bool current
)
: QSyntaxHighlighter(doc)
, m_pattern(pattern)
, m_caseSensitivity(caseSensitivity)
{
auto color = current ? CurrentHighlightColor : HighlightColor;
m_textCharFormat.setBackground(QColor::fromRgba(color));
m_textCharFormat.setForeground(profiler_gui::isLightColor(color) ? normalTextColor : lightTextColor);
}
TextHighlighter::~TextHighlighter()
{
}
void TextHighlighter::highlightBlock(const QString& text)
{
if (m_pattern.isEmpty())
{
return;
}
QRegExp expression(m_pattern, m_caseSensitivity);
int index = text.indexOf(expression);
while (index >= 0)
{
const auto length = expression.cap().length();
setFormat(index, length, m_textCharFormat);
auto prevIndex = index;
index = text.indexOf(expression, index + length);
if (index <= prevIndex)
{
break;
}
}
}

View File

@ -0,0 +1,83 @@
/************************************************************************
* file name : text_highlighter.h
* ----------------- :
* creation time : 2019/10/12
* author : Victor Zarubkin
* email : v.s.zarubkin@gmail.com
* ----------------- :
* description : The file contains declaration of TextHighlighter - an auxiliary class
* : for highlighting text in QTextDocument.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2019 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 EASY_PROFILER_TEXT_HIGHLIGHTER_H
#define EASY_PROFILER_TEXT_HIGHLIGHTER_H
#include <QSyntaxHighlighter>
class TextHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
QString m_pattern;
Qt::CaseSensitivity m_caseSensitivity;
QTextCharFormat m_textCharFormat;
public:
TextHighlighter(
QTextDocument* doc,
const QColor& normalTextColor,
const QColor& lightTextColor,
const QString& pattern,
Qt::CaseSensitivity caseSensitivity,
bool current
);
~TextHighlighter() override;
protected:
void highlightBlock(const QString& text) override;
};
#endif //EASY_PROFILER_TEXT_HIGHLIGHTER_H

View File

@ -64,7 +64,10 @@ QSplitter::handle:pressed {
QLabel#BlocksTreeWidget_HintLabel {
color: gray;
font-size: 13pt; }
font-size: 12pt; }
QLabel#BlocksTreeWidget_HintLabel[hovered=true] {
color: black; }
/* ****************************************************************************************************************** */
QLineEdit, QSpinBox {
@ -303,9 +306,10 @@ QMenu::indicator:exclusive:checked:disabled {
/* ****************************************************************************************************************** */
QHeaderView::section {
height: 15.3ex;
width: 60ex;
min-width: 40ex;
background: #eeeeee; }
min-height: 15.3ex;
max-height: 15.3ex;
background: #eeeeee;
/*{lin}font-weight: bold;*/ }
/* ****************************************************************************************************************** */
DockWidget QWidget#EasyDockWidgetTitle {
@ -399,9 +403,9 @@ QScrollBar::add-line, QScrollBar::sub-line {
WindowHeader {
background-color: white;
height: 24ex;
min-height: 24ex;
max-height: 24ex;
height: 15.6ex;
min-height: 15.6ex;
max-height: 15.6ex;
margin: 0;
padding: 0 0 0 6ex;
border: none; }
@ -426,8 +430,8 @@ WindowHeader {
image: url(":/images/default/minimize");
padding: 2ex; }
WindowHeader QPushButton#WindowHeader_MinButton:hover {
background-color: #d1d1d1;
border-bottom: 1px solid #d1d1d1; }
background-color: #e8e8e8;
border-bottom: 1px solid #e8e8e8; }
WindowHeader QPushButton#WindowHeader_MinButton:pressed {
background-color: #c4c4c4;
border-bottom: 1px solid #c4c4c4; }
@ -438,8 +442,8 @@ WindowHeader {
image: url(":/images/default/to-window");
padding: 1ex; }
WindowHeader QPushButton#WindowHeader_MaxButton:hover {
background-color: #d1d1d1;
border-bottom: 1px solid #d1d1d1; }
background-color: #e8e8e8;
border-bottom: 1px solid #e8e8e8; }
WindowHeader QPushButton#WindowHeader_MaxButton:pressed {
background-color: #c4c4c4;
border-bottom: 1px solid #c4c4c4; }

View File

@ -40,11 +40,12 @@ $IndicatorBorderColor: darken($DarkSelectionColor, 5%);
$DisabledIndicatorBackgroundColor: $SelectionColor;
$DisabledIndicatorBorderColor: darken($SelectionColor, 5%);
$FocusBorderColor: $DarkSelectionColor;//#ffbcbc;
$FocusBorderColor: $DarkSelectionColor; // #ffbcbc;
$TooltipColor: #ffeccc;
$InputHeight: 15ex;
$WindowHeaderSize: 24ex;
$WindowHeaderSize: 15.6ex;
$WindowHeaderHoverColor: lighten($BorderColor, 14%); // #e8e8e8
// STYLES -------------------------------------------------
* {
@ -122,7 +123,11 @@ QSplitter::handle:pressed {
QLabel#BlocksTreeWidget_HintLabel {
color: gray;
font-size: 13pt;
font-size: 12pt;
}
QLabel#BlocksTreeWidget_HintLabel[hovered=true] {
color: black;
}
/* ****************************************************************************************************************** */
@ -407,9 +412,10 @@ QMenu::indicator:exclusive:checked:disabled {
/* ****************************************************************************************************************** */
QHeaderView::section {
height: 15.3ex;
width: 60ex;
min-width: 40ex;
min-height: 15.3ex;
max-height: 15.3ex;
background: #eeeeee;
/*{lin}font-weight: bold;*/
}
/* ****************************************************************************************************************** */
@ -548,8 +554,8 @@ WindowHeader {
}
QPushButton#WindowHeader_MinButton:hover {
background-color: lighten($BorderColor, 5%);
border-bottom: 1px solid lighten($BorderColor, 5%);
background-color: $WindowHeaderHoverColor;
border-bottom: 1px solid $WindowHeaderHoverColor;
}
QPushButton#WindowHeader_MinButton:pressed {
@ -568,8 +574,8 @@ WindowHeader {
}
QPushButton#WindowHeader_MaxButton:hover {
background-color: lighten($BorderColor, 5%);
border-bottom: 1px solid lighten($BorderColor, 5%);
background-color: $WindowHeaderHoverColor;
border-bottom: 1px solid $WindowHeaderHoverColor;
}
QPushButton#WindowHeader_MaxButton:pressed {

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of ThreadPool.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of ThreadPool.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of ThreadPoolTask.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -51,22 +51,25 @@
#include "thread_pool_task.h"
#include "thread_pool.h"
ThreadPoolTask::ThreadPoolTask() : m_func([]{}), m_interrupt(nullptr)
static std::atomic_bool s_dummy_flag {false};
ThreadPoolTask::ThreadPoolTask() : m_func([] {}), m_interrupt(&s_dummy_flag)
{
m_status = static_cast<int8_t>(TaskStatus::Finished);
}
ThreadPoolTask::~ThreadPoolTask()
{
m_signals.disconnect();
dequeue();
}
void ThreadPoolTask::enqueue(std::function<void()>&& func, std::atomic_bool& interruptFlag)
void ThreadPoolTask::enqueue(Func&& func, std::atomic_bool& interruptFlag)
{
dequeue();
setStatus(TaskStatus::Enqueued);
m_interrupt = & interruptFlag;
m_interrupt = &interruptFlag;
m_interrupt->store(false, std::memory_order_release);
m_func = std::move(func);
@ -75,19 +78,22 @@ void ThreadPoolTask::enqueue(std::function<void()>&& func, std::atomic_bool& int
void ThreadPoolTask::dequeue()
{
if (m_interrupt == nullptr || status() == TaskStatus::Finished)
if (m_interrupt == nullptr || m_interrupt == &s_dummy_flag || status() == TaskStatus::Finished)
{
return;
}
m_interrupt->store(true, std::memory_order_release);
ThreadPool::instance().dequeue(*this);
// wait for finish
m_mutex.lock();
setStatus(TaskStatus::Finished);
m_mutex.unlock();
{
const std::lock_guard<std::mutex> guard(m_mutex);
setStatus(TaskStatus::Finished);
}
m_interrupt->store(false, std::memory_order_release);
//m_interrupt->store(false, std::memory_order_release);
}
TaskStatus ThreadPoolTask::status() const
@ -97,16 +103,29 @@ TaskStatus ThreadPoolTask::status() const
void ThreadPoolTask::execute()
{
const std::lock_guard<std::mutex> guard(m_mutex);
// execute if not cancelled
{
const std::lock_guard<std::mutex> guard(m_mutex);
if (status() == TaskStatus::Finished || m_interrupt->load(std::memory_order_acquire))
return;
if (status() == TaskStatus::Finished || m_interrupt->load(std::memory_order_acquire))
{
// cancelled
return;
}
m_func();
setStatus(TaskStatus::Finished);
m_func();
setStatus(TaskStatus::Finished);
}
emit m_signals.finished();
}
void ThreadPoolTask::setStatus(TaskStatus status)
{
m_status.store(static_cast<int8_t>(status), std::memory_order_release);
}
ThreadPoolTaskSignals& ThreadPoolTask::events()
{
return m_signals;
}

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of ThreadPoolTask.
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -56,6 +56,8 @@
#include <atomic>
#include <mutex>
#include <QObject>
enum class TaskStatus : int8_t
{
Enqueued,
@ -63,14 +65,34 @@ enum class TaskStatus : int8_t
Finished,
};
class ThreadPoolTaskSignals : public QObject
{
Q_OBJECT;
public:
ThreadPoolTaskSignals() : QObject() {}
signals:
void finished();
};
class ThreadPoolTask EASY_FINAL
{
public:
using Func = std::function<void()>;
private:
friend class ThreadPool;
std::function<void()> m_func;
std::mutex m_mutex;
std::atomic<int8_t> m_status;
std::atomic_bool* m_interrupt;
ThreadPoolTaskSignals m_signals;
Func m_func;
std::atomic_bool* m_interrupt;
std::mutex m_mutex;
std::atomic<int8_t> m_status;
public:
@ -80,9 +102,11 @@ public:
ThreadPoolTask();
~ThreadPoolTask();
void enqueue(std::function<void()>&& func, std::atomic_bool& interruptFlag);
void enqueue(Func&& func, std::atomic_bool& interruptFlag);
void dequeue();
ThreadPoolTaskSignals& events();
private:
void execute();

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : *
* ----------------- :
* license : Lightweight profiler library for c++
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
* : Copyright(C) 2016-2019 Sergey Yagovtsev, Victor Zarubkin
* :
* : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -54,32 +54,39 @@
************************************************************************/
#include "tree_widget_item.h"
#include "globals.h"
#include <QAbstractTextDocumentLayout>
#include <QFont>
#include <QPainter>
#include <QPoint>
#include <QBrush>
#include <QRect>
#include <QSize>
#include <QTextDocument>
#include <QVariant>
#include "globals.h"
#include "blocks_tree_widget.h"
#include "text_highlighter.h"
//////////////////////////////////////////////////////////////////////////
EASY_CONSTEXPR int BlockColorRole = Qt::UserRole + 1;
//////////////////////////////////////////////////////////////////////////
namespace {
EASY_CONSTEXPR int ColumnBit[COL_COLUMNS_NUMBER] = {
-1 // COL_NAME = 0,
, 0 // COL_BEGIN,
, 1 // COL_DURATION,
, 2 // COL_SELF_DURATION,
, 3 // COL_DURATION_SUM_PER_PARENT,
, 4 // COL_DURATION_SUM_PER_FRAME,
, 5 // COL_DURATION_SUM_PER_THREAD,
, 1 // COL_TIME,
, 2 // COL_SELF_TIME,
, 3 // COL_TOTAL_TIME_PER_PARENT,
, 4 // COL_TOTAL_TIME_PER_FRAME,
, 5 // COL_TOTAL_TIME_PER_THREAD,
, -1 // COL_SELF_DURATION_PERCENT,
, -1 // COL_SELF_TIME_PERCENT,
, -1 // COL_PERCENT_PER_PARENT,
, -1 // COL_PERCENT_PER_FRAME,
, -1 // COL_PERCENT_SUM_PER_PARENT,
@ -90,30 +97,41 @@ EASY_CONSTEXPR int ColumnBit[COL_COLUMNS_NUMBER] = {
, 7 // COL_MIN_PER_FRAME,
, 8 // COL_MAX_PER_FRAME,
, 9 // COL_AVERAGE_PER_FRAME,
, 9 // COL_AVG_PER_FRAME,
, -1 // COL_NCALLS_PER_FRAME,
, 10 // COL_MIN_PER_THREAD,
, 11 // COL_MAX_PER_THREAD,
, 12 // COL_AVERAGE_PER_THREAD,
, 12 // COL_AVG_PER_THREAD,
, -1 // COL_NCALLS_PER_THREAD,
, 13 // COL_MIN_PER_PARENT,
, 14 // COL_MAX_PER_PARENT,
, 15 // COL_AVERAGE_PER_PARENT,
, 15 // COL_AVG_PER_PARENT,
, -1 // COL_NCALLS_PER_PARENT,
, 16 // COL_ACTIVE_TIME,
, -1 // COL_ACTIVE_PERCENT,
, -1 // COL_PERCENT_PER_AREA,
, 17 // COL_TOTAL_TIME_PER_AREA,
, -1 // COL_PERCENT_SUM_PER_AREA,
, 18 // COL_MIN_PER_AREA,
, 19 // COL_MAX_PER_AREA,
, 20 // COL_AVG_PER_AREA,
, -1 // COL_NCALLS_PER_AREA,
};
} // end of namespace <noname>.
//////////////////////////////////////////////////////////////////////////
TreeWidgetItem::TreeWidgetItem(const profiler::block_index_t _treeBlock, Parent* _parent)
TreeWidgetItem::TreeWidgetItem(profiler::block_index_t _treeBlock, Parent* _parent)
: Parent(_parent, QTreeWidgetItem::UserType)
, m_block(_treeBlock)
, m_customBGColor(0)
, m_bMain(false)
, m_partial(false)
{
}
@ -139,16 +157,19 @@ bool TreeWidgetItem::operator < (const Parent& _other) const
case COL_NCALLS_PER_THREAD:
case COL_NCALLS_PER_PARENT:
case COL_NCALLS_PER_FRAME:
case COL_NCALLS_PER_AREA:
{
return data(col, Qt::UserRole).toUInt() < _other.data(col, Qt::UserRole).toUInt();
}
case COL_SELF_DURATION_PERCENT:
case COL_SELF_TIME_PERCENT:
case COL_PERCENT_PER_PARENT:
case COL_PERCENT_PER_FRAME:
case COL_PERCENT_SUM_PER_PARENT:
case COL_PERCENT_SUM_PER_FRAME:
case COL_PERCENT_SUM_PER_THREAD:
case COL_PERCENT_PER_AREA:
case COL_PERCENT_SUM_PER_AREA:
{
return data(col, Qt::UserRole).toInt() < _other.data(col, Qt::UserRole).toInt();
}
@ -166,6 +187,11 @@ bool TreeWidgetItem::operator < (const Parent& _other) const
}
}
bool TreeWidgetItem::isPartial() const
{
return m_partial;
}
bool TreeWidgetItem::hasToolTip(int _column) const
{
const int bit = ColumnBit[_column];
@ -194,16 +220,143 @@ QVariant TreeWidgetItem::data(int _column, int _role) const
switch (_role)
{
case Qt::ForegroundRole:
return m_bMain ? QVariant::fromValue(QColor::fromRgb(profiler_gui::SELECTED_THREAD_FOREGROUND)) : QVariant();
{
if (m_bMain)
return QVariant::fromValue(QColor::fromRgb(profiler_gui::SELECTED_THREAD_FOREGROUND));
auto fg = Parent::data(_column, _role);
if (!fg.isNull())
return fg;
if (m_partial)
return partialForeground();
break;
}
case Qt::ToolTipRole:
return hasToolTip(_column) ?
QVariant::fromValue(QString("%1 ns").arg(QTreeWidgetItem::data(_column, Qt::UserRole).toULongLong())) :
QVariant();
{
if (hasToolTip(_column))
return QVariant::fromValue(QString("%1 ns").arg(data(_column, Qt::UserRole).toULongLong()));
break;
}
default:
return QTreeWidgetItem::data(_column, _role);
{
if (_role != Qt::UserRole && _role != Qt::DisplayRole)
return QTreeWidgetItem::data(_column, _role);
return relevantData(_column, _role);
}
}
return QVariant();
}
QVariant TreeWidgetItem::relevantData(int _column, int _role) const
{
switch (_column)
{
case COL_NAME:
case COL_BEGIN:
case COL_END:
case COL_NCALLS_PER_PARENT:
case COL_NCALLS_PER_FRAME:
case COL_NCALLS_PER_THREAD:
case COL_NCALLS_PER_AREA:
case COL_SELF_TIME:
case COL_SELF_TIME_PERCENT:
case COL_ACTIVE_TIME:
case COL_ACTIVE_PERCENT:
case COL_PERCENT_PER_PARENT:
case COL_PERCENT_PER_FRAME:
case COL_PERCENT_PER_AREA:
case COL_PERCENT_SUM_PER_THREAD:
{
return Parent::data(_column, _role);
}
default:
{
break;
}
}
auto var = Parent::data(_column, _role);
if (!var.isNull() || (EASY_GLOBALS.display_only_relevant_stats && _role == Qt::DisplayRole))
{
return var;
}
switch (_column)
{
case COL_TOTAL_TIME_PER_PARENT:
case COL_TOTAL_TIME_PER_FRAME:
case COL_TOTAL_TIME_PER_THREAD:
case COL_TOTAL_TIME_PER_AREA:
case COL_MIN_PER_PARENT:
case COL_MIN_PER_FRAME:
case COL_MIN_PER_THREAD:
case COL_MIN_PER_AREA:
case COL_MAX_PER_PARENT:
case COL_MAX_PER_FRAME:
case COL_MAX_PER_THREAD:
case COL_MAX_PER_AREA:
case COL_AVG_PER_PARENT:
case COL_AVG_PER_FRAME:
case COL_AVG_PER_THREAD:
case COL_AVG_PER_AREA:
{
return Parent::data(COL_TIME, _role);
}
case COL_PERCENT_SUM_PER_PARENT:
{
return Parent::data(COL_PERCENT_PER_PARENT, _role);
}
case COL_PERCENT_SUM_PER_FRAME:
{
return Parent::data(COL_PERCENT_PER_FRAME, _role);
}
case COL_PERCENT_SUM_PER_AREA:
{
return Parent::data(COL_PERCENT_PER_AREA, _role);
}
default:
{
break;
}
}
return var;
}
QVariant TreeWidgetItem::partialForeground() const
{
const auto mode = static_cast<const BlocksTreeWidget*>(treeWidget())->mode();
profiler::calls_number_t ncalls = 0;
switch (mode)
{
case TreeMode::Plain:
{
ncalls = data(COL_NCALLS_PER_FRAME, Qt::UserRole).toUInt();
break;
}
case TreeMode::SelectedArea:
{
ncalls = data(COL_NCALLS_PER_AREA, Qt::UserRole).toUInt();
break;
}
default:
break;
}
if (ncalls < 3)
return QVariant::fromValue(QColor::fromRgb(profiler::colors::Grey500));
return QVariant::fromValue(QColor::fromRgb(profiler::colors::Grey700));
}
profiler::block_index_t TreeWidgetItem::block_index() const
@ -221,16 +374,26 @@ const profiler::BlocksTree& TreeWidgetItem::block() const
return easyBlocksTree(m_block);
}
profiler::thread_id_t TreeWidgetItem::threadId() const
{
const QTreeWidgetItem* parentItem = this;
while (parentItem->parent() != nullptr)
{
parentItem = parent();
}
return static_cast<profiler::thread_id_t>(parentItem->data(COL_NAME, Qt::UserRole).toULongLong());
}
profiler::timestamp_t TreeWidgetItem::duration() const
{
if (parent() != nullptr)
return block().node->duration();
return data(COL_DURATION, Qt::UserRole).toULongLong();
return data(COL_TIME, Qt::UserRole).toULongLong();
}
profiler::timestamp_t TreeWidgetItem::selfDuration() const
{
return data(COL_SELF_DURATION, Qt::UserRole).toULongLong();
return data(COL_SELF_TIME, Qt::UserRole).toULongLong();
}
void TreeWidgetItem::setTimeSmart(int _column, profiler_gui::TimeUnits _units, const profiler::timestamp_t& _time, const QString& _prefix)
@ -240,23 +403,6 @@ void TreeWidgetItem::setTimeSmart(int _column, profiler_gui::TimeUnits _units, c
setData(_column, Qt::UserRole, (quint64)nanosecondsTime);
setHasToolTip(_column);
setText(_column, QString("%1%2").arg(_prefix).arg(profiler_gui::timeStringRealNs(_units, nanosecondsTime, 3)));
// if (_time < 1e3)
// {
// setText(_column, QString("%1%2 ns").arg(_prefix).arg(nanosecondsTime));
// }
// else if (_time < 1e6)
// {
// setText(_column, QString("%1%2 us").arg(_prefix).arg(double(nanosecondsTime) * 1e-3, 0, 'f', 3));
// }
// else if (_time < 1e9)
// {
// setText(_column, QString("%1%2 ms").arg(_prefix).arg(double(nanosecondsTime) * 1e-6, 0, 'f', 3));
// }
// else
// {
// setText(_column, QString("%1%2 s").arg(_prefix).arg(double(nanosecondsTime) * 1e-9, 0, 'f', 3));
// }
}
void TreeWidgetItem::setTimeSmart(int _column, profiler_gui::TimeUnits _units, const profiler::timestamp_t& _time)
@ -294,6 +440,11 @@ void TreeWidgetItem::setMain(bool _main)
m_bMain = _main;
}
void TreeWidgetItem::setPartial(bool partial)
{
m_partial = partial;
}
void TreeWidgetItem::collapseAll()
{
for (int i = 0, childrenNumber = childCount(); i < childrenNumber; ++i)
@ -320,7 +471,9 @@ void TreeWidgetItem::expandAll()
//////////////////////////////////////////////////////////////////////////
TreeWidgetItemDelegate::TreeWidgetItemDelegate(QTreeWidget* parent) : QStyledItemDelegate(parent), m_treeWidget(parent)
TreeWidgetItemDelegate::TreeWidgetItemDelegate(BlocksTreeWidget* parent)
: QStyledItemDelegate(parent)
, m_treeWidget(parent)
{
}
@ -337,9 +490,11 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
{
// Draw item as usual
QStyledItemDelegate::paint(painter, option, index);
highlightMatchingText(painter, option, index);
return;
}
const auto padding = px(2);
const auto colorBlockSize = option.rect.height() >> 1;
const auto currentTreeIndex = m_treeWidget->currentIndex();
if (index.parent() == currentTreeIndex.parent() && index.row() == currentTreeIndex.row())
@ -348,16 +503,17 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
painter->save();
painter->setBrush(m_treeWidget->palette().highlight());
painter->setPen(Qt::NoPen);
painter->drawRect(QRect(option.rect.left(), option.rect.top(), colorBlockSize, option.rect.height()));
painter->drawRect(QRect(option.rect.left(), option.rect.top(), colorBlockSize + padding, option.rect.height()));
painter->restore();
}
// Adjust rect size for drawing color marker
QStyleOptionViewItem opt = option;
opt.rect.adjust(colorBlockSize, 0, 0, 0);
opt.rect.adjust(colorBlockSize + padding, 0, 0, 0);
// Draw item as usual
QStyledItemDelegate::paint(painter, opt, index);
highlightMatchingText(painter, opt, index);
const auto colorBlockRest = option.rect.height() - colorBlockSize;
@ -374,7 +530,117 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
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->drawLine(QPoint(bottomLeft.x() - colorBlockSize - padding, bottomLeft.y()), bottomLeft);
painter->restore();
}
void TreeWidgetItemDelegate::highlightMatchingText(
QPainter* painter,
const QStyleOptionViewItem& option,
const QModelIndex& index
) const {
if (m_treeWidget->lastFoundItem() != nullptr && !m_treeWidget->searchString().isEmpty())
{
// Highlight matching word
auto displayData = m_treeWidget->model()->data(index);
if (displayData.canConvert<QString>())
{
const auto text = displayData.toString();
const auto caseSensitivity = m_treeWidget->caseSensitiveSearch() ? Qt::CaseSensitive : Qt::CaseInsensitive;
if (text.contains(m_treeWidget->searchString(), caseSensitivity))
{
auto lastFoundIndex = m_treeWidget->indexFromItem(m_treeWidget->lastFoundItem(), index.column());
highlightMatchingText(
painter,
option,
text,
m_treeWidget->searchString(),
caseSensitivity,
lastFoundIndex == index
);
}
}
}
}
void TreeWidgetItemDelegate::highlightMatchingText(
QPainter* painter,
const QStyleOptionViewItem& option,
const QString& text,
const QString& pattern,
Qt::CaseSensitivity caseSensitivity,
bool current
) const {
const auto padding = px(2);
QTextDocument doc;
doc.setDefaultFont(painter->font());
doc.setTextWidth(option.rect.width() - padding);
const auto elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight, std::max(option.rect.width() - padding, 0));
doc.setHtml(elidedText);
TextHighlighter highlighter(
&doc,
painter->pen().color(),
QColor::fromRgb(profiler::colors::Grey100),
pattern,
caseSensitivity,
current
);
painter->save();
#ifdef _WIN32
EASY_CONSTEXPR int fixed_padding_x = -1;
EASY_CONSTEXPR int fixed_padding_y = 0;
#else
EASY_CONSTEXPR int fixed_padding_x = -1;
EASY_CONSTEXPR int fixed_padding_y = -1;
#endif
auto dh = std::max((option.rect.height() - doc.size().height()) * 0.5, 0.);
painter->translate(option.rect.left() + fixed_padding_x, option.rect.top() + dh + fixed_padding_y);
QRect clip(0, 0, option.rect.width(), option.rect.height());
painter->setClipRect(clip);
QAbstractTextDocumentLayout::PaintContext ctx;
ctx.clip = clip;
ctx.palette.setColor(QPalette::Text, Qt::transparent);
doc.documentLayout()->draw(painter, ctx);
painter->restore();
}
QSize TreeWidgetItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
auto* tree = m_treeWidget;
if (tree == nullptr)
return QStyledItemDelegate::sizeHint(option, index);
auto* model = tree->model();
if (model == nullptr)
return QStyledItemDelegate::sizeHint(option, index);
auto displayData = m_treeWidget->model()->data(index);
if (!displayData.canConvert<QString>())
{
return QStyledItemDelegate::sizeHint(option, index);
}
// unfortunately, Qt does not take padding into account, so have to add it manually...
const auto padding = px(15);
auto text = displayData.toString();
const auto width = static_cast<int>((m_treeWidget->fontMetrics().width(text) + padding) * 1.05);
const auto brushData = m_treeWidget->model()->data(index, BlockColorRole);
if (brushData.isNull())
{
return QSize(width, option.rect.height());
}
const auto colorBlockSize = option.rect.height() >> 1;
return QSize(width + colorBlockSize + px(2), option.rect.height());
}

Some files were not shown because too many files have changed in this diff Show More