0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-26 08:01: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 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -6,7 +6,7 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of profiling blocks * description : The file contains implementation of profiling blocks
* : * :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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. * : * 2016/09/17 Victor Zarubkin: added log messages printing.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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. * description : This file contains auxiliary profiler macros for different compiler support.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -298,6 +298,7 @@ namespace profiler {
using blocks_t = profiler::BlocksTree::blocks_t; 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 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 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++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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 * description : The file contains implementation of Profile manager and implement access c-function
* : * :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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 * description : The file contains implementation of Profile manager and implement access c-function
* : * :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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. * : which reads profiler file and fill profiler blocks tree.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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 IdMap = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
using CsStatsMap = std::unordered_map<profiler::string_with_hash, profiler::BlockStatistics*>; 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. 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(); auto duration = _current.node->duration();
//StatsMap::key_type key(_current.node->name()); //StatsMap::key_type key(_current.node->name());
//auto it = _stats_map.find(key); //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); _current.per_frame_stats = update_statistics(_stats_map, _current, _current_index, _parent_index, _blocks, false);
for (auto i : _current.children) 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; PerThreadStats parent_statistics, frame_statistics;
IdMap identification_table; IdMap identification_table;
@ -808,7 +813,7 @@ extern "C" PROFILER_API profiler::block_index_t fillTreesFromStream(std::atomic<
if (inStream.eof()) if (inStream.eof())
break; break;
StatsMap per_thread_statistics; profiler::stats_map_t per_thread_statistics;
blocks_number_in_thread = 0; blocks_number_in_thread = 0;
read(inStream, blocks_number_in_thread); read(inStream, blocks_number_in_thread);

View File

@ -16,7 +16,7 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "EasySolutions" VALUE "CompanyName", "EasySolutions"
VALUE "FileDescription", "Lightweight profiler library for C++" 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 "LegalTrademarks1", "All Rights Reserved"
VALUE "LegalTrademarks2", "All Rights Reserved" VALUE "LegalTrademarks2", "All Rights Reserved"
VALUE "ProductName", "easy_profiler lib" VALUE "ProductName", "easy_profiler lib"

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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. * : which reads profiler file and fill profiler blocks tree.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

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

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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); auto color = profiler_gui::darken(c.color, 0.65f);
if (profiler_gui::alpha(color) < 0xc0) 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 else
p.setPen(QColor::fromRgba(color)); p.setPen(QColor::fromRgba(color));
p.setBrush(QColor::fromRgba(0xc8ffffff)); p.setBrush(QColor::fromRgba(0xc8ffffff));
@ -1456,7 +1456,7 @@ void ArbitraryValuesChartItem::updateComplexityImageAsync(QRectF _boundingRect,
auto color = profiler_gui::darken(c.color, 0.65f); auto color = profiler_gui::darken(c.color, 0.65f);
if (profiler_gui::alpha(color) < 0xc0) 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 else
p.setPen(QColor::fromRgba(color)); p.setPen(QColor::fromRgba(color));
p.setBrush(QColor::fromRgba(0xc8ffffff)); p.setBrush(QColor::fromRgba(0xc8ffffff));
@ -1546,12 +1546,14 @@ void ArbitraryValuesChartItem::clear()
m_collections.clear(); m_collections.clear();
m_minValue = m_maxValue = 0; m_minValue = m_maxValue = 0;
m_minDuration = m_maxDuration = 0; m_minDuration = m_maxDuration = 0;
setEmpty(true);
} }
void ArbitraryValuesChartItem::update(Collections _collections) void ArbitraryValuesChartItem::update(Collections _collections)
{ {
cancelImageUpdate(); cancelImageUpdate();
m_collections = std::move(_collections); m_collections = std::move(_collections);
setEmpty(m_collections.empty());
updateImage(); updateImage();
} }
@ -1866,6 +1868,7 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(bool _isMainWidget, profiler::threa
, m_threadId(_threadId) , m_threadId(_threadId)
, m_blockIndex(_blockIndex) , m_blockIndex(_blockIndex)
, m_blockId(_blockId) , m_blockId(_blockId)
, m_bInitialized(false)
, m_bMainWidget(_isMainWidget) , m_bMainWidget(_isMainWidget)
{ {
m_collectionsTimer.setInterval(100); m_collectionsTimer.setInterval(100);
@ -1903,12 +1906,12 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(bool _isMainWidget, profiler::threa
auto actionGroup = new QActionGroup(this); auto actionGroup = new QActionGroup(this);
actionGroup->setExclusive(true); 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->setCheckable(true);
actionRegulatChart->setChecked(true); actionRegulatChart->setChecked(true);
tb->addAction(actionRegulatChart); 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); actionComplexityChart->setCheckable(true);
tb->addAction(actionComplexityChart); tb->addAction(actionComplexityChart);
@ -1950,6 +1953,8 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(bool _isMainWidget, profiler::threa
connect(globalEvents, &GlobalSignals::selectedBlockIdChanged, this, &This::onSelectedBlockIdChanged); connect(globalEvents, &GlobalSignals::selectedBlockIdChanged, this, &This::onSelectedBlockIdChanged);
connect(globalEvents, &GlobalSignals::allDataGoingToBeDeleted, this, &This::clear); connect(globalEvents, &GlobalSignals::allDataGoingToBeDeleted, this, &This::clear);
connect(m_treeWidget->header(), &QHeaderView::sectionResized, this, &This::onHeaderSectionResized);
if (_isMainWidget) if (_isMainWidget)
{ {
connect(m_treeWidget, &QTreeWidget::itemDoubleClicked, this, &This::onItemDoubleClicked); connect(m_treeWidget, &QTreeWidget::itemDoubleClicked, this, &This::onItemDoubleClicked);
@ -1989,6 +1994,69 @@ ArbitraryValuesWidget::ArbitraryValuesWidget(QWidget* _parent)
m_exportToCsvAction->setEnabled(false); 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) ArbitraryTreeWidgetItem* findSimilarItem(QTreeWidgetItem* _parentItem, ArbitraryTreeWidgetItem* _item)
{ {
const auto index = _item->getSelfIndexInArray(); 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); auto viewer = new ArbitraryValuesWidget(m_checkedItems, m_treeWidget->currentItem(), m_threadId, m_blockIndex, m_blockId);
#ifdef WIN32 auto dialog = new Dialog(nullptr, "EasyProfiler", viewer, WindowHeader::AllButtons, QMessageBox::NoButton);
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);
dialog->setProperty("stayVisible", true); dialog->setProperty("stayVisible", true);
dialog->setAttribute(Qt::WA_DeleteOnClose, true); dialog->setAttribute(Qt::WA_DeleteOnClose, true);
connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::allDataGoingToBeDeleted, dialog, &QDialog::reject); connect(&EASY_GLOBALS.events, &profiler_gui::GlobalSignals::allDataGoingToBeDeleted, dialog, &QDialog::reject);

View File

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

View File

@ -9,7 +9,7 @@
* : for displaying arbitrary value in Diagram and Hierarchy widgets. * : for displaying arbitrary value in Diagram and Hierarchy widgets.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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. * : for displaying arbitrary value in Diagram and Hierarchy widgets.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -24,7 +24,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -500,7 +500,12 @@ bool BackgroundItem::mouseDoubleClick(const QPointF& scenePos)
{ {
qApp->restoreOverrideCursor(); qApp->restoreOverrideCursor();
auto editor = new BookmarkEditor(m_bookmark, false, sceneView->parentWidget()); 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->show();
editor->hide();
#endif
editor->exec();
} }
else else
{ {
@ -523,7 +528,12 @@ bool BackgroundItem::mouseDoubleClick(const QPointF& scenePos)
{ {
qApp->restoreOverrideCursor(); qApp->restoreOverrideCursor();
auto editor = new BookmarkEditor(m_bookmark, true, sceneView->parentWidget()); 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->show();
editor->hide();
#endif
editor->exec();
} }
} }
@ -1528,11 +1538,11 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
const profiler_gui::EasyBlock* selectedBlock = nullptr; const profiler_gui::EasyBlock* selectedBlock = nullptr;
profiler::thread_id_t selectedBlockThread = 0; profiler::thread_id_t selectedBlockThread = 0;
const auto previouslySelectedBlock = EASY_GLOBALS.selected_block; bool jumpToZone = false;
if (m_mouseButtons & Qt::LeftButton) 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) if (m_rulerItem->isVisible() && m_rulerItem->width() < 1e-6)
{ {
chronoHidden = true; chronoHidden = true;
@ -1542,12 +1552,14 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
else if (m_selectionItem->isVisible() && m_selectionItem->hoverIndicator()) else if (m_selectionItem->isVisible() && m_selectionItem->hoverIndicator())
{ {
// Jump to selected zone // Jump to selected zone
clicked = true; jumpToZone = true;
m_flickerSpeedX = m_flickerSpeedY = 0; m_flickerSpeedX = m_flickerSpeedY = 0;
notifyVisibleRegionPosChange(m_selectionItem->left() + (m_selectionItem->width() - m_visibleRegionWidth) * 0.5); 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 // Handle Click
@ -1568,7 +1580,7 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
selectedBlock = block; selectedBlock = block;
selectedBlockThread = item->threadId(); selectedBlockThread = item->threadId();
EASY_GLOBALS.selected_block = i; EASY_GLOBALS.selected_block = i;
EASY_GLOBALS.selected_block_id = easyBlock(i).tree.node->id(); EASY_GLOBALS.selected_block_id = block->tree.node->id();
break; break;
} }
} }
@ -1580,6 +1592,43 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
profiler_gui::set_max(EASY_GLOBALS.selected_block_id); 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) 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) if (changedSelectedItem)
{ {
profiler_gui::BoolFlagGuard guard(m_bUpdatingRect, true); 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) if (EASY_GLOBALS.selecting_block_changes_thread && selectedBlock != nullptr && EASY_GLOBALS.selected_thread != selectedBlockThread)
{ {
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.unlockCharts();
} }
emit EASY_GLOBALS.events.selectedBlockChanged(EASY_GLOBALS.selected_block);
if (selectedBlock != nullptr && isDoubleClick) if (selectedBlock != nullptr && isDoubleClick)
{ {
if (!selectedBlock->tree.children.empty()) if (!selectedBlock->tree.children.empty())
@ -1641,6 +1701,10 @@ void BlocksGraphicsView::mouseReleaseEvent(QMouseEvent* _event)
repaintScene(); repaintScene();
} }
else if (jumpToZone)
{
repaintScene();
}
else if (chronoHidden) else if (chronoHidden)
{ {
emit sceneUpdated(); emit sceneUpdated();
@ -1677,7 +1741,13 @@ void BlocksGraphicsView::addSelectionToHierarchy()
if (changedSelection) 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 repaintScene(); // repaint scene
} }
void BlocksGraphicsView::onInspectCurrentView(bool _strict) void BlocksGraphicsView::onInspectCurrentView(bool strict)
{ {
if (m_bEmpty) if (m_bEmpty)
return; return;
if (!m_selectionItem->isVisible()) 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->setLeftRight(m_offset, m_offset + m_visibleRegionWidth);
m_selectionItem->show(); m_selectionItem->show();
m_pScrollbar->setSelectionPos(m_selectionItem->left(), m_selectionItem->right()); 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); ruler_item->setReverse(false);
_chronometerItem->setLeftRight(_chronometerItem->right(), _mouseX); ruler_item->setLeftRight(ruler_item->right(), mouse_x);
if (_chronometerItem->hoverLeft()) if (ruler_item->hoverLeft())
{ {
_chronometerItem->setHoverLeft(false); ruler_item->setHoverLeft(false);
_chronometerItem->setHoverRight(true); ruler_item->setHoverRight(true);
} }
} }
else else
{ {
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->right()); ruler_item->setLeftRight(mouse_x, ruler_item->right());
} }
} }
else else
{ {
if (_mouseX < _chronometerItem->left()) if (mouse_x < ruler_item->left())
{ {
_chronometerItem->setReverse(true); ruler_item->setReverse(true);
_chronometerItem->setLeftRight(_mouseX, _chronometerItem->left()); ruler_item->setLeftRight(mouse_x, ruler_item->left());
if (_chronometerItem->hoverRight()) if (ruler_item->hoverRight())
{ {
_chronometerItem->setHoverLeft(true); ruler_item->setHoverLeft(true);
_chronometerItem->setHoverRight(false); ruler_item->setHoverRight(false);
} }
} }
else 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); emit EASY_GLOBALS.events.rulerVisible(true);
return true; return true;
} }
@ -1786,7 +1862,7 @@ bool BlocksGraphicsView::moveChrono(GraphicsRulerItem* _chronometerItem, qreal _
return false; return false;
} }
void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event) void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* event)
{ {
if (needToIgnoreMouseEvent()) if (needToIgnoreMouseEvent())
return; return;
@ -1795,26 +1871,26 @@ void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
if (m_bEmpty) if (m_bEmpty)
{ {
_event->accept(); event->accept();
return; return;
} }
auto scenePos = mapToScene(_event->pos()); auto scenePos = mapToScene(event->pos());
scenePos.setX(m_offset + scenePos.x() / m_scale); scenePos.setX(m_offset + scenePos.x() / m_scale);
if (m_backgroundItem->mouseMove(scenePos)) if (m_backgroundItem->mouseMove(scenePos))
{ {
_event->accept(); event->accept();
return; return;
} }
if (m_mouseButtons == 0 && !m_selectionItem->isVisible() && !m_rulerItem->isVisible()) if (m_mouseButtons == 0 && !m_selectionItem->isVisible() && !m_rulerItem->isVisible())
{ {
_event->accept(); event->accept();
return; return;
} }
bool needUpdate = false; bool needUpdate = false;
const auto pos = _event->pos(); const auto pos = event->pos();
const auto delta = pos - m_mousePressPos; const auto delta = pos - m_mousePressPos;
m_mousePressPos = pos; m_mousePressPos = pos;
@ -1851,7 +1927,9 @@ void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
{ {
auto vbar = verticalScrollBar(); 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()); vbar->setValue(vbar->value() - delta.y());
notifyVisibleRegionPosChange(m_offset - delta.x() / m_scale); notifyVisibleRegionPosChange(m_offset - delta.x() / m_scale);
guard.restore(); guard.restore();
@ -1913,16 +1991,16 @@ void BlocksGraphicsView::mouseMoveEvent(QMouseEvent* _event)
repaintScene(); // repaint scene repaintScene(); // repaint scene
} }
_event->accept(); event->accept();
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void BlocksGraphicsView::keyPressEvent(QKeyEvent* _event) void BlocksGraphicsView::keyPressEvent(QKeyEvent* event)
{ {
static const int KeyStep = 100; static const int KeyStep = 100;
const int key = _event->key(); const int key = event->key();
switch (key) switch (key)
{ {
@ -1971,14 +2049,14 @@ void BlocksGraphicsView::keyPressEvent(QKeyEvent* _event)
} }
m_idleTime = 0; 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 QRectF previousRect = m_visibleSceneRect;
const int vbar_width = updateVisibleSceneRect(); // Update scene visible rect only once 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]() connect(globalSignals, &profiler_gui::GlobalSignals::blocksTreeModeChanged, [this]()
{ {
if (!m_selectedBlocks.empty()) 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); connect(globalSignals, &profiler_gui::GlobalSignals::chartSliderChanged, this, &This::onGraphicsScrollbarValueChange);
@ -2095,11 +2179,11 @@ void BlocksGraphicsView::onScrollbarValueChange(int)
updateVisibleSceneRect(); updateVisibleSceneRect();
} }
void BlocksGraphicsView::onGraphicsScrollbarValueChange(qreal _value) void BlocksGraphicsView::onGraphicsScrollbarValueChange(qreal value)
{ {
if (!m_bEmpty) if (!m_bEmpty)
{ {
m_offset = _value; m_offset = value;
if (!m_bUpdatingRect) if (!m_bUpdatingRect)
{ {
updateVisibleSceneRect(); updateVisibleSceneRect();
@ -2184,7 +2268,7 @@ void BlocksGraphicsView::onIdleTimeout()
if (m_popupWidget != nullptr) if (m_popupWidget != nullptr)
return; return;
if (!window()->isActiveWindow()) if (window() == nullptr || !window()->isActiveWindow())
return; return;
auto focusWidget = qApp->focusWidget(); 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); 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; ++col;
auto parent_duration = easyBlocksTree(itemBlock.per_parent_stats->parent_block).node->duration(); auto parent_duration = easyBlocksTree(itemBlock.per_parent_stats->parent_block).node->duration();
@ -2592,18 +2676,24 @@ void BlocksGraphicsView::onHierarchyFlagChange(bool)
if (changedSelection) 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; return;
} }
if (_id == 0) if (id == 0)
{ {
m_pScrollbar->setHistogramSource(0, nullptr); m_pScrollbar->setHistogramSource(0, nullptr);
return; return;
@ -2611,9 +2701,9 @@ void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t _id)
for (auto item : m_items) 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; bool changedSelection = false;
if (EASY_GLOBALS.only_current_thread_hierarchy) if (EASY_GLOBALS.only_current_thread_hierarchy)
@ -2634,7 +2724,13 @@ void BlocksGraphicsView::onSelectedThreadChange(profiler::thread_id_t _id)
if (changedSelection) 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(); repaintScene();
@ -3007,7 +3103,7 @@ void ThreadNamesWidget::onIdleTimeout()
if (m_popupWidget != nullptr) if (m_popupWidget != nullptr)
return; return;
if (!window()->isActiveWindow()) if (window() == nullptr || !window()->isActiveWindow())
return; return;
auto focusWidget = qApp->focusWidget(); auto focusWidget = qApp->focusWidget();
@ -3123,7 +3219,7 @@ void ThreadNamesWidget::onIdleTimeout()
m_popupWidget = widget; m_popupWidget = widget;
if (m_popupWidget != nullptr) if (m_popupWidget != nullptr)
{ {
auto focusWidget = qApp->focusWidget(); focusWidget = qApp->focusWidget();
m_popupWidget->move(QCursor::pos()); m_popupWidget->move(QCursor::pos());
m_popupWidget->show(); m_popupWidget->show();

View File

@ -20,7 +20,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -236,9 +236,9 @@ public:
void mousePressEvent(QMouseEvent* _event) override; void mousePressEvent(QMouseEvent* _event) override;
void mouseDoubleClickEvent(QMouseEvent* _event) override; void mouseDoubleClickEvent(QMouseEvent* _event) override;
void mouseReleaseEvent(QMouseEvent* _event) override; void mouseReleaseEvent(QMouseEvent* _event) override;
void mouseMoveEvent(QMouseEvent* _event) override; void mouseMoveEvent(QMouseEvent* event) override;
void keyPressEvent(QKeyEvent* _event) override; void keyPressEvent(QKeyEvent* event) override;
void resizeEvent(QResizeEvent* _event) override; void resizeEvent(QResizeEvent* event) override;
void dragEnterEvent(QDragEnterEvent*) override {} void dragEnterEvent(QDragEnterEvent*) override {}
@ -288,7 +288,7 @@ private:
bool needToIgnoreMouseEvent() const; bool needToIgnoreMouseEvent() const;
GraphicsRulerItem* createRuler(bool _main = true); GraphicsRulerItem* createRuler(bool _main = true);
bool moveChrono(GraphicsRulerItem* _chronometerItem, qreal _mouseX); bool moveChrono(GraphicsRulerItem* ruler_item, qreal mouse_x);
void initMode(); void initMode();
int updateVisibleSceneRect(); int updateVisibleSceneRect();
void updateTimelineStep(qreal _windowWidth); void updateTimelineStep(qreal _windowWidth);
@ -313,7 +313,7 @@ private slots:
void onFlickerTimeout(); void onFlickerTimeout();
void onIdleTimeout(); void onIdleTimeout();
void onHierarchyFlagChange(bool _value); 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 onSelectedBlockChange(unsigned int _block_index);
void onRefreshRequired(); void onRefreshRequired();
void onThreadViewChanged(); 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 * : Moved sources of TreeWidgetItem into tree_widget_item.h/.cpp
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -95,13 +95,18 @@ protected:
class QLabel* m_hintLabel; class QLabel* m_hintLabel;
class ArbitraryValueToolTip* m_valueTooltip; class ArbitraryValueToolTip* m_valueTooltip;
TreeMode m_mode; TreeMode m_mode;
int m_lastFoundIndex;
bool m_bLocked; bool m_bLocked;
bool m_bSilentExpandCollapse; bool m_bSilentExpandCollapse;
bool m_bCaseSensitiveSearch;
bool m_bInitialized; bool m_bInitialized;
char m_columnsHiddenStatus[COL_COLUMNS_NUMBER]; char m_columnsHiddenStatus[COL_COLUMNS_NUMBER];
int m_columnsMinimumWidth[COL_COLUMNS_NUMBER];
public: public:
using Parent::indexFromItem;
explicit BlocksTreeWidget(QWidget* _parent = nullptr); explicit BlocksTreeWidget(QWidget* _parent = nullptr);
~BlocksTreeWidget() override; ~BlocksTreeWidget() override;
@ -114,11 +119,22 @@ public:
int findNext(const QString& _str, Qt::MatchFlags _flags); int findNext(const QString& _str, Qt::MatchFlags _flags);
int findPrev(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: 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 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: protected:
@ -127,6 +143,8 @@ protected:
private slots: private slots:
void onHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
void onJumpToItemClicked(bool); void onJumpToItemClicked(bool);
void onCollapseAllClicked(bool); void onCollapseAllClicked(bool);
@ -140,6 +158,7 @@ private slots:
void onItemExpand(QTreeWidgetItem* _item); void onItemExpand(QTreeWidgetItem* _item);
void onItemCollapse(QTreeWidgetItem* _item); void onItemCollapse(QTreeWidgetItem* _item);
void onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem*); void onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem*);
void onItemDoubleClicked(QTreeWidgetItem* _item, int _column);
void onSelectedThreadChange(::profiler::thread_id_t _id); void onSelectedThreadChange(::profiler::thread_id_t _id);
@ -192,6 +211,8 @@ public:
explicit HierarchyWidget(QWidget* _parent = nullptr); explicit HierarchyWidget(QWidget* _parent = nullptr);
~HierarchyWidget() override; ~HierarchyWidget() override;
void enterEvent(QEvent* event) override;
void leaveEvent(QEvent* event) override;
void keyPressEvent(QKeyEvent* _event) override; void keyPressEvent(QKeyEvent* _event) override;
void contextMenuEvent(QContextMenuEvent* _event) override; void contextMenuEvent(QContextMenuEvent* _event) override;
void dragEnterEvent(QDragEnterEvent*) override {} void dragEnterEvent(QDragEnterEvent*) override {}

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of BookmarkEditor. * description : The file contains implementation of BookmarkEditor.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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); setAttribute(Qt::WA_DeleteOnClose, true);
setSizeGripEnabled(EASY_GLOBALS.use_custom_window_header); setSizeGripEnabled(EASY_GLOBALS.use_custom_window_header);
setModal(true);
const auto& bookmark = EASY_GLOBALS.bookmarks[m_bookmarkIndex]; 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); contentLayout->addWidget(m_textEdit, 1);
const WindowHeader::Buttons buttons {WindowHeader::MaximizeButton | WindowHeader::CloseButton}; 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); auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(1, 1, 1, 1); mainLayout->setContentsMargins(1, 1, 1, 1);
@ -174,10 +173,11 @@ void BookmarkEditor::onColorButtonClicked(bool)
QColorDialog colorDialog(palette.brush(QPalette::Background).color(), this); QColorDialog colorDialog(palette.brush(QPalette::Background).color(), this);
colorDialog.exec(); 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->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()->unpolish(m_colorButton);
m_colorButton->style()->polish(m_colorButton); m_colorButton->style()->polish(m_colorButton);
m_colorButton->update(); m_colorButton->update();

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of BookmarkEditor. * description : The file contains declaration of BookmarkEditor.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -96,13 +96,9 @@ struct EasyBlockItem Q_DECL_FINAL
}; // END of struct EasyBlockItem. }; // END of struct EasyBlockItem.
//#define EASY_TREE_WIDGET__USE_VECTOR
struct EasyBlock Q_DECL_FINAL struct EasyBlock Q_DECL_FINAL
{ {
::profiler::BlocksTree tree; ::profiler::BlocksTree tree;
#ifdef EASY_TREE_WIDGET__USE_VECTOR
uint32_t tree_item;
#endif
uint32_t graphics_item_index; uint32_t graphics_item_index;
uint8_t graphics_item_level; uint8_t graphics_item_level;
uint8_t graphics_item; uint8_t graphics_item;
@ -112,9 +108,6 @@ struct EasyBlock Q_DECL_FINAL
EasyBlock(EasyBlock&& that) EASY_NOEXCEPT EasyBlock(EasyBlock&& that) EASY_NOEXCEPT
: tree(::std::move(that.tree)) : 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_index(that.graphics_item_index)
, graphics_item_level(that.graphics_item_level) , graphics_item_level(that.graphics_item_level)
, graphics_item(that.graphics_item) , graphics_item(that.graphics_item)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -53,26 +53,31 @@
* : limitations under the License. * : limitations under the License.
************************************************************************/ ************************************************************************/
#include <QMenu> #include <QAbstractTextDocumentLayout>
#include <QAction> #include <QAction>
#include <QActionGroup> #include <QActionGroup>
#include <QHeaderView>
#include <QString>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QKeyEvent> #include <QKeyEvent>
#include <QSignalBlocker>
#include <QSettings>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QToolBar> #include <QMenu>
#include <QVBoxLayout> #include <QSettings>
#include <QHBoxLayout> #include <QSignalBlocker>
#include <QSplitter> #include <QSplitter>
#include <QVariant> #include <QString>
#include <QTextDocument>
#include <QTimer> #include <QTimer>
#include <QToolBar>
#include <QVariant>
#include <QVBoxLayout>
#include "descriptors_tree_widget.h" #include "descriptors_tree_widget.h"
#include "arbitrary_value_inspector.h"
#include "globals.h" #include "globals.h"
#include "arbitrary_value_inspector.h"
#include "text_highlighter.h"
#include "thread_pool.h" #include "thread_pool.h"
#ifdef max #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) ::profiler::EasyBlockStatus nextStatus(::profiler::EasyBlockStatus _status)
{ {
switch (_status) switch (_status)
@ -240,10 +233,15 @@ QVariant DescriptorsTreeItem::data(int _column, int _role) const
DescriptorsTreeWidget::DescriptorsTreeWidget(QWidget* _parent) DescriptorsTreeWidget::DescriptorsTreeWidget(QWidget* _parent)
: Parent(_parent) : Parent(_parent)
, m_lastFound(nullptr) , m_lastFound(nullptr)
, m_lastFoundIndex(0)
, m_lastSearchColumn(-1) , m_lastSearchColumn(-1)
, m_searchColumn(DESC_COL_NAME) , m_searchColumn(DESC_COL_NAME)
, m_bLocked(false) , m_bLocked(false)
, m_bCaseSensitiveSearch(false)
, m_bInitialized(false)
{ {
memset(m_columnsMinimumWidth, 0, sizeof(m_columnsMinimumWidth));
setAutoFillBackground(false); setAutoFillBackground(false);
setAlternatingRowColors(true); setAlternatingRowColors(true);
setItemsExpandable(true); setItemsExpandable(true);
@ -264,8 +262,11 @@ DescriptorsTreeWidget::DescriptorsTreeWidget(QWidget* _parent)
connect(this, &Parent::itemExpanded, this, &This::onItemExpand); connect(this, &Parent::itemExpanded, this, &This::onItemExpand);
connect(this, &Parent::itemDoubleClicked, this, &This::onDoubleClick); connect(this, &Parent::itemDoubleClicked, this, &This::onDoubleClick);
connect(this, &Parent::currentItemChanged, this, &This::onCurrentItemChange); connect(this, &Parent::currentItemChanged, this, &This::onCurrentItemChange);
connect(header(), &QHeaderView::sectionResized, this, &This::onHeaderSectionResized);
loadSettings(); loadSettings();
setItemDelegateForColumn(m_searchColumn, new DescWidgetItemDelegate(this));
} }
DescriptorsTreeWidget::~DescriptorsTreeWidget() DescriptorsTreeWidget::~DescriptorsTreeWidget()
@ -279,11 +280,83 @@ DescriptorsTreeWidget::~DescriptorsTreeWidget()
saveSettings(); 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) void DescriptorsTreeWidget::setSearchColumn(int column)
{ {
const int prevColumn = m_searchColumn;
m_searchColumn = column; 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); emit searchColumnChanged(column);
} }
@ -292,6 +365,26 @@ int DescriptorsTreeWidget::searchColumn() const
return m_searchColumn; 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) void DescriptorsTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
@ -348,10 +441,8 @@ void DescriptorsTreeWidget::clearSilent(bool _global)
const QSignalBlocker b(this); const QSignalBlocker b(this);
setSortingEnabled(false); setSortingEnabled(false);
m_lastFound = nullptr; resetSearch(false);
m_lastSearch.clear();
m_highlightItems.clear();
m_items.clear(); m_items.clear();
if (topLevelItemCount() != 0) if (topLevelItemCount() != 0)
@ -464,7 +555,23 @@ void DescriptorsTreeWidget::build()
setSortingEnabled(true); setSortingEnabled(true);
sortByColumn(DESC_COL_FILE_LINE, Qt::AscendingOrder); sortByColumn(DESC_COL_FILE_LINE, Qt::AscendingOrder);
resizeColumnsToContents(); 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) 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) 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) if (::profiler_gui::is_max(EASY_GLOBALS.selected_block) && _item->parent() != nullptr)
{ {
const auto id = static_cast<DescriptorsTreeItem*>(_item)->desc(); 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() void DescriptorsTreeWidget::loadSettings()
{ {
QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME); 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()) if (_str.isEmpty())
{ {
resetHighlight(); resetSearch();
m_lastSearchColumn = m_searchColumn;
return 0; return 0;
} }
const bool isNewSearch = (m_lastSearchColumn != m_searchColumn || m_lastSearch != _str); const bool isNewSearch = (m_lastSearchColumn != m_searchColumn || m_lastSearch != _str);
auto itemsList = findItems(_str, Qt::MatchContains | Qt::MatchRecursive | _flags, m_searchColumn); auto itemsList = findItems(_str, Qt::MatchContains | Qt::MatchRecursive | _flags, m_searchColumn);
m_bCaseSensitiveSearch = _flags.testFlag(Qt::MatchCaseSensitive);
if (!isNewSearch) if (!isNewSearch)
{ {
if (!itemsList.empty()) if (!itemsList.empty())
{ {
bool stop = false; bool stop = false;
int i = 0;
decltype(m_lastFound) next = nullptr; decltype(m_lastFound) next = nullptr;
for (auto item : itemsList) for (auto item : itemsList)
{ {
@ -658,29 +745,24 @@ int DescriptorsTreeWidget::findNext(const QString& _str, Qt::MatchFlags _flags)
} }
stop = item == m_lastFound; stop = item == m_lastFound;
++i;
} }
m_lastFound = next == nullptr ? itemsList.front() : next; m_lastFound = next == nullptr ? itemsList.front() : next;
m_lastFoundIndex = next == nullptr ? 0 : i;
} }
else else
{ {
m_lastFound = nullptr; m_lastFound = nullptr;
m_lastFoundIndex = 0;
} }
} }
else else
{ {
resetHighlight();
m_lastSearchColumn = m_searchColumn; m_lastSearchColumn = m_searchColumn;
m_lastSearch = _str; m_lastSearch = _str;
m_lastFound = !itemsList.empty() ? itemsList.front() : nullptr; m_lastFound = !itemsList.empty() ? itemsList.front() : nullptr;
m_lastFoundIndex = 0;
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)));
}
} }
if (m_lastFound != nullptr) if (m_lastFound != nullptr)
@ -689,6 +771,8 @@ int DescriptorsTreeWidget::findNext(const QString& _str, Qt::MatchFlags _flags)
setCurrentItem(m_lastFound); setCurrentItem(m_lastFound);
} }
viewport()->update();
return itemsList.size(); return itemsList.size();
} }
@ -696,48 +780,54 @@ int DescriptorsTreeWidget::findPrev(const QString& _str, Qt::MatchFlags _flags)
{ {
if (_str.isEmpty()) if (_str.isEmpty())
{ {
resetHighlight(); resetSearch();
m_lastSearchColumn = m_searchColumn;
return 0; return 0;
} }
const bool isNewSearch = (m_lastSearchColumn != m_searchColumn || m_lastSearch != _str); const bool isNewSearch = (m_lastSearchColumn != m_searchColumn || m_lastSearch != _str);
auto itemsList = findItems(_str, Qt::MatchContains | Qt::MatchRecursive | _flags, m_searchColumn); auto itemsList = findItems(_str, Qt::MatchContains | Qt::MatchRecursive | _flags, m_searchColumn);
m_bCaseSensitiveSearch = _flags.testFlag(Qt::MatchCaseSensitive);
if (!isNewSearch) if (!isNewSearch)
{ {
if (!itemsList.empty()) if (!itemsList.empty())
{ {
int i = 0;
decltype(m_lastFound) prev = nullptr; decltype(m_lastFound) prev = nullptr;
for (auto item : itemsList) for (auto item : itemsList)
{ {
if (item == m_lastFound) if (item == m_lastFound)
{
--i;
break; break;
}
prev = item; prev = item;
++i;
} }
m_lastFound = prev == nullptr ? itemsList.back() : prev; m_lastFound = prev == nullptr ? itemsList.back() : prev;
m_lastFoundIndex = prev == nullptr ? itemsList.length() - 1 : i;
} }
else else
{ {
m_lastFound = nullptr; m_lastFound = nullptr;
m_lastFoundIndex = 0;
} }
} }
else else
{ {
resetHighlight();
m_lastSearchColumn = m_searchColumn; m_lastSearchColumn = m_searchColumn;
m_lastSearch = _str; m_lastSearch = _str;
m_lastFound = !itemsList.empty() ? itemsList.front() : nullptr; if (!itemsList.empty())
m_highlightItems.reserve(itemsList.size());
for (auto item : itemsList)
{ {
m_highlightItems.push_back(item); m_lastFound = itemsList.back();
for (int i = 0; i < DESC_COL_COLUMNS_NUMBER; ++i) m_lastFoundIndex = itemsList.length() - 1;
item->setBackgroundColor(i, QColor::fromRgba(0x80000000 | (0x00ffffff & ::profiler::colors::Yellow))); }
else
{
m_lastFound = nullptr;
m_lastFoundIndex = 0;
} }
} }
@ -747,6 +837,8 @@ int DescriptorsTreeWidget::findPrev(const QString& _str, Qt::MatchFlags _flags)
setCurrentItem(m_lastFound); setCurrentItem(m_lastFound);
} }
viewport()->update();
return itemsList.size(); return itemsList.size();
} }
@ -757,7 +849,7 @@ BlockDescriptorsWidget::BlockDescriptorsWidget(QWidget* _parent) : Parent(_paren
, m_tree(new DescriptorsTreeWidget(this)) , m_tree(new DescriptorsTreeWidget(this))
, m_values(new ArbitraryValuesWidget(this)) , m_values(new ArbitraryValuesWidget(this))
, m_searchBox(new QLineEdit(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_searchButton(nullptr)
, m_bCaseSensitiveSearch(false) , m_bCaseSensitiveSearch(false)
{ {
@ -897,12 +989,24 @@ void BlockDescriptorsWidget::saveSettings()
void BlockDescriptorsWidget::keyPressEvent(QKeyEvent* _event) void BlockDescriptorsWidget::keyPressEvent(QKeyEvent* _event)
{ {
if (_event->key() == Qt::Key_F3) switch (_event->key())
{
case Qt::Key_F3:
{ {
if (_event->modifiers() & Qt::ShiftModifier) if (_event->modifiers() & Qt::ShiftModifier)
findPrev(true); findPrev(true);
else else
findNext(true); findNext(true);
break;
}
case Qt::Key_Escape:
{
m_searchBox->clear();
break;
}
default: break;
} }
_event->accept(); _event->accept();
@ -922,7 +1026,7 @@ void BlockDescriptorsWidget::showEvent(QShowEvent* event)
void BlockDescriptorsWidget::build() void BlockDescriptorsWidget::build()
{ {
m_tree->clearSilent(false); m_tree->clearSilent(false);
m_foundNumber->setText(QString("0 matches")); m_foundNumber->setText(QStringLiteral("<font color=\"red\">0</font> matches"));
m_foundNumber->hide(); m_foundNumber->hide();
m_tree->build(); m_tree->build();
m_values->rebuild(); m_values->rebuild();
@ -931,7 +1035,7 @@ void BlockDescriptorsWidget::build()
void BlockDescriptorsWidget::clear() void BlockDescriptorsWidget::clear()
{ {
m_tree->clearSilent(true); m_tree->clearSilent(true);
m_foundNumber->setText(QString("0 matches")); m_foundNumber->setText(QStringLiteral("<font color=\"red\">0</font> matches"));
m_foundNumber->hide(); m_foundNumber->hide();
m_values->clear(); m_values->clear();
} }
@ -943,7 +1047,7 @@ ArbitraryValuesWidget* BlockDescriptorsWidget::dataViewer() const
void BlockDescriptorsWidget::onSeachBoxReturnPressed() void BlockDescriptorsWidget::onSeachBoxReturnPressed()
{ {
if (m_searchButton->data().toBool() == true) if (m_searchButton->data().toBool())
findNext(true); findNext(true);
else else
findPrev(true); findPrev(true);
@ -952,7 +1056,10 @@ void BlockDescriptorsWidget::onSeachBoxReturnPressed()
void BlockDescriptorsWidget::onSearchBoxTextChanged(const QString& _text) void BlockDescriptorsWidget::onSearchBoxTextChanged(const QString& _text)
{ {
if (_text.isEmpty()) if (_text.isEmpty())
{
m_foundNumber->hide(); m_foundNumber->hide();
m_tree->resetSearch();
}
} }
void BlockDescriptorsWidget::onSearchColumnChanged(int column) void BlockDescriptorsWidget::onSearchColumnChanged(int column)
@ -989,15 +1096,27 @@ void BlockDescriptorsWidget::findNext(bool)
{ {
if (m_foundNumber->isVisible()) if (m_foundNumber->isVisible())
m_foundNumber->hide(); m_foundNumber->hide();
m_tree->resetSearch();
return; return;
} }
auto matches = m_tree->findNext(text, m_bCaseSensitiveSearch ? Qt::MatchCaseSensitive : Qt::MatchFlags()); auto matches = m_tree->findNext(text, m_bCaseSensitiveSearch ? Qt::MatchCaseSensitive : Qt::MatchFlags());
if (matches == 1) if (matches == 0)
m_foundNumber->setText(QString("1 match")); {
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 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()) if (!m_foundNumber->isVisible())
m_foundNumber->show(); m_foundNumber->show();
@ -1010,15 +1129,27 @@ void BlockDescriptorsWidget::findPrev(bool)
{ {
if (m_foundNumber->isVisible()) if (m_foundNumber->isVisible())
m_foundNumber->hide(); m_foundNumber->hide();
m_tree->resetSearch();
return; return;
} }
auto matches = m_tree->findPrev(text, m_bCaseSensitiveSearch ? Qt::MatchCaseSensitive : Qt::MatchFlags()); auto matches = m_tree->findPrev(text, m_bCaseSensitiveSearch ? Qt::MatchCaseSensitive : Qt::MatchFlags());
if (matches == 1) if (matches == 0)
m_foundNumber->setText(QString("1 match")); {
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 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()) if (!m_foundNumber->isVisible())
m_foundNumber->show(); m_foundNumber->show();
@ -1029,7 +1160,7 @@ void BlockDescriptorsWidget::findNextFromMenu(bool _checked)
if (!_checked) if (!_checked)
return; return;
if (m_searchButton->data().toBool() == false) if (!m_searchButton->data().toBool())
{ {
m_searchButton->setData(true); m_searchButton->setData(true);
m_searchButton->setText(tr("Find next")); m_searchButton->setText(tr("Find next"));
@ -1046,7 +1177,7 @@ void BlockDescriptorsWidget::findPrevFromMenu(bool _checked)
if (!_checked) if (!_checked)
return; return;
if (m_searchButton->data().toBool() == true) if (m_searchButton->data().toBool())
{ {
m_searchButton->setData(false); m_searchButton->setData(false);
m_searchButton->setText(tr("Find prev")); 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++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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 class DescriptorsTreeItem : public QTreeWidgetItem
{ {
using Parent = QTreeWidgetItem; using Parent = QTreeWidgetItem;
@ -121,19 +133,21 @@ class DescriptorsTreeWidget : public QTreeWidget
using This = DescriptorsTreeWidget; using This = DescriptorsTreeWidget;
using Items = ::std::vector<DescriptorsTreeItem*>; using Items = ::std::vector<DescriptorsTreeItem*>;
using TreeItems = ::std::vector<QTreeWidgetItem*>;
using ExpandedFiles = ::std::unordered_set<::std::string>; using ExpandedFiles = ::std::unordered_set<::std::string>;
protected: protected:
ExpandedFiles m_expandedFilesTemp; ExpandedFiles m_expandedFilesTemp;
Items m_items; Items m_items;
TreeItems m_highlightItems;
QString m_lastSearch; QString m_lastSearch;
QTreeWidgetItem* m_lastFound; QTreeWidgetItem* m_lastFound;
int m_columnsMinimumWidth[DESC_COL_COLUMNS_NUMBER];
int m_lastFoundIndex;
int m_lastSearchColumn; int m_lastSearchColumn;
int m_searchColumn; int m_searchColumn;
bool m_bLocked; bool m_bLocked;
bool m_bCaseSensitiveSearch;
bool m_bInitialized;
public: public:
@ -141,17 +155,29 @@ public:
explicit DescriptorsTreeWidget(QWidget* _parent = nullptr); explicit DescriptorsTreeWidget(QWidget* _parent = nullptr);
~DescriptorsTreeWidget() override; ~DescriptorsTreeWidget() override;
void contextMenuEvent(QContextMenuEvent* _event) override; void contextMenuEvent(QContextMenuEvent* _event) override;
void showEvent(class QShowEvent* event) override;
public: public:
using Parent::indexFromItem;
// Public non-virtual methods // Public non-virtual methods
int findNext(const QString& _str, Qt::MatchFlags _flags); int findNext(const QString& _str, Qt::MatchFlags _flags);
int findPrev(const QString& _str, Qt::MatchFlags _flags); int findPrev(const QString& _str, Qt::MatchFlags _flags);
void resetSearch(bool repaint = true);
void setSearchColumn(int column); void setSearchColumn(int column);
int searchColumn() const; int searchColumn() const;
QTreeWidgetItem* lastFoundItem() const;
const QString& searchString() const;
bool caseSensitiveSearch() const;
int lastFoundIndex() const;
signals: signals:
void searchColumnChanged(int column); void searchColumnChanged(int column);
@ -163,6 +189,7 @@ public slots:
private slots: private slots:
void onHeaderSectionResized(int logicalIndex, int oldSize, int newSize);
void onBlockStatusChangeClicked(bool); void onBlockStatusChangeClicked(bool);
void onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem* _prev); void onCurrentItemChange(QTreeWidgetItem* _item, QTreeWidgetItem* _prev);
void onItemExpand(QTreeWidgetItem* _item); void onItemExpand(QTreeWidgetItem* _item);
@ -175,7 +202,6 @@ private:
// Private methods // Private methods
void resetHighlight();
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
@ -243,6 +269,35 @@ private:
}; // END of class BlockDescriptorsWidget. }; // 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 #endif // EASY_DESCRIPTORS_WIDGET_H

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of Dialog. * description : The file contains implementation of Dialog.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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); 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); auto mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(1, 1, 1, 1); mainLayout->setContentsMargins(1, 1, 1, 1);

View File

@ -9,7 +9,7 @@
* : for all dialogs in the application. * : for all dialogs in the application.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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); centerOn(0, 0);
// Dirty hack for QDockWidget stupid initial size policy :( // 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 setFixedHeight(10); // Set very small height to enable appropriate minimum height on the application startup
QTimer::singleShot(100, [this] QTimer::singleShot(100, [this]
{ {
// Now set appropriate minimum height // Now set appropriate minimum height
setMinimumHeight((QFontMetrics(scene()->font()).height() + 3) * 6); setMinimumHeight((QFontMetrics(scene()->font()).height() + px(3)) * 3);
setMaximumHeight(minimumHeight() * 20); setMaximumHeight(minimumHeight() * 20);
}); });
} }
@ -294,6 +295,16 @@ void FpsWidget::addPoint(uint32_t _maxFrameTime, uint32_t _avgFrameTime)
scene()->update(); 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) void FpsWidget::resizeEvent(QResizeEvent* _event)
{ {
Parent::resizeEvent(_event); Parent::resizeEvent(_event);

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -109,6 +109,8 @@ public:
explicit FpsWidget(QWidget* _parent = nullptr); explicit FpsWidget(QWidget* _parent = nullptr);
~FpsWidget() override; ~FpsWidget() override;
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
void resizeEvent(QResizeEvent* _event) override; void resizeEvent(QResizeEvent* _event) override;
void hideEvent(QHideEvent* _event) override; void hideEvent(QHideEvent* _event) override;
void showEvent(QShowEvent* _event) override; void showEvent(QShowEvent* _event) override;

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -59,25 +59,25 @@
namespace profiler_gui { namespace profiler_gui {
Globals& Globals::instance() Globals& Globals::instance()
{ {
// It's okay even without C++11 "magic statics" feature because first call happens // 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. // on application initialization - there is only one thread and no data races occur.
static Globals globals; static Globals globals;
return globals; return globals;
} }
Globals::Fonts::Fonts() Globals::Fonts::Fonts()
: default_font(::profiler_gui::EFont("DejaVu Sans", 13)) : default_font(::profiler_gui::EFont("DejaVu Sans", 13))
, background(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Bold)) , background(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Bold))
, ruler(::profiler_gui::EFont("DejaVu Sans", 16, QFont::Bold)) , ruler(::profiler_gui::EFont("DejaVu Sans", 16, QFont::Bold))
, item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium)) , item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium))
, selected_item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium)) , selected_item(::profiler_gui::EFont("DejaVu Sans", 13, QFont::Medium))
{ {
} }
Globals::Globals() Globals::Globals()
: theme("default") : theme("default")
, pid(0) , pid(0)
, begin_time(0) , begin_time(0)
@ -109,7 +109,7 @@ namespace profiler_gui {
, draw_graphics_items_borders(true) , draw_graphics_items_borders(true)
, hide_narrow_children(false) , hide_narrow_children(false)
, hide_minsize_blocks(false) , hide_minsize_blocks(false)
, display_only_relevant_stats(true) , display_only_relevant_stats(false)
, collapse_items_on_tree_close(false) , collapse_items_on_tree_close(false)
, all_items_expanded_by_default(true) , all_items_expanded_by_default(true)
, only_current_thread_hierarchy(false) , only_current_thread_hierarchy(false)
@ -119,9 +119,9 @@ namespace profiler_gui {
, auto_adjust_chart_height(false) , auto_adjust_chart_height(false)
, display_only_frames_on_histogram(false) , display_only_frames_on_histogram(false)
, bind_scene_and_tree_expand_status(true) , bind_scene_and_tree_expand_status(true)
{ {
} }
} // END of namespace profiler_gui. } // END of namespace profiler_gui.

View File

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

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of GraphicsBlockItem. * description : The file contains implementation of GraphicsBlockItem.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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; size_t itemIndex = 0;
if (first != level0.end()) if (first != level0.end())
{ {
itemIndex = first - level0.begin(); itemIndex = static_cast<size_t>(std::distance(level0.begin(), first));
if (itemIndex > 0) if (itemIndex > 0)
itemIndex -= 1; itemIndex -= 1;
} }

View File

@ -9,7 +9,7 @@
* : used to draw profiler blocks on graphics scene. * : used to draw profiler blocks on graphics scene.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of GraphicsImageItem. * description : The file contains implementation of GraphicsImageItem.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -70,6 +70,7 @@ GraphicsImageItem::GraphicsImageItem() : Parent(nullptr)
, m_maxValue(0) , m_maxValue(0)
, m_minValue(0) , m_minValue(0)
, m_timer(::std::bind(&This::onTimeout, this)) , m_timer(::std::bind(&This::onTimeout, this))
, m_bEmpty(true)
, m_bPermitImageUpdate(true) , m_bPermitImageUpdate(true)
{ {
m_bReady = false; 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); 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) void GraphicsImageItem::setMousePos(const QPointF& pos)
{ {
m_mousePos = pos; m_mousePos = pos;
@ -173,6 +184,11 @@ bool GraphicsImageItem::cancelImageUpdate()
bool GraphicsImageItem::pickTopValue() bool GraphicsImageItem::pickTopValue()
{ {
if (isEmpty())
{
return false;
}
const auto y = m_mousePos.y(); const auto y = m_mousePos.y();
if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom()) if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom())
{ {
@ -187,6 +203,11 @@ bool GraphicsImageItem::pickTopValue()
bool GraphicsImageItem::increaseTopValue() bool GraphicsImageItem::increaseTopValue()
{ {
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_topValue < m_maxValue) if (isImageUpdatePermitted() && m_topValue < m_maxValue)
{ {
auto step = 0.05 * (m_maxValue - m_bottomValue); auto step = 0.05 * (m_maxValue - m_bottomValue);
@ -202,6 +223,11 @@ bool GraphicsImageItem::increaseTopValue()
bool GraphicsImageItem::decreaseTopValue() bool GraphicsImageItem::decreaseTopValue()
{ {
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_topValue > m_bottomValue) if (isImageUpdatePermitted() && m_topValue > m_bottomValue)
{ {
auto step = 0.05 * (m_maxValue - m_bottomValue); auto step = 0.05 * (m_maxValue - m_bottomValue);
@ -221,6 +247,11 @@ bool GraphicsImageItem::decreaseTopValue()
bool GraphicsImageItem::pickBottomValue() bool GraphicsImageItem::pickBottomValue()
{ {
if (isEmpty())
{
return false;
}
const auto y = m_mousePos.y(); const auto y = m_mousePos.y();
if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom()) if (isImageUpdatePermitted() && m_boundingRect.top() < y && y < m_boundingRect.bottom())
{ {
@ -235,6 +266,11 @@ bool GraphicsImageItem::pickBottomValue()
bool GraphicsImageItem::increaseBottomValue() bool GraphicsImageItem::increaseBottomValue()
{ {
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_bottomValue < m_topValue) if (isImageUpdatePermitted() && m_bottomValue < m_topValue)
{ {
auto step = 0.05 * (m_topValue - m_minValue); auto step = 0.05 * (m_topValue - m_minValue);
@ -254,6 +290,11 @@ bool GraphicsImageItem::increaseBottomValue()
bool GraphicsImageItem::decreaseBottomValue() bool GraphicsImageItem::decreaseBottomValue()
{ {
if (isEmpty())
{
return false;
}
if (isImageUpdatePermitted() && m_bottomValue > m_minValue) if (isImageUpdatePermitted() && m_bottomValue > m_minValue)
{ {
auto step = 0.05 * (m_topValue - m_minValue); auto step = 0.05 * (m_topValue - m_minValue);
@ -270,7 +311,7 @@ bool GraphicsImageItem::decreaseBottomValue()
void GraphicsImageItem::paintImage(QPainter* _painter) void GraphicsImageItem::paintImage(QPainter* _painter)
{ {
_painter->setPen(Qt::NoPen); _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, 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. * : used to display, scroll and zoom QImage on graphics scene.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -80,6 +80,7 @@ protected:
qreal m_bottomValue; qreal m_bottomValue;
qreal m_maxValue; qreal m_maxValue;
qreal m_minValue; qreal m_minValue;
bool m_bEmpty;
std::atomic_bool m_bReady; std::atomic_bool m_bReady;
private: private:
@ -111,6 +112,7 @@ protected:
public: public:
bool isEmpty() const;
void onValueChanged(); void onValueChanged();
void setMousePos(const QPointF& pos); void setMousePos(const QPointF& pos);
void setMousePos(qreal x, qreal y); void setMousePos(qreal x, qreal y);
@ -120,6 +122,7 @@ public:
protected: protected:
void setEmpty(bool empty);
void paintImage(QPainter* _painter); void paintImage(QPainter* _painter);
void paintImage(QPainter* _painter, qreal _scale, qreal _sceneLeft, qreal _sceneRight, void paintImage(QPainter* _painter, qreal _scale, qreal _sceneLeft, qreal _sceneRight,
qreal _visibleRegionLeft, qreal _visibleRegionWidth); qreal _visibleRegionLeft, qreal _visibleRegionWidth);

View File

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

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -75,24 +75,25 @@ class GraphicsRulerItem : public QGraphicsItem
typedef GraphicsRulerItem This; typedef GraphicsRulerItem This;
QPolygonF m_indicator; ///< Indicator displayed when this chrono item is out of screen (displaying only for main item) QPolygonF m_indicator; ///< Indicator displayed when this chrono item is out of screen (displaying only for main item)
QRectF m_boundingRect; ///< boundingRect (see QGraphicsItem) QRectF m_bounding_rect; ///< boundingRect (see QGraphicsItem)
QColor m_color; ///< Color of the item QColor m_color; ///< Color of the item
qreal m_left, m_right; ///< Left and right bounds of the selection zone 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_main; ///< Is this ruler item main (true, by default)
bool m_bReverse; ///< bool m_reverse; ///<
bool m_bHoverIndicator; ///< Mouse hover above indicator bool m_strict; ///<
bool m_bHoverLeftBorder; bool m_hover_on_indicator; ///< Mouse hover above indicator
bool m_bHoverRightBorder; bool m_hover_on_left_border;
bool m_hover_on_right_border;
public: public:
explicit GraphicsRulerItem(bool _main = true); explicit GraphicsRulerItem(bool main = true);
virtual ~GraphicsRulerItem(); virtual ~GraphicsRulerItem();
// Public virtual methods // Public virtual methods
QRectF boundingRect() const override; 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: public:
@ -100,46 +101,57 @@ public:
void hide(); void hide();
void setColor(const QColor& _color); void setColor(const QColor& color);
void setBoundingRect(qreal x, qreal y, qreal w, qreal h); 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 setHoverLeft(bool hover);
void setHoverRight(bool _hover); void setHoverRight(bool hover);
bool hoverLeft(qreal _x) const; bool hoverLeft(qreal x) const;
bool hoverRight(qreal _x) const; bool hoverRight(qreal x) const;
QPointF toItem(const QPointF& _pos) const; QPointF toItem(const QPointF& pos) const;
qreal toItem(qreal _x) const; qreal toItem(qreal x) const;
inline bool hoverIndicator() const inline bool hoverIndicator() const
{ {
return m_bHoverIndicator; return m_hover_on_indicator;
} }
inline bool hoverLeft() const inline bool hoverLeft() const
{ {
return m_bHoverLeftBorder; return m_hover_on_left_border;
} }
inline bool hoverRight() const 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 inline bool reverse() const
{ {
return m_bReverse; return m_reverse;
}
inline bool strict() const
{
return m_strict;
} }
inline qreal left() const inline qreal left() const

View File

@ -12,7 +12,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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) 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) if (_font_h != 0 && _top < _mouse_y && _mouse_y < _bottom)
{ {
const int half_font_h = _font_h >> 1; const int half_font_h = _font_h >> 1;
@ -178,7 +183,7 @@ void GraphicsHistogramItem::paintByPtr(QPainter* _painter)
_painter->setPen(profiler_gui::TEXT_COLOR); _painter->setPen(profiler_gui::TEXT_COLOR);
_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, bindMode ? " Mode: Zoom" : " Mode: Overview"); _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) 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); 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 // Draw marker displaying expected frame_time step
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff; 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->setPen(profiler_gui::TEXT_COLOR);
_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextDontClip, bindMode ? " Mode: Zoom" : " Mode: Overview"); _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) 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); 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 // Draw marker displaying required frame_time step
const auto h = bottom - (EASY_GLOBALS.frame_time - m_bottomValue) * coeff; 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); _painter->setPen(profiler_gui::TEXT_COLOR);
rect.setRect(0, bottom + 2, width, font_h); rect.setRect(0, bottom + 2, width, font_h);
if (!m_selectedBlocks.empty()) if (!items.empty())
{ {
if (m_threadProfiledTime != 0) if (m_threadProfiledTime != 0)
{ {
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip, _painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip,
QString("%1 | %2 | %3 calls | %4% of thread profiled time") 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))); .arg(QString::number(100. * (double)m_blockTotalDuraion / (double)m_threadProfiledTime, 'f', 2)));
} }
else else
{ {
_painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip, _painter->drawText(rect, Qt::AlignCenter | Qt::TextDontClip,
QString("%1 | %2 | %3 calls | 100% of thread profiled time") 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 else
@ -380,6 +385,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
m_imageScaleUpdate = m_imageScale = 1; m_imageScaleUpdate = m_imageScale = 1;
m_selectedBlocks.clear(); m_selectedBlocks.clear();
setEmpty(true);
{ profiler::BlocksTree::children_t().swap(m_selectedBlocks); } { profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
setImageUpdatePermitted(false); setImageUpdatePermitted(false);
@ -464,6 +470,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, const pr
m_bottomDurationStr.clear(); m_bottomDurationStr.clear();
} }
setEmpty(empty);
setReady(true); setReady(true);
}, m_bReady); }, m_bReady);
@ -505,6 +512,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
m_imageScaleUpdate = m_imageScale = 1; m_imageScaleUpdate = m_imageScale = 1;
m_selectedBlocks.clear(); m_selectedBlocks.clear();
setEmpty(true);
{ profiler::BlocksTree::children_t().swap(m_selectedBlocks); } { profiler::BlocksTree::children_t().swap(m_selectedBlocks); }
m_threadId = _thread_id; m_threadId = _thread_id;
@ -658,6 +666,7 @@ void GraphicsHistogramItem::setSource(profiler::thread_id_t _thread_id, profiler
m_topValue = m_maxValue; m_topValue = m_maxValue;
m_bottomValue = m_minValue; m_bottomValue = m_minValue;
setEmpty(m_selectedBlocks.empty());
setReady(true); setReady(true);
}, m_bReady); }, m_bReady);
@ -770,7 +779,7 @@ bool GraphicsHistogramItem::decreaseBottomValue()
void GraphicsHistogramItem::pickFrameTime(qreal _y) const 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(); 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); 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++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -1,6 +1,6 @@
/** /**
Lightweight profiler library for c++ 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 Licensed under either of
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * 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/yx.svg - Icon made by Freepik from www.flaticon.com
default/svg2.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/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/to-window.svg - Icon made by Freepik from www.flaticon.com
default/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"?> <?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!-- 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" <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> <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 <rect stroke="black" stroke-width="5" stroke-linecap="butt" stroke-linejoin="miter" fill="none" x="38" y="38" width="52" height="52"/>
C374.277,144.439,367.561,137.723,359.277,137.723z M344.278,344.279L344.278,344.279H167.721V167.723h176.557V344.279z"/>
</g> </g>
</svg> </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. * description : Main file for EasyProfiler GUI.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -18,7 +18,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -87,6 +87,7 @@
#include <QPushButton> #include <QPushButton>
#include <QProgressDialog> #include <QProgressDialog>
#include <QTextCodec> #include <QTextCodec>
#include <QPlainTextEdit>
#include <QTextStream> #include <QTextStream>
#include <QToolBar> #include <QToolBar>
#include <QToolButton> #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 { static const QStringList themes {
"default" "default"
@ -150,15 +151,8 @@ inline void clear_stream(std::stringstream& _stream)
#endif #endif
} }
inline void loadTheme(const QString& _theme) static void convertPointSizes(QString& style)
{ {
QFile file(QStringLiteral(":/themes/") + _theme);
if (file.open(QFile::ReadOnly | QFile::Text))
{
QTextStream in(&file);
QString style = in.readAll();
if (!style.isEmpty())
{
// Find font family // Find font family
const auto fontMatch = QRegularExpression("font-family:\\s*\\\"(.*)\\\"\\s*;").match(style); const auto fontMatch = QRegularExpression("font-family:\\s*\\\"(.*)\\\"\\s*;").match(style);
const auto fontFamily = fontMatch.hasMatch() ? fontMatch.captured(fontMatch.lastCapturedIndex()) : QString("DejaVu Sans"); const auto fontFamily = fontMatch.hasMatch() ? fontMatch.captured(fontMatch.lastCapturedIndex()) : QString("DejaVu Sans");
@ -189,11 +183,58 @@ inline void loadTheme(const QString& _theme)
for (const auto& capturedTexts : matches) for (const auto& capturedTexts : matches)
{ {
const auto pt = capturedTexts.back().toDouble(); const auto pt = capturedTexts.back().toDouble();
const int pixels = static_cast<int>(pointSizeF * pt + 0.5); const int pixels = static_cast<int>(lround(pointSizeF * pt));
//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(QString(" %1").arg(capturedTexts.front()), QString(" %1px").arg(pixels));
style.replace(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))
{
QTextStream in(&file);
QString style = in.readAll();
if (!style.isEmpty())
{
convertPointSizes(style);
replaceOsDependentSettings(style);
qApp->setStyleSheet(style); qApp->setStyleSheet(style);
} }
} }
@ -253,7 +294,7 @@ void MainWindow::configureSizes()
EASY_GLOBALS.font.default_font = w.font(); EASY_GLOBALS.font.default_font = w.font();
const QFontMetricsF fm(w.font()); const QFontMetricsF fm(w.font());
#ifdef WIN32 #ifdef _WIN32
EASY_CONSTEXPR qreal DefaultHeight = 16; EASY_CONSTEXPR qreal DefaultHeight = 16;
#else #else
EASY_CONSTEXPR qreal DefaultHeight = 17; EASY_CONSTEXPR qreal DefaultHeight = 17;
@ -268,7 +309,7 @@ void MainWindow::configureSizes()
size.graphics_row_full = size.graphics_row_height; size.graphics_row_full = size.graphics_row_height;
size.threads_row_spacing = size.graphics_row_full >> 1; size.threads_row_spacing = size.graphics_row_full >> 1;
size.timeline_height = size.font_height + px(10); 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 fontFamily = w.font().family();
const auto pixelSize = w.font().pixelSize(); 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); action->setChecked(EASY_GLOBALS.bind_scene_and_tree_expand_status);
connect(action, &QAction::triggered, this, &This::onBindExpandStatusChange); 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 = 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->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); action->setCheckable(true);
@ -1375,6 +1422,11 @@ void MainWindow::onBindExpandStatusChange(bool _checked)
EASY_GLOBALS.bind_scene_and_tree_expand_status = _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) void MainWindow::onHierarchyFlagChange(bool _checked)
{ {
EASY_GLOBALS.only_current_thread_hierarchy = _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 != 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->raise();
m_descTreeDialog.ptr->setFocus(); m_descTreeDialog.ptr->setFocus();
return; return;
} }
@ -1647,6 +1705,10 @@ void MainWindow::loadSettings()
if (!flag.isNull()) if (!flag.isNull())
EASY_GLOBALS.bind_scene_and_tree_expand_status = flag.toBool(); 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"); flag = settings.value("selecting_block_changes_thread");
if (!flag.isNull()) if (!flag.isNull())
EASY_GLOBALS.selecting_block_changes_thread = flag.toBool(); 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("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("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("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("selecting_block_changes_thread", EASY_GLOBALS.selecting_block_changes_thread);
settings.setValue("enable_event_indicators", EASY_GLOBALS.enable_event_markers); settings.setValue("enable_event_indicators", EASY_GLOBALS.enable_event_markers);
settings.setValue("auto_adjust_histogram_height", EASY_GLOBALS.auto_adjust_histogram_height); 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]; auto& guiblock = EASY_GLOBALS.gui_blocks[i];
guiblock.tree = std::move(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); 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) void DialogWithGeometry::create(QWidget* content, QWidget* parent)
{ {
#ifdef WIN32 ptr = new Dialog(parent, EASY_DEFAULT_WINDOW_TITLE, content, WindowHeader::AllButtons, QMessageBox::NoButton);
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->setProperty("stayVisible", true); ptr->setProperty("stayVisible", true);
ptr->setAttribute(Qt::WA_DeleteOnClose, true); ptr->setAttribute(Qt::WA_DeleteOnClose, true);
} }

View File

@ -11,7 +11,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -337,6 +337,7 @@ protected slots:
void onAllItemsExpandedByDefaultChange(bool); void onAllItemsExpandedByDefaultChange(bool);
void onBindExpandStatusChange(bool); void onBindExpandStatusChange(bool);
void onHierarchyFlagChange(bool); void onHierarchyFlagChange(bool);
void onDisplayRelevantStatsChange(bool);
void onExpandAllClicked(bool); void onExpandAllClicked(bool);
void onCollapseAllClicked(bool); void onCollapseAllClicked(bool);
void onViewportInfoClicked(bool); void onViewportInfoClicked(bool);

View File

@ -18,7 +18,7 @@ BEGIN
VALUE "CompanyName", "EasySolutions" VALUE "CompanyName", "EasySolutions"
VALUE "FileDescription", "EasyProfiler" VALUE "FileDescription", "EasyProfiler"
VALUE "InternalName", "profiler_gui" 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 "LegalTrademarks1", "All Rights Reserved"
VALUE "LegalTrademarks2", "All Rights Reserved" VALUE "LegalTrademarks2", "All Rights Reserved"
VALUE "OriginalFilename", "profiler_gui.exe" VALUE "OriginalFilename", "profiler_gui.exe"

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of RoundProgressWidget. * description : The file contains implementation of RoundProgressWidget.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of RoundProgressWidget. * description : The file contains declaration of RoundProgressWidget.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * 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 { QLabel#BlocksTreeWidget_HintLabel {
color: gray; color: gray;
font-size: 13pt; } font-size: 12pt; }
QLabel#BlocksTreeWidget_HintLabel[hovered=true] {
color: black; }
/* ****************************************************************************************************************** */ /* ****************************************************************************************************************** */
QLineEdit, QSpinBox { QLineEdit, QSpinBox {
@ -303,9 +306,10 @@ QMenu::indicator:exclusive:checked:disabled {
/* ****************************************************************************************************************** */ /* ****************************************************************************************************************** */
QHeaderView::section { QHeaderView::section {
height: 15.3ex; height: 15.3ex;
width: 60ex; min-height: 15.3ex;
min-width: 40ex; max-height: 15.3ex;
background: #eeeeee; } background: #eeeeee;
/*{lin}font-weight: bold;*/ }
/* ****************************************************************************************************************** */ /* ****************************************************************************************************************** */
DockWidget QWidget#EasyDockWidgetTitle { DockWidget QWidget#EasyDockWidgetTitle {
@ -399,9 +403,9 @@ QScrollBar::add-line, QScrollBar::sub-line {
WindowHeader { WindowHeader {
background-color: white; background-color: white;
height: 24ex; height: 15.6ex;
min-height: 24ex; min-height: 15.6ex;
max-height: 24ex; max-height: 15.6ex;
margin: 0; margin: 0;
padding: 0 0 0 6ex; padding: 0 0 0 6ex;
border: none; } border: none; }
@ -426,8 +430,8 @@ WindowHeader {
image: url(":/images/default/minimize"); image: url(":/images/default/minimize");
padding: 2ex; } padding: 2ex; }
WindowHeader QPushButton#WindowHeader_MinButton:hover { WindowHeader QPushButton#WindowHeader_MinButton:hover {
background-color: #d1d1d1; background-color: #e8e8e8;
border-bottom: 1px solid #d1d1d1; } border-bottom: 1px solid #e8e8e8; }
WindowHeader QPushButton#WindowHeader_MinButton:pressed { WindowHeader QPushButton#WindowHeader_MinButton:pressed {
background-color: #c4c4c4; background-color: #c4c4c4;
border-bottom: 1px solid #c4c4c4; } border-bottom: 1px solid #c4c4c4; }
@ -438,8 +442,8 @@ WindowHeader {
image: url(":/images/default/to-window"); image: url(":/images/default/to-window");
padding: 1ex; } padding: 1ex; }
WindowHeader QPushButton#WindowHeader_MaxButton:hover { WindowHeader QPushButton#WindowHeader_MaxButton:hover {
background-color: #d1d1d1; background-color: #e8e8e8;
border-bottom: 1px solid #d1d1d1; } border-bottom: 1px solid #e8e8e8; }
WindowHeader QPushButton#WindowHeader_MaxButton:pressed { WindowHeader QPushButton#WindowHeader_MaxButton:pressed {
background-color: #c4c4c4; background-color: #c4c4c4;
border-bottom: 1px solid #c4c4c4; } border-bottom: 1px solid #c4c4c4; }

View File

@ -40,11 +40,12 @@ $IndicatorBorderColor: darken($DarkSelectionColor, 5%);
$DisabledIndicatorBackgroundColor: $SelectionColor; $DisabledIndicatorBackgroundColor: $SelectionColor;
$DisabledIndicatorBorderColor: darken($SelectionColor, 5%); $DisabledIndicatorBorderColor: darken($SelectionColor, 5%);
$FocusBorderColor: $DarkSelectionColor;//#ffbcbc; $FocusBorderColor: $DarkSelectionColor; // #ffbcbc;
$TooltipColor: #ffeccc; $TooltipColor: #ffeccc;
$InputHeight: 15ex; $InputHeight: 15ex;
$WindowHeaderSize: 24ex; $WindowHeaderSize: 15.6ex;
$WindowHeaderHoverColor: lighten($BorderColor, 14%); // #e8e8e8
// STYLES ------------------------------------------------- // STYLES -------------------------------------------------
* { * {
@ -122,7 +123,11 @@ QSplitter::handle:pressed {
QLabel#BlocksTreeWidget_HintLabel { QLabel#BlocksTreeWidget_HintLabel {
color: gray; 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 { QHeaderView::section {
height: 15.3ex; height: 15.3ex;
width: 60ex; min-height: 15.3ex;
min-width: 40ex; max-height: 15.3ex;
background: #eeeeee; background: #eeeeee;
/*{lin}font-weight: bold;*/
} }
/* ****************************************************************************************************************** */ /* ****************************************************************************************************************** */
@ -548,8 +554,8 @@ WindowHeader {
} }
QPushButton#WindowHeader_MinButton:hover { QPushButton#WindowHeader_MinButton:hover {
background-color: lighten($BorderColor, 5%); background-color: $WindowHeaderHoverColor;
border-bottom: 1px solid lighten($BorderColor, 5%); border-bottom: 1px solid $WindowHeaderHoverColor;
} }
QPushButton#WindowHeader_MinButton:pressed { QPushButton#WindowHeader_MinButton:pressed {
@ -568,8 +574,8 @@ WindowHeader {
} }
QPushButton#WindowHeader_MaxButton:hover { QPushButton#WindowHeader_MaxButton:hover {
background-color: lighten($BorderColor, 5%); background-color: $WindowHeaderHoverColor;
border-bottom: 1px solid lighten($BorderColor, 5%); border-bottom: 1px solid $WindowHeaderHoverColor;
} }
QPushButton#WindowHeader_MaxButton:pressed { QPushButton#WindowHeader_MaxButton:pressed {

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of ThreadPool. * description : The file contains implementation of ThreadPool.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains declaration of ThreadPool. * description : The file contains declaration of ThreadPool.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -8,7 +8,7 @@
* description : The file contains implementation of ThreadPoolTask. * description : The file contains implementation of ThreadPoolTask.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -51,22 +51,25 @@
#include "thread_pool_task.h" #include "thread_pool_task.h"
#include "thread_pool.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); m_status = static_cast<int8_t>(TaskStatus::Finished);
} }
ThreadPoolTask::~ThreadPoolTask() ThreadPoolTask::~ThreadPoolTask()
{ {
m_signals.disconnect();
dequeue(); dequeue();
} }
void ThreadPoolTask::enqueue(std::function<void()>&& func, std::atomic_bool& interruptFlag) void ThreadPoolTask::enqueue(Func&& func, std::atomic_bool& interruptFlag)
{ {
dequeue(); dequeue();
setStatus(TaskStatus::Enqueued); setStatus(TaskStatus::Enqueued);
m_interrupt = & interruptFlag; m_interrupt = &interruptFlag;
m_interrupt->store(false, std::memory_order_release); m_interrupt->store(false, std::memory_order_release);
m_func = std::move(func); m_func = std::move(func);
@ -75,19 +78,22 @@ void ThreadPoolTask::enqueue(std::function<void()>&& func, std::atomic_bool& int
void ThreadPoolTask::dequeue() void ThreadPoolTask::dequeue()
{ {
if (m_interrupt == nullptr || status() == TaskStatus::Finished) if (m_interrupt == nullptr || m_interrupt == &s_dummy_flag || status() == TaskStatus::Finished)
{
return; return;
}
m_interrupt->store(true, std::memory_order_release); m_interrupt->store(true, std::memory_order_release);
ThreadPool::instance().dequeue(*this); ThreadPool::instance().dequeue(*this);
// wait for finish // wait for finish
m_mutex.lock(); {
const std::lock_guard<std::mutex> guard(m_mutex);
setStatus(TaskStatus::Finished); setStatus(TaskStatus::Finished);
m_mutex.unlock(); }
m_interrupt->store(false, std::memory_order_release); //m_interrupt->store(false, std::memory_order_release);
} }
TaskStatus ThreadPoolTask::status() const TaskStatus ThreadPoolTask::status() const
@ -97,16 +103,29 @@ TaskStatus ThreadPoolTask::status() const
void ThreadPoolTask::execute() void ThreadPoolTask::execute()
{ {
// execute if not cancelled
{
const std::lock_guard<std::mutex> guard(m_mutex); const std::lock_guard<std::mutex> guard(m_mutex);
if (status() == TaskStatus::Finished || m_interrupt->load(std::memory_order_acquire)) if (status() == TaskStatus::Finished || m_interrupt->load(std::memory_order_acquire))
{
// cancelled
return; return;
}
m_func(); m_func();
setStatus(TaskStatus::Finished); setStatus(TaskStatus::Finished);
}
emit m_signals.finished();
} }
void ThreadPoolTask::setStatus(TaskStatus status) void ThreadPoolTask::setStatus(TaskStatus status)
{ {
m_status.store(static_cast<int8_t>(status), std::memory_order_release); 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. * description : The file contains declaration of ThreadPoolTask.
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -56,6 +56,8 @@
#include <atomic> #include <atomic>
#include <mutex> #include <mutex>
#include <QObject>
enum class TaskStatus : int8_t enum class TaskStatus : int8_t
{ {
Enqueued, Enqueued,
@ -63,14 +65,34 @@ enum class TaskStatus : int8_t
Finished, Finished,
}; };
class ThreadPoolTaskSignals : public QObject
{
Q_OBJECT;
public:
ThreadPoolTaskSignals() : QObject() {}
signals:
void finished();
};
class ThreadPoolTask EASY_FINAL class ThreadPoolTask EASY_FINAL
{ {
public:
using Func = std::function<void()>;
private:
friend class ThreadPool; friend class ThreadPool;
std::function<void()> m_func; ThreadPoolTaskSignals m_signals;
Func m_func;
std::atomic_bool* m_interrupt;
std::mutex m_mutex; std::mutex m_mutex;
std::atomic<int8_t> m_status; std::atomic<int8_t> m_status;
std::atomic_bool* m_interrupt;
public: public:
@ -80,9 +102,11 @@ public:
ThreadPoolTask(); ThreadPoolTask();
~ThreadPoolTask(); ~ThreadPoolTask();
void enqueue(std::function<void()>&& func, std::atomic_bool& interruptFlag); void enqueue(Func&& func, std::atomic_bool& interruptFlag);
void dequeue(); void dequeue();
ThreadPoolTaskSignals& events();
private: private:
void execute(); void execute();

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)

View File

@ -13,7 +13,7 @@
* : * * : *
* ----------------- : * ----------------- :
* license : Lightweight profiler library for c++ * 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 * : Licensed under either of
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT) * : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
@ -54,32 +54,39 @@
************************************************************************/ ************************************************************************/
#include "tree_widget_item.h" #include "tree_widget_item.h"
#include "globals.h"
#include <QAbstractTextDocumentLayout>
#include <QFont>
#include <QPainter> #include <QPainter>
#include <QPoint> #include <QPoint>
#include <QBrush> #include <QBrush>
#include <QRect> #include <QRect>
#include <QSize> #include <QSize>
#include <QTextDocument>
#include <QVariant> #include <QVariant>
#include "globals.h"
#include "blocks_tree_widget.h"
#include "text_highlighter.h"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
EASY_CONSTEXPR int BlockColorRole = Qt::UserRole + 1; EASY_CONSTEXPR int BlockColorRole = Qt::UserRole + 1;
////////////////////////////////////////////////////////////////////////// namespace {
EASY_CONSTEXPR int ColumnBit[COL_COLUMNS_NUMBER] = { EASY_CONSTEXPR int ColumnBit[COL_COLUMNS_NUMBER] = {
-1 // COL_NAME = 0, -1 // COL_NAME = 0,
, 0 // COL_BEGIN, , 0 // COL_BEGIN,
, 1 // COL_DURATION, , 1 // COL_TIME,
, 2 // COL_SELF_DURATION, , 2 // COL_SELF_TIME,
, 3 // COL_DURATION_SUM_PER_PARENT, , 3 // COL_TOTAL_TIME_PER_PARENT,
, 4 // COL_DURATION_SUM_PER_FRAME, , 4 // COL_TOTAL_TIME_PER_FRAME,
, 5 // COL_DURATION_SUM_PER_THREAD, , 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_PARENT,
, -1 // COL_PERCENT_PER_FRAME, , -1 // COL_PERCENT_PER_FRAME,
, -1 // COL_PERCENT_SUM_PER_PARENT, , -1 // COL_PERCENT_SUM_PER_PARENT,
@ -90,30 +97,41 @@ EASY_CONSTEXPR int ColumnBit[COL_COLUMNS_NUMBER] = {
, 7 // COL_MIN_PER_FRAME, , 7 // COL_MIN_PER_FRAME,
, 8 // COL_MAX_PER_FRAME, , 8 // COL_MAX_PER_FRAME,
, 9 // COL_AVERAGE_PER_FRAME, , 9 // COL_AVG_PER_FRAME,
, -1 // COL_NCALLS_PER_FRAME, , -1 // COL_NCALLS_PER_FRAME,
, 10 // COL_MIN_PER_THREAD, , 10 // COL_MIN_PER_THREAD,
, 11 // COL_MAX_PER_THREAD, , 11 // COL_MAX_PER_THREAD,
, 12 // COL_AVERAGE_PER_THREAD, , 12 // COL_AVG_PER_THREAD,
, -1 // COL_NCALLS_PER_THREAD, , -1 // COL_NCALLS_PER_THREAD,
, 13 // COL_MIN_PER_PARENT, , 13 // COL_MIN_PER_PARENT,
, 14 // COL_MAX_PER_PARENT, , 14 // COL_MAX_PER_PARENT,
, 15 // COL_AVERAGE_PER_PARENT, , 15 // COL_AVG_PER_PARENT,
, -1 // COL_NCALLS_PER_PARENT, , -1 // COL_NCALLS_PER_PARENT,
, 16 // COL_ACTIVE_TIME, , 16 // COL_ACTIVE_TIME,
, -1 // COL_ACTIVE_PERCENT, , -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) : Parent(_parent, QTreeWidgetItem::UserType)
, m_block(_treeBlock) , m_block(_treeBlock)
, m_customBGColor(0) , m_customBGColor(0)
, m_bMain(false) , 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_THREAD:
case COL_NCALLS_PER_PARENT: case COL_NCALLS_PER_PARENT:
case COL_NCALLS_PER_FRAME: case COL_NCALLS_PER_FRAME:
case COL_NCALLS_PER_AREA:
{ {
return data(col, Qt::UserRole).toUInt() < _other.data(col, Qt::UserRole).toUInt(); 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_PARENT:
case COL_PERCENT_PER_FRAME: case COL_PERCENT_PER_FRAME:
case COL_PERCENT_SUM_PER_PARENT: case COL_PERCENT_SUM_PER_PARENT:
case COL_PERCENT_SUM_PER_FRAME: case COL_PERCENT_SUM_PER_FRAME:
case COL_PERCENT_SUM_PER_THREAD: 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(); 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 bool TreeWidgetItem::hasToolTip(int _column) const
{ {
const int bit = ColumnBit[_column]; const int bit = ColumnBit[_column];
@ -194,16 +220,143 @@ QVariant TreeWidgetItem::data(int _column, int _role) const
switch (_role) switch (_role)
{ {
case Qt::ForegroundRole: 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: case Qt::ToolTipRole:
return hasToolTip(_column) ? {
QVariant::fromValue(QString("%1 ns").arg(QTreeWidgetItem::data(_column, Qt::UserRole).toULongLong())) : if (hasToolTip(_column))
QVariant(); return QVariant::fromValue(QString("%1 ns").arg(data(_column, Qt::UserRole).toULongLong()));
break;
}
default: default:
{
if (_role != Qt::UserRole && _role != Qt::DisplayRole)
return QTreeWidgetItem::data(_column, _role); 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 profiler::block_index_t TreeWidgetItem::block_index() const
@ -221,16 +374,26 @@ const profiler::BlocksTree& TreeWidgetItem::block() const
return easyBlocksTree(m_block); 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 profiler::timestamp_t TreeWidgetItem::duration() const
{ {
if (parent() != nullptr) if (parent() != nullptr)
return block().node->duration(); return block().node->duration();
return data(COL_DURATION, Qt::UserRole).toULongLong(); return data(COL_TIME, Qt::UserRole).toULongLong();
} }
profiler::timestamp_t TreeWidgetItem::selfDuration() const 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) 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); setData(_column, Qt::UserRole, (quint64)nanosecondsTime);
setHasToolTip(_column); setHasToolTip(_column);
setText(_column, QString("%1%2").arg(_prefix).arg(profiler_gui::timeStringRealNs(_units, nanosecondsTime, 3))); 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) 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; m_bMain = _main;
} }
void TreeWidgetItem::setPartial(bool partial)
{
m_partial = partial;
}
void TreeWidgetItem::collapseAll() void TreeWidgetItem::collapseAll()
{ {
for (int i = 0, childrenNumber = childCount(); i < childrenNumber; ++i) 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 // Draw item as usual
QStyledItemDelegate::paint(painter, option, index); QStyledItemDelegate::paint(painter, option, index);
highlightMatchingText(painter, option, index);
return; return;
} }
const auto padding = px(2);
const auto colorBlockSize = option.rect.height() >> 1; const auto colorBlockSize = option.rect.height() >> 1;
const auto currentTreeIndex = m_treeWidget->currentIndex(); const auto currentTreeIndex = m_treeWidget->currentIndex();
if (index.parent() == currentTreeIndex.parent() && index.row() == currentTreeIndex.row()) if (index.parent() == currentTreeIndex.parent() && index.row() == currentTreeIndex.row())
@ -348,16 +503,17 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
painter->save(); painter->save();
painter->setBrush(m_treeWidget->palette().highlight()); painter->setBrush(m_treeWidget->palette().highlight());
painter->setPen(Qt::NoPen); 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(); painter->restore();
} }
// Adjust rect size for drawing color marker // Adjust rect size for drawing color marker
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
opt.rect.adjust(colorBlockSize, 0, 0, 0); opt.rect.adjust(colorBlockSize + padding, 0, 0, 0);
// Draw item as usual // Draw item as usual
QStyledItemDelegate::paint(painter, opt, index); QStyledItemDelegate::paint(painter, opt, index);
highlightMatchingText(painter, opt, index);
const auto colorBlockRest = option.rect.height() - colorBlockSize; const auto colorBlockRest = option.rect.height() - colorBlockSize;
@ -374,7 +530,117 @@ void TreeWidgetItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem
const auto bottomLeft = opt.rect.bottomLeft(); const auto bottomLeft = opt.rect.bottomLeft();
painter->setBrush(Qt::NoBrush); painter->setBrush(Qt::NoBrush);
painter->setPen(profiler_gui::SYSTEM_BORDER_COLOR); 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(); 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