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

[ui] fixed slider freeze after load new file in "Zoom" mode;

[core] #157 added new build flag EASY_OPTION_TRUNCATE_RUNTIME_NAMES which will prevent from crash for very big block names, but will reduce performance. Disabled by default because of very rare use case;
[core] #157 added new build flag EASY_OPTION_CHECK_MAX_VALUE_SIZE for EASY_VALUE arrays and strings - same as the flag above for block names. Also disabled by default;
This commit is contained in:
Victor Zarubkin 2019-10-28 19:14:05 +03:00
parent 0dc5a71aad
commit 272c0ceab1
11 changed files with 187 additions and 53 deletions

View File

@ -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)

View File

@ -376,4 +376,37 @@ public:
//////////////////////////////////////////////////////////////////////////
template <const uint16_t N, bool, bool>
struct aligned_size;
template <const uint16_t N, bool dummy>
struct aligned_size<N, true, dummy> {
EASY_STATIC_CONSTEXPR uint16_t Size = N;
};
template <const uint16_t N>
struct aligned_size<N, false, true> {
EASY_STATIC_CONSTEXPR uint16_t Size = static_cast<uint16_t>(N - (N % EASY_ALIGNMENT_SIZE));
};
template <const uint16_t N>
struct aligned_size<N, false, false> {
EASY_STATIC_CONSTEXPR uint16_t Size = static_cast<uint16_t>(N + EASY_ALIGNMENT_SIZE - (N % EASY_ALIGNMENT_SIZE));
};
template <const size_t N>
struct get_aligned_size {
EASY_STATIC_CONSTEXPR uint16_t Size =
aligned_size<static_cast<uint16_t>(N), (N % EASY_ALIGNMENT_SIZE) == 0, (N > (65536 - EASY_ALIGNMENT_SIZE))>::Size;
};
static_assert(get_aligned_size<EASY_ALIGNMENT_SIZE - 3>::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

View File

@ -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<Type>::data_type, &_value, static_cast<uint16_t>(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 <class T>
inline void setValue(const BaseBlockDescriptor* _desc, const T* _valueArray, ValueId _vin, uint16_t _arraySize)
{
@ -251,24 +249,24 @@ namespace profiler
static_assert(StdToDataType<T>::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<T>::data_type, _value, static_cast<uint16_t>(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<uint16_t>(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<uint16_t>(_text.size() + 1), true, _vin);
@ -277,7 +275,7 @@ namespace profiler
template <size_t N>
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<uint16_t>(N), true, _vin);
}

View File

@ -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

View File

@ -45,6 +45,8 @@ The Apache License, Version 2.0 (the "License");
#include <easy/details/profiler_public_types.h>
#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"

View File

@ -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 <list>
#include <algorithm>
#include <cstdlib>
#include <list>
#include "nonscoped_block.h"
#ifdef max
#undef max

View File

@ -40,11 +40,32 @@ The Apache License, Version 2.0 (the "License");
**/
#include <algorithm>
#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<uint16_t>(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<uint16_t>(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<profiler::vin_t>(reinterpret_cast<uintptr_t>(ptr));
}
} // end of namespace <noname>.
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<uint16_t>(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<uint16_t>(strlen(block.name())), MAX_BLOCK_NAME_LENGTH);
#else
const uint16_t nameLength = static_cast<uint16_t>(strlen(block.name()));
#endif
#if EASY_OPTION_MEASURE_STORAGE_EXPAND == 0
const
#endif
uint16_t serializedDataSize = static_cast<uint16_t>(sizeof(profiler::BaseBlockData) + nameLength + 1);
auto serializedDataSize = static_cast<uint16_t>(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<uint16_t>(strlen(block.name()));
const uint16_t serializedDataSize = static_cast<uint16_t>(sizeof(profiler::BaseBlockData) + nameLength + 1);
const auto nameLength = static_cast<uint16_t>(strlen(block.name()));
const auto serializedDataSize = static_cast<uint16_t>(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<uint16_t>(strlen(block.name()));
const uint16_t serializedDataSize = static_cast<uint16_t>(sizeof(profiler::CSwitchEvent) + nameLength + 1);
const auto nameLength = static_cast<uint16_t>(strlen(block.name()));
const auto serializedDataSize = static_cast<uint16_t>(sizeof(profiler::CSwitchEvent) + nameLength + 1);
void* data = sync.closedList.allocate(serializedDataSize);
::new (data) profiler::SerializedCSwitch(block, nameLength);

View File

@ -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 <atomic>
#include <functional>
#include <string>
#include <vector>
#include <easy/details/profiler_public_types.h>
#include <easy/details/arbitrary_value_public_types.h>
#include <easy/serialized_block.h>
#include <vector>
#include <string>
#include <atomic>
#include <functional>
#include "stack_buffer.h"
#include "chunk_allocator.h"
#include "stack_buffer.h"
//////////////////////////////////////////////////////////////////////////
template <class T, const uint16_t N>
struct BlocksList
{
BlocksList(const BlocksList&) = delete;
BlocksList(BlocksList&&) = delete;
BlocksList() = default;
std::vector<T> 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<SIZEOF_BLOCK * BLOCKS_IN_CHUNK>::Size;
EASY_CONSTEXPR uint16_t CSWITCH_CHUNK_SIZE = get_aligned_size<SIZEOF_BLOCK * BLOCKS_IN_CHUNK>::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<NonscopedBlock> nonscopedBlocks;
BlocksList<std::reference_wrapper<profiler::Block>, SIZEOF_BLOCK * (uint16_t)128U> blocks;
BlocksList<CSwitchBlock, SIZEOF_CSWITCH * (uint16_t)128U> sync;
using BlocksStorage = BlocksList<std::reference_wrapper<profiler::Block>, BLOCK_CHUNK_SIZE>;
using ContextSwitchStorage = BlocksList<CSwitchBlock, CSWITCH_CHUNK_SIZE>;
StackBuffer<NonscopedBlock> nonscopedBlocks;
BlocksStorage blocks;
ContextSwitchStorage sync;
std::string name; ///< Thread name
profiler::timestamp_t frameStartTime; ///< Current frame start time. Used to calculate FPS.

View File

@ -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();
}
//////////////////////////////////////////////////////////////////////////

View File

@ -280,7 +280,7 @@ public:
protected:
//bool canShowSlider() const override;
bool canShowSlider() const override;
private slots:

View File

@ -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();
}
}