diff --git a/easy_profiler_core/CMakeLists.txt b/easy_profiler_core/CMakeLists.txt index ae5e4d5..9125d54 100644 --- a/easy_profiler_core/CMakeLists.txt +++ b/easy_profiler_core/CMakeLists.txt @@ -3,6 +3,8 @@ message(STATUS "EASY_PROFILER.Core version = ${EASY_PRODUCT_VERSION_STRING}") message(STATUS "") +set(EASY_MAX_SIZE_VALUE 2816) + ##################################################################### # Checking c++11 thread_local support @@ -39,6 +41,8 @@ set(EASY_DEFAULT_PORT 28077 CACHE STRING "Default listening po set(EASY_OPTION_LISTEN OFF CACHE BOOL "Enable automatic startListen on startup") set(EASY_OPTION_PROFILE_SELF OFF CACHE BOOL "Enable self profiling (measure time for internal storage expand)") set(EASY_OPTION_PROFILE_SELF_BLOCKS_ON OFF CACHE BOOL "Storage expand default status (profiler::ON or profiler::OFF)") +set(EASY_OPTION_TRUNCATE_RUNTIME_NAMES OFF CACHE BOOL "Enable truncation of block dynamic names (set at run-time, not compile-time). Reduces performance. Turn ON only if you want to use dynamic block names of length >${EASY_MAX_SIZE_VALUE} symbols at runtime. It is better to use EASY_VALUE instead of such long names.") +set(EASY_OPTION_CHECK_MAX_VALUE_SIZE OFF CACHE BOOL "Enable checking EASY_VALUE maximum data size. Slightly reduces performance. Turn ON only if you want to pass big EASY_ARRAY, EASY_STRING, EASY_TEXT of length >${EASY_MAX_SIZE_VALUE} bytes. It is better to split such arrays into the smaller ones.") set(EASY_OPTION_LOG OFF CACHE BOOL "Print errors to stderr") set(EASY_OPTION_PRETTY_PRINT OFF CACHE BOOL "Use pretty-printed function names with signature and argument types") set(EASY_OPTION_PREDEFINED_COLORS ON CACHE BOOL "Use predefined set of colors (see profiler_colors.h). If you want to use your own colors palette you can turn this option OFF") @@ -81,6 +85,19 @@ message(STATUS " Default listening port = ${EASY_DEFAULT_PORT}") message(STATUS " Auto-start listening = ${EASY_OPTION_LISTEN}") message(STATUS " Profile self = ${EASY_OPTION_PROFILE_SELF}") message(STATUS " Profile self blocks initial status = ${EASY_OPTION_PROFILE_SELF_BLOCKS_ON}") + +if (EASY_OPTION_TRUNCATE_RUNTIME_NAMES) + message(STATUS " Truncate block dynamic names = ${EASY_OPTION_TRUNCATE_RUNTIME_NAMES} (reduces performance)") +else() + message(STATUS " Truncate block dynamic names = ${EASY_OPTION_TRUNCATE_RUNTIME_NAMES} (may cause crash if using dynamic block names of length >${EASY_MAX_SIZE_VALUE} symbols)") +endif() + +if (EASY_OPTION_CHECK_MAX_VALUE_SIZE) + message(STATUS " Check maximum EASY_VALUE data size = ${EASY_OPTION_CHECK_MAX_VALUE_SIZE} (slightly reduces performance)") +else() + message(STATUS " Check maximum EASY_VALUE data size = ${EASY_OPTION_CHECK_MAX_VALUE_SIZE} (may cause crash if using EASY_VALUE arrays of total data size >${EASY_MAX_SIZE_VALUE} bytes)") +endif() + message(STATUS " Implicit thread registration = ${EASY_OPTION_IMPLICIT_THREAD_REGISTRATION}") if (WIN32) message(STATUS " Event tracing = ${EASY_OPTION_EVENT_TRACING}") @@ -201,6 +218,8 @@ easy_define_target_option(easy_profiler BUILD_WITH_CHRONO_HIGH_RESOLUTION_CLOCK easy_define_target_option(easy_profiler EASY_OPTION_LISTEN EASY_OPTION_START_LISTEN_ON_STARTUP) easy_define_target_option(easy_profiler EASY_OPTION_PROFILE_SELF EASY_OPTION_MEASURE_STORAGE_EXPAND) easy_define_target_option(easy_profiler EASY_OPTION_PROFILE_SELF_BLOCKS_ON EASY_OPTION_STORAGE_EXPAND_BLOCKS_ON) +easy_define_target_option(easy_profiler EASY_OPTION_TRUNCATE_RUNTIME_NAMES EASY_OPTION_TRUNCATE_LONG_RUNTIME_NAMES) +easy_define_target_option(easy_profiler EASY_OPTION_CHECK_MAX_VALUE_SIZE EASY_OPTION_CHECK_MAX_VALUE_DATA_SIZE) easy_define_target_option(easy_profiler EASY_OPTION_IMPLICIT_THREAD_REGISTRATION EASY_OPTION_IMPLICIT_THREAD_REGISTRATION) if (WIN32) easy_define_target_option(easy_profiler EASY_OPTION_EVENT_TRACING EASY_OPTION_EVENT_TRACING_ENABLED) diff --git a/easy_profiler_core/chunk_allocator.h b/easy_profiler_core/chunk_allocator.h index 2ab3048..d3cc258 100644 --- a/easy_profiler_core/chunk_allocator.h +++ b/easy_profiler_core/chunk_allocator.h @@ -376,4 +376,37 @@ public: ////////////////////////////////////////////////////////////////////////// +template +struct aligned_size; + +template +struct aligned_size { + EASY_STATIC_CONSTEXPR uint16_t Size = N; +}; + +template +struct aligned_size { + EASY_STATIC_CONSTEXPR uint16_t Size = static_cast(N - (N % EASY_ALIGNMENT_SIZE)); +}; + +template +struct aligned_size { + EASY_STATIC_CONSTEXPR uint16_t Size = static_cast(N + EASY_ALIGNMENT_SIZE - (N % EASY_ALIGNMENT_SIZE)); +}; + +template +struct get_aligned_size { + EASY_STATIC_CONSTEXPR uint16_t Size = + aligned_size(N), (N % EASY_ALIGNMENT_SIZE) == 0, (N > (65536 - EASY_ALIGNMENT_SIZE))>::Size; +}; + +static_assert(get_aligned_size::Size == EASY_ALIGNMENT_SIZE, "wrong get_aligned_size"); +static_assert(get_aligned_size<2 * EASY_ALIGNMENT_SIZE - 3>::Size == 2 * EASY_ALIGNMENT_SIZE, "wrong get_aligned_size"); +static_assert(get_aligned_size<65530>::Size == 65536 - EASY_ALIGNMENT_SIZE, "wrong get_aligned_size"); +static_assert(get_aligned_size<65526>::Size == 65536 - EASY_ALIGNMENT_SIZE, "wrong get_aligned_size"); +static_assert(get_aligned_size<65536 - EASY_ALIGNMENT_SIZE>::Size == 65536 - EASY_ALIGNMENT_SIZE, "wrong get_aligned_size"); +static_assert(get_aligned_size<65536 + 3 - EASY_ALIGNMENT_SIZE * 2>::Size == 65536 - EASY_ALIGNMENT_SIZE, "wrong get_aligned_size"); + +////////////////////////////////////////////////////////////////////////// + #endif // EASY_PROFILER_CHUNK_ALLOCATOR_H diff --git a/easy_profiler_core/include/easy/arbitrary_value.h b/easy_profiler_core/include/easy/arbitrary_value.h index 2366957..82e86cb 100644 --- a/easy_profiler_core/include/easy/arbitrary_value.h +++ b/easy_profiler_core/include/easy/arbitrary_value.h @@ -158,9 +158,9 @@ void foo(const A& a) { \note Currently arbitrary values support only compile-time names. -\warning Max array size is 4096. Passing bigger size has undefined behavior. +\warning Max data size (sizeof(value) * size) is MAX_BLOCK_DATA_SIZE. Passing bigger size has undefined behavior. -\sa EASY_VALUE, EASY_TEXT, EASY_STRING +\sa EASY_VALUE, EASY_TEXT, EASY_STRING, MAX_BLOCK_DATA_SIZE \ingroup profiler */ @@ -178,9 +178,9 @@ Could be C-string or std::string. \note Currently arbitrary values support only compile-time names. -\warning Max string length is 4096 (including trailing '\0'). Passing bigger size has undefined behavior. +\warning Max string length is MAX_BLOCK_DATA_SIZE (including trailing '\0'). Passing bigger size has undefined behavior. -\sa EASY_VALUE, EASY_ARRAY, EASY_STRING +\sa EASY_VALUE, EASY_ARRAY, EASY_STRING, MAX_BLOCK_DATA_SIZE \ingroup profiler */ @@ -201,9 +201,9 @@ Use this for C-strings of known length (compile-time or run-time). \note Currently arbitrary values support only compile-time names. -\warning Max string length is 4096 (including trailing '\0'). Passing bigger size has undefined behavior. +\warning Max string length is MAX_BLOCK_DATA_SIZE (including trailing '\0'). Passing bigger size has undefined behavior. -\sa EASY_VALUE, EASY_ARRAY, EASY_TEXT +\sa EASY_VALUE, EASY_ARRAY, EASY_TEXT, MAX_BLOCK_DATA_SIZE \ingroup profiler */ @@ -216,8 +216,6 @@ Use this for C-strings of known length (compile-time or run-time). namespace profiler { - EASY_CONSTEXPR uint16_t MaxArbitraryValuesArraySize = 4096; - extern "C" PROFILER_API void storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, uint16_t _size, bool _isArray, ValueId _vin); @@ -235,7 +233,7 @@ namespace profiler storeValue(_desc, StdToDataType::data_type, &_value, static_cast(sizeof(Type)), false, _vin); } - ///< WARNING: Passing _arraySize > 4096 may cause undefined behavior! + ///< WARNING: Passing _arraySize > (MAX_BLOCK_DATA_SIZE / sizeof(T)) may cause undefined behavior! template inline void setValue(const BaseBlockDescriptor* _desc, const T* _valueArray, ValueId _vin, uint16_t _arraySize) { @@ -251,24 +249,24 @@ namespace profiler static_assert(StdToDataType::data_type != DataType::TypesCount, "You should use standard builtin scalar types as profiler::Value type!"); - static_assert(N <= MaxArbitraryValuesArraySize, "Maximum arbitrary values array size is 4096."); + static_assert(sizeof(_value) <= MAX_BLOCK_DATA_SIZE, "Maximum arbitrary values data size exceeded."); storeValue(_desc, StdToDataType::data_type, _value, static_cast(sizeof(_value)), true, _vin); } - ///< WARNING: Passing _textLength > 4096 may cause undefined behavior! + ///< WARNING: Passing _textLength > MAX_BLOCK_DATA_SIZE may cause undefined behavior! inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin, uint16_t _textLength) { storeValue(_desc, DataType::String, _text, _textLength, true, _vin); } - ///< WARNING: Passing _text with length > 4096 may cause undefined behavior! + ///< WARNING: Passing _text with length > MAX_BLOCK_DATA_SIZE may cause undefined behavior! inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin) { storeValue(_desc, DataType::String, _text, static_cast(strlen(_text) + 1), true, _vin); } - ///< WARNING: Passing _text with length > 4096 may cause undefined behavior! + ///< WARNING: Passing _text with length > MAX_BLOCK_DATA_SIZE may cause undefined behavior! inline void setText(const BaseBlockDescriptor* _desc, const ::std::string& _text, ValueId _vin) { storeValue(_desc, DataType::String, _text.c_str(), static_cast(_text.size() + 1), true, _vin); @@ -277,7 +275,7 @@ namespace profiler template inline void setText(const BaseBlockDescriptor* _desc, const char (&_text)[N], ValueId _vin) { - static_assert(N <= MaxArbitraryValuesArraySize, "Maximum arbitrary values array size is 4096."); + static_assert(N <= MAX_BLOCK_DATA_SIZE, "Maximum arbitrary values data size exceeded."); storeValue(_desc, DataType::String, &_text[0], static_cast(N), true, _vin); } diff --git a/easy_profiler_core/include/easy/details/profiler_public_types.h b/easy_profiler_core/include/easy/details/profiler_public_types.h index 7e5a3cb..ff9f4b4 100644 --- a/easy_profiler_core/include/easy/details/profiler_public_types.h +++ b/easy_profiler_core/include/easy/details/profiler_public_types.h @@ -198,6 +198,8 @@ namespace profiler { }; // END of class ThreadGuard. + EASY_CONSTEXPR uint16_t MAX_BLOCK_DATA_SIZE = 2048 + 512 + 256; ///< Estimated maximum size of block dynamic name or EASY_VALUE data size + } // END of namespace profiler. #endif // EASY_PROFILER_PUBLIC_TYPES_H diff --git a/easy_profiler_core/include/easy/profiler.h b/easy_profiler_core/include/easy/profiler.h index 98d162f..7a735ba 100644 --- a/easy_profiler_core/include/easy/profiler.h +++ b/easy_profiler_core/include/easy/profiler.h @@ -45,6 +45,8 @@ The Apache License, Version 2.0 (the "License"); #include +#define MAX_DYNAMIC_BLOCK_NAME_SIZE_ESTIMATED MAX_BLOCK_DATA_SIZE + #if defined ( __clang__ ) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" diff --git a/easy_profiler_core/stack_buffer.h b/easy_profiler_core/stack_buffer.h index 4393ea0..0797e84 100644 --- a/easy_profiler_core/stack_buffer.h +++ b/easy_profiler_core/stack_buffer.h @@ -43,10 +43,11 @@ The Apache License, Version 2.0 (the "License"); #ifndef EASY_PROFILER_STACK_BUFFER_H #define EASY_PROFILER_STACK_BUFFER_H -#include "nonscoped_block.h" -#include #include #include +#include + +#include "nonscoped_block.h" #ifdef max #undef max diff --git a/easy_profiler_core/thread_storage.cpp b/easy_profiler_core/thread_storage.cpp index bd376e8..825d2fd 100644 --- a/easy_profiler_core/thread_storage.cpp +++ b/easy_profiler_core/thread_storage.cpp @@ -40,11 +40,32 @@ The Apache License, Version 2.0 (the "License"); **/ +#include #include "thread_storage.h" #include "current_thread.h" #include "current_time.h" -static profiler::vin_t ptr2vin(const void* ptr) +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +namespace { + +EASY_CONSTEXPR uint16_t BASE_SIZE = static_cast(sizeof(profiler::BaseBlockData) + 1U); + +#if EASY_OPTION_TRUNCATE_LONG_RUNTIME_NAMES != 0 +EASY_CONSTEXPR uint16_t MAX_BLOCK_NAME_LENGTH = BLOCK_CHUNK_SIZE - BASE_SIZE; +#endif + +#if EASY_OPTION_CHECK_MAX_VALUE_DATA_SIZE != 0 +EASY_CONSTEXPR uint16_t MAX_VALUE_DATA_SIZE = BLOCK_CHUNK_SIZE - static_cast(sizeof(profiler::ArbitraryValue)); +#endif + +profiler::vin_t ptr2vin(const void* ptr) { static_assert(sizeof(uintptr_t) == sizeof(void*), "Can not cast void* to uintptr_t. Different sizes."); @@ -55,6 +76,8 @@ static profiler::vin_t ptr2vin(const void* ptr) return static_cast(reinterpret_cast(ptr)); } +} // end of namespace . + ThreadStorage::ThreadStorage() : nonscopedBlocks(16) , frameStartTime(0) @@ -68,9 +91,23 @@ ThreadStorage::ThreadStorage() expired = ATOMIC_VAR_INIT(0); } -void ThreadStorage::storeValue(profiler::timestamp_t _timestamp, profiler::block_id_t _id, profiler::DataType _type, const void* _data, uint16_t _size, bool _isArray, profiler::ValueId _vin) -{ +void ThreadStorage::storeValue( + profiler::timestamp_t _timestamp, + profiler::block_id_t _id, + profiler::DataType _type, + const void* _data, + uint16_t _size, + bool _isArray, + profiler::ValueId _vin +) { +#if EASY_OPTION_CHECK_MAX_VALUE_DATA_SIZE != 0 + if (_size > MAX_VALUE_DATA_SIZE) + { + return; + } +#endif const uint16_t serializedDataSize = _size + static_cast(sizeof(profiler::ArbitraryValue)); + void* data = blocks.closedList.allocate(serializedDataSize); ::new (data) profiler::ArbitraryValue(_timestamp, ptr2vin(_vin.m_id), _id, _size, _type, _isArray); @@ -94,11 +131,16 @@ void ThreadStorage::storeBlock(const profiler::Block& block) EASY_THREAD_LOCAL static profiler::timestamp_t endTime = 0ULL; #endif +#if EASY_OPTION_TRUNCATE_LONG_RUNTIME_NAMES != 0 + const uint16_t nameLength = std::min(static_cast(strlen(block.name())), MAX_BLOCK_NAME_LENGTH); +#else const uint16_t nameLength = static_cast(strlen(block.name())); +#endif + #if EASY_OPTION_MEASURE_STORAGE_EXPAND == 0 const #endif - uint16_t serializedDataSize = static_cast(sizeof(profiler::BaseBlockData) + nameLength + 1); + auto serializedDataSize = static_cast(BASE_SIZE + nameLength); #if EASY_OPTION_MEASURE_STORAGE_EXPAND != 0 const bool expanded = (desc->m_status & profiler::ON) && blocks.closedList.need_expand(serializedDataSize); @@ -130,8 +172,8 @@ void ThreadStorage::storeBlock(const profiler::Block& block) void ThreadStorage::storeBlockForce(const profiler::Block& block) { - const uint16_t nameLength = static_cast(strlen(block.name())); - const uint16_t serializedDataSize = static_cast(sizeof(profiler::BaseBlockData) + nameLength + 1); + const auto nameLength = static_cast(strlen(block.name())); + const auto serializedDataSize = static_cast(sizeof(profiler::BaseBlockData) + nameLength + 1); void* data = blocks.closedList.marked_allocate(serializedDataSize); ::new (data) profiler::SerializedBlock(block, nameLength); @@ -140,8 +182,8 @@ void ThreadStorage::storeBlockForce(const profiler::Block& block) void ThreadStorage::storeCSwitch(const CSwitchBlock& block) { - const uint16_t nameLength = static_cast(strlen(block.name())); - const uint16_t serializedDataSize = static_cast(sizeof(profiler::CSwitchEvent) + nameLength + 1); + const auto nameLength = static_cast(strlen(block.name())); + const auto serializedDataSize = static_cast(sizeof(profiler::CSwitchEvent) + nameLength + 1); void* data = sync.closedList.allocate(serializedDataSize); ::new (data) profiler::SerializedCSwitch(block, nameLength); diff --git a/easy_profiler_core/thread_storage.h b/easy_profiler_core/thread_storage.h index 36a4cdb..9cc6f32 100644 --- a/easy_profiler_core/thread_storage.h +++ b/easy_profiler_core/thread_storage.h @@ -43,21 +43,26 @@ The Apache License, Version 2.0 (the "License"); #ifndef EASY_PROFILER_THREAD_STORAGE_H #define EASY_PROFILER_THREAD_STORAGE_H +#include +#include +#include +#include + #include #include #include -#include -#include -#include -#include -#include "stack_buffer.h" + #include "chunk_allocator.h" +#include "stack_buffer.h" ////////////////////////////////////////////////////////////////////////// template struct BlocksList { + BlocksList(const BlocksList&) = delete; + BlocksList(BlocksList&&) = delete; + BlocksList() = default; std::vector openedList; @@ -65,17 +70,13 @@ struct BlocksList uint64_t usedMemorySize = 0; uint64_t frameMemorySize = 0; - void clearClosed() { + void clearClosed() + { //closedList.clear(); usedMemorySize = 0; frameMemorySize = 0; } -private: - - BlocksList(const BlocksList&) = delete; - BlocksList(BlocksList&&) = delete; - }; // END of struct BlocksList. ////////////////////////////////////////////////////////////////////////// @@ -92,17 +93,29 @@ public: ////////////////////////////////////////////////////////////////////////// -EASY_CONSTEXPR uint16_t SIZEOF_BLOCK = sizeof(profiler::BaseBlockData) + 1 + sizeof(uint16_t); // SerializedBlock stores BaseBlockData + at least 1 character for name ('\0') + 2 bytes for size of serialized data -EASY_CONSTEXPR uint16_t SIZEOF_CSWITCH = sizeof(profiler::CSwitchEvent) + 1 + sizeof(uint16_t); // SerializedCSwitch also stores additional 4 bytes to be able to save 64-bit thread_id +EASY_CONSTEXPR uint16_t BLOCKS_IN_CHUNK = 128U; +EASY_CONSTEXPR uint16_t SIZEOF_BLOCK = sizeof(profiler::BaseBlockData) + 1U + sizeof(uint16_t); // SerializedBlock stores BaseBlockData + at least 1 character for name ('\0') + 2 bytes for size of serialized data +EASY_CONSTEXPR uint16_t SIZEOF_CSWITCH = sizeof(profiler::CSwitchEvent) + 1U + sizeof(uint16_t); // SerializedCSwitch also stores additional 4 bytes to be able to save 64-bit thread_id -static_assert((int)SIZEOF_BLOCK * 128 < 65536, "Chunk size for profiler::Block must be less than 65536"); -static_assert((int)SIZEOF_CSWITCH * 128 < 65536, "Chunk size for CSwitchBlock must be less than 65536"); +static_assert(((int)SIZEOF_BLOCK * (int)BLOCKS_IN_CHUNK) < 65536, "Chunk size for profiler::Block must be less than 65536"); +static_assert(((int)SIZEOF_CSWITCH * (int)BLOCKS_IN_CHUNK) < 65536, "Chunk size for CSwitchBlock must be less than 65536"); + +EASY_CONSTEXPR uint16_t BLOCK_CHUNK_SIZE = get_aligned_size::Size; +EASY_CONSTEXPR uint16_t CSWITCH_CHUNK_SIZE = get_aligned_size::Size; + +static_assert((BLOCK_CHUNK_SIZE % EASY_ALIGNMENT_SIZE) == 0, "BLOCK_CHUNK_SIZE not aligned"); +static_assert((CSWITCH_CHUNK_SIZE % EASY_ALIGNMENT_SIZE) == 0, "CSWITCH_CHUNK_SIZE not aligned"); +static_assert(BLOCK_CHUNK_SIZE > 2048, "wrong BLOCK_CHUNK_SIZE"); +static_assert(CSWITCH_CHUNK_SIZE > 2048, "wrong CSWITCH_CHUNK_SIZE"); struct ThreadStorage EASY_FINAL { - StackBuffer nonscopedBlocks; - BlocksList, SIZEOF_BLOCK * (uint16_t)128U> blocks; - BlocksList sync; + using BlocksStorage = BlocksList, BLOCK_CHUNK_SIZE>; + using ContextSwitchStorage = BlocksList; + + StackBuffer nonscopedBlocks; + BlocksStorage blocks; + ContextSwitchStorage sync; std::string name; ///< Thread name profiler::timestamp_t frameStartTime; ///< Current frame start time. Used to calculate FPS. diff --git a/profiler_gui/arbitrary_value_inspector.cpp b/profiler_gui/arbitrary_value_inspector.cpp index f4e1473..1fa3cd3 100644 --- a/profiler_gui/arbitrary_value_inspector.cpp +++ b/profiler_gui/arbitrary_value_inspector.cpp @@ -709,9 +709,23 @@ void ArbitraryValuesChartItem::paint(QPainter* _painter, const QStyleOptionGraph drawImage(); } - QRectF rect(0, m_boundingRect.top() - widget->margin(), width - 3, m_boundingRect.height() + widget->margins()); - _painter->setPen(profiler_gui::TEXT_COLOR); - _painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop, bindMode ? " Mode: Zoom" : " Mode: Overview"); + // MODE + { + QRectF rect(3, m_boundingRect.top() - widget->margin(), width - 3, m_boundingRect.height() + widget->margins()); + QRectF textBounds; + + _painter->setPen(Qt::blue); + _painter->drawText( + rect, + Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip | Qt::TextIncludeTrailingSpaces, + QStringLiteral("MODE: "), + &textBounds + ); + rect.adjust(textBounds.width(), 0, 0, 0); + + _painter->setPen(profiler_gui::TEXT_COLOR); + _painter->drawText(rect, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, bindMode ? "Zoom" : "Overview"); + } _painter->setPen(Qt::darkGray); _painter->drawLine(QLineF(0, bottom, width, bottom)); @@ -1705,10 +1719,10 @@ int GraphicsChart::filterWindowSize() const return m_chartItem->filterWindowSize(); } -//bool GraphicsChart::canShowSlider() const -//{ -// return chartType() != ChartType::Complexity && !m_bBindMode; -//} +bool GraphicsChart::canShowSlider() const +{ + return chartType() != ChartType::Complexity && !bindMode(); +} ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/arbitrary_value_inspector.h b/profiler_gui/arbitrary_value_inspector.h index 79b8ace..eaa6a1e 100644 --- a/profiler_gui/arbitrary_value_inspector.h +++ b/profiler_gui/arbitrary_value_inspector.h @@ -280,7 +280,7 @@ public: protected: - //bool canShowSlider() const override; + bool canShowSlider() const override; private slots: diff --git a/profiler_gui/graphics_slider_area.cpp b/profiler_gui/graphics_slider_area.cpp index 069b33e..054c527 100644 --- a/profiler_gui/graphics_slider_area.cpp +++ b/profiler_gui/graphics_slider_area.cpp @@ -383,7 +383,11 @@ bool GraphicsSliderArea::setValue(qreal _value) } if (m_imageItem->isVisible()) + { m_imageItem->onValueChanged(); + if (!m_slider->isVisible()) + scene()->update(); + } return true; } @@ -415,10 +419,14 @@ void GraphicsSliderArea::setRange(qreal _minValue, qreal _maxValue) void GraphicsSliderArea::setSliderWidth(qreal _width) { m_slider->setWidth(_width); - if (!setValue(m_value)) + if (setValue(m_value)) + return; + + if (m_imageItem->isVisible()) { - if (m_imageItem->isVisible()) - m_imageItem->onValueChanged(); + m_imageItem->onValueChanged(); + if (!m_slider->isVisible()) + scene()->update(); } } @@ -480,8 +488,10 @@ void GraphicsSliderArea::mousePressEvent(QMouseEvent* _event) if (!_event->modifiers()) { m_bBindMode = !m_bBindMode; + m_slider->setVisible(canShowSlider()); if (m_imageItem->isVisible()) m_imageItem->onModeChanged(); + scene()->update(); } }