diff --git a/README.md b/README.md index 8d9ec160..9b29778e 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ ---- +## v.1.0.27 released! + +Checkout the ['plot view'](./md/plot_view/plot_view.md#plot-view) feature! + +---- + ![DLT Message Analyzer logo](./md/DLTMessageAnalyzer_logo.png) ![Build linux](https://github.com/svlad-90/DLT-Message-Analyzer/workflows/Build%20linux%20Qt5/badge.svg) @@ -80,6 +86,10 @@ There are the following schemas of deployment: - Plugin supports integration with the PlantUML tool, which allows you to create sequence diagrams out of the logs +### [Plot view](./md/plot_view/plot_view.md) + +- Plugin supports integration with the QCustomPlot library, which allows you to create plots out of the logs + ### [Files view](./md/files_view/files_view.md) - Extension, which lists the paths & names of all currently opened DLT files diff --git a/dltmessageanalyzerplugin/src/CMakeLists.txt b/dltmessageanalyzerplugin/src/CMakeLists.txt index 6d3af60b..58792a92 100644 --- a/dltmessageanalyzerplugin/src/CMakeLists.txt +++ b/dltmessageanalyzerplugin/src/CMakeLists.txt @@ -32,6 +32,28 @@ function (DMA_QT_WRAP_UI ui_headers_var_name wrap_ui_var_name) endfunction() ################### QT_SPECIFIC ( END ) ################### +################### QCUSTOMPLOT ########################### +# function - sync_qcustomplot +# Syncs QCustomPlot, implementation, which is used for +# the creation of plots +function (DMA_sync_q_custom_plot) + include(FetchContent) + FetchContent_Declare( + qcustomplot + GIT_REPOSITORY https://github.com/svlad-90/QCustomPlot-library + GIT_TAG 2.1.1.1 + ) + + FetchContent_GetProperties(qcustomplot) + if(NOT qcustomplot_POPULATED) + FetchContent_Populate(qcustomplot) + add_subdirectory(${qcustomplot_SOURCE_DIR} ${qcustomplot_BINARY_DIR}) + endif() + +# include_directories(${qcustomplot_SOURCE_DIR}/DMA_Plantuml/include) +endfunction(DMA_sync_q_custom_plot) +################### QCUSTOMPLOT ( END ) ################### + ################### COMMON_DEPS ########################### include(FetchContent) FetchContent_Declare( @@ -60,6 +82,7 @@ add_definitions(-DDMA_FORCE_LINK_ON) DMA_sync_g_test_framework() DMA_sync_plantuml() DMA_sync_framework() +DMA_sync_q_custom_plot() ################### DEPENDENCIES ( END )################### ################### COMPATIBILITY ######################### diff --git a/dltmessageanalyzerplugin/src/common/BaseDefinitions.cpp b/dltmessageanalyzerplugin/src/common/BaseDefinitions.cpp new file mode 100644 index 00000000..5ef930a5 --- /dev/null +++ b/dltmessageanalyzerplugin/src/common/BaseDefinitions.cpp @@ -0,0 +1,12 @@ +/** + * @file BaseDefinitions.cpp + * @author vgoncharuk + * @brief Implementation of the BaseDefinitions + */ + +#include "BaseDefinitions.hpp" + +bool QOptionalColor::operator== ( const QOptionalColor& rhs ) const +{ + return color == rhs.color && isSet == rhs.isSet; +} diff --git a/dltmessageanalyzerplugin/src/common/BaseDefinitions.hpp b/dltmessageanalyzerplugin/src/common/BaseDefinitions.hpp new file mode 100644 index 00000000..57d6d437 --- /dev/null +++ b/dltmessageanalyzerplugin/src/common/BaseDefinitions.hpp @@ -0,0 +1,48 @@ +/** + * @file BaseDefinitions.hpp + * @author vgoncharuk + * @brief Declaration of the BaseDefinitions + */ + +#ifndef BASE_DEFINITIONS_HPP +#define BASE_DEFINITIONS_HPP + +#include +#include + +#include +#include +#include +#include + +typedef std::shared_ptr tQStringPtr; +typedef std::vector tQStringPtrVec; + +struct tQStringPtrWrapper +{ + tQStringPtrWrapper(); + tQStringPtrWrapper(const tQStringPtr& pString_); + bool operator== ( const tQStringPtrWrapper& rVal ) const; + bool operator< ( const tQStringPtrWrapper& rVal ) const; + tQStringPtr pString = nullptr; +}; + +namespace std { +template<> struct hash { + std::size_t operator()(const tQStringPtrWrapper& pS) const noexcept { + return pS.pString ? (size_t) qHash(*pS.pString) : 0u; + } +}; +} + +Q_DECLARE_METATYPE(tQStringPtrWrapper) + +struct QOptionalColor +{ + bool isSet = false; + QColor color; + bool operator== ( const QOptionalColor& rhs ) const; +}; +typedef QVector QOptionalColorVec; + +#endif // BASE_DEFINITIONS_HPP diff --git a/dltmessageanalyzerplugin/src/common/CMakeLists.txt b/dltmessageanalyzerplugin/src/common/CMakeLists.txt index 15583ab3..6aed044d 100644 --- a/dltmessageanalyzerplugin/src/common/CMakeLists.txt +++ b/dltmessageanalyzerplugin/src/common/CMakeLists.txt @@ -1,6 +1,8 @@ add_library(DMA_common STATIC + BaseDefinitions.cpp CTreeItem.cpp Definitions.cpp + PlotDefinitions.cpp CBGColorAnimation.cpp CRegexDirectoryMonitor.cpp CTableMemoryJumper.cpp diff --git a/dltmessageanalyzerplugin/src/common/Definitions.cpp b/dltmessageanalyzerplugin/src/common/Definitions.cpp index 95130162..2e6a3452 100644 --- a/dltmessageanalyzerplugin/src/common/Definitions.cpp +++ b/dltmessageanalyzerplugin/src/common/Definitions.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -138,166 +139,191 @@ const tUML_IDs_Map s_UML_IDs_Map = createUMLIDsMap(); const tMsgId INVALID_MSG_ID = -1; const tRequestId INVALID_REQUEST_ID = static_cast(-1); -const std::map sColorsMap = -{ -{"ok", QColor(0,150,0)}, -{"warning", QColor(150,150,0)}, -{"error", QColor(150,0,0)}, -{"black", QColor(0,0,0)}, -{"white", QColor(255,255,255)}, -{"red", QColor(255,0,0)}, -{"lime", QColor(0,255,0)}, -{"blue", QColor(0,0,255)}, -{"yellow", QColor(255,255,0)}, -{"cyan", QColor(0,255,255)}, -{"magenta", QColor(255,0,255)}, -{"silver", QColor(192,192,192)}, -{"gray", QColor(128,128,128)}, -{"maroon", QColor(128,0,0)}, -{"olive", QColor(128,128,0)}, -{"green", QColor(0,128,0)}, -{"purple", QColor(128,0,128)}, -{"teal", QColor(0,128,128)}, -{"navy", QColor(0,0,128)}, -{"maroon", QColor(128,0,0)}, -{"dark_red", QColor(139,0,0)}, -{"brown", QColor(165,42,42)}, -{"firebrick", QColor(178,34,34)}, -{"crimson", QColor(220,20,60)}, -{"red", QColor(255,0,0)}, -{"tomato", QColor(255,99,71)}, -{"coral", QColor(255,127,80)}, -{"indian_red", QColor(205,92,92)}, -{"light_coral", QColor(240,128,128)}, -{"dark_salmon", QColor(233,150,122)}, -{"salmon", QColor(250,128,114)}, -{"light_salmon", QColor(255,160,122)}, -{"orange_red", QColor(255,69,0)}, -{"dark_orange", QColor(255,140,0)}, -{"orange", QColor(255,165,0)}, -{"gold", QColor(255,215,0)}, -{"dark_golden_rod", QColor(184,134,11)}, -{"golden_rod", QColor(218,165,32)}, -{"pale_golden_rod", QColor(238,232,170)}, -{"dark_khaki", QColor(189,183,107)}, -{"khaki", QColor(240,230,140)}, -{"olive", QColor(128,128,0)}, -{"yellow", QColor(255,255,0)}, -{"yellow_green", QColor(154,205,50)}, -{"dark_olive_green", QColor(85,107,47)}, -{"olive_drab", QColor(107,142,35)}, -{"lawn_green", QColor(124,252,0)}, -{"chart_reuse", QColor(127,255,0)}, -{"green_yellow", QColor(173,255,47)}, -{"dark_green", QColor(0,100,0)}, -{"green", QColor(0,128,0)}, -{"forest_green", QColor(34,139,34)}, -{"lime", QColor(0,255,0)}, -{"lime_green", QColor(50,205,50)}, -{"light_green", QColor(144,238,144)}, -{"pale_green", QColor(152,251,152)}, -{"dark_sea_green", QColor(143,188,143)}, -{"medium_spring_green", QColor(0,250,154)}, -{"spring_green", QColor(0,255,127)}, -{"sea_green", QColor(46,139,87)}, -{"medium_aqua_marine", QColor(102,205,170)}, -{"medium_sea_green", QColor(60,179,113)}, -{"light_sea_green", QColor(32,178,170)}, -{"dark_slate_gray", QColor(47,79,79)}, -{"teal", QColor(0,128,128)}, -{"dark_cyan", QColor(0,139,139)}, -{"aqua", QColor(0,255,255)}, -{"cyan", QColor(0,255,255)}, -{"light_cyan", QColor(224,255,255)}, -{"dark_turquoise", QColor(0,206,209)}, -{"turquoise", QColor(64,224,208)}, -{"medium_turquoise", QColor(72,209,204)}, -{"pale_turquoise", QColor(175,238,238)}, -{"aqua_marine", QColor(127,255,212)}, -{"powder_blue", QColor(176,224,230)}, -{"cadet_blue", QColor(95,158,160)}, -{"steel_blue", QColor(70,130,180)}, -{"corn_flower_blue", QColor(100,149,237)}, -{"deep_sky_blue", QColor(0,191,255)}, -{"dodger_blue", QColor(30,144,255)}, -{"light_blue", QColor(173,216,230)}, -{"sky_blue", QColor(135,206,235)}, -{"light_sky_blue", QColor(135,206,250)}, -{"midnight_blue", QColor(25,25,112)}, -{"navy", QColor(0,0,128)}, -{"dark_blue", QColor(0,0,139)}, -{"medium_blue", QColor(0,0,205)}, -{"blue", QColor(0,0,255)}, -{"royal_blue", QColor(65,105,225)}, -{"blue_violet", QColor(138,43,226)}, -{"indigo", QColor(75,0,130)}, -{"dark_slate_blue", QColor(72,61,139)}, -{"slate_blue", QColor(106,90,205)}, -{"medium_slate_blue", QColor(123,104,238)}, -{"medium_purple", QColor(147,112,219)}, -{"dark_magenta", QColor(139,0,139)}, -{"dark_violet", QColor(148,0,211)}, -{"dark_orchid", QColor(153,50,204)}, -{"medium_orchid", QColor(186,85,211)}, -{"purple", QColor(128,0,128)}, -{"thistle", QColor(216,191,216)}, -{"plum", QColor(221,160,221)}, -{"violet", QColor(238,130,238)}, -{"magenta", QColor(255,0,255)}, -{"orchid", QColor(218,112,214)}, -{"medium_violet_red", QColor(199,21,133)}, -{"pale_violet_red", QColor(219,112,147)}, -{"deep_pink", QColor(255,20,147)}, -{"hot_pink", QColor(255,105,180)}, -{"light_pink", QColor(255,182,193)}, -{"pink", QColor(255,192,203)}, -{"antique_white", QColor(250,235,215)}, -{"beige", QColor(245,245,220)}, -{"bisque", QColor(255,228,196)}, -{"blanched_almond", QColor(255,235,205)}, -{"wheat", QColor(245,222,179)}, -{"corn_silk", QColor(255,248,220)}, -{"lemon_chiffon", QColor(255,250,205)}, -{"light golden rod yellow", QColor(250,250,210)}, -{"light_yellow", QColor(255,255,224)}, -{"saddle_brown", QColor(139,69,19)}, -{"sienna", QColor(160,82,45)}, -{"chocolate", QColor(210,105,30)}, -{"peru", QColor(205,133,63)}, -{"sandy_brown", QColor(244,164,96)}, -{"burly_wood", QColor(222,184,135)}, -{"tan", QColor(210,180,140)}, -{"rosy_brown", QColor(188,143,143)}, -{"moccasin", QColor(255,228,181)}, -{"navajo_white", QColor(255,222,173)}, -{"peach_puff", QColor(255,218,185)}, -{"misty_rose", QColor(255,228,225)}, -{"lavender_blush", QColor(255,240,245)}, -{"linen", QColor(250,240,230)}, -{"old_lace", QColor(253,245,230)}, -{"papaya_whip", QColor(255,239,213)}, -{"sea_shell", QColor(255,245,238)}, -{"mint_cream", QColor(245,255,250)}, -{"slate_gray", QColor(112,128,144)}, -{"light_slate_gray", QColor(119,136,153)}, -{"light_steel_blue", QColor(176,196,222)}, -{"lavender", QColor(230,230,250)}, -{"floral_white", QColor(255,250,240)}, -{"alice_blue", QColor(240,248,255)}, -{"ghost_white", QColor(248,248,255)}, -{"honeydew", QColor(240,255,240)}, -{"ivory", QColor(255,255,240)}, -{"azure", QColor(240,255,255)}, -{"snow", QColor(255,250,250)}, -{"black", QColor(0,0,0)}, -{"dim_gray", QColor(105,105,105)}, -{"gray", QColor(128,128,128)}, -{"dark_gray", QColor(169,169,169)}, -{"silver", QColor(192,192,192)}, -{"ight_gray", QColor(211,211,211)}, -{"gainsboro", QColor(220,220,220)}, -{"white_smoke", QColor(245,245,245)}, -{"white", QColor(255,255,255)}}; +const std::map& getColorsMap() +{ + static const std::map sColorsMap = + { + {"ok", QColor(0,150,0)}, + {"warning", QColor(150,150,0)}, + {"error", QColor(150,0,0)}, + {"black", QColor(0,0,0)}, + {"white", QColor(255,255,255)}, + {"red", QColor(255,0,0)}, + {"lime", QColor(0,255,0)}, + {"blue", QColor(0,0,255)}, + {"yellow", QColor(255,255,0)}, + {"cyan", QColor(0,255,255)}, + {"magenta", QColor(255,0,255)}, + {"silver", QColor(192,192,192)}, + {"gray", QColor(128,128,128)}, + {"maroon", QColor(128,0,0)}, + {"olive", QColor(128,128,0)}, + {"green", QColor(0,128,0)}, + {"purple", QColor(128,0,128)}, + {"teal", QColor(0,128,128)}, + {"navy", QColor(0,0,128)}, + {"maroon", QColor(128,0,0)}, + {"dark_red", QColor(139,0,0)}, + {"brown", QColor(165,42,42)}, + {"firebrick", QColor(178,34,34)}, + {"crimson", QColor(220,20,60)}, + {"red", QColor(255,0,0)}, + {"tomato", QColor(255,99,71)}, + {"coral", QColor(255,127,80)}, + {"indian_red", QColor(205,92,92)}, + {"light_coral", QColor(240,128,128)}, + {"dark_salmon", QColor(233,150,122)}, + {"salmon", QColor(250,128,114)}, + {"light_salmon", QColor(255,160,122)}, + {"orange_red", QColor(255,69,0)}, + {"dark_orange", QColor(255,140,0)}, + {"orange", QColor(255,165,0)}, + {"gold", QColor(255,215,0)}, + {"dark_golden_rod", QColor(184,134,11)}, + {"golden_rod", QColor(218,165,32)}, + {"pale_golden_rod", QColor(238,232,170)}, + {"dark_khaki", QColor(189,183,107)}, + {"khaki", QColor(240,230,140)}, + {"olive", QColor(128,128,0)}, + {"yellow", QColor(255,255,0)}, + {"yellow_green", QColor(154,205,50)}, + {"dark_olive_green", QColor(85,107,47)}, + {"olive_drab", QColor(107,142,35)}, + {"lawn_green", QColor(124,252,0)}, + {"chart_reuse", QColor(127,255,0)}, + {"green_yellow", QColor(173,255,47)}, + {"dark_green", QColor(0,100,0)}, + {"green", QColor(0,128,0)}, + {"forest_green", QColor(34,139,34)}, + {"lime", QColor(0,255,0)}, + {"lime_green", QColor(50,205,50)}, + {"light_green", QColor(144,238,144)}, + {"pale_green", QColor(152,251,152)}, + {"dark_sea_green", QColor(143,188,143)}, + {"medium_spring_green", QColor(0,250,154)}, + {"spring_green", QColor(0,255,127)}, + {"sea_green", QColor(46,139,87)}, + {"medium_aqua_marine", QColor(102,205,170)}, + {"medium_sea_green", QColor(60,179,113)}, + {"light_sea_green", QColor(32,178,170)}, + {"dark_slate_gray", QColor(47,79,79)}, + {"teal", QColor(0,128,128)}, + {"dark_cyan", QColor(0,139,139)}, + {"aqua", QColor(0,255,255)}, + {"cyan", QColor(0,255,255)}, + {"light_cyan", QColor(224,255,255)}, + {"dark_turquoise", QColor(0,206,209)}, + {"turquoise", QColor(64,224,208)}, + {"medium_turquoise", QColor(72,209,204)}, + {"pale_turquoise", QColor(175,238,238)}, + {"aqua_marine", QColor(127,255,212)}, + {"powder_blue", QColor(176,224,230)}, + {"cadet_blue", QColor(95,158,160)}, + {"steel_blue", QColor(70,130,180)}, + {"corn_flower_blue", QColor(100,149,237)}, + {"deep_sky_blue", QColor(0,191,255)}, + {"dodger_blue", QColor(30,144,255)}, + {"light_blue", QColor(173,216,230)}, + {"sky_blue", QColor(135,206,235)}, + {"light_sky_blue", QColor(135,206,250)}, + {"midnight_blue", QColor(25,25,112)}, + {"navy", QColor(0,0,128)}, + {"dark_blue", QColor(0,0,139)}, + {"medium_blue", QColor(0,0,205)}, + {"blue", QColor(0,0,255)}, + {"royal_blue", QColor(65,105,225)}, + {"blue_violet", QColor(138,43,226)}, + {"indigo", QColor(75,0,130)}, + {"dark_slate_blue", QColor(72,61,139)}, + {"slate_blue", QColor(106,90,205)}, + {"medium_slate_blue", QColor(123,104,238)}, + {"medium_purple", QColor(147,112,219)}, + {"dark_magenta", QColor(139,0,139)}, + {"dark_violet", QColor(148,0,211)}, + {"dark_orchid", QColor(153,50,204)}, + {"medium_orchid", QColor(186,85,211)}, + {"purple", QColor(128,0,128)}, + {"thistle", QColor(216,191,216)}, + {"plum", QColor(221,160,221)}, + {"violet", QColor(238,130,238)}, + {"magenta", QColor(255,0,255)}, + {"orchid", QColor(218,112,214)}, + {"medium_violet_red", QColor(199,21,133)}, + {"pale_violet_red", QColor(219,112,147)}, + {"deep_pink", QColor(255,20,147)}, + {"hot_pink", QColor(255,105,180)}, + {"light_pink", QColor(255,182,193)}, + {"pink", QColor(255,192,203)}, + {"antique_white", QColor(250,235,215)}, + {"beige", QColor(245,245,220)}, + {"bisque", QColor(255,228,196)}, + {"blanched_almond", QColor(255,235,205)}, + {"wheat", QColor(245,222,179)}, + {"corn_silk", QColor(255,248,220)}, + {"lemon_chiffon", QColor(255,250,205)}, + {"light golden rod yellow", QColor(250,250,210)}, + {"light_yellow", QColor(255,255,224)}, + {"saddle_brown", QColor(139,69,19)}, + {"sienna", QColor(160,82,45)}, + {"chocolate", QColor(210,105,30)}, + {"peru", QColor(205,133,63)}, + {"sandy_brown", QColor(244,164,96)}, + {"burly_wood", QColor(222,184,135)}, + {"tan", QColor(210,180,140)}, + {"rosy_brown", QColor(188,143,143)}, + {"moccasin", QColor(255,228,181)}, + {"navajo_white", QColor(255,222,173)}, + {"peach_puff", QColor(255,218,185)}, + {"misty_rose", QColor(255,228,225)}, + {"lavender_blush", QColor(255,240,245)}, + {"linen", QColor(250,240,230)}, + {"old_lace", QColor(253,245,230)}, + {"papaya_whip", QColor(255,239,213)}, + {"sea_shell", QColor(255,245,238)}, + {"mint_cream", QColor(245,255,250)}, + {"slate_gray", QColor(112,128,144)}, + {"light_slate_gray", QColor(119,136,153)}, + {"light_steel_blue", QColor(176,196,222)}, + {"lavender", QColor(230,230,250)}, + {"floral_white", QColor(255,250,240)}, + {"alice_blue", QColor(240,248,255)}, + {"ghost_white", QColor(248,248,255)}, + {"honeydew", QColor(240,255,240)}, + {"ivory", QColor(255,255,240)}, + {"azure", QColor(240,255,255)}, + {"snow", QColor(255,250,250)}, + {"black", QColor(0,0,0)}, + {"dim_gray", QColor(105,105,105)}, + {"gray", QColor(128,128,128)}, + {"dark_gray", QColor(169,169,169)}, + {"silver", QColor(192,192,192)}, + {"ight_gray", QColor(211,211,211)}, + {"gainsboro", QColor(220,220,220)}, + {"white_smoke", QColor(245,245,245)}, + {"white", QColor(255,255,255)}}; + + return sColorsMap; +} + +static std::list createColorsList() +{ + std::list result; + + const auto& colorsMap = getColorsMap(); + + for(const auto& colorPair : colorsMap) + { + result.push_back(colorPair.second); + } + + return result; +} + +const std::list& getColorsList() +{ + static std::list sColorsList = createColorsList(); + return sColorsList; +} QVector generateColors( const tHighlightingGradient& gradient ) { @@ -415,29 +441,29 @@ from(0), to(0), color(0,0,0), explicitColor(false) bool tHighlightingRange::operator< ( const tHighlightingRange& rVal ) const { - bool bResult = false; - - if( from < rVal.from ) - { - bResult = true; - } - else if( from > rVal.from ) - { - bResult = false; - } - else // if from == rVal.from - { - if( to < rVal.to ) - { - bResult = true; - } - else - { - bResult = false; - } - } - - return bResult; + bool bResult = false; + + if( from < rVal.from ) + { + bResult = true; + } + else if( from > rVal.from ) + { + bResult = false; + } + else // if from == rVal.from + { + if( to < rVal.to ) + { + bResult = true; + } + else + { + bResult = false; + } + } + + return bResult; } /////////////////////////////tIntRangePtrWrapper///////////////////////////// @@ -998,8 +1024,8 @@ tTreeItemSharedPtr tItemMetadata::updateHighlightingInfo( const tFoundMatches& f } tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMatches& foundMatches, - const tRegexScriptingMetadata& regexScriptingMetadata, - tTreeItemSharedPtr pTree) + const tRegexScriptingMetadata& regexScriptingMetadata, + tTreeItemSharedPtr pTree) { tUpdateUMLInfoResult result; @@ -1027,7 +1053,8 @@ tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMat * UMLDataMap( { eUML_ID::UML_CLIENT, { eSearchResultColumn::Apid, {0, 3} }, * { eUML_ID::UML_SEQUENCE_ID, { eSearchResultColumn::Payload, {22, 26} } * { eUML_ID::UML_SERVICE, { eSearchResultColumn::Payload, {28, 40} } - * { eUML_ID::UML_RESPONSE, { eSearchResultColumn::Payload, {44, 45} } ) + * { eUML_ID::UML_RESPONSE, { eSearchResultColumn::Payload, {44, 45} } ), + * bContains_Req_Resp_Ev = false * ); */ @@ -1058,7 +1085,7 @@ tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMat const auto& pGroupMetadata = groups[groupIdx]; if(nullptr != pGroupMetadata && - ( false == pGroupMetadata->optionalUML_ID.optional_UML_IDMap.empty() ) ) + ( false == pGroupMetadata->optionalUML_ID.optional_UML_IDMap.empty() ) ) { res.first = true; // we got the UML data res.second = &pGroupMetadata->optionalUML_ID.optional_UML_IDMap; @@ -1079,13 +1106,14 @@ tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMat auto isReqResEv = [&UML_IDItem]() { return UML_IDItem.first == eUML_ID::UML_REQUEST || - UML_IDItem.first == eUML_ID::UML_RESPONSE || - UML_IDItem.first == eUML_ID::UML_EVENT; + UML_IDItem.first == eUML_ID::UML_RESPONSE || + UML_IDItem.first == eUML_ID::UML_EVENT; }; if(false == isReqResEv() || false == UMLInfo.bContains_Req_Resp_Ev) { - if(true == UML_IDItem.second.UML_Custom_Value.isEmpty()) // if there is no client's custom value + if(nullptr == UML_IDItem.second.pUML_Custom_Value || + true == UML_IDItem.second.pUML_Custom_Value->isEmpty()) // if there is no client's custom value { //let's grab groups content tUMLDataItem UMLDataItem; @@ -1095,13 +1123,13 @@ tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMat const auto& fieldRange = *it; bool insideRange = (match.range.from >= fieldRange.from || match.range.to >= fieldRange.from) && - (match.range.from <= fieldRange.to || match.range.to <= fieldRange.to); + (match.range.from <= fieldRange.to || match.range.to <= fieldRange.to); if(true == insideRange) // if group is even partially inside the range { tStringCoverageItem stringCoverageItem; stringCoverageItem.range = tIntRange( std::max(fieldRange.from, match.range.from) - fieldRange.from, - std::min( fieldRange.to, match.range.to ) - fieldRange.from ); + std::min( fieldRange.to, match.range.to ) - fieldRange.from ); stringCoverageItem.bAddSeparator = match.range.to > fieldRange.to; UMLDataItem.stringCoverageMap[it.key()] = stringCoverageItem; } @@ -1113,7 +1141,7 @@ tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMat { // let's directly assign custom client's value tUMLDataItem UMLDataItem; - UMLDataItem.UML_Custom_Value = UML_IDItem.second.UML_Custom_Value; + UMLDataItem.pUML_Custom_Value = UML_IDItem.second.pUML_Custom_Value; UMLInfo.UMLDataMap[UML_IDItem.first].push_back(UMLDataItem); } @@ -1141,6 +1169,132 @@ tItemMetadata::tUpdateUMLInfoResult tItemMetadata::updateUMLInfo(const tFoundMat return result; } +tItemMetadata::tUpdatePlotViewInfoResult +tItemMetadata::updatePlotViewInfo(const tFoundMatches& foundMatches, + const tRegexScriptingMetadata& regexScriptingMetadata, + tTreeItemSharedPtr pTree) +{ + tUpdatePlotViewInfoResult result; + + tRegexScriptingMetadata::tCheckIDs checkIDs; + + for(const auto& match : foundMatches) + { + checkIDs.insert(match.idx); + } + + // check if string matches all required UML attributes + plotViewInfo.bPlotViewConstraintsFulfilled = regexScriptingMetadata.doesContainConsistentPlotViewData(false, checkIDs, true).first; + plotViewInfo.plotViewDataMap.clear(); + + /* + * What should we fill in here? + * E.g. for the following string: + * {"TIMESTAMP": 1682268321.122626, "MODULE_NAME": "CPU_LOAD", "THREAD_ID": 281472591822624, "API_NAME": "MY_API", "CPU": 7.142857} + * With the following regex: + * (?(?{))"TIMESTAMP": (?([\d]+\.[\d]+)).*? + * "MODULE_NAME": .*?"CPU_LOAD".*API_NAME": "(?.*?)".*?"CPU": (?[\d]+\.[\d]+) + * We will need to fill in the following information: + * tPlotViewInfo( bPlotViewConstraintsFulfilled = true, + * plotViewDataMap( { ePlotViewID::PLOT_X_NAME, { eSearchResultColumn::Payload, {0, 0} }, + * { ePlotViewID::PLOT_Y_NAME, { eSearchResultColumn::Payload, {0, 0} }, + * { ePlotViewID::PLOT_X_DATA, { eSearchResultColumn::Payload, {15, 31} }, + * { ePlotViewID::PLOT_GRAPH_NAME, { eSearchResultColumn::Payload, {104, 109} }, + * { ePlotViewID::PLOT_Y_DATA, { eSearchResultColumn::Payload, {120, 127} } ) + * ); + */ + + auto pMatchesTree = pTree != nullptr ? pTree : getMatchesTree(foundMatches); + + if(true == plotViewInfo.bPlotViewConstraintsFulfilled) // if UML matches are sufficient + { + if(nullptr != pMatchesTree) + { + auto preVisitFunction = [®exScriptingMetadata, this](tTreeItem* pItem) + { + const auto& match = *(pItem->data(static_cast(eTreeColumns::eTreeColumn_FoundMatch)).get()); + + // for each tree element we should check, whether it is related to the plot view data representation. + // That can be done with checking each tree element against regexScriptingMetadata + + // lambda, which checks whether specific match is representing a plot view data + auto isPlotViewData = [&match, ®exScriptingMetadata]()->std::pair + { + std::pair res; + res.first = false; + + auto groupIdx = match.idx; + auto groups = regexScriptingMetadata.getItemsVec(); + + if(groupIdx >= 0 && groupIdx < groups.size()) + { + const auto& pGroupMetadata = groups[groupIdx]; + + if(nullptr != pGroupMetadata && + ( false == pGroupMetadata->plotViewIDParameters.plotViewIDParametersMap.empty() ) ) + { + res.first = true; // we got the UML data + res.second = &pGroupMetadata->plotViewIDParameters.plotViewIDParametersMap; + } + } + + return res; + }; + + auto plotViewDataRes = isPlotViewData(); + + if(true == plotViewDataRes.first) // if we have a plot view data + { + auto fillInFieldRanges = [this, &match](tPlotViewDataItem& plotViewDataItem) + { + //let's grab groups content + for(auto it = fieldRanges.begin(); it != fieldRanges.end(); ++it) + { + const auto& fieldRange = *it; + + bool insideRange = (match.range.from >= fieldRange.from || match.range.to >= fieldRange.from) && + (match.range.from <= fieldRange.to || match.range.to <= fieldRange.to); + + if(true == insideRange) // if group is even partially inside the range + { + tStringCoverageItem stringCoverageItem; + stringCoverageItem.range = tIntRange( std::max(fieldRange.from, match.range.from) - fieldRange.from, + std::min( fieldRange.to, match.range.to ) - fieldRange.from ); + stringCoverageItem.bAddSeparator = match.range.to > fieldRange.to; + plotViewDataItem.stringCoverageMap[it.key()] = stringCoverageItem; + } + } + }; + + auto fillInParameters = [this](tPlotViewDataItem& plotViewDataItem, const tPlotViewIDParametersMap::value_type& plotViewIDParametersMap) + { + plotViewDataItem.optColor = plotViewIDParametersMap.second.optColor; + plotViewDataItem.pPlotViewGroupName = plotViewIDParametersMap.second.pPlotViewGroupName; + plotViewDataItem.plotViewSplitParameters = plotViewIDParametersMap.second.plotViewSplitParameters; + plotViewInfo.plotViewDataMap[plotViewIDParametersMap.first].push_back(plotViewDataItem); + }; + + for(const auto& plotViewIDParametersItem : *(plotViewDataRes.second)) + { + tPlotViewDataItem plotViewDataItem; + + fillInFieldRanges(plotViewDataItem); + fillInParameters(plotViewDataItem, plotViewIDParametersItem); + } + } + + return true; + }; + + pMatchesTree->visit(preVisitFunction, CTreeItem::tVisitFunction(), false, true, false); + } + } + + result.pTreeItem = pMatchesTree; + + return result; +} + //tFoundMatch tFoundMatch::tFoundMatch(): pMatchStr(std::make_shared()), @@ -1227,6 +1381,11 @@ QString getName(eSearchResultColumn val) result = "UML"; } break; + case eSearchResultColumn::PlotView_Applicability: + { + result = "Plot"; + } + break; case eSearchResultColumn::Apid: { result = "Apid"; @@ -1613,7 +1772,9 @@ bool tHighlightingGradient::operator!=(const tHighlightingGradient& rhs) const return !( *this == rhs ); } -tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bool bParseUMLData ) +tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, + bool bParseUMLData, + bool bParsePlotViewData ) { #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList splitGroupName = groupName.split(sRegexScriptingDelimiter, @@ -1633,33 +1794,6 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo static const QString varRegexStr( QString("%1([\\w\\d]+)").arg(sVARPrefix) ); static const QRegularExpression varRegex(varRegexStr, QRegularExpression::CaseInsensitiveOption); - auto createUMLRegexStr = []( ) -> QString - { - QString resultRegex("^("); - - auto finalIter = s_UML_IDs_Map.end(); - --finalIter; - - for( auto it = s_UML_IDs_Map.begin(); it != s_UML_IDs_Map.end(); ++it ) - { - const auto& UML_IDs_MapItem = *it; - - resultRegex.append(UML_IDs_MapItem.second.id_str); - - if(it != finalIter) - { - resultRegex.append("|"); - } - } - - resultRegex.append(QString(")[%1]{0,1}([\\w\\d]*)$").arg(s_UML_ALIAS_DELIMITER)); - - return resultRegex; - }; - - static const QString UMLRegexStr = createUMLRegexStr(); - static const QRegularExpression UMLRegex(UMLRegexStr, QRegularExpression::CaseInsensitiveOption); - auto normalizeRGBItem = [](const int& rgbItem)->int { int normalizationResult = 0; @@ -1688,6 +1822,8 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo tOptional_UML_ID optUML_ID; + tPlotViewIDParameters plotViewIDParameters; + for( const auto& groupNamePart : splitGroupName ) { // parse color @@ -1770,9 +1906,11 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo { QString lowerGroupNamePart = groupNamePart.toLower(); - auto foundColor = sColorsMap.find(lowerGroupNamePart); + const auto& colorsMap = getColorsMap(); + + auto foundColor = colorsMap.find(lowerGroupNamePart); - if(sColorsMap.end() != foundColor) + if(colorsMap.end() != foundColor) { optColor.isSet = true; optColor.color = foundColor->second; @@ -1800,6 +1938,33 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo if(true == bParseUMLData) { // parse UML data + auto createUMLRegexStr = []( ) -> QString + { + QString resultRegex("^("); + + auto finalIter = s_UML_IDs_Map.end(); + --finalIter; + + for( auto it = s_UML_IDs_Map.begin(); it != s_UML_IDs_Map.end(); ++it ) + { + const auto& UML_IDs_MapItem = *it; + + resultRegex.append(UML_IDs_MapItem.second.id_str); + + if(it != finalIter) + { + resultRegex.append("|"); + } + } + + resultRegex.append(QString(")[%1]{0,1}([\\w\\d]*)$").arg(s_UML_ALIAS_DELIMITER)); + + return resultRegex; + }; + + static const QString UMLRegexStr = createUMLRegexStr(); + static const QRegularExpression UMLRegex(UMLRegexStr, QRegularExpression::CaseInsensitiveOption); + QRegularExpressionMatch varMatch = UMLRegex.match(groupNamePart); if(varMatch.hasMatch()) @@ -1814,7 +1979,7 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo if(true == bUML_ID_Parsed) { const auto& key = UML_ID; - auto& value = optUML_ID.optional_UML_IDMap[key].UML_Custom_Value; + auto& pValue = optUML_ID.optional_UML_IDMap[key].pUML_Custom_Value; if(varMatch.lastCapturedIndex() == 2) // if 2 groups found { @@ -1823,7 +1988,46 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo if(true == b_UML_Custom_Value_Found) { - value = capturedString; + pValue = std::make_shared(capturedString); + } + } + } + } + } + } + + if(true == bParsePlotViewData) + { + static const QRegularExpression plotViewRegex = createPlotViewRegex(); + + QRegularExpressionMatch varMatch = plotViewRegex.match(groupNamePart); + + if(varMatch.hasMatch()) + { + bool b_PlotView_ID_Found = varMatch.lastCapturedIndex() >= 1; // if 1 or more groups found + + if(true == b_PlotView_ID_Found) + { + ePlotViewID plotView_ID = ePlotViewID::PLOT_AXIS_RECTANGLE_TYPE; // any value + bool bPlotView_ID_Parsed = parsePlotViewIDFromString( varMatch.captured(1), plotView_ID ); + + if(true == bPlotView_ID_Parsed) + { + const auto& key = plotView_ID; + plotViewIDParameters.plotViewIDParametersMap[key].pPlotViewGroupName = std::make_shared(groupName); + + if(varMatch.lastCapturedIndex() == 2) // if 2 groups found + { + QString parameters = varMatch.captured(2); + bool b_PlotView_Parameters_Found = false == parameters.isEmpty(); // if 2 groups found + + if(true == b_PlotView_Parameters_Found) + { + auto splitParameters = splitPlotViewParameters(parameters); + for(const auto& splitParameter : splitParameters) + { + plotViewIDParameters.plotViewIDParametersMap[key].plotViewSplitParameters.push_back(std::make_shared(splitParameter)); + } } } } @@ -1832,16 +2036,24 @@ tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bo } } + for(auto& pair : plotViewIDParameters.plotViewIDParametersMap) + { + pair.second.optColor = optColor; + } + tRegexScriptingMetadataItemPtr pItem = std::make_shared(); pItem->highlightingColor = optColor; pItem->varName = optVarName; pItem->optionalUML_ID = optUML_ID; + pItem->plotViewIDParameters = plotViewIDParameters; return pItem; } //tRegexScriptingMetadata -bool tRegexScriptingMetadata::parse(const QRegularExpression& regex, bool bParseUMLData) +bool tRegexScriptingMetadata::parse(const QRegularExpression& regex, + bool bParseUMLData, + bool bParsePlotViewData ) { bool bResult = true; @@ -1851,7 +2063,9 @@ bool tRegexScriptingMetadata::parse(const QRegularExpression& regex, bool bParse for(const auto& groupName : groupNames) { - mItemsVec.push_back(parseRegexGroupName(groupName, bParseUMLData)); + mItemsVec.push_back(parseRegexGroupName(groupName, + bParseUMLData, + bParsePlotViewData)); } } else @@ -1867,27 +2081,28 @@ const tRegexScriptingMetadataItemPtrVec& tRegexScriptingMetadata::getItemsVec() return mItemsVec; } -std::pair +tRegexScriptingMetadata::tStatusPair tRegexScriptingMetadata::doesContainConsistentUMLData(bool fillInStringMsg) const { return doesContainConsistentUMLData(fillInStringMsg, tCheckIDs(), true); } -std::pair +tRegexScriptingMetadata::tStatusPair tRegexScriptingMetadata::doesContainConsistentUMLData(bool fillInStringMsg, const tCheckIDs& checkIDs) const { return doesContainConsistentUMLData(fillInStringMsg, checkIDs, false); } -std::pair +tRegexScriptingMetadata::tStatusPair tRegexScriptingMetadata::doesContainConsistentUMLData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool bCheckAll) const { std::pair result; + result.first = false; if(true == fillInStringMsg) { - result.second.append("UML parsing result: "); + result.second.append("UML parsing result:"); } if(false == bCheckAll && true == checkIDs.empty()) @@ -1942,7 +2157,7 @@ tRegexScriptingMetadata::doesContainConsistentUMLData(bool fillInStringMsg, cons if(true == mandatoryUMLElements.empty()) { - break; + break; } } } @@ -2043,7 +2258,7 @@ tRegexScriptingMetadata::doesContainConsistentUMLData(bool fillInStringMsg, cons } } - return result; + return result; } bool tRegexScriptingMetadata::doesContainAnyUMLGroup() const @@ -2070,6 +2285,240 @@ bool tRegexScriptingMetadata::doesContainAnyUMLGroup() const return bResult; } +tRegexScriptingMetadata::tStatusPair +tRegexScriptingMetadata::doesContainConsistentPlotViewData(bool fillInStringMsg, bool checkParameters) const +{ + return doesContainConsistentPlotViewData(fillInStringMsg, tCheckIDs(), true, checkParameters); +} + +tRegexScriptingMetadata::tStatusPair +tRegexScriptingMetadata::doesContainConsistentPlotViewData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool checkParameters) const +{ + return doesContainConsistentPlotViewData(fillInStringMsg, checkIDs, false, checkParameters); +} + +tRegexScriptingMetadata::tStatusPair +tRegexScriptingMetadata::doesContainConsistentPlotViewData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool bCheckAll, bool checkParameters) const +{ + std::pair result; + result.first = false; + + if(true == fillInStringMsg) + { + result.second.append("Plot view parsing result:"); + } + + if(false == bCheckAll && true == checkIDs.empty()) + { + if(true == fillInStringMsg) + { + result.second.append("No groups available. Result is \"false\""); + } + } + else + { + tRegexScriptingMetadataItemPtrVec iterationVec; + + if(true == bCheckAll) + { + iterationVec = mItemsVec; + } + else + { + for(const auto& checkId : checkIDs) + { + if(checkId >= 0 && checkId < mItemsVec.size()) + { + iterationVec.push_back(mItemsVec[checkId]); + } + } + } + + auto checkMandatoryElements = [&iterationVec, &fillInStringMsg]( ePlotViewIDType parameterType, QString& msg ) -> bool + { + bool bResult = false; + + tPlotViewIDsMap mandatoryElements; + + for(const auto& element : sPlotViewIDsMap) + { + if(element.second.id_type == parameterType) + { + mandatoryElements.insert(std::make_pair(element.first, element.second)); + } + } + + for(const auto& pElement : iterationVec) + { + if(nullptr != pElement) + { + if(false == pElement->plotViewIDParameters.plotViewIDParametersMap.empty()) + { + for(const auto& PlotView_IDItem : pElement->plotViewIDParameters.plotViewIDParametersMap) + { + auto foundElement = mandatoryElements.find(PlotView_IDItem.first); + + if(foundElement != mandatoryElements.end()) + { + mandatoryElements.erase(foundElement); + + if(true == mandatoryElements.empty()) + { + bResult = true; + } + } + } + } + } + } + + if(false == mandatoryElements.empty()) + { + bResult = false; + + if(true == fillInStringMsg) + { + // collect warning string + for(const auto& element : mandatoryElements) + { + msg.append(QString(" ").arg(getPlotIDAsString(element.first))); + } + } + } + + return bResult; + }; + + auto checkAllParameters = [&iterationVec, &fillInStringMsg](QString& msg) -> bool + { + bool bResult = true; + + for(const auto& pElement : iterationVec) + { + if(nullptr != pElement) + { + if(false == pElement->plotViewIDParameters.plotViewIDParametersMap.empty()) + { + bool bCheckParametersTmp = checkPlotViewParameters(msg, fillInStringMsg, pElement->plotViewIDParameters.plotViewIDParametersMap); + + if(true == bResult) + { + bResult = bCheckParametersTmp; + } + } + } + } + + return bResult; + }; + + auto uniqueAvailableAxisTypes = getUniqueAvailableAxisTypes(); + + if(uniqueAvailableAxisTypes.find(ePlotViewAxisType::e_GANTT) != uniqueAvailableAxisTypes.end()) + { + bool bMandatoryGanttParametersCheck = checkMandatoryElements(ePlotViewIDType::e_Mandatory_Gantt, result.second); + bool bMandatoryNonGanttParametersCheck = true; + + if(uniqueAvailableAxisTypes.size() > 1) + { + bMandatoryNonGanttParametersCheck = checkMandatoryElements(ePlotViewIDType::e_Mandatory_Non_Gantt, result.second); + } + + if(true == checkParameters) + { + bool bCheckParameters = checkAllParameters(result.second); + result.first = bMandatoryGanttParametersCheck && bMandatoryNonGanttParametersCheck && bCheckParameters; + } + else + { + result.first = bMandatoryGanttParametersCheck && bMandatoryNonGanttParametersCheck; + } + } + else if(false == uniqueAvailableAxisTypes.empty()) + { + bool bMandatoryNonGanttParametersCheck = checkMandatoryElements(ePlotViewIDType::e_Mandatory_Non_Gantt, result.second); + + if(true == checkParameters) + { + bool bCheckParameters = checkAllParameters(result.second); + result.first = bMandatoryNonGanttParametersCheck && bCheckParameters; + } + else + { + result.first = bMandatoryNonGanttParametersCheck; + } + } + } + + return result; +} + +bool tRegexScriptingMetadata::doesContainAnyPlotViewGroup() const +{ + bool bResult = false; + + for(const auto& element : mItemsVec) + { + if(false == element->plotViewIDParameters.plotViewIDParametersMap.empty()) + { + for(const auto& UML_IDItem : element->plotViewIDParameters.plotViewIDParametersMap) + { + auto foundElement = sPlotViewIDsMap.find(UML_IDItem.first); + + if(foundElement != sPlotViewIDsMap.end()) // match found + { + bResult = true; + break; + } + } + } + } + + return bResult; +} + +std::set sAllAxisTypes = +{ + ePlotViewAxisType::e_GANTT, + ePlotViewAxisType::e_LINEAR, + ePlotViewAxisType::e_POINT +}; + +std::set tRegexScriptingMetadata::getUniqueAvailableAxisTypes() const +{ + std::set result; + + for(const auto& item : mItemsVec) + { + const auto& optionalPlot_IDMap = item->plotViewIDParameters.plotViewIDParametersMap; + auto foundItem = optionalPlot_IDMap.find(ePlotViewID::PLOT_AXIS_RECTANGLE_TYPE); + if(foundItem != optionalPlot_IDMap.end()) + { + ePlotViewAxisType axisType = ePlotViewAxisType::e_LINEAR; + auto parameterIndex = getPlotViewParameterIndex(ePlotViewID::PLOT_AXIS_RECTANGLE_TYPE, "axisRectType"); + + if(parameterIndex >= 0 && parameterIndex <= static_cast(foundItem->second.plotViewSplitParameters.size() - 1) ) + { + assert(foundItem->second.plotViewSplitParameters[parameterIndex] != nullptr); + if(true == parseAxisTypeFromString(*foundItem->second.plotViewSplitParameters[parameterIndex], axisType)) + { + result.insert(axisType); + if(result == sAllAxisTypes) + { + break; + } + } + } + } + } + + if(true == result.empty()) + { + result.insert(ePlotViewAxisType::e_LINEAR); + } + + return result; +} ////////////////////////////////////////////////////////// Qt::CheckState V_2_CS( const tDataItem& val ) @@ -2207,11 +2656,6 @@ tDataItem toRegexDataItem(const QVariant& variant, const eRegexFiltersColumn& co return result; } -bool QOptionalColor::operator== ( const QOptionalColor& rhs ) const -{ - return color == rhs.color && isSet == rhs.isSet; -} - bool tColorWrapper::operator< ( const tColorWrapper& rhs ) const { bool bResult; @@ -2262,7 +2706,6 @@ bool tColorWrapper::operator== ( const tColorWrapper& rhs ) const return optColor == rhs.optColor; } - QString rgb2hex(const QColor& color, bool with_head) { QString result; @@ -3021,6 +3464,11 @@ tQStringPtr getDataStrFromMsg(const tMsgId& msgId, const tMsgWrapperPtr &pMsg, e *pStrRes = ""; // no string value provided for this column } break; + case eSearchResultColumn::PlotView_Applicability: + { + *pStrRes = ""; // no string value provided for this column + } + break; case eSearchResultColumn::Last: { *pStrRes = "Unhandled field type!"; @@ -3033,6 +3481,37 @@ tQStringPtr getDataStrFromMsg(const tMsgId& msgId, const tMsgWrapperPtr &pMsg, e return pStrRes; } +QColor getChartColor() +{ + static const std::vector sColors + { + QColor(230, 25, 75), + QColor(60, 180, 75), + QColor(255, 255, 25), + QColor(67, 99, 216), + QColor(245, 130, 49), + QColor(145, 30, 180), + QColor(70, 240, 240), + QColor(240, 50, 230), + QColor(188, 246, 12), + QColor(250, 190, 190), + QColor(0, 128, 128), + QColor(230, 190, 255), + QColor(154, 99, 36), + QColor(255, 250, 200), + QColor(128, 0, 0), + QColor(170, 255, 195), + QColor(255, 216, 177), + QColor(0, 0, 117), + QColor(128, 128, 128), + QColor(99, 243, 163), + QColor(25, 64, 163), + }; + static const int sColorsSize = sColors.size(); + static std::atomic sColorsCounter(0); + return sColors[sColorsCounter++ % sColorsSize]; +} + PUML_PACKAGE_BEGIN(Qt) PUML_CLASS_BEGIN(QThread) PUML_CLASS_END() @@ -3088,3 +3567,18 @@ PUML_PACKAGE_BEGIN(DLT) PUML_CLASS_BEGIN(QDltMsg) PUML_CLASS_END() PUML_PACKAGE_END() + +PUML_PACKAGE_BEGIN(qcustomplot) + PUML_CLASS_BEGIN(QCustomPlot) + PUML_INHERITANCE(QWidget, extends) + PUML_CLASS_END() + PUML_CLASS_BEGIN(QCPLegend) + PUML_INHERITANCE(QObject, extends) + PUML_CLASS_END() + PUML_CLASS_BEGIN(QCPAxisRect) + PUML_INHERITANCE(QObject, extends) + PUML_CLASS_END() + PUML_CLASS_BEGIN(QCPGraph) + PUML_INHERITANCE(QObject, extends) + PUML_CLASS_END() +PUML_PACKAGE_END() diff --git a/dltmessageanalyzerplugin/src/common/Definitions.hpp b/dltmessageanalyzerplugin/src/common/Definitions.hpp index fd1c5a38..d4225f8e 100644 --- a/dltmessageanalyzerplugin/src/common/Definitions.hpp +++ b/dltmessageanalyzerplugin/src/common/Definitions.hpp @@ -6,8 +6,8 @@ #ifndef DEFINITIONS_HPP #define DEFINITIONS_HPP -#include "memory" -#include "set" +#include +#include #include "QMap" #include "QString" @@ -15,12 +15,17 @@ #include "QMetaType" #include "QColor" #include "QPair" +#include "TOptional.hpp" #include "../common/variant/variant.hpp" +#include "BaseDefinitions.hpp" +#include "PlotDefinitions.hpp" + //#define DEBUG_BUILD -extern const std::map sColorsMap; +const std::map& getColorsMap(); +const std::list& getColorsList(); extern const QString sVARPrefix; extern const QString sRegexScriptingDelimiter; @@ -81,18 +86,7 @@ typedef std::shared_ptr tPatternsModelPtr; extern const QString sDefaultStatusText; extern const QString sDefaultRegexFileName; -typedef std::shared_ptr tQStringPtr; - -struct tQStringPtrWrapper -{ - tQStringPtrWrapper(); - tQStringPtrWrapper(const tQStringPtr& pString_); - bool operator== ( const tQStringPtrWrapper& rVal ) const; - bool operator< ( const tQStringPtrWrapper& rVal ) const; - tQStringPtr pString = nullptr; -}; -Q_DECLARE_METATYPE(tQStringPtrWrapper) typedef int tMsgId; extern const tMsgId INVALID_MSG_ID; @@ -184,6 +178,7 @@ typedef std::set tIntRangeSet; enum class eSearchResultColumn : int { UML_Applicability = 0, + PlotView_Applicability, Index, Time, Timestamp, @@ -371,14 +366,6 @@ struct tFoundMatch Q_DECLARE_METATYPE( const tFoundMatch* ) -struct QOptionalColor -{ - bool isSet; - QColor color; - bool operator== ( const QOptionalColor& rhs ) const; -}; -typedef QVector QOptionalColorVec; - struct tColorWrapper { QOptionalColor optColor; @@ -418,7 +405,7 @@ struct tOptional_UML_ID_Item { // optional string, which can be assigned by the user in form of e.g. . // In above case this variable will be filled in with "myService" value - QString UML_Custom_Value; + tQStringPtr pUML_Custom_Value; }; typedef std::map tOptional_UML_IDMap; @@ -445,6 +432,9 @@ struct tRegexScriptingMetadataItem // UML_ID data tOptional_UML_ID optionalUML_ID; + + // PlotView data + tPlotViewIDParameters plotViewIDParameters; }; typedef std::shared_ptr tRegexScriptingMetadataItemPtr; @@ -461,22 +451,34 @@ Q_DECLARE_METATYPE( tRegexScriptingMetadataItemPtr ) */ struct tRegexScriptingMetadata { - bool parse(const QRegularExpression& regex, bool bParseUMLData); + typedef std::pair tStatusPair; + bool parse(const QRegularExpression& regex, + bool bParseUMLData, + bool bParsePlotViewData); const tRegexScriptingMetadataItemPtrVec& getItemsVec() const; typedef std::set tCheckIDs; - std::pair doesContainConsistentUMLData(bool fillInStringMsg) const; - std::pair doesContainConsistentUMLData(bool fillInStringMsg, const tCheckIDs& checkIDs) const; + tStatusPair doesContainConsistentUMLData(bool fillInStringMsg) const; + tStatusPair doesContainConsistentUMLData(bool fillInStringMsg, const tCheckIDs& checkIDs) const; bool doesContainAnyUMLGroup() const; + tStatusPair doesContainConsistentPlotViewData(bool fillInStringMsg, bool checkParameters) const; + tStatusPair doesContainConsistentPlotViewData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool checkParameters) const; + bool doesContainAnyPlotViewGroup() const; private: - std::pair doesContainConsistentUMLData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool bCheckAll) const; + tStatusPair doesContainConsistentUMLData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool bCheckAll) const; + tStatusPair doesContainConsistentPlotViewData(bool fillInStringMsg, const tCheckIDs& checkIDs, bool bCheckAll, bool checkParameters) const; + std::set getUniqueAvailableAxisTypes() const; + typedef TOptional tOptionalStatusPair; + typedef TOptional tOptionalBool; private: tRegexScriptingMetadataItemPtrVec mItemsVec; }; Q_DECLARE_METATYPE(tRegexScriptingMetadata) -tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, bool bParseUMLData ); +tRegexScriptingMetadataItemPtr parseRegexGroupName( const QString& groupName, + bool bParseUMLData, + bool bParsePlotViewData ); //////////////////////////////////////////////////////////// @@ -523,9 +525,11 @@ struct tStringCoverageItem typedef std::map tStringCoverageMap; +// UML data, parsed from each processed string + struct tUMLDataItem { - QString UML_Custom_Value; + tQStringPtr pUML_Custom_Value; tStringCoverageMap stringCoverageMap; }; @@ -540,6 +544,26 @@ struct tUMLInfo bool bContains_Req_Resp_Ev = false; }; +// Plot view data, that is parsed from each processed string + +struct tPlotViewDataItem +{ + QOptionalColor optColor; + tQStringPtr pPlotViewGroupName; + tQStringPtrVec plotViewSplitParameters; + tStringCoverageMap stringCoverageMap; +}; + +typedef std::vector tPlotViewDataItemVec; + +typedef std::map tPlotViewDataMap; +struct tPlotViewInfo +{ + bool bPlotViewConstraintsFulfilled = false; + bool bApplyForPlotCreation = false; + tPlotViewDataMap plotViewDataMap; +}; + struct tItemMetadata { tItemMetadata(); @@ -563,6 +587,16 @@ struct tItemMetadata tUpdateUMLInfoResult updateUMLInfo(const tFoundMatches& foundMatches, const tRegexScriptingMetadata& regexScriptingMetadata, tTreeItemSharedPtr pTree = nullptr); + + struct tUpdatePlotViewInfoResult + { + tTreeItemSharedPtr pTreeItem; + }; + + tUpdatePlotViewInfoResult updatePlotViewInfo(const tFoundMatches& foundMatches, + const tRegexScriptingMetadata& regexScriptingMetadata, + tTreeItemSharedPtr pTree = nullptr); + tMsgId msgId; tMsgId msgIdFiltered; tHighlightingInfoMulticolor highlightingInfoMultiColor; @@ -571,6 +605,7 @@ struct tItemMetadata unsigned int msgSize; unsigned int timeStamp; tUMLInfo UMLInfo; + tPlotViewInfo plotViewInfo; }; typedef QPair tProcessingStringItem; @@ -717,4 +752,9 @@ bool isDarkMode(); */ tQStringPtr getDataStrFromMsg(const tMsgId& msgId, const tMsgWrapperPtr &pMsg, eSearchResultColumn field); +/** + * @brief getChartColor - get color for chart + */ +QColor getChartColor(); + #endif // DEFINITIONS_HPP diff --git a/dltmessageanalyzerplugin/src/common/PCRE/PCREHelper.cpp b/dltmessageanalyzerplugin/src/common/PCRE/PCREHelper.cpp index 3ea40633..3aab39d9 100644 --- a/dltmessageanalyzerplugin/src/common/PCRE/PCREHelper.cpp +++ b/dltmessageanalyzerplugin/src/common/PCRE/PCREHelper.cpp @@ -138,7 +138,9 @@ class CParseFiltersViewVisitor : pcre_parser::PCREBaseVisitor { currentParsingItem.groupName = QString::fromStdString(text); - auto pRegexMetadataItem = parseRegexGroupName(QString::fromStdString(text), false); + auto pRegexMetadataItem = parseRegexGroupName(QString::fromStdString(text), + false, + false); if(nullptr != pRegexMetadataItem) { diff --git a/dltmessageanalyzerplugin/src/common/PlotDefinitions.cpp b/dltmessageanalyzerplugin/src/common/PlotDefinitions.cpp new file mode 100644 index 00000000..151cd2fa --- /dev/null +++ b/dltmessageanalyzerplugin/src/common/PlotDefinitions.cpp @@ -0,0 +1,1063 @@ +/** + * @file PlotDefinitions.cpp + * @author vgoncharuk + * @brief Implementation of the PlotDefinitions class + */ + +#include + +#include + +#include "PlotDefinitions.hpp" + +//////// PLOT_IDENTIFIERS //////// +const QString s_PLOT_AXIS_RECTANGLE_TYPE = "PARType"; +const QString s_PLOT_X_MAX = "PXMx"; +const QString s_PLOT_X_MIN = "PXMn"; +const QString s_PLOT_Y_MAX = "PYMx"; +const QString s_PLOT_Y_MIN = "PYMn"; +const QString s_PLOT_X_NAME = "PXN"; +const QString s_PLOT_Y_NAME = "PYN"; +const QString s_PLOT_X_UNIT = "PXU"; +const QString s_PLOT_Y_UNIT = "PYU"; +const QString s_PLOT_X_DATA = "PXData"; +const QString s_PLOT_X_TIMESTAMP = "PXT"; +const QString s_PLOT_Y_DATA = "PYData"; +const QString s_PLOT_Y_TIMESTAMP = "PYT"; +const QString s_PLOT_GRAPH_NAME = "PGN"; +const QString s_PLOT_GRAPH_METADATA = "PGMD"; +const QString s_PLOT_GANTT_EVENT = "PGE"; +const QString s_PLOT_PARAMETER_DELIMITER = "_"; + +QString tPlotViewIDItem::getParametersDescription() +{ + QString result = id_str; + + if(false == parameters.empty()) + { + result.append(" + _ + "); + } + + for(auto it = parameters.begin(); it != parameters.end(); ++it) + { + switch((*it)->type) + { + case ePlotViewParameterType::e_Mandatory: + { + result.append(QString("<%1>").arg((*it)->name)); + } + break; + case ePlotViewParameterType::e_Optional: + { + result.append(QString("[%1]").arg((*it)->name)); + } + break; + } + + if(it < parameters.end() - 1) + { + result.append(" + _ + "); + } + } + return result; +} + +void tPlotViewIDItem::addParameter(const tPlotViewIDParameterPtr& parameter) +{ + parameters.push_back(parameter); + + switch(parameter->type) + { + case ePlotViewParameterType::e_Mandatory: + mandatoryParameters.push_back(parameter); + break; + case ePlotViewParameterType::e_Optional: + optionalParameters.push_back(parameter); + break; + } +} + +const tPlotViewIDParameterPtrVec& tPlotViewIDItem::getParameters() const +{ + return parameters; +} + +const tPlotViewIDParameterPtrVec& tPlotViewIDItem::getMandatoryParameters() const +{ + return mandatoryParameters; +} + +const tPlotViewIDParameterPtrVec& tPlotViewIDItem::getOptionalParameters() const +{ + return optionalParameters; +} + +static tPlotViewIDsMap createPlotIDsMap() +{ + tPlotViewIDsMap result; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_AXIS_RECTANGLE_TYPE; + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectType"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + if(value.compare( "GANTT", Qt::CaseInsensitive ) != 0 && + value.compare( "BAR", Qt::CaseInsensitive ) != 0 && + value.compare( "POINT", Qt::CaseInsensitive ) != 0 && + value.compare( "LINEAR", Qt::CaseInsensitive ) != 0) + { + if(fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. Expected values for the " + "'axisRectType' parameter are: GANTT, BAR, POINT, LINEAR.").arg(value)); + } + bResult = false; + } + return bResult; + }; + item.addParameter(pParameter); + } + + item.description = QString("Plot axis rectangle type. %1. " + "PARType_CPUC_LINEAR. Type of the specific plot axis rectangle. " + "Supported types are - GANNT, BAR, POINT, LINEAR. " + "If not specified, the LINEAR value is used. " + "If multiple values appear - the 'last win' strategy is applied.").arg(item.getParametersDescription()); + + result.insert(std::make_pair(ePlotViewID::PLOT_AXIS_RECTANGLE_TYPE, item)); + } + + auto formMinMaxParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "integer_part_value"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toInt(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to integer.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "real_part_value"; + pParameter->type = ePlotViewParameterType::e_Optional; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toInt(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to integer.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "neg"; + pParameter->type = ePlotViewParameterType::e_Optional; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + if(value.compare( "neg", Qt::CaseInsensitive ) != 0) + { + if(fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. Expected value for the " + "'neg' parameter is: neg.").arg(value)); + } + bResult = false; + } + return bResult; + }; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_X_MAX; + formMinMaxParameters(item); + item.description = QString("Plot X Max. %1. " + "Sets the maximum visible value on axis X of the specified axis rectangle. " + "Last win. If not set, then the maximum value will be derived from the provided data. " + "You can omit 'real_part_value' if not needed. " + "Use the 'neg' keyword as the last parameter to specify negative values. " + "Not applicable to Gantt charts.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_X_MAX, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_X_MIN; + formMinMaxParameters(item); + item.description = QString("Plot X Min. %1. " + "Sets the minimum visible value on axis X of the specified axis rectangle. " + "Last win. If not set, then the minimum value will be derived from the provided data. " + "You can omit 'real_part_value' if not needed. " + "Use the 'neg' keyword as the last parameter to specify negative values. " + "Not applicable to Gantt charts.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_X_MIN, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_Y_MAX; + formMinMaxParameters(item); + item.description = QString("Plot Y Max. %1. " + "Sets the maximum visible value on axis Y of the specified axis rectangle. " + "Last win. If not set, then the maximum value will be derived from the provided data. " + "You can omit 'real_part_value' if not needed. " + "Use the 'neg' keyword as the last parameter to specify negative values. " + "Not applicable to Gantt charts.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_Y_MAX, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_Y_MIN; + formMinMaxParameters(item); + item.description = QString("Plot Y Min. %1. " + "Sets the minimum visible value on axis Y of the specified axis rectangle. " + "Last win. If not set, then the minimum value will be derived from the provided data. " + "You can omit 'real_part_value' if not needed. " + "Use the 'neg' keyword as the last parameter to specify negative values. " + "Not applicable to Gantt charts.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_Y_MIN, item)); + } + + auto formNameParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "name"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_X_NAME; + formNameParameters(item); + item.description = QString("Plot X-axis name. %1. " + "Sets plot X-axis name for the specified plot axis rectangle. " + "Use camelStyleNaming. E.g. 'camelStyleNaming' will be represented as \"Camel style naming\" inside the diagram. " + "If not set, the default 'Timestamp' value is used.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_X_NAME, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_Y_NAME; + formNameParameters(item); + item.description = QString("Plot Y-axis name. %1. " + "Sets plot Y-axis name for the specified plot axis rectangle. " + "Use camelStyleNaming. E.g. 'camelStyleNaming' will be represented as 'Camel style naming' inside the diagram. " + "If not set - remains empty.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_Y_NAME, item)); + } + + auto formUnitParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "unit"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_X_UNIT; + formUnitParameters(item); + item.description = QString("Plot X-axis unit. %1. " + "Sets the plot X-axis unit for the . " + "Use camelStyleNaming. E.g. 'camelStyleNaming' will be represented as 'Camel style naming' inside the diagram. " + "If not set, then the 'seconds' default value is used, as the X-axis is usually used to represent the time, " + "and in dlt, the timestamp is measured in seconds ( with real part, " + "representing milliseconds, microseconds, etc. )").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_X_UNIT, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_Y_UNIT; + formUnitParameters(item); + item.description = QString("Plot Y-axis unit. %1. " + "Sets plot Y-axis name for the specified plot axis rectangle. Use camelStyleNaming. " + "E.g. 'camelStyleNaming' will be represented as 'Camel style naming' inside the diagram. " + "If not set - remains empty.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_Y_UNIT, item)); + } + + auto formDataParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "graphId"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toInt(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to integer.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "value"; + pParameter->type = ePlotViewParameterType::e_Optional; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toDouble(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to double.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_X_DATA; + formDataParameters(item); + item.description = QString("Plot axis X data. %1. " + "The content of this regex group contains the data, that will be placed at axis X " + "of the specified graph id and axis rectangle. The data of EACH VALUE should " + "be convertible from the string to the float or the date-time. " + "For conversion to date-time see PXT parameter. " + "The graphId parameter should be convertible to an integer. If an optional 'value' " + "parameter was spcified, the captured data would be ignored. The 'value' param will " + "be NOT considered as the 'time', even if the PXT data was provided." + "Optional. If not set, the timestamp of each involved DLT message would be used. " + "This parameter can be used for the Gantt chart to get the timestamp from the " + "message's payload.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_X_DATA, item)); + } + + auto formTimeParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "timeFormat"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static const QString allowedCharacters = "0-9wyMdHmsf"; + QRegularExpression re("^[" + allowedCharacters + "]+$"); + + bool isMatch = re.match(value).hasMatch(); + if(false == isMatch) + { + + bResult = false; + if(true == fillInStringMsg) + { + QString allRedundantChars = value; + allRedundantChars.remove(QRegularExpression("[" + allowedCharacters + "]")); + QString uniqueRedundantChars; + for (QChar c : allRedundantChars) + { + if (!uniqueRedundantChars.contains(c)) + uniqueRedundantChars.append(c); + } + + msg.append(QString("Provided literal should contain only \"0-9wyMdHmsf\" characters. " + "The \"%1\" characters are redundant.").arg(uniqueRedundantChars)); + } + } + + return bResult; + }; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_X_TIMESTAMP; + formTimeParameters(item); + item.description = QString("Plot X-axis time format. %1. " + "Specifies, how to decode the date and time from the string out of the PXData. " + "E.g. the '05-24 18:25:01.439' time format can be decoded with PXT_2Mw2dw2Hw2mw2sw3f. " + "y - year. M - month. d - day. H - hour. m - minute. s - second. w - any delimiter symbol. " + "f - a real part of the second ( milliseconds, microseconds, etc. ). " + "Useful for custom imported logs, like Android logcat traces, " + "which do not have proper dlt timestamp. Optional. If not specified - " + "there would be no attempt to decode PXData as time.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_X_TIMESTAMP, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Mandatory_Non_Gantt; + item.id_str = s_PLOT_Y_DATA; + formDataParameters(item); + item.description = QString("Plot Y-axis time format. %1. " + "The content of this regex group contains the data, that will be placed " + "at axis Y of the specified graph id and axis rectangle. The data of " + "EACH VALUE should be convertible from the string to the float or the date-time. " + "For conversion to date-time see PYT parameter. The graphId parameter should be " + "convertible to an integer. If an optional 'value' " + "parameter was spcified, the captured data would be ignored. The 'value' param will " + "be NOT considered as the 'time', even if the PYT data was provided." + "Mandatory for plots in which 'PARType' is not equal to 'GANTT'.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_Y_DATA, item)); + } + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_Y_TIMESTAMP; + formTimeParameters(item); + item.description = QString("Plot Y-axis time format. %1. " + "Specifies, how to decode the date and time from the string out of the PYData. " + "E.g. the '05-24 18:25:01.439' time format can be decoded with PYT_2Mw2dw2Hw2mw2sw3f. " + "y - year. M - month. d - day. H - hour. m - minute. s - second. w - any delimiter symbol. " + "f - a real part of the second ( milliseconds, microseconds, etc. ). Useful for custom imported logs, " + "like Android logcat traces, which do not have proper dlt timestamp. " + "If not specified - there would be no attempt to decode PYData as time.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_Y_TIMESTAMP, item)); + } + + auto formGraphNameParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "graphId"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toInt(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to integer.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "name"; + pParameter->type = ePlotViewParameterType::e_Optional; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Mandatory_Non_Gantt; + item.id_str = s_PLOT_GRAPH_NAME; + formGraphNameParameters(item); + item.description = QString("Plot graph name. %1." + "Specifies the graph name for the specified graph id. If custom_value parameter is not specified, " + "then graph names would be derived from the capture content, and a separate graph on the " + "plot would be created for each unique captured graph name. If custom_value parameter is " + "specified, then all names of the specified graphId would be the hard-coded ones, and only " + "one graph would be produced on the plot for that graph id.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_GRAPH_NAME, item)); + } + + auto formGraphMetadataParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "graphId"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toInt(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to integer.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "key"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "value"; + pParameter->type = ePlotViewParameterType::e_Optional; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Optional; + item.id_str = s_PLOT_GRAPH_METADATA; + formGraphMetadataParameters(item); + item.description = QString("Plot graph metadata. %1." + "Declares a metadata item, which ( if found for a specific plot point ) " + "will be added to point's representation when it is selected by the user. " + "Optional. One or more. If 'value' parameter is not explicitly set, then " + "captured data will be set as 'value'. If multiple 'value'-s are found in " + "the analyzed string for the same 'key' - they will be concatenated. That " + "includes both captured and explicitly set 'value'-s.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_GRAPH_METADATA, item)); + } + + auto formGanttParameters = [](tPlotViewIDItem& item) + { + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "axisRectName"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "graphId"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + static_cast(value.toInt(&bResult)); + if(false == bResult) + { + if(true == fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. It is not convertible to integer.").arg(value)); + } + } + return bResult; + }; + item.addParameter(pParameter); + } + + { + tPlotViewIDParameterPtr pParameter = std::make_shared(); + pParameter->name = "eventType"; + pParameter->type = ePlotViewParameterType::e_Mandatory; + pParameter->validationFunction = [](const QString&, + ePlotViewParameterType, + const QString& value, + QString& msg, + bool fillInStringMsg) + { + bool bResult = true; + QString lowerValue = value.toLower(); + if(lowerValue.compare( "start", Qt::CaseInsensitive ) != 0 && + lowerValue.compare( "stop", Qt::CaseInsensitive ) != 0) + { + if(fillInStringMsg) + { + msg.append(QString("Wrong literal '%1' provided. Expected values for the " + "'eventType' parameter are: 'start' or 'end'.").arg(value)); + } + bResult = false; + } + return bResult; + }; + item.addParameter(pParameter); + } + }; + + { + tPlotViewIDItem item; + item.id_type = ePlotViewIDType::e_Mandatory_Gantt; + item.id_str = s_PLOT_GANTT_EVENT; + formGanttParameters(item); + item.description = QString("Declares event of a certain type ( either \"start\" or \"end\" ). " + "Used to identify start and end points of different events, which should " + "be represented on the Gantt chart. " + "Mandatory. One or more.").arg(item.getParametersDescription()); + result.insert(std::make_pair(ePlotViewID::PLOT_GANTT_EVENT, item)); + } + + return result; +} + +const tPlotViewIDsMap sPlotViewIDsMap = createPlotIDsMap(); + +QString getPlotIDAsString( const ePlotViewID& val ) +{ + QString result; + + auto foundValue = sPlotViewIDsMap.find(val); + + if(foundValue != sPlotViewIDsMap.end()) + { + result = foundValue->second.id_str; + } + + return result; +} + +bool parsePlotViewIDFromString( const QString& data, ePlotViewID& val ) +{ + bool bResult = false; + + if(false == data.isEmpty()) + { + for(const auto& item : sPlotViewIDsMap) + { + if( data.compare(item.second.id_str, Qt::CaseInsensitive) == 0 ) + { + val = item.first; + bResult = true; + break; + } + } + } + + return bResult; +} + +QString getPlotIDTypeAsString( const ePlotViewIDType& val ) +{ + QString result; + + switch( val ) + { + case ePlotViewIDType::e_Optional: + { + result = "optional"; + } + break; + case ePlotViewIDType::e_Mandatory_Non_Gantt: + { + result = "mandatory_non_gantt"; + } + break; + case ePlotViewIDType::e_Mandatory_Gantt: + { + result = "mandatory_gantt"; + } + break; + } + + return result; +} + +QString getPlotViewParameterTypeAsString( const ePlotViewParameterType& val ) +{ + QString result; + + switch( val ) + { + case ePlotViewParameterType::e_Optional: + { + result = "optional"; + } + break; + case ePlotViewParameterType::e_Mandatory: + { + result = "mandatory"; + } + break; + } + + return result; +} + +QString getAxisTypeAsString( const ePlotViewAxisType& val ) +{ + QString result; + + switch( val ) + { + case ePlotViewAxisType::e_GANTT: + { + result = "Gantt"; + } + break; + case ePlotViewAxisType::e_POINT: + { + result = "Point"; + } + break; + case ePlotViewAxisType::e_LINEAR: + { + result = "Linear"; + } + break; + } + + return result; +} + +bool parseAxisTypeFromString( const QString& data, ePlotViewAxisType& val ) +{ + bool bResult = false; + + if( data.compare("Gantt", Qt::CaseInsensitive) == 0 ) + { + val = ePlotViewAxisType::e_GANTT; + bResult = true; + } + else if( data.compare("Point", Qt::CaseInsensitive) == 0 ) + { + val = ePlotViewAxisType::e_POINT; + bResult = true; + } + else if( data.compare("Linear", Qt::CaseInsensitive) == 0 ) + { + val = ePlotViewAxisType::e_LINEAR; + bResult = true; + } + + return bResult; +} + +QRegularExpression createPlotViewRegex() +{ + auto createPlotViewRegexStr = []( ) -> QString + { + QString resultRegex("^("); + + auto finalIter = sPlotViewIDsMap.end(); + --finalIter; + + for( auto it = sPlotViewIDsMap.begin(); it != sPlotViewIDsMap.end(); ++it ) + { + const auto& UML_IDs_MapItem = *it; + + resultRegex.append(UML_IDs_MapItem.second.id_str); + + if(it != finalIter) + { + resultRegex.append("|"); + } + } + + resultRegex.append(QString(")[%1]{0,1}([\\w\\d]*)$").arg(s_PLOT_PARAMETER_DELIMITER)); + + return resultRegex; + }; + + const QString plotViewRegexStr = createPlotViewRegexStr(); + return QRegularExpression (plotViewRegexStr, QRegularExpression::CaseInsensitiveOption); +} + +bool checkPlotViewParameters(QString& errorMsg, bool fillInStringMsg, const tPlotViewIDParametersMap& plotViewIDParametersMap) +{ + bool bResult = true; + + for(const auto& pair : plotViewIDParametersMap) + { + const auto& plotViewId = pair.first; + bool bResultTmp = checkPlotViewParameter(errorMsg, + fillInStringMsg, + plotViewId, + pair.second.pPlotViewGroupName, + pair.second.plotViewSplitParameters); + if(true == bResult) + { + bResult = bResultTmp; + } + } + + return bResult; +} + +bool checkPlotViewParameter(QString& errorMsg, + bool fillInStringMsg, + ePlotViewID plotViewId, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& plotViewSplitParameters) +{ + bool bResult = true; + + auto foundPlotID = sPlotViewIDsMap.find(plotViewId); + + if(foundPlotID != sPlotViewIDsMap.end()) + { + assert(pPlotViewGroupName != nullptr); + + const auto& mandatoryParameters = foundPlotID->second.getMandatoryParameters(); + int32_t mandatoryParametersDiff = static_cast(mandatoryParameters.size()) - static_cast(plotViewSplitParameters.size()); + + const auto& parameters = foundPlotID->second.getParameters(); + int32_t parametersDiff = static_cast(parameters.size()) - static_cast(plotViewSplitParameters.size()); + + if(mandatoryParametersDiff > 0) + { + if(true == fillInStringMsg) + { + errorMsg.append(QString(" <'%1' has").arg(*pPlotViewGroupName)); + for(std::size_t i = plotViewSplitParameters.size(); i < mandatoryParameters.size(); ++i) + { + errorMsg.append(QString(" '%1'").arg(mandatoryParameters[i]->name)); + if(i < mandatoryParameters.size() - 1) + { + errorMsg.append(" and"); + } + } + errorMsg.append(QString(mandatoryParametersDiff > 1 ? " mandatory parameters" : " mandatory parameter" ) + " missing>"); + } + bResult = false; + } + else if(parametersDiff < 0) + { + if(true == fillInStringMsg) + { + errorMsg.append(QString(" <'%1' has '%2' parameters. Expected maximum number of parameters - '%3'>") + .arg(*pPlotViewGroupName).arg(plotViewSplitParameters.size()).arg(parameters.size())); + } + bResult = false; + } + else + { + size_t paramCounter = 0; + + for(const auto& pParameter : parameters) + { + if(paramCounter >= plotViewSplitParameters.size()) + { + break; + } + + if(pParameter->validationFunction) + { + const auto& pPlotViewParameter = plotViewSplitParameters[paramCounter]; + assert(pPlotViewParameter != nullptr); + + QString subMsg; + bool bResultTmp = pParameter->validationFunction(pParameter->name, pParameter->type, *pPlotViewParameter, subMsg, fillInStringMsg); + if(true == bResult) + { + bResult = bResultTmp; + } + + if(false == bResult) + { + if(true == fillInStringMsg) + { + errorMsg.append(QString(" <'%1'. Parameter '%2' did not pass validation: \"%3\"").arg(*pPlotViewGroupName, pParameter->name, subMsg)); + } + } + } + ++paramCounter; + } + } + } + + return bResult; +} + +QStringList splitPlotViewParameters(const QString& parameters) +{ + return parameters.split(s_PLOT_PARAMETER_DELIMITER, Qt::SkipEmptyParts); +} + +int32_t getPlotViewParameterIndex(ePlotViewID plotViewID, const QString& parameterName) +{ + int32_t result = -1; + + auto foundPlotViewId = sPlotViewIDsMap.find(plotViewID); + + if(foundPlotViewId != sPlotViewIDsMap.end()) + { + const auto& parameters = foundPlotViewId->second.getParameters(); + auto foundParameter = std::find_if(parameters.begin(), parameters.end(), + [¶meterName](const tPlotViewIDParameterPtr pParameter) + { + if(pParameter) + { + return pParameter->name.compare(parameterName, Qt::CaseInsensitive) == 0; + } + else + { + return false; + } + }); + + if(foundParameter != parameters.end()) + { + result = foundParameter - parameters.begin(); + } + } + + return result; +} + +bool stringsToDouble(double& res, const QString& intPartStr, const QString fracPartStr) +{ + bool bResult = false; + + bool bIsInt = false; + int32_t intPart = intPartStr.toInt(&bIsInt); + + if(true == bIsInt) + { + int32_t fracPart = fracPartStr.toInt(&bIsInt); + if(true == bIsInt) + { + int32_t fracPartLen = fracPartStr.length(); + res = intPart + static_cast(fracPart) / pow(10, fracPartLen); + bResult = true; + } + } + + return bResult; +} + +const tPlotViewIDItem getPlotViewIDItem(ePlotViewID plotViewID) +{ + const auto& foundPlotViewIDItem = sPlotViewIDsMap.find(plotViewID); + assert(foundPlotViewIDItem != sPlotViewIDsMap.end()); + return foundPlotViewIDItem->second; +} diff --git a/dltmessageanalyzerplugin/src/common/PlotDefinitions.hpp b/dltmessageanalyzerplugin/src/common/PlotDefinitions.hpp new file mode 100644 index 00000000..f4939baa --- /dev/null +++ b/dltmessageanalyzerplugin/src/common/PlotDefinitions.hpp @@ -0,0 +1,863 @@ +/** + * @file PlotDefinitions.hpp + * @author vgoncharuk + * @brief Declaration of the PlotDefinitions.hpp class + */ +#ifndef PLOT_DEFINITIONS_HPP +#define PLOT_DEFINITIONS_HPP + +#include +#include +#include +#include +#include + +#include "TOptional.hpp" +#include "BaseDefinitions.hpp" + +#include "QString" +#include "QStringList" +#include "QColor" + +////////////////////// PLOT DEFINITIONS ////////////////////// +typedef double tPlotData; +typedef std::vector tPlotDataVec; + +typedef tQStringPtrWrapper tPlotGraphMetadataKey; +typedef tQStringPtrWrapper tPlotGraphMetadataValue; +typedef std::unordered_map tPlotGraphMetadataMap; + +enum class ePlotViewID +{ + PLOT_AXIS_RECTANGLE_TYPE = 0, + PLOT_X_MAX, + PLOT_X_MIN, + PLOT_Y_MAX, + PLOT_Y_MIN, + PLOT_X_NAME, + PLOT_Y_NAME, + PLOT_X_UNIT, + PLOT_Y_UNIT, + PLOT_GRAPH_NAME, // this enum entry should have less value than all which have graph id parameter + PLOT_GRAPH_METADATA, + PLOT_X_TIMESTAMP, // this enum entry should have less value than PLOT_X_DATA + PLOT_X_DATA, + PLOT_Y_TIMESTAMP, // this enum entry should have less value than PLOT_Y_DATA + PLOT_Y_DATA, + PLOT_GANTT_EVENT +}; + +QString getPlotIDAsString( const ePlotViewID& val ); +bool parsePlotViewIDFromString( const QString& data, ePlotViewID& val ); + +///////////////tPlotViewIDParameters//////////////// +/* + * All declarations, related to the tPlotViewIDParameters structure. + * This one is parsed from the regex + */ +struct tPlotViewIDParametersItem +{ + QOptionalColor optColor; + tQStringPtr pPlotViewGroupName; + tQStringPtrVec plotViewSplitParameters; +}; + +typedef std::map tPlotViewIDParametersMap; + +struct tPlotViewIDParameters +{ + tPlotViewIDParametersMap plotViewIDParametersMap; +}; +///////////////tPlotViewIDParameters ( end ) /////// + +enum class ePlotViewIDType +{ + e_Optional, + e_Mandatory_Non_Gantt, + e_Mandatory_Gantt +}; + +QString getPlotIDTypeAsString( const ePlotViewIDType& val ); + +enum class ePlotViewParameterType +{ + e_Optional, + e_Mandatory +}; + +QString getPlotViewParameterTypeAsString( const ePlotViewParameterType& val ); + +typedef std::function + tParameterValidationFunc; + +struct tPlotViewIDparameter +{ + QString name; + ePlotViewParameterType type; + tParameterValidationFunc validationFunction; +}; + +typedef std::shared_ptr tPlotViewIDParameterPtr; +typedef std::vector tPlotViewIDParameterPtrVec; + +struct tPlotViewIDItem +{ + ePlotViewIDType id_type; + QString id_str; + QString description; + + QString getParametersDescription(); + void addParameter(const tPlotViewIDParameterPtr& parameter); + const tPlotViewIDParameterPtrVec& getParameters() const; + const tPlotViewIDParameterPtrVec& getMandatoryParameters() const; + const tPlotViewIDParameterPtrVec& getOptionalParameters() const; + +private: + tPlotViewIDParameterPtrVec parameters; + tPlotViewIDParameterPtrVec mandatoryParameters; + tPlotViewIDParameterPtrVec optionalParameters; +}; + +typedef std::map tPlotViewIDsMap; +extern const tPlotViewIDsMap sPlotViewIDsMap; +////////////////////// PLOT DEFINITIONS (END) //////////////// + +enum class ePlotViewAxisType +{ + e_GANTT = 0, + e_POINT, + e_LINEAR +}; + +QString getAxisTypeAsString( const ePlotViewAxisType& val ); +bool parseAxisTypeFromString( const QString& data, ePlotViewAxisType& val ); + +QRegularExpression createPlotViewRegex(); +bool checkPlotViewParameters(QString& errorMsg, bool fillInStringMsg, const tPlotViewIDParametersMap& plotViewIDParametersMap); +bool checkPlotViewParameter(QString& errorMsgs, + bool fillInStringMsg, + ePlotViewID plotViewId, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& plotViewSplitParameters); +QStringList splitPlotViewParameters(const QString& parameters); +int32_t getPlotViewParameterIndex(ePlotViewID plotViewID, const QString& parameterName); + +bool stringsToDouble(double& res, const QString& intPartStr, const QString fracPartStr); + +const tPlotViewIDItem getPlotViewIDItem(ePlotViewID plotViewID); + +// parameters parsing + +template +struct tPlotParametersParser; + +template<> +struct tPlotParametersParser +{ + const ePlotViewID plotViewId = ePlotViewID::PLOT_AXIS_RECTANGLE_TYPE; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + ePlotViewAxisType axisRectType = ePlotViewAxisType::e_LINEAR; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + ePlotViewAxisType axisType = ePlotViewAxisType::e_LINEAR; + assert(splitParameters[1] != nullptr); + const auto& axisTypeStr = *splitParameters[1]; + if(true == parseAxisTypeFromString(axisTypeStr, axisType)) + { + result.axisRectType = axisType; + result.bParsingSuccessful = true; + } + else + { + if(true == fillInStringMsg) + { + result.errors.append(QString(" < Unknown axis type '%1'>").arg(axisTypeStr)); + } + } + } + + return result; + } +}; + +template<> +struct tPlotParametersParser +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_X_MAX; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + double value; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + + assert(splitParameters[1] != nullptr); + + tQStringPtr pFracPartStr = nullptr; + + if(splitParameters.size() >= 3) + { + assert(splitParameters[2] != nullptr); + pFracPartStr = splitParameters[2]; + } + + if(true == stringsToDouble(result.value, *splitParameters[1], pFracPartStr ? *pFracPartStr : "00")) + { + result.bParsingSuccessful = true; + if(splitParameters.size() >= 4) + { + assert(splitParameters[3] != nullptr); + if(splitParameters[3]->compare( "neg", Qt::CaseInsensitive ) == 0) + { + result.value = -(result.value); + } + } + } + else + { + if(true == fillInStringMsg) + { + result.errors.append(" < Was not able to parse the max value. Please, check the provided data. >"); + } + } + } + + return result; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_X_MIN; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_Y_MAX; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_Y_MIN; + } +}; + +template<> +struct tPlotParametersParser +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_X_NAME; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + QString value; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + + assert(splitParameters[1] != nullptr); + result.value = *splitParameters[1]; + + result.bParsingSuccessful = true; + } + + return result; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_Y_NAME; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_X_UNIT; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_Y_UNIT; + } +}; + +typedef uint32_t tGraphId; + +template<> +struct tPlotParametersParser +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_GRAPH_NAME; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + tGraphId graphId; + TOptional graphName; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + + assert(splitParameters[1] != nullptr); + result.graphId = splitParameters[1]->toInt(&result.bParsingSuccessful); + + if(false == result.bParsingSuccessful) + { + result.errors.append(QString(" ").arg(*splitParameters[1])); + } + else if( splitParameters.size() > 2) + { + assert(splitParameters[2] != nullptr); + result.graphName.setValue(*splitParameters[2]); + } + } + + return result; + } +}; + +template<> +struct tPlotParametersParser +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_GRAPH_METADATA; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + tGraphId graphId; + QString key; + TOptional value; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + + assert(splitParameters[1] != nullptr); + result.graphId = splitParameters[1]->toInt(&result.bParsingSuccessful); + + if(false == result.bParsingSuccessful) + { + result.errors.append(QString(" ").arg(*splitParameters[1])); + } + else if( splitParameters.size() > 2) + { + assert(splitParameters[2] != nullptr); + result.key = *splitParameters[2]; + + if(splitParameters.size() > 3) + { + assert(splitParameters[3] != nullptr); + result.value.setValue(*splitParameters[3]); + } + } + } + + return result; + } +}; + +template<> +struct tPlotParametersParser +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_X_DATA; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + tGraphId graphId; + TOptional value; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + + assert(splitParameters[1] != nullptr); + result.graphId = splitParameters[1]->toInt(&result.bParsingSuccessful); + + if(false == result.bParsingSuccessful) + { + result.errors.append(QString(" ").arg(*splitParameters[1])); + } + else + { + if(splitParameters.size() > 2) + { + assert(splitParameters[2] != nullptr); + + result.value.setValue(splitParameters[1]->toDouble(&result.bParsingSuccessful)); + + if(false == result.bParsingSuccessful) + { + result.errors.append(QString(" ").arg(*splitParameters[2])); + } + } + } + } + + return result; + } +}; + +template<> +struct tPlotParametersParser : +public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_Y_DATA; + } +}; + +struct tTimestampParserBase +{ + enum class eTimestampItemType + { + separator = 0, + year, + month, + day, + hour, + minute, + second, + fraction + }; + + typedef uint32_t tNumberOfSymbols; + typedef std::vector> tTimestampDataVec; + + struct tParsedData + { + tTimestampDataVec timestampDataVec; + QString regularExpressionStr; + QString dateTimeFormat; + int32_t minValueLength = 0; + }; +}; + +template<> +struct tPlotParametersParser: +public tTimestampParserBase +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_X_TIMESTAMP; + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + tParsedData parsedData; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + + TOptional timestampItemType; + TOptional numberOfSymbolsStr; + + for(const auto& ch : *splitParameters[0]) + { + if(ch == 'w') + { + timestampItemType.setValue(eTimestampItemType::separator); + } + else if(ch == 'y') + { + timestampItemType.setValue(eTimestampItemType::year); + } + else if(ch == 'M') + { + timestampItemType.setValue(eTimestampItemType::month); + } + else if(ch == 'd') + { + timestampItemType.setValue(eTimestampItemType::day); + } + else if(ch == 'H') + { + timestampItemType.setValue(eTimestampItemType::hour); + } + else if(ch == 'm') + { + timestampItemType.setValue(eTimestampItemType::minute); + } + else if(ch == 's') + { + timestampItemType.setValue(eTimestampItemType::second); + } + else if(ch == 'f') + { + timestampItemType.setValue(eTimestampItemType::fraction); + } + else if(ch.digitValue() != -1) + { + if(true == numberOfSymbolsStr.isSet()) + { + numberOfSymbolsStr.getWriteableValue().append(ch); + } + else + { + numberOfSymbolsStr.setValue(QString(ch)); + } + } + else + { + result.errors.append(QString(" ") + .arg(ch, *splitParameters[0])); + return result; + } + + if(true == timestampItemType.isSet()) + { + TOptional numberOfSymbolsOpt; + + if(false == numberOfSymbolsStr.isSet()) + { + numberOfSymbolsOpt.setValue(1); + } + else + { + bool convertedToDigit = false; + + auto numberOfSymbols = numberOfSymbolsStr.getValue().toInt(&convertedToDigit); + + if(true == convertedToDigit) + { + numberOfSymbolsOpt.setValue(numberOfSymbols); + } + else + { + result.errors.append(QString(" ") + .arg(numberOfSymbolsStr.getValue(), *splitParameters[0])); + return result; + } + } + + result.parsedData.minValueLength += numberOfSymbolsOpt.getValue(); + + result.parsedData.timestampDataVec.push_back(std::make_pair(timestampItemType.getValue(), + numberOfSymbolsOpt.getValue())); + + timestampItemType.reset(); + numberOfSymbolsStr.reset(); + } + } + + if(false == result.parsedData.timestampDataVec.empty()) + { + typedef tPlotParametersParser::eTimestampItemType eTimestampItemType; + + for(const auto& timestampPair : result.parsedData.timestampDataVec) + { + switch(timestampPair.first) + { + case eTimestampItemType::separator: + { + result.parsedData.regularExpressionStr.append(QString(".{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(":"); + } + break; + case eTimestampItemType::year: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 'y')); + } + break; + case eTimestampItemType::month: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 'M')); + } + break; + case eTimestampItemType::day: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 'd')); + } + break; + case eTimestampItemType::hour: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 'H')); + } + break; + case eTimestampItemType::minute: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 'm')); + } + break; + case eTimestampItemType::second: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 's')); + } + break; + case eTimestampItemType::fraction: + { + result.parsedData.regularExpressionStr.append(QString("[\\d]{%1}").arg(timestampPair.second)); + result.parsedData.dateTimeFormat.append(QString(timestampPair.second, 'z')); + } + break; + } + } + + if(true == result.parsedData.regularExpressionStr.isEmpty()) + { + result.errors.append(QString(" ") + .arg(*splitParameters[0])); + } + + if(true == result.parsedData.dateTimeFormat.isEmpty()) + { + result.errors.append(QString(" ") + .arg(*splitParameters[0])); + } + + if(false == result.parsedData.regularExpressionStr.isEmpty() && + false == result.parsedData.dateTimeFormat.isEmpty()) + { + result.bParsingSuccessful = true; + } + } + else + { + result.errors.append(QString(" ") + .arg(*splitParameters[0])); + } + } + + return result; + } +}; + +template<> +struct tPlotParametersParser : + public tPlotParametersParser +{ + tPlotParametersParser() + { + plotViewId = ePlotViewID::PLOT_Y_TIMESTAMP; + } +}; + +template<> +struct tPlotParametersParser +{ + ePlotViewID plotViewId = ePlotViewID::PLOT_GANTT_EVENT; + + enum class eGanttEventType + { + START = 0, + END + }; + + static std::pair parseGanttEventType(const QString& val) + { + std::pair result; + result.first = false; + + QString lowerVal = val.toLower(); + + if(lowerVal == "start") + { + result.first = true; + result.second = eGanttEventType::START; + } + else if(lowerVal == "end") + { + result.first = true; + result.second = eGanttEventType::END; + } + + return result; + } + + struct tParsingResult + { + bool bParsingSuccessful = false; + QString errors; + QString axisRectName; + tGraphId graphId; + eGanttEventType eventType; + }; + + tParsingResult parse(bool fillInStringMsg, + const tQStringPtr& pPlotViewGroupName, + const tQStringPtrVec& splitParameters) + { + tParsingResult result; + + if(checkPlotViewParameter(result.errors, + fillInStringMsg, + plotViewId, + pPlotViewGroupName, + splitParameters)) + { + assert(splitParameters[0] != nullptr); + result.axisRectName = *splitParameters[0]; + + assert(splitParameters[1] != nullptr); + result.graphId = splitParameters[1]->toInt(&result.bParsingSuccessful); + + if(false == result.bParsingSuccessful) + { + result.errors.append(QString(" ").arg(*splitParameters[1])); + } + else + { + assert(splitParameters[2] != nullptr); + auto ganttEventTypeParsingResult = parseGanttEventType(*splitParameters[2]); + + if(true == ganttEventTypeParsingResult.first) + { + result.bParsingSuccessful = true; + result.eventType = ganttEventTypeParsingResult.second; + } + else + { + result.errors.append(QString(" ").arg(*splitParameters[2])); + } + } + } + + return result; + } +}; + + +#endif // PLOT_DEFINITIONS_HPP diff --git a/dltmessageanalyzerplugin/src/common/TOptional.hpp b/dltmessageanalyzerplugin/src/common/TOptional.hpp index 18564c4b..eda7c914 100644 --- a/dltmessageanalyzerplugin/src/common/TOptional.hpp +++ b/dltmessageanalyzerplugin/src/common/TOptional.hpp @@ -15,7 +15,10 @@ class TOptional { public: - TOptional(); + TOptional(): + mData(), + mbIsSet(false) + {} explicit TOptional(const T& val): mData(val), @@ -45,6 +48,12 @@ class TOptional return mbIsSet; } + void reset() + { + mData = T(); + mbIsSet = false; + } + private: T mData; bool mbIsSet; diff --git a/dltmessageanalyzerplugin/src/common/variant/variant.hpp b/dltmessageanalyzerplugin/src/common/variant/variant.hpp index dc5ef27b..441e397c 100644 --- a/dltmessageanalyzerplugin/src/common/variant/variant.hpp +++ b/dltmessageanalyzerplugin/src/common/variant/variant.hpp @@ -670,7 +670,7 @@ struct typelist_max_alignof< typelist > template< class List > struct typelist_size { - enum V { value = 1 }; + enum V { value = 1 }; }; template<> struct typelist_size< T0 > { enum V { value = 0 }; }; diff --git a/dltmessageanalyzerplugin/src/components/CMakeLists.txt b/dltmessageanalyzerplugin/src/components/CMakeLists.txt index a030c131..3ea213e0 100644 --- a/dltmessageanalyzerplugin/src/components/CMakeLists.txt +++ b/dltmessageanalyzerplugin/src/components/CMakeLists.txt @@ -6,5 +6,6 @@ DMA_add_subdirectory_with_clang_tidy(logo) DMA_add_subdirectory_with_clang_tidy(logsWrapper) DMA_add_subdirectory_with_clang_tidy(patternsView) DMA_add_subdirectory_with_clang_tidy(plant_uml) +DMA_add_subdirectory_with_clang_tidy(plotView) DMA_add_subdirectory_with_clang_tidy(searchView) -DMA_add_subdirectory_with_clang_tidy(settings) \ No newline at end of file +DMA_add_subdirectory_with_clang_tidy(settings) diff --git a/dltmessageanalyzerplugin/src/components/analyzer/api/Definitions.hpp b/dltmessageanalyzerplugin/src/components/analyzer/api/Definitions.hpp index 10ed4a49..6f811058 100644 --- a/dltmessageanalyzerplugin/src/components/analyzer/api/Definitions.hpp +++ b/dltmessageanalyzerplugin/src/components/analyzer/api/Definitions.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "stdint.h" #include "QRegularExpression" @@ -44,7 +46,7 @@ struct tProgressNotificationData { tProgressNotificationData(); - /* + /* * @param requestId - id of the request, about which we notify the client * @param requestState - the state of the request * @param progress - progress in percents diff --git a/dltmessageanalyzerplugin/src/components/analyzer/api/IDLTMessageAnalyzerControllerConsumer.hpp b/dltmessageanalyzerplugin/src/components/analyzer/api/IDLTMessageAnalyzerControllerConsumer.hpp index 6907a7c6..d91ee4e8 100644 --- a/dltmessageanalyzerplugin/src/components/analyzer/api/IDLTMessageAnalyzerControllerConsumer.hpp +++ b/dltmessageanalyzerplugin/src/components/analyzer/api/IDLTMessageAnalyzerControllerConsumer.hpp @@ -34,7 +34,8 @@ public slots: protected: IDLTMessageAnalyzerControllerConsumer( const std::weak_ptr& pController ); tRequestId requestAnalyze( const tRequestParameters& requestParameters, - bool bUMLFeatureActive ); + bool bUMLFeatureActive, + bool bPlotViewFeatureActive ); void cancelRequest( const tRequestId& requestId ); protected: // fields diff --git a/dltmessageanalyzerplugin/src/components/analyzer/src/CContinuousAnalyzer.hpp b/dltmessageanalyzerplugin/src/components/analyzer/src/CContinuousAnalyzer.hpp index e0979445..8174fcec 100644 --- a/dltmessageanalyzerplugin/src/components/analyzer/src/CContinuousAnalyzer.hpp +++ b/dltmessageanalyzerplugin/src/components/analyzer/src/CContinuousAnalyzer.hpp @@ -19,14 +19,14 @@ class IDLTMessageAnalyzerControllerConsumer; */ class CSubConsumer : public IDLTMessageAnalyzerControllerConsumer { - Q_OBJECT + Q_OBJECT public: - typedef std::function tCallback; - CSubConsumer(const tDLTMessageAnalyzerControllerPtr& pController); - void setCallback(const tCallback& callback); - void progressNotification( const tProgressNotificationData& progressNotificationData ) override; + typedef std::function tCallback; + CSubConsumer(const tDLTMessageAnalyzerControllerPtr& pController); + void setCallback(const tCallback& callback); + void progressNotification( const tProgressNotificationData& progressNotificationData ) override; private: - tCallback mCallback; + tCallback mCallback; }; /** diff --git a/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp b/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp index 07c5e6e8..38282ca5 100644 --- a/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp +++ b/dltmessageanalyzerplugin/src/components/analyzer/src/CDLTRegexAnalyzerWorker.cpp @@ -75,6 +75,15 @@ void CDLTRegexAnalyzerWorker::analyzePortion( const tAnalyzePortionData& analyz bAnalyzeUML = true; } + bool bAnalyzePlotView = false; + + if(true == getSettingsManager()->getPlotViewFeatureActive() && + true == analyzePortionData.regexMetadata.doesContainAnyPlotViewGroup() && + true == analyzePortionData.regexMetadata.doesContainConsistentPlotViewData(false, true).first) + { + bAnalyzePlotView = true; + } + ePortionAnalysisState portionAnalysisState = ePortionAnalysisState::ePortionAnalysisState_SUCCESSFUL; tFoundMatchesPack foundMatchesPack; @@ -130,6 +139,13 @@ void CDLTRegexAnalyzerWorker::analyzePortion( const tAnalyzePortionData& analyz } } + if(true == bAnalyzePlotView) + { + auto updatePlotViewInfoResult = itemMetadata.updatePlotViewInfo(foundMatches, + analyzePortionData.regexMetadata, + pTree); + } + foundMatchesPack.matchedItemVec.push_back( tFoundMatchesPackItem( std::move(itemMetadata), std::move(foundMatches) ) ); } } diff --git a/dltmessageanalyzerplugin/src/components/analyzer/src/IDLTMessageAnalyzerControllerConsumer.cpp b/dltmessageanalyzerplugin/src/components/analyzer/src/IDLTMessageAnalyzerControllerConsumer.cpp index c8370985..3f4c6be0 100644 --- a/dltmessageanalyzerplugin/src/components/analyzer/src/IDLTMessageAnalyzerControllerConsumer.cpp +++ b/dltmessageanalyzerplugin/src/components/analyzer/src/IDLTMessageAnalyzerControllerConsumer.cpp @@ -26,7 +26,8 @@ IDLTMessageAnalyzerControllerConsumer::IDLTMessageAnalyzerControllerConsumer( co } tRequestId IDLTMessageAnalyzerControllerConsumer::requestAnalyze( const tRequestParameters& requestParameters, - bool bUMLFeatureActive ) + bool bUMLFeatureActive, + bool bPlotViewFeatureActive ) { tRequestId requestId = INVALID_REQUEST_ID; @@ -34,7 +35,7 @@ tRequestId IDLTMessageAnalyzerControllerConsumer::requestAnalyze( const tRequest { tRegexScriptingMetadata regexMetadata; - bool bParseResult = regexMetadata.parse(requestParameters.regex, bUMLFeatureActive); + bool bParseResult = regexMetadata.parse(requestParameters.regex, bUMLFeatureActive, bPlotViewFeatureActive); if(false == bParseResult) { @@ -54,6 +55,19 @@ tRequestId IDLTMessageAnalyzerControllerConsumer::requestAnalyze( const tRequest } } } + + if(true == bPlotViewFeatureActive) + { + if(true == regexMetadata.doesContainAnyPlotViewGroup()) // if has at least one plot view group + { + auto checkPlotViewDataResult = regexMetadata.doesContainConsistentPlotViewData(true, true); + + if(false == checkPlotViewDataResult.first) // let's check and trace the warnings + { + SEND_WRN(checkPlotViewDataResult.second); + } + } + } } requestId = mpController.lock()->requestAnalyze(shared_from_this(), requestParameters, regexMetadata); diff --git a/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersViewComponent.cpp b/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersViewComponent.cpp index a276be35..6dd09dc4 100644 --- a/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersViewComponent.cpp +++ b/dltmessageanalyzerplugin/src/components/filtersView/src/CFiltersViewComponent.cpp @@ -14,88 +14,88 @@ CSettingsManagerClient(pSettingsManager), mpFiltersModel(nullptr), mpFiltersView(pFiltersView) { - DMA_FORCE_LINK_REFERENCE(IFiltersModel) + DMA_FORCE_LINK_REFERENCE(IFiltersModel) } std::shared_ptr CFiltersViewComponent::getFiltersModel() { - return mpFiltersModel; + return mpFiltersModel; } const char* CFiltersViewComponent::getName() const { - return "CFiltersViewComponent"; + return "CFiltersViewComponent"; } DMA::tSyncInitOperationResult CFiltersViewComponent::init() { - DMA::tSyncInitOperationResult result; - - try - { - if(nullptr != mpFiltersView) - { - auto pFiltersModel= std::make_shared(getSettingsManager()); - - if( nullptr != pFiltersModel ) - { - mpFiltersView->setSettingsManager(getSettingsManager()); - mpFiltersModel = pFiltersModel; - mpFiltersView->setSpecificModel(pFiltersModel.get()); - } - - result.bIsOperationSuccessful = true; - result.returnCode = 0; - } - else - { - result.bIsOperationSuccessful = false; - result.returnCode = -1; - } - } - catch (...) - { - result.bIsOperationSuccessful = false; - result.returnCode = -1; - } - - return result; + DMA::tSyncInitOperationResult result; + + try + { + if(nullptr != mpFiltersView) + { + auto pFiltersModel= std::make_shared(getSettingsManager()); + + if( nullptr != pFiltersModel ) + { + mpFiltersView->setSettingsManager(getSettingsManager()); + mpFiltersModel = pFiltersModel; + mpFiltersView->setSpecificModel(pFiltersModel.get()); + } + + result.bIsOperationSuccessful = true; + result.returnCode = 0; + } + else + { + result.bIsOperationSuccessful = false; + result.returnCode = -1; + } + } + catch (...) + { + result.bIsOperationSuccessful = false; + result.returnCode = -1; + } + + return result; } DMA::tSyncInitOperationResult CFiltersViewComponent::shutdown() { - DMA::tSyncInitOperationResult result; - - try - { - if(nullptr != mpFiltersModel) - { - mpFiltersModel.reset(); - } - - result.bIsOperationSuccessful = true; - result.returnCode = 0; - } - catch (...) - { - result.bIsOperationSuccessful = false; - result.returnCode = -1; - } - - return result; + DMA::tSyncInitOperationResult result; + + try + { + if(nullptr != mpFiltersModel) + { + mpFiltersModel.reset(); + } + + result.bIsOperationSuccessful = true; + result.returnCode = 0; + } + catch (...) + { + result.bIsOperationSuccessful = false; + result.returnCode = -1; + } + + return result; } CFiltersView* CFiltersViewComponent::getFiltersView() const { - return mpFiltersView; + return mpFiltersView; } PUML_PACKAGE_BEGIN(DMA_FiltersView_API) - PUML_CLASS_BEGIN(CFiltersViewComponent) - PUML_INHERITANCE_CHECKED(DMA::IComponent, implements) - PUML_INHERITANCE_CHECKED(CSettingsManagerClient, extends) - PUML_COMPOSITION_DEPENDENCY_CHECKED(IFiltersModel, 1, 1, contains) - PUML_USE_DEPENDENCY_CHECKED(CFiltersModel, 1, 1, using to create IFiltersModel) - PUML_AGGREGATION_DEPENDENCY_CHECKED(CFiltersView, 1, 1, uses) - PUML_CLASS_END() + PUML_CLASS_BEGIN(CFiltersViewComponent) + PUML_INHERITANCE_CHECKED(DMA::IComponent, implements) + PUML_INHERITANCE_CHECKED(CSettingsManagerClient, extends) + PUML_COMPOSITION_DEPENDENCY_CHECKED(IFiltersModel, 1, 1, contains) + PUML_USE_DEPENDENCY_CHECKED(CFiltersModel, 1, 1, using to create IFiltersModel) + PUML_AGGREGATION_DEPENDENCY_CHECKED(CFiltersView, 1, 1, uses) + PUML_CLASS_END() PUML_PACKAGE_END() diff --git a/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp b/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp index a7697575..1cac2e0d 100644 --- a/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp +++ b/dltmessageanalyzerplugin/src/components/groupedView/src/CGroupedViewModel.cpp @@ -33,59 +33,25 @@ CGroupedViewModel::CGroupedViewModel(const tSettingsManagerPtr& pSettingsManager const int& sortingColumn, Qt::SortOrder sortingOrder) -> QVector { - tTreeItem::tChildrenVector result; + auto result = children; switch(static_cast(sortingColumn)) { case eGroupedViewColumn::SubString: { - struct tComparator + result = children; + std::sort(result.begin(), result.end(), + [&sortingColumn](const tTreeItemPtr& lVal, const tTreeItemPtr& rVal) { - QString val; - bool operator< (const tComparator& rVal) const + const tQStringPtrWrapper& lValSubString = lVal->data(sortingColumn).get(); + const tQStringPtrWrapper& rValSubString = rVal->data(sortingColumn).get(); + bool bResult = false; + if(nullptr != lValSubString.pString && nullptr != rValSubString.pString) { - return val.compare( rVal.val, Qt::CaseInsensitive ) < 0; + bResult = lValSubString.pString->compare( *rValSubString.pString ) < 0; } - }; - - - QMultiMap sortedChildrenMap; - - for(const auto& pChild : children) - { - if(nullptr != pChild) - { - const tQStringPtrWrapper& subString = pChild->data(sortingColumn).get(); - tComparator comparator; - - if(nullptr != subString.pString) - { - comparator.val = *subString.pString; - } - - sortedChildrenMap.insert(comparator, pChild); - } - } - - for(const auto& pChild : sortedChildrenMap) - { - if(nullptr != pChild) - { - switch(sortingOrder) - { - case Qt::SortOrder::AscendingOrder: - { - result.push_back(pChild); - } - break; - case Qt::SortOrder::DescendingOrder: - { - result.push_front(pChild); - } - break; - } - } - } + return bResult; + }); } break; case eGroupedViewColumn::Messages: @@ -93,8 +59,6 @@ CGroupedViewModel::CGroupedViewModel(const tSettingsManagerPtr& pSettingsManager case eGroupedViewColumn::Payload: case eGroupedViewColumn::PayloadPerSecondAverage: { - QMultiMap sortedChildrenMap; - for(const auto& pChild : children) { if(nullptr != pChild) @@ -107,38 +71,22 @@ CGroupedViewModel::CGroupedViewModel(const tSettingsManagerPtr& pSettingsManager { updateAverageValues(pChild, false, true); } - - int statistics = pChild->data(static_cast(sortingColumn)).get(); - sortedChildrenMap.insert(statistics, pChild); } } - for(const auto& pChild : sortedChildrenMap) + result = children; + std::sort(result.begin(), result.end(), + [&sortingColumn](const tTreeItemPtr& lVal, const tTreeItemPtr& rVal) { - if(nullptr != pChild) - { - switch(sortingOrder) - { - case Qt::SortOrder::AscendingOrder: - { - result.push_back(pChild); - } - break; - case Qt::SortOrder::DescendingOrder: - { - result.push_front(pChild); - } - break; - } - } - } + const auto& lValInt = lVal->data(sortingColumn).get(); + const auto& rValInt = rVal->data(sortingColumn).get(); + return lValInt < rValInt; + }); } break; case eGroupedViewColumn::PayloadPercantage: case eGroupedViewColumn::MessagesPercantage: { - QMultiMap sortedChildrenMap; - for(const auto& pChild : children) { if(nullptr != pChild) @@ -151,31 +99,17 @@ CGroupedViewModel::CGroupedViewModel(const tSettingsManagerPtr& pSettingsManager { updatePercentageValues(pChild, false, true); } - - double statistics = pChild->data(static_cast(sortingColumn)).get(); - sortedChildrenMap.insert(statistics, pChild); } } - for(const auto& pChild : sortedChildrenMap) + result = children; + std::sort(result.begin(), result.end(), + [&sortingColumn](const tTreeItemPtr& lVal, const tTreeItemPtr& rVal) { - if(nullptr != pChild) - { - switch(sortingOrder) - { - case Qt::SortOrder::AscendingOrder: - { - result.push_back(pChild); - } - break; - case Qt::SortOrder::DescendingOrder: - { - result.push_front(pChild); - } - break; - } - } - } + const auto& lValInt = lVal->data(sortingColumn).get(); + const auto& rValInt = rVal->data(sortingColumn).get(); + return lValInt < rValInt; + }); } break; case eGroupedViewColumn::AfterLastVisible: @@ -184,6 +118,11 @@ CGroupedViewModel::CGroupedViewModel(const tSettingsManagerPtr& pSettingsManager break; } + if( sortingOrder == Qt::SortOrder::DescendingOrder) + { + std::reverse(result.begin(), result.end()); + } + return result; }; @@ -622,11 +561,11 @@ std::pair CGroupedViewModel::exportToHTML(QS if(true == bIsAnythingToShow) { mpRootItem->sort(static_cast(mSortingColumn), mSortOrder, true); - + QString& finalText = resultHTML; - + QString currentTime = QString().append("[").append(QDateTime::currentDateTime().toString()).append("]"); - + finalText.append(QString("\n" "\n" "\n" @@ -671,7 +610,7 @@ std::pair CGroupedViewModel::exportToHTML(QS "\n" "\n" "\n"); - + finalText.append( QString("\n

Trace spam analysis report %1

").arg(currentTime) ); finalText.append( QString("\n

Analysis based on regex: \"").append(mRegex.toHtmlEscaped()).append("\"

") ); finalText.append("
    "); @@ -792,7 +731,7 @@ std::pair CGroupedViewModel::exportToHTML(QS }; mpRootItem->visit( preVisitFunction, postVisitFunction ); - + finalText.append("
" "" "