0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 08:41:02 +08:00

#31 [Core] Arbitrary values: replaced size_t with uint16_t; [Gui] Added support of arrays to arbitrary values tree

This commit is contained in:
Victor Zarubkin 2018-03-07 20:52:39 +03:00
parent 49f000d11a
commit 5e632bedee
17 changed files with 472 additions and 119 deletions

View File

@ -129,7 +129,7 @@ void foo(const A& a) {
\note Also stores a time-stamp of it's occurrence like an Event. \note Also stores a time-stamp of it's occurrence like an Event.
\note To store an array, please, use EASY_ARRAY macro. \note To store a dynamic array (which size is unknown at compile time), please, use EASY_ARRAY macro.
\note Currently arbitrary values support only compile-time names. \note Currently arbitrary values support only compile-time names.
@ -149,6 +149,8 @@ void foo(const A& a) {
\note Currently arbitrary values support only compile-time names. \note Currently arbitrary values support only compile-time names.
\warning Max array size is 4096. Passing bigger size has undefined behavior.
\sa EASY_VALUE, EASY_TEXT, EASY_STRING \sa EASY_VALUE, EASY_TEXT, EASY_STRING
\ingroup profiler \ingroup profiler
@ -167,6 +169,8 @@ Could be C-string or std::string.
\note Currently arbitrary values support only compile-time names. \note Currently arbitrary values support only compile-time names.
\warning Max string length is 4096 (including trailing '\0'). Passing bigger size has undefined behavior.
\sa EASY_VALUE, EASY_ARRAY, EASY_STRING \sa EASY_VALUE, EASY_ARRAY, EASY_STRING
\ingroup profiler \ingroup profiler
@ -188,6 +192,8 @@ Use this for C-strings of known length (compile-time or run-time).
\note Currently arbitrary values support only compile-time names. \note Currently arbitrary values support only compile-time names.
\warning Max string length is 4096 (including trailing '\0'). Passing bigger size has undefined behavior.
\sa EASY_VALUE, EASY_ARRAY, EASY_TEXT \sa EASY_VALUE, EASY_ARRAY, EASY_TEXT
\ingroup profiler \ingroup profiler
@ -201,10 +207,10 @@ Use this for C-strings of known length (compile-time or run-time).
namespace profiler namespace profiler
{ {
EASY_CONSTEXPR uint16_t MaxArbitraryValuesArraySize = 65535; EASY_CONSTEXPR uint16_t MaxArbitraryValuesArraySize = 4096;
extern "C" PROFILER_API void storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, extern "C" PROFILER_API void storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data,
size_t _size, bool _isArray, ValueId _vin); uint16_t _size, bool _isArray, ValueId _vin);
template <class T> template <class T>
inline void setValue(const BaseBlockDescriptor* _desc, T _value, ValueId _vin) inline void setValue(const BaseBlockDescriptor* _desc, T _value, ValueId _vin)
@ -217,16 +223,17 @@ namespace profiler
static_assert(StdToDataType<Type>::data_type != DataType::TypesCount, static_assert(StdToDataType<Type>::data_type != DataType::TypesCount,
"You should use standard builtin scalar types as profiler::Value type!"); "You should use standard builtin scalar types as profiler::Value type!");
storeValue(_desc, StdToDataType<Type>::data_type, &_value, sizeof(Type), false, _vin); storeValue(_desc, StdToDataType<Type>::data_type, &_value, static_cast<uint16_t>(sizeof(Type)), false, _vin);
} }
///< WARNING: Passing _arraySize > 4096 may cause undefined behavior!
template <class T> template <class T>
inline void setValue(const BaseBlockDescriptor* _desc, const T* _valueArray, ValueId _vin, uint16_t _arraySize) inline void setValue(const BaseBlockDescriptor* _desc, const T* _valueArray, ValueId _vin, uint16_t _arraySize)
{ {
static_assert(StdToDataType<T>::data_type != DataType::TypesCount, static_assert(StdToDataType<T>::data_type != DataType::TypesCount,
"You should use standard builtin scalar types as profiler::Value type!"); "You should use standard builtin scalar types as profiler::Value type!");
storeValue(_desc, StdToDataType<T>::data_type, _valueArray, sizeof(T) * _arraySize, true, _vin); storeValue(_desc, StdToDataType<T>::data_type, _valueArray, static_cast<uint16_t>(sizeof(T) * _arraySize), true, _vin);
} }
template <class T, size_t N> template <class T, size_t N>
@ -235,31 +242,34 @@ namespace profiler
static_assert(StdToDataType<T>::data_type != DataType::TypesCount, static_assert(StdToDataType<T>::data_type != DataType::TypesCount,
"You should use standard builtin scalar types as profiler::Value type!"); "You should use standard builtin scalar types as profiler::Value type!");
static_assert(N <= MaxArbitraryValuesArraySize, "Maximum arbitrary values array size is 65535."); static_assert(N <= MaxArbitraryValuesArraySize, "Maximum arbitrary values array size is 4096.");
storeValue(_desc, StdToDataType<T>::data_type, _value, sizeof(_value), true, _vin); storeValue(_desc, StdToDataType<T>::data_type, _value, static_cast<uint16_t>(sizeof(_value)), true, _vin);
} }
///< WARNING: Passing _textLength > 4096 may cause undefined behavior!
inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin, uint16_t _textLength) inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin, uint16_t _textLength)
{ {
storeValue(_desc, DataType::String, _text, _textLength, true, _vin); storeValue(_desc, DataType::String, _text, _textLength, true, _vin);
} }
///< WARNING: Passing _text with length > 4096 may cause undefined behavior!
inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin) inline void setText(const BaseBlockDescriptor* _desc, const char* _text, ValueId _vin)
{ {
storeValue(_desc, DataType::String, _text, strlen(_text) + 1, true, _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!
inline void setText(const BaseBlockDescriptor* _desc, const ::std::string& _text, ValueId _vin) inline void setText(const BaseBlockDescriptor* _desc, const ::std::string& _text, ValueId _vin)
{ {
storeValue(_desc, DataType::String, _text.c_str(), _text.size() + 1, true, _vin); storeValue(_desc, DataType::String, _text.c_str(), static_cast<uint16_t>(_text.size() + 1), true, _vin);
} }
template <size_t N> template <size_t N>
inline void setText(const BaseBlockDescriptor* _desc, const char (&_text)[N], ValueId _vin) inline void setText(const BaseBlockDescriptor* _desc, const char (&_text)[N], ValueId _vin)
{ {
static_assert(N <= MaxArbitraryValuesArraySize, "Maximum arbitrary values array size is 65535."); static_assert(N <= MaxArbitraryValuesArraySize, "Maximum arbitrary values array size is 4096.");
storeValue(_desc, DataType::String, &_text[0], N, true, _vin); storeValue(_desc, DataType::String, &_text[0], static_cast<uint16_t>(N), true, _vin);
} }
} // end of namespace profiler. } // end of namespace profiler.
@ -277,7 +287,7 @@ namespace profiler
namespace profiler namespace profiler
{ {
inline void storeValue(const BaseBlockDescriptor*, DataType, const void*, size_t, bool, ValueId) {} inline void storeValue(const BaseBlockDescriptor*, DataType, const void*, uint16_t, bool, ValueId) {}
template <class T> template <class T>
inline void setValue(const BaseBlockDescriptor*, T, ValueId) {} inline void setValue(const BaseBlockDescriptor*, T, ValueId) {}

View File

@ -202,6 +202,10 @@ namespace profiler {
return reinterpret_cast<const char*>(this) + sizeof(ArbitraryValue); return reinterpret_cast<const char*>(this) + sizeof(ArbitraryValue);
} }
uint16_t data_size() const {
return m_size;
}
vin_t value_id() const { vin_t value_id() const {
return m_value_id; return m_value_id;
} }

View File

@ -321,7 +321,7 @@ extern "C" {
return MANAGER.isEnabled(); return MANAGER.isEnabled();
} }
PROFILER_API void storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, size_t _size, bool _isArray, ValueId _vin) PROFILER_API void storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, uint16_t _size, bool _isArray, ValueId _vin)
{ {
MANAGER.storeValue(_desc, _type, _data, _size, _isArray, _vin); MANAGER.storeValue(_desc, _type, _data, _size, _isArray, _vin);
} }
@ -487,7 +487,7 @@ extern "C" {
PROFILER_API void endBlock() { } PROFILER_API void endBlock() { }
PROFILER_API void setEnabled(bool) { } PROFILER_API void setEnabled(bool) { }
PROFILER_API bool isEnabled() { return false; } PROFILER_API bool isEnabled() { return false; }
PROFILER_API void storeValue(const BaseBlockDescriptor*, DataType, const void*, size_t, bool, ValueId) {} PROFILER_API void storeValue(const BaseBlockDescriptor*, DataType, const void*, uint16_t, bool, ValueId) {}
PROFILER_API void storeEvent(const BaseBlockDescriptor*, const char*) { } PROFILER_API void storeEvent(const BaseBlockDescriptor*, const char*) { }
PROFILER_API void storeBlock(const BaseBlockDescriptor*, const char*, timestamp_t, timestamp_t) { } PROFILER_API void storeBlock(const BaseBlockDescriptor*, const char*, timestamp_t, timestamp_t) { }
PROFILER_API void beginBlock(Block&) { } PROFILER_API void beginBlock(Block&) { }
@ -781,7 +781,7 @@ const BaseBlockDescriptor* ProfileManager::addBlockDescriptor(EasyBlockStatus _d
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void ProfileManager::storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, size_t _size, bool _isArray, ValueId _vin) void ProfileManager::storeValue(const BaseBlockDescriptor* _desc, DataType _type, const void* _data, uint16_t _size, bool _isArray, ValueId _vin)
{ {
if (!isEnabled() || (_desc->m_status & profiler::ON) == 0) if (!isEnabled() || (_desc->m_status & profiler::ON) == 0)
return; return;

View File

@ -140,7 +140,7 @@ public:
profiler::color_t _color, profiler::color_t _color,
bool _copyName = false); bool _copyName = false);
void storeValue(const profiler::BaseBlockDescriptor* _desc, profiler::DataType _type, const void* _data, size_t _size, bool _isArray, profiler::ValueId _vin); void storeValue(const profiler::BaseBlockDescriptor* _desc, profiler::DataType _type, const void* _data, uint16_t _size, bool _isArray, profiler::ValueId _vin);
bool storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName); bool storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName);
bool storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, profiler::timestamp_t _beginTime, profiler::timestamp_t _endTime); bool storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName, profiler::timestamp_t _beginTime, profiler::timestamp_t _endTime);
void beginBlock(profiler::Block& _block); void beginBlock(profiler::Block& _block);

View File

@ -57,12 +57,12 @@ ThreadStorage::ThreadStorage()
expired = ATOMIC_VAR_INIT(0); expired = ATOMIC_VAR_INIT(0);
} }
void ThreadStorage::storeValue(profiler::timestamp_t _timestamp, profiler::block_id_t _id, profiler::DataType _type, const void* _data, size_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)
{ {
const uint16_t serializedDataSize = static_cast<uint16_t>(sizeof(profiler::ArbitraryValue) + _size); const uint16_t serializedDataSize = _size + static_cast<uint16_t>(sizeof(profiler::ArbitraryValue));
void* data = blocks.closedList.allocate(serializedDataSize); void* data = blocks.closedList.allocate(serializedDataSize);
::new (data) profiler::ArbitraryValue(_timestamp, _vin.m_id, _id, static_cast<uint16_t>(_size), _type, _isArray); ::new (data) profiler::ArbitraryValue(_timestamp, _vin.m_id, _id, _size, _type, _isArray);
char* cdata = reinterpret_cast<char*>(data); char* cdata = reinterpret_cast<char*>(data);
memcpy(cdata + sizeof(profiler::ArbitraryValue), _data, _size); memcpy(cdata + sizeof(profiler::ArbitraryValue), _data, _size);

View File

@ -114,7 +114,7 @@ struct ThreadStorage EASY_FINAL
bool guarded; ///< True if thread has been registered using ThreadGuard bool guarded; ///< True if thread has been registered using ThreadGuard
bool frameOpened; ///< Is new frame opened (this does not depend on profiling status) \sa profiledFrameOpened bool frameOpened; ///< Is new frame opened (this does not depend on profiling status) \sa profiledFrameOpened
void storeValue(profiler::timestamp_t _timestamp, profiler::block_id_t _id, profiler::DataType _type, const void* _data, size_t _size, bool _isArray, profiler::ValueId _vin); void 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 storeBlock(const profiler::Block& _block); void storeBlock(const profiler::Block& _block);
void storeBlockForce(const profiler::Block& _block); void storeBlockForce(const profiler::Block& _block);
void storeCSwitch(const CSwitchBlock& _block); void storeCSwitch(const CSwitchBlock& _block);

View File

@ -246,7 +246,7 @@ qreal ArbitraryValuesCollection::maxValue() const
} }
void ArbitraryValuesCollection::collectValues(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId void ArbitraryValuesCollection::collectValues(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId
, const char* _valueName, profiler::block_id_t _parentBlockId) , const char* _valueName, profiler::block_id_t _parentBlockId, int _index)
{ {
interrupt(); interrupt();
@ -262,13 +262,13 @@ void ArbitraryValuesCollection::collectValues(ChartType _chartType, profiler::th
} }
if (_valueId == 0) if (_valueId == 0)
m_worker.enqueue([=] { collectByName(_threadId, _valueName, _parentBlockId); }, m_bInterrupt); m_worker.enqueue([=] { collectByName(_threadId, _valueName, _parentBlockId, _index); }, m_bInterrupt);
else else
m_worker.enqueue([=] { collectById(_threadId, _valueId, _parentBlockId); }, m_bInterrupt); m_worker.enqueue([=] { collectById(_threadId, _valueId, _parentBlockId, _index); }, m_bInterrupt);
} }
void ArbitraryValuesCollection::collectValuesAndPoints(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId void ArbitraryValuesCollection::collectValuesAndPoints(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId
, const char* _valueName, profiler::timestamp_t _beginTime, profiler::block_id_t _parentBlockId) , const char* _valueName, profiler::timestamp_t _beginTime, profiler::block_id_t _parentBlockId, int _index)
{ {
interrupt(); interrupt();
@ -287,9 +287,9 @@ void ArbitraryValuesCollection::collectValuesAndPoints(ChartType _chartType, pro
} }
if (_valueId == 0) if (_valueId == 0)
m_worker.enqueue([=] { collectByName(_threadId, _valueName, _parentBlockId); }, m_bInterrupt); m_worker.enqueue([=] { collectByName(_threadId, _valueName, _parentBlockId, _index); }, m_bInterrupt);
else else
m_worker.enqueue([=] { collectById(_threadId, _valueId, _parentBlockId); }, m_bInterrupt); m_worker.enqueue([=] { collectById(_threadId, _valueId, _parentBlockId, _index); }, m_bInterrupt);
} }
bool ArbitraryValuesCollection::calculatePoints(profiler::timestamp_t _beginTime) bool ArbitraryValuesCollection::calculatePoints(profiler::timestamp_t _beginTime)
@ -332,7 +332,7 @@ void ArbitraryValuesCollection::setStatus(JobStatus _status)
} }
void ArbitraryValuesCollection::collectById(profiler::thread_id_t _threadId, profiler::vin_t _valueId void ArbitraryValuesCollection::collectById(profiler::thread_id_t _threadId, profiler::vin_t _valueId
, profiler::block_id_t _parentBlockId) , profiler::block_id_t _parentBlockId, int _index)
{ {
const bool doCalculatePoints = (m_jobType & PointsJob) != 0; const bool doCalculatePoints = (m_jobType & PointsJob) != 0;
@ -345,7 +345,7 @@ void ArbitraryValuesCollection::collectById(profiler::thread_id_t _threadId, pro
for (const auto& it : EASY_GLOBALS.profiler_blocks) for (const auto& it : EASY_GLOBALS.profiler_blocks)
{ {
if (!collectByIdForThread(it.second, _valueId, calculatePointsInner, _parentBlockId)) if (!collectByIdForThread(it.second, _valueId, calculatePointsInner, _parentBlockId, _index))
return; return;
} }
@ -365,7 +365,7 @@ void ArbitraryValuesCollection::collectById(profiler::thread_id_t _threadId, pro
{ {
const auto t = EASY_GLOBALS.profiler_blocks.find(_threadId); const auto t = EASY_GLOBALS.profiler_blocks.find(_threadId);
if (t != EASY_GLOBALS.profiler_blocks.end() && if (t != EASY_GLOBALS.profiler_blocks.end() &&
!collectByIdForThread(t->second, _valueId, doCalculatePoints, _parentBlockId)) !collectByIdForThread(t->second, _valueId, doCalculatePoints, _parentBlockId, _index))
{ {
return; return;
} }
@ -386,7 +386,7 @@ void ArbitraryValuesCollection::collectById(profiler::thread_id_t _threadId, pro
} }
bool ArbitraryValuesCollection::collectByIdForThread(const profiler::BlocksTreeRoot& _threadRoot bool ArbitraryValuesCollection::collectByIdForThread(const profiler::BlocksTreeRoot& _threadRoot
, profiler::vin_t _valueId, bool _calculatePoints, profiler::block_id_t _parentBlockId) , profiler::vin_t _valueId, bool _calculatePoints, profiler::block_id_t _parentBlockId, int _index)
{ {
if (profiler_gui::is_max(_parentBlockId)) if (profiler_gui::is_max(_parentBlockId))
{ {
@ -406,20 +406,23 @@ bool ArbitraryValuesCollection::collectByIdForThread(const profiler::BlocksTreeR
if (value->value_id() != _valueId) if (value->value_id() != _valueId)
continue; continue;
if (_index >= 0 && (!value->isArray() || profiler_gui::valueArraySize(*value) <= _index))
continue;
m_values.push_back(value); m_values.push_back(value);
if (_calculatePoints) if (_calculatePoints)
addPoint(*value); addPoint(*value, _index);
} }
return true; return true;
} }
return depthFirstSearch(_threadRoot, _calculatePoints, _parentBlockId return depthFirstSearch(_threadRoot, _calculatePoints, _parentBlockId, _index
, [=] (profiler::vin_t _id, const char*) -> bool { return _id == _valueId; }); , [=] (profiler::vin_t _id, const char*) -> bool { return _id == _valueId; });
} }
void ArbitraryValuesCollection::collectByName(profiler::thread_id_t _threadId, const std::string _valueName void ArbitraryValuesCollection::collectByName(profiler::thread_id_t _threadId, const std::string _valueName
, profiler::block_id_t _parentBlockId) , profiler::block_id_t _parentBlockId, int _index)
{ {
const bool doCalculatePoints = (m_jobType & PointsJob) != 0; const bool doCalculatePoints = (m_jobType & PointsJob) != 0;
@ -432,7 +435,7 @@ void ArbitraryValuesCollection::collectByName(profiler::thread_id_t _threadId, c
for (const auto& it : EASY_GLOBALS.profiler_blocks) for (const auto& it : EASY_GLOBALS.profiler_blocks)
{ {
if (!collectByNameForThread(it.second, _valueName, calculatePointsInner, _parentBlockId)) if (!collectByNameForThread(it.second, _valueName, calculatePointsInner, _parentBlockId, _index))
return; return;
} }
@ -452,7 +455,7 @@ void ArbitraryValuesCollection::collectByName(profiler::thread_id_t _threadId, c
{ {
const auto t = EASY_GLOBALS.profiler_blocks.find(_threadId); const auto t = EASY_GLOBALS.profiler_blocks.find(_threadId);
if (t != EASY_GLOBALS.profiler_blocks.end() && if (t != EASY_GLOBALS.profiler_blocks.end() &&
!collectByNameForThread(t->second, _valueName, doCalculatePoints, _parentBlockId)) !collectByNameForThread(t->second, _valueName, doCalculatePoints, _parentBlockId, _index))
{ {
return; return;
} }
@ -473,7 +476,7 @@ void ArbitraryValuesCollection::collectByName(profiler::thread_id_t _threadId, c
} }
bool ArbitraryValuesCollection::collectByNameForThread(const profiler::BlocksTreeRoot& _threadRoot bool ArbitraryValuesCollection::collectByNameForThread(const profiler::BlocksTreeRoot& _threadRoot
, const std::string& _valueName, bool _calculatePoints, profiler::block_id_t _parentBlockId) , const std::string& _valueName, bool _calculatePoints, profiler::block_id_t _parentBlockId, int _index)
{ {
if (profiler_gui::is_max(_parentBlockId)) if (profiler_gui::is_max(_parentBlockId))
{ {
@ -489,20 +492,24 @@ bool ArbitraryValuesCollection::collectByNameForThread(const profiler::BlocksTre
if (desc.type() != profiler::BlockType::Value || _valueName != desc.name()) if (desc.type() != profiler::BlockType::Value || _valueName != desc.name())
continue; continue;
m_values.push_back(block.value); const auto value = block.value;
if (_index >= 0 && (!value->isArray() || profiler_gui::valueArraySize(*value) <= _index))
continue;
m_values.push_back(value);
if (_calculatePoints) if (_calculatePoints)
addPoint(*block.value); addPoint(*value, _index);
} }
return true; return true;
} }
return depthFirstSearch(_threadRoot, _calculatePoints, _parentBlockId return depthFirstSearch(_threadRoot, _calculatePoints, _parentBlockId, _index
, [&_valueName] (profiler::vin_t, const char* _name) -> bool { return _valueName == _name; }); , [&_valueName] (profiler::vin_t, const char* _name) -> bool { return _valueName == _name; });
} }
bool ArbitraryValuesCollection::depthFirstSearch(const profiler::BlocksTreeRoot& _threadRoot, bool _calculatePoints bool ArbitraryValuesCollection::depthFirstSearch(const profiler::BlocksTreeRoot& _threadRoot, bool _calculatePoints
, profiler::block_id_t _parentBlockId, std::function<bool(profiler::vin_t, const char*)> _isSuitableValue) , profiler::block_id_t _parentBlockId, int _index, std::function<bool(profiler::vin_t, const char*)> _isSuitableValue)
{ {
if (_threadRoot.children.empty()) if (_threadRoot.children.empty())
return true; return true;
@ -538,11 +545,13 @@ bool ArbitraryValuesCollection::depthFirstSearch(const profiler::BlocksTreeRoot&
{ {
const auto value = block.value; const auto value = block.value;
if (_isSuitableValue(value->value_id(), desc.name())) if (_isSuitableValue(value->value_id(), desc.name()))
{
if (_index < 0 || (value->isArray() && _index < profiler_gui::valueArraySize(*value)))
{ {
m_values.push_back(value); m_values.push_back(value);
if (_calculatePoints) if (_calculatePoints)
{ {
const auto val = addPoint(*value); const auto val = addPoint(*value, _index);
if (m_chartType == ChartType::Complexity) if (m_chartType == ChartType::Complexity)
{ {
m_complexityMap[val].push_back(lastMatchedParentDuration); m_complexityMap[val].push_back(lastMatchedParentDuration);
@ -554,6 +563,7 @@ bool ArbitraryValuesCollection::depthFirstSearch(const profiler::BlocksTreeRoot&
} }
} }
} }
}
if (first < block.children.size()) if (first < block.children.size())
{ {
@ -580,9 +590,9 @@ bool ArbitraryValuesCollection::depthFirstSearch(const profiler::BlocksTreeRoot&
return true; return true;
} }
double ArbitraryValuesCollection::addPoint(const profiler::ArbitraryValue& _value) double ArbitraryValuesCollection::addPoint(const profiler::ArbitraryValue& _value, int _index)
{ {
const auto p = point(_value); const auto p = point(_value, _index);
if (p.y() > m_maxValue) if (p.y() > m_maxValue)
m_maxValue = p.y(); m_maxValue = p.y();
@ -595,10 +605,10 @@ double ArbitraryValuesCollection::addPoint(const profiler::ArbitraryValue& _valu
return p.y(); return p.y();
} }
QPointF ArbitraryValuesCollection::point(const profiler::ArbitraryValue& _value) const QPointF ArbitraryValuesCollection::point(const profiler::ArbitraryValue& _value, int _index) const
{ {
const qreal x = PROF_MICROSECONDS(qreal(_value.begin() - m_beginTime)); const qreal x = PROF_MICROSECONDS(qreal(_value.begin() - m_beginTime));
const qreal y = profiler_gui::value2real(_value); const qreal y = profiler_gui::value2real(_value, std::max(_index, 0));
return {x, y}; return {x, y};
} }
@ -1297,12 +1307,9 @@ void ArbitraryValuesChartItem::updateComplexityImageAsync(QRectF _boundingRect,
continue; continue;
} }
const auto first = leftBounds[i]; const auto first = leftBounds[i++];
if (first == complexityMap.end()) if (first == complexityMap.end() || first->first > right)
{
++i;
continue; continue;
}
if (c.selected) if (c.selected)
{ {
@ -1323,9 +1330,12 @@ void ArbitraryValuesChartItem::updateComplexityImageAsync(QRectF _boundingRect,
averages.reserve(complexityMap.size()); averages.reserve(complexityMap.size());
auto it = first; auto it = first;
while (it->first < left) while (it != complexityMap.end() && it->first < left)
++it; ++it;
if (it == complexityMap.end() || it->first > right)
continue;
qreal x = getx(it->first); qreal x = getx(it->first);
profiler::timestamp_t average = 0; profiler::timestamp_t average = 0;
@ -1667,15 +1677,22 @@ struct UsedValueTypes {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
ArbitraryTreeWidgetItem::ArbitraryTreeWidgetItem(QTreeWidgetItem* _parent, profiler::color_t _color, profiler::vin_t _vin) ArbitraryTreeWidgetItem::ArbitraryTreeWidgetItem(QTreeWidgetItem* _parent, bool _checkable, profiler::color_t _color, profiler::vin_t _vin)
: Parent(_parent, ValueItemType) : Parent(_parent, ValueItemType)
, m_vin(_vin) , m_vin(_vin)
, m_color(_color) , m_color(_color)
, m_widthHint(0) , m_widthHint(0)
{
if (_checkable)
{ {
setFlags(flags() | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable); setFlags(flags() | Qt::ItemIsUserCheckable | Qt::ItemIsSelectable);
setCheckState(CheckColumn, Qt::Unchecked); setCheckState(CheckColumn, Qt::Unchecked);
} }
else
{
setFlags(flags() & ~Qt::ItemIsUserCheckable);
}
}
ArbitraryTreeWidgetItem::~ArbitraryTreeWidgetItem() ArbitraryTreeWidgetItem::~ArbitraryTreeWidgetItem()
{ {
@ -1711,6 +1728,35 @@ ArbitraryValuesCollection* ArbitraryTreeWidgetItem::collection()
return m_collection.get(); return m_collection.get();
} }
bool ArbitraryTreeWidgetItem::isArrayItem() const
{
return childCount() != 0;
}
profiler::block_id_t ArbitraryTreeWidgetItem::getParentBlockId(QTreeWidgetItem* _item) const
{
auto parentItem = _item->parent();
const auto parentRole = parentItem->data(int_cast(ArbitraryColumns::Type), Qt::UserRole).toInt();
switch (parentRole)
{
case 1:
return parentItem->data(int_cast(ArbitraryColumns::Vin), Qt::UserRole).toUInt();
case 2:
return getParentBlockId(parentItem);
default:
return EASY_GLOBALS.selected_block_id;
}
}
int ArbitraryTreeWidgetItem::getSelfIndexInArray()
{
if (data(int_cast(ArbitraryColumns::Type), Qt::UserRole).toInt() != 3)
return -1;
return parent()->indexOfChild(this);
}
void ArbitraryTreeWidgetItem::collectValues(profiler::thread_id_t _threadId, ChartType _chartType) void ArbitraryTreeWidgetItem::collectValues(profiler::thread_id_t _threadId, ChartType _chartType)
{ {
if (!m_collection) if (!m_collection)
@ -1718,17 +1764,14 @@ void ArbitraryTreeWidgetItem::collectValues(profiler::thread_id_t _threadId, Cha
else else
m_collection->interrupt(); m_collection->interrupt();
auto parentItem = parent(); const auto parentBlockId = getParentBlockId(this);
const int index = getSelfIndexInArray();
profiler::block_id_t parentBlockId = 0; EASY_CONSTEXPR auto nameColumn = int_cast(ArbitraryColumns::Name);
if (parentItem->data(int_cast(ArbitraryColumns::Type), Qt::UserRole).toInt() == 1) const auto name = index < 0 ? text(nameColumn).toStdString() : parent()->text(nameColumn).toStdString();
parentBlockId = parentItem->data(int_cast(ArbitraryColumns::Vin), Qt::UserRole).toUInt();
else
parentBlockId = EASY_GLOBALS.selected_block_id;
m_collection->collectValuesAndPoints(_chartType, _threadId, m_vin m_collection->collectValuesAndPoints(_chartType, _threadId, m_vin, name.c_str(),
, text(int_cast(ArbitraryColumns::Name)).toStdString().c_str(), EASY_GLOBALS.begin_time EASY_GLOBALS.begin_time, parentBlockId, index);
, parentBlockId);
} }
void ArbitraryTreeWidgetItem::interrupt() void ArbitraryTreeWidgetItem::interrupt()
@ -1918,10 +1961,10 @@ void ArbitraryValuesWidget::onSelectedBlockIdChanged(::profiler::block_id_t)
void ArbitraryValuesWidget::onItemDoubleClicked(QTreeWidgetItem* _item, int) void ArbitraryValuesWidget::onItemDoubleClicked(QTreeWidgetItem* _item, int)
{ {
if (_item == nullptr || _item->type() != ValueItemType) if (_item == nullptr || _item->type() != ValueItemType || (_item->flags() & Qt::ItemIsUserCheckable) == 0)
return; return;
_item->setCheckState(CheckColumn, _item->checkState(CheckColumn) == Qt::Checked ? Qt::Unchecked : Qt::Checked); _item->setCheckState(CheckColumn, _item->checkState(CheckColumn) != Qt::Unchecked ? Qt::Unchecked : Qt::Checked);
} }
void ArbitraryValuesWidget::onItemChanged(QTreeWidgetItem* _item, int _column) void ArbitraryValuesWidget::onItemChanged(QTreeWidgetItem* _item, int _column)
@ -1929,16 +1972,62 @@ void ArbitraryValuesWidget::onItemChanged(QTreeWidgetItem* _item, int _column)
if (_item == nullptr || _item->type() != ValueItemType || _column != CheckColumn) if (_item == nullptr || _item->type() != ValueItemType || _column != CheckColumn)
return; return;
if (_item->checkState(CheckColumn) == Qt::PartiallyChecked)
return;
auto item = static_cast<ArbitraryTreeWidgetItem*>(_item); auto item = static_cast<ArbitraryTreeWidgetItem*>(_item);
if (item->checkState(CheckColumn) == Qt::Checked) if (item->checkState(CheckColumn) == Qt::Checked)
{ {
m_exportToCsvAction->setEnabled(true); m_exportToCsvAction->setEnabled(true);
const auto prevSize = m_checkedItems.size();
if (!item->isArrayItem())
{
m_checkedItems.push_back(item); m_checkedItems.push_back(item);
item->collectValues(EASY_GLOBALS.selected_thread, m_chart->chartType()); item->collectValues(EASY_GLOBALS.selected_thread, m_chart->chartType());
if (item->getSelfIndexInArray() >= 0)
{
Qt::CheckState newState = Qt::Checked;
auto parentItem = item->parent();
for (int i = 0; i < parentItem->childCount(); ++i)
{
auto child = parentItem->child(i);
if (child->checkState(CheckColumn) != Qt::Checked)
{
newState = Qt::PartiallyChecked;
break;
}
}
disconnect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
parentItem->setCheckState(CheckColumn, newState);
connect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
}
}
else
{
disconnect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
for (int i = 0; i < item->childCount(); ++i)
{
auto child = static_cast<ArbitraryTreeWidgetItem*>(item->child(i));
if (child->checkState(CheckColumn) != Qt::Checked)
{
child->setCheckState(CheckColumn, Qt::Checked);
m_checkedItems.push_back(child);
child->collectValues(EASY_GLOBALS.selected_thread, m_chart->chartType());
}
}
connect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
}
if (prevSize != m_checkedItems.size())
{
if (!m_collectionsTimer.isActive()) if (!m_collectionsTimer.isActive())
m_collectionsTimer.start(100); m_collectionsTimer.start(100);
} }
}
else else
{ {
// !!! // !!!
@ -1949,10 +2038,56 @@ void ArbitraryValuesWidget::onItemChanged(QTreeWidgetItem* _item, int _column)
// in interrupt(). // in interrupt().
// !!! // !!!
decltype(m_checkedItems) uncheckedItems;
if (!item->isArrayItem())
{
uncheckedItems.push_back(item);
m_checkedItems.removeOne(item); m_checkedItems.removeOne(item);
if (item->getSelfIndexInArray() >= 0)
{
Qt::CheckState newState = Qt::Unchecked;
auto parentItem = item->parent();
for (int i = 0; i < parentItem->childCount(); ++i)
{
auto child = parentItem->child(i);
if (child->checkState(CheckColumn) != Qt::Unchecked)
{
newState = Qt::PartiallyChecked;
break;
}
}
disconnect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
parentItem->setCheckState(CheckColumn, newState);
connect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
}
}
else
{
disconnect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
for (int i = 0; i < item->childCount(); ++i)
{
auto child = static_cast<ArbitraryTreeWidgetItem*>(item->child(i));
if (child->checkState(CheckColumn) == Qt::Checked)
{
child->setCheckState(CheckColumn, Qt::Unchecked);
uncheckedItems.push_back(child);
m_checkedItems.removeOne(child);
}
}
connect(m_treeWidget, &QTreeWidget::itemChanged, this, &This::onItemChanged);
}
if (!uncheckedItems.isEmpty())
{
m_exportToCsvAction->setEnabled(!m_checkedItems.empty()); m_exportToCsvAction->setEnabled(!m_checkedItems.empty());
onCollectionsTimeout(); onCollectionsTimeout();
item->interrupt();
for (auto uncheckedItem : uncheckedItems)
uncheckedItem->interrupt();
}
} }
} }
@ -2214,11 +2349,13 @@ QTreeWidgetItem* ArbitraryValuesWidget::buildTreeForThread(const profiler::Block
const auto& desc = easyDescriptor(block.node->id()); const auto& desc = easyDescriptor(block.node->id());
if (desc.type() == profiler::BlockType::Value) if (desc.type() == profiler::BlockType::Value)
{ {
auto valueItem = new ArbitraryTreeWidgetItem(rootItem, desc.color(), block.value->value_id()); auto value = block.value;
valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*block.value)); const bool isString = value->type() == profiler::DataType::String;
auto valueItem = new ArbitraryTreeWidgetItem(rootItem, !isString, desc.color(), value->value_id());
valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*value));
valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name()); valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name());
valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(block.value->value_id(), 0, 16)); valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(value->value_id(), 0, 16));
valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*block.value)); valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*value));
valueItem->setData(int_cast(ArbitraryColumns::Type), Qt::UserRole, 2); valueItem->setData(int_cast(ArbitraryColumns::Type), Qt::UserRole, 2);
const auto sizeHintWidth = valueItem->sizeHint(CheckColumn).width(); const auto sizeHintWidth = valueItem->sizeHint(CheckColumn).width();
@ -2311,8 +2448,31 @@ QTreeWidgetItem* ArbitraryValuesWidget::buildTreeForThread(const profiler::Block
if (valueItem != nullptr) if (valueItem != nullptr)
{ {
if (i == _blockIndex) if (i == _blockIndex)
valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*value)); valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::shortValueString(*value));
//continue; // already in set //continue; // already in set
if (value->isArray() && value->type() != profiler::DataType::String)
{
const int size = profiler_gui::valueArraySize(*value);
if (valueItem->childCount() < size)
{
for (int childIndex = valueItem->childCount(); childIndex < size; ++childIndex)
{
auto item = new ArbitraryTreeWidgetItem(valueItem, true, desc.color(), vin);
item->setText(int_cast(ArbitraryColumns::Name), QString("%1[%2]").arg(desc.name()).arg(childIndex));
item->setData(int_cast(ArbitraryColumns::Type), Qt::UserRole, 3);
if (i == _blockIndex)
item->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*value, childIndex));
const auto sizeHintWidth = valueItem->sizeHint(CheckColumn).width();
item->setWidthHint(std::max(sizeHintWidth, fm.width(valueItem->text(CheckColumn))) + 32);
}
auto typeString = profiler_gui::valueTypeString(*value);
valueItem->setText(int_cast(ArbitraryColumns::Type), typeString.replace("[]", "[%1]").arg(size));
}
}
} }
else else
{ {
@ -2339,19 +2499,43 @@ QTreeWidgetItem* ArbitraryValuesWidget::buildTreeForThread(const profiler::Block
} }
} }
valueItem = new ArbitraryTreeWidgetItem(blockItem, desc.color(), vin); const bool isString = value->type() == profiler::DataType::String;
valueItem = new ArbitraryTreeWidgetItem(blockItem, !isString, desc.color(), vin);
valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*value)); valueItem->setText(int_cast(ArbitraryColumns::Type), profiler_gui::valueTypeString(*value));
valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name()); valueItem->setText(int_cast(ArbitraryColumns::Name), desc.name());
valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(vin, 0, 16)); valueItem->setText(int_cast(ArbitraryColumns::Vin), QString("0x%1").arg(vin, 0, 16));
valueItem->setData(int_cast(ArbitraryColumns::Type), Qt::UserRole, 2); valueItem->setData(int_cast(ArbitraryColumns::Type), Qt::UserRole, 2);
if (i == _blockIndex) if (i == _blockIndex)
valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*value)); valueItem->setText(int_cast(ArbitraryColumns::Value), profiler_gui::shortValueString(*value));
const auto sizeHintWidth = valueItem->sizeHint(CheckColumn).width(); auto sizeHintWidth = valueItem->sizeHint(CheckColumn).width();
valueItem->setWidthHint(std::max(sizeHintWidth, fm.width(valueItem->text(CheckColumn))) + 32); valueItem->setWidthHint(std::max(sizeHintWidth, fm.width(valueItem->text(CheckColumn))) + 32);
*(usedItems + typeIndex) = valueItem; *(usedItems + typeIndex) = valueItem;
if (value->isArray() && !isString)
{
const int size = profiler_gui::valueArraySize(*value);
if (valueItem->childCount() < size)
{
for (int childIndex = valueItem->childCount(); childIndex < size; ++childIndex)
{
auto item = new ArbitraryTreeWidgetItem(valueItem, true, desc.color(), vin);
item->setText(int_cast(ArbitraryColumns::Name), QString("%1[%2]").arg(desc.name()).arg(childIndex));
item->setData(int_cast(ArbitraryColumns::Type), Qt::UserRole, 3);
if (i == _blockIndex)
item->setText(int_cast(ArbitraryColumns::Value), profiler_gui::valueString(*value, childIndex));
sizeHintWidth = valueItem->sizeHint(CheckColumn).width();
item->setWidthHint(std::max(sizeHintWidth, fm.width(valueItem->text(CheckColumn))) + 32);
}
auto typeString = profiler_gui::valueTypeString(*value);
valueItem->setText(int_cast(ArbitraryColumns::Type), typeString.replace("[]", "[%1]").arg(size));
}
}
} }
} }

View File

@ -142,25 +142,39 @@ public:
qreal minValue() const; qreal minValue() const;
qreal maxValue() const; qreal maxValue() const;
void collectValues(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId, const char* _valueName, profiler::block_id_t _parentBlockId); void collectValues(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId
, const char* _valueName, profiler::block_id_t _parentBlockId, int _index = -1);
bool calculatePoints(profiler::timestamp_t _beginTime); bool calculatePoints(profiler::timestamp_t _beginTime);
void collectValuesAndPoints(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId, const char* _valueName, profiler::timestamp_t _beginTime, profiler::block_id_t _parentBlockId); void collectValuesAndPoints(ChartType _chartType, profiler::thread_id_t _threadId, profiler::vin_t _valueId
, const char* _valueName, profiler::timestamp_t _beginTime, profiler::block_id_t _parentBlockId
, int _index = -1);
void interrupt(); void interrupt();
private: private:
void setStatus(JobStatus _status); void setStatus(JobStatus _status);
void collectById(profiler::thread_id_t _threadId, profiler::vin_t _valueId, profiler::block_id_t _parentBlockId);
void collectByName(profiler::thread_id_t _threadId, const std::string _valueName, profiler::block_id_t _parentBlockId); void collectById(profiler::thread_id_t _threadId, profiler::vin_t _valueId
bool collectByIdForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::vin_t _valueId, bool _calculatePoints, profiler::block_id_t _parentBlockId); , profiler::block_id_t _parentBlockId, int _index);
bool collectByNameForThread(const profiler::BlocksTreeRoot& _threadRoot, const std::string& _valueName, bool _calculatePoints, profiler::block_id_t _parentBlockId);
void collectByName(profiler::thread_id_t _threadId, const std::string _valueName
, profiler::block_id_t _parentBlockId, int _index);
bool collectByIdForThread(const profiler::BlocksTreeRoot& _threadRoot, profiler::vin_t _valueId
, bool _calculatePoints, profiler::block_id_t _parentBlockId, int _index);
bool collectByNameForThread(const profiler::BlocksTreeRoot& _threadRoot, const std::string& _valueName
, bool _calculatePoints, profiler::block_id_t _parentBlockId, int _index);
bool depthFirstSearch(const profiler::BlocksTreeRoot& _threadRoot, bool _calculatePoints bool depthFirstSearch(const profiler::BlocksTreeRoot& _threadRoot, bool _calculatePoints
, profiler::block_id_t _parentBlockId, std::function<bool(profiler::vin_t, const char*)> _isSuitableValue); , profiler::block_id_t _parentBlockId, int _index
, std::function<bool(profiler::vin_t, const char*)> _isSuitableValue);
double addPoint(const profiler::ArbitraryValue& _value); double addPoint(const profiler::ArbitraryValue& _value, int _index);
QPointF point(const profiler::ArbitraryValue& _value) const; QPointF point(const profiler::ArbitraryValue& _value, int _index) const;
}; // end of class ArbitraryValuesCollection. }; // end of class ArbitraryValuesCollection.
@ -290,7 +304,7 @@ class ArbitraryTreeWidgetItem : public QTreeWidgetItem
public: public:
explicit ArbitraryTreeWidgetItem(QTreeWidgetItem* _parent, profiler::color_t _color, profiler::vin_t _vin = 0); explicit ArbitraryTreeWidgetItem(QTreeWidgetItem* _parent, bool _checkable, profiler::color_t _color, profiler::vin_t _vin = 0);
~ArbitraryTreeWidgetItem() override; ~ArbitraryTreeWidgetItem() override;
QVariant data(int _column, int _role) const override; QVariant data(int _column, int _role) const override;
@ -305,6 +319,13 @@ public:
profiler::color_t color() const; profiler::color_t color() const;
bool isArrayItem() const;
int getSelfIndexInArray();
private:
profiler::block_id_t getParentBlockId(QTreeWidgetItem* _item) const;
}; // end of class ArbitraryTreeWidgetItem. }; // end of class ArbitraryTreeWidgetItem.
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -1743,7 +1743,7 @@ void BlocksGraphicsView::onIdleTimeout()
++row; ++row;
lay->addWidget(new QLabel("Value:", widget), row, 0, Qt::AlignRight); lay->addWidget(new QLabel("Value:", widget), row, 0, Qt::AlignRight);
lay->addWidget(new QLabel(::profiler_gui::valueString(*itemBlock.value), widget), row, 1, Qt::AlignLeft); lay->addWidget(new QLabel(::profiler_gui::shortValueString(*itemBlock.value), widget), row, 1, Qt::AlignLeft);
++row; ++row;
lay->addWidget(new QLabel("VIN:", widget), row, 0, Qt::AlignRight); lay->addWidget(new QLabel("VIN:", widget), row, 0, Qt::AlignRight);

View File

@ -54,6 +54,11 @@
#include "common_functions.h" #include "common_functions.h"
template <class T>
static QString toString(const profiler::ArbitraryValue& _serializedValue, int _index) {
return QString::number(_serializedValue.toArray<T>()->at(_index));
}
template <class T> template <class T>
static QString toString(const profiler::ArbitraryValue& _serializedValue) { static QString toString(const profiler::ArbitraryValue& _serializedValue) {
return QString::number(_serializedValue.toValue<T>()->value()); return QString::number(_serializedValue.toValue<T>()->value());
@ -69,6 +74,58 @@ static double toReal(const profiler::ArbitraryValue& _serializedValue) {
return static_cast<double>(_serializedValue.toValue<T>()->value()); return static_cast<double>(_serializedValue.toValue<T>()->value());
} }
template <profiler::DataType type>
inline EASY_CONSTEXPR_FCN uint16_t sizeOf() {
return static_cast<uint16_t>(sizeof(typename profiler::StdType<type>::value_type));
}
QString arrayToString(const profiler::ArbitraryValue& _serializedValue, int _index)
{
switch (_serializedValue.type())
{
case profiler::DataType::Bool:
{
const auto value = _serializedValue.toArray<bool>()->at(_index);
return value ? QStringLiteral("true") : QStringLiteral("false");
}
case profiler::DataType::Char: return QChar(_serializedValue.toArray<char> ()->at(_index));
case profiler::DataType::Int8: return QChar(_serializedValue.toArray<int8_t>()->at(_index));
case profiler::DataType::Uint8: return toString<uint8_t> (_serializedValue, _index);
case profiler::DataType::Int16: return toString<int16_t> (_serializedValue, _index);
case profiler::DataType::Uint16: return toString<uint16_t>(_serializedValue, _index);
case profiler::DataType::Int32: return toString<int32_t> (_serializedValue, _index);
case profiler::DataType::Uint32: return toString<uint32_t>(_serializedValue, _index);
case profiler::DataType::Int64: return toString<int64_t> (_serializedValue, _index);
case profiler::DataType::Uint64: return toString<uint64_t>(_serializedValue, _index);
case profiler::DataType::Float: return toString<float> (_serializedValue, _index);
case profiler::DataType::Double: return toString<double> (_serializedValue, _index);
case profiler::DataType::String: return QChar(_serializedValue.data()[_index]);
default: return QStringLiteral("??");
}
}
QString singleValueToString(const profiler::ArbitraryValue& _serializedValue)
{
switch (_serializedValue.type())
{
case profiler::DataType::Bool: return _serializedValue.toValue<bool>()->value() ? QStringLiteral("true") : QStringLiteral("false");
case profiler::DataType::Char: return QChar(_serializedValue.toValue<char> ()->value());
case profiler::DataType::Int8: return QChar(_serializedValue.toValue<int8_t>()->value());
case profiler::DataType::Uint8: return toString<uint8_t> (_serializedValue);
case profiler::DataType::Int16: return toString<int16_t> (_serializedValue);
case profiler::DataType::Uint16: return toString<uint16_t>(_serializedValue);
case profiler::DataType::Int32: return toString<int32_t> (_serializedValue);
case profiler::DataType::Uint32: return toString<uint32_t>(_serializedValue);
case profiler::DataType::Int64: return toString<int64_t> (_serializedValue);
case profiler::DataType::Uint64: return toString<uint64_t>(_serializedValue);
case profiler::DataType::Float: return toString<float> (_serializedValue);
case profiler::DataType::Double: return toString<double> (_serializedValue);
case profiler::DataType::String: return _serializedValue.data();
default: return QStringLiteral("??");
}
}
namespace profiler_gui { namespace profiler_gui {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -281,26 +338,74 @@ namespace profiler_gui {
{ {
if (_serializedValue.type() == ::profiler::DataType::String) if (_serializedValue.type() == ::profiler::DataType::String)
return _serializedValue.data(); return _serializedValue.data();
return QStringLiteral("[...] array");
auto str = QString("[%1").arg(valueString(_serializedValue, 0));
const int size = valueArraySize(_serializedValue);
for (int i = 1; i < size; ++i)
str.append(QString(", %1").arg(valueString(_serializedValue, i)));
str.append(QChar(']'));
return str;
} }
switch (_serializedValue.type()) return singleValueToString(_serializedValue);
{
case ::profiler::DataType::Bool: return _serializedValue.toValue<bool>()->value() ? QStringLiteral("true") : QStringLiteral("false");
case ::profiler::DataType::Char: return QChar(_serializedValue.toValue<char> ()->value());
case ::profiler::DataType::Int8: return QChar(_serializedValue.toValue<int8_t>()->value());
case ::profiler::DataType::Uint8: return toString<uint8_t> (_serializedValue);
case ::profiler::DataType::Int16: return toString<int16_t> (_serializedValue);
case ::profiler::DataType::Uint16: return toString<uint16_t>(_serializedValue);
case ::profiler::DataType::Int32: return toString<int32_t> (_serializedValue);
case ::profiler::DataType::Uint32: return toString<uint32_t>(_serializedValue);
case ::profiler::DataType::Int64: return toString<int64_t> (_serializedValue);
case ::profiler::DataType::Uint64: return toString<uint64_t>(_serializedValue);
case ::profiler::DataType::Float: return toString<float> (_serializedValue);
case ::profiler::DataType::Double: return toString<double> (_serializedValue);
case ::profiler::DataType::String: return _serializedValue.data();
default: return QStringLiteral("Unknown");
} }
QString shortValueString(const ::profiler::ArbitraryValue& _serializedValue)
{
if (_serializedValue.isArray())
{
if (_serializedValue.type() == ::profiler::DataType::String)
return _serializedValue.data();
auto str = QString("[%1").arg(valueString(_serializedValue, 0));
const int size = valueArraySize(_serializedValue);
if (size < 7)
{
for (int i = 1; i < size; ++i)
str.append(QString(", %1").arg(valueString(_serializedValue, i)));
}
else
{
for (int i = 1; i < 6; ++i)
str.append(QString(", %1").arg(valueString(_serializedValue, i)));
str.append(QString(", ..., %1").arg(valueString(_serializedValue, size - 1)));
}
str.append(QChar(']'));
return str;
}
return singleValueToString(_serializedValue);
}
QString valueString(const ::profiler::ArbitraryValue& _serializedValue, int _index)
{
if (_serializedValue.isArray())
return arrayToString(_serializedValue, _index);
return singleValueToString(_serializedValue);
}
int valueArraySize(const ::profiler::ArbitraryValue& _serializedValue)
{
EASY_STATIC_CONSTEXPR uint16_t DataSizes[] = {
sizeOf<::profiler::DataType::Bool>(),
sizeOf<::profiler::DataType::Char>(),
sizeOf<::profiler::DataType::Int8>(),
sizeOf<::profiler::DataType::Uint8>(),
sizeOf<::profiler::DataType::Int16>(),
sizeOf<::profiler::DataType::Uint16>(),
sizeOf<::profiler::DataType::Int32>(),
sizeOf<::profiler::DataType::Uint32>(),
sizeOf<::profiler::DataType::Int64>(),
sizeOf<::profiler::DataType::Uint64>(),
sizeOf<::profiler::DataType::Float>(),
sizeOf<::profiler::DataType::Double>(),
sizeOf<::profiler::DataType::String>(),
1
};
return _serializedValue.data_size() / DataSizes[int_cast(_serializedValue.type())];
} }
double value2real(const ::profiler::ArbitraryValue& _serializedValue, int _index) double value2real(const ::profiler::ArbitraryValue& _serializedValue, int _index)

View File

@ -204,6 +204,9 @@ inline QFont EFont(const char* _family, int _size, int _weight = -1) {
QString valueTypeString(::profiler::DataType _dataType); QString valueTypeString(::profiler::DataType _dataType);
QString valueTypeString(const ::profiler::ArbitraryValue& _serializedValue); QString valueTypeString(const ::profiler::ArbitraryValue& _serializedValue);
QString valueString(const ::profiler::ArbitraryValue& _serializedValue); QString valueString(const ::profiler::ArbitraryValue& _serializedValue);
QString shortValueString(const ::profiler::ArbitraryValue& _serializedValue);
QString valueString(const ::profiler::ArbitraryValue& _serializedValue, int _index);
int valueArraySize(const ::profiler::ArbitraryValue& _serializedValue);
double value2real(const ::profiler::ArbitraryValue& _serializedValue, int _index = 0); double value2real(const ::profiler::ArbitraryValue& _serializedValue, int _index = 0);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<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"
width="64px" height="64px" viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
<g>
<rect fill="#98CE98" x="16" y="16" width="32" height="32"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 358 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<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"
width="64px" height="64px" viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
<g>
<rect fill="#237423" x="16" y="16" width="32" height="32"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 358 B

View File

@ -31,6 +31,8 @@
<file alias="check-disabled">images/default/check-disabled.svg</file> <file alias="check-disabled">images/default/check-disabled.svg</file>
<file alias="radio-check">images/default/radio-indicator.svg</file> <file alias="radio-check">images/default/radio-indicator.svg</file>
<file alias="radio-check-disabled">images/default/radio-indicator-disabled.svg</file> <file alias="radio-check-disabled">images/default/radio-indicator-disabled.svg</file>
<file alias="partial-check">images/default/check-partial.svg</file>
<file alias="partial-check-disabled">images/default/check-partial-disabled.svg</file>
<file alias="dock-maximize-white">images/default/maximize-white.svg</file> <file alias="dock-maximize-white">images/default/maximize-white.svg</file>
<file alias="dock-maximize-white-hover">images/default/maximize-white-hover.svg</file> <file alias="dock-maximize-white-hover">images/default/maximize-white-hover.svg</file>
<file alias="dock-maximize-white-pressed">images/default/maximize-white-pressed.svg</file> <file alias="dock-maximize-white-pressed">images/default/maximize-white-pressed.svg</file>

View File

@ -175,7 +175,7 @@ QTreeView::indicator {
padding: 1px; padding: 1px;
margin: 0; } margin: 0; }
QTreeView::indicator:hover, QTreeView::indicator:checked { QTreeView::indicator:hover, QTreeView::indicator:checked, QTreeView::indicator:indeterminate {
background-color: white; background-color: white;
border: 1px solid #cccccc; } border: 1px solid #cccccc; }
@ -185,6 +185,12 @@ QTreeView::indicator:checked {
QTreeView::indicator:checked:disabled { QTreeView::indicator:checked:disabled {
image: url(":/images/default/check-disabled"); } image: url(":/images/default/check-disabled"); }
QTreeView::indicator:indeterminate {
image: url(":/images/default/partial-check"); }
QTreeView::indicator:indeterminate:disabled {
image: url(":/images/default/partial-check-disabled"); }
/* ****************************************************************************************************************** */ /* ****************************************************************************************************************** */
QMenu { QMenu {
background-color: white; background-color: white;

View File

@ -200,7 +200,7 @@ QTreeView::indicator {
margin: 0; margin: 0;
} }
QTreeView::indicator:hover, QTreeView::indicator:checked { QTreeView::indicator:hover, QTreeView::indicator:checked, QTreeView::indicator:indeterminate {
background-color: $BackgroundColor; background-color: $BackgroundColor;
border: 1px solid $BorderColor; border: 1px solid $BorderColor;
} }
@ -208,6 +208,9 @@ QTreeView::indicator:hover, QTreeView::indicator:checked {
QTreeView::indicator:checked { image: url(":/images/default/check"); } QTreeView::indicator:checked { image: url(":/images/default/check"); }
QTreeView::indicator:checked:disabled { image: url(":/images/default/check-disabled"); } QTreeView::indicator:checked:disabled { image: url(":/images/default/check-disabled"); }
QTreeView::indicator:indeterminate { image: url(":/images/default/partial-check"); }
QTreeView::indicator:indeterminate:disabled { image: url(":/images/default/partial-check-disabled"); }
/* ****************************************************************************************************************** */ /* ****************************************************************************************************************** */
QMenu { QMenu {
background-color: $BackgroundColor; background-color: $BackgroundColor;

View File

@ -185,7 +185,8 @@ void modellingThread(){
localSleep(1200000); localSleep(1200000);
++step; ++step;
EASY_VALUE("step", sin((double)step), profiler::colors::Gold, EASY_VIN(step)); double vals[] = {(double)step, sin((double)step), cos((double)step)};
EASY_VALUE("step", vals, profiler::colors::Gold, EASY_VIN(step));
if (step > 10000000) if (step > 10000000)
step = 0; step = 0;