diff --git a/YUViewLib/src/decoder/decoderDav1d.cpp b/YUViewLib/src/decoder/decoderDav1d.cpp index 8bcd40915..ef6ebd27e 100644 --- a/YUViewLib/src/decoder/decoderDav1d.cpp +++ b/YUViewLib/src/decoder/decoderDav1d.cpp @@ -590,18 +590,14 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons using namespace stats::color; statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(0) - .withTypeName("Pred Mode") + StatisticsTypeBuilder(0, "Pred Mode") .withDescription("The prediction mode (intra/inter) per block") .withValueDataOptions({.colorMapper = ColorMapper({0, 1}, PredefinedType::Jet)}) .withMappingValues({"INTRA", "INTER"}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(1) - .withTypeName("Segment ID") + StatisticsTypeBuilder(1, "Segment ID") .withDescription( "Specifies which segment is associated with the current intra block being " "decoded") @@ -609,9 +605,7 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(2) - .withTypeName("Skip") + StatisticsTypeBuilder(2, "Skip") .withDescription( "Equal to 0 indicates that there may be some transform coefficients for this " "block. 1 Indicates there are none.") @@ -620,9 +614,7 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(3) - .withTypeName("Skip Mode") + StatisticsTypeBuilder(3, "Skip Mode") .withDescription( "Equal to 1 indicates that signaling of most of the mode info is skipped") .withValueDataOptions( @@ -630,9 +622,7 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(4) - .withTypeName("Intra Pred Mode (Y)") + StatisticsTypeBuilder(4, "Intra Pred Mode (Y)") .withDescription("Intra prediction mode Luma") .withValueDataOptions({.colorMapper = ColorMapper({0, 13}, PredefinedType::Jet)}) .withMappingValues({"DC_PRED", @@ -652,9 +642,7 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(5) - .withTypeName("Intra Pred Mode (UV)") + StatisticsTypeBuilder(5, "Intra Pred Mode (UV)") .withDescription("Intra prediction mode Chroma") .withValueDataOptions({.colorMapper = ColorMapper({0, 12}, PredefinedType::Jet)}) .withMappingValues({"DC_PRED", @@ -673,58 +661,44 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(6) - .withTypeName("Palette Size (Y)") + StatisticsTypeBuilder(6, "Palette Size (Y)") .withDescription("Palette Size Luma") .withValueDataOptions( {.colorMapper = ColorMapper({0, 255}, Color(0, 0, 0), Color(0, 0, 255))}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(7) - .withTypeName("Palette Size Chroma") + StatisticsTypeBuilder(7, "Palette Size Chroma") .withValueDataOptions( {.colorMapper = ColorMapper({0, 255}, Color(0, 0, 0), Color(0, 0, 255))}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(8) - .withTypeName("Intra Angle Delta (Y)") + StatisticsTypeBuilder(8, "Intra Angle Delta (Y)") .withDescription("Offset to be applied to the intra prediction angle specified by the " "prediction mode") .withValueDataOptions({.colorMapper = ColorMapper({-3, 4}, PredefinedType::Col3_bblg)}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(9) - .withTypeName("Intra Angle Delta (UV)") + StatisticsTypeBuilder(9, "Intra Angle Delta (UV)") .withDescription("Offset to be applied to the chroma prediction angle specified by the " "prediction mode") .withValueDataOptions({.colorMapper = ColorMapper({-3, 4}, PredefinedType::Col3_bblg)}) .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(10) - .withTypeName("Intra Direction Luma") + statisticsData.addStatType(StatisticsTypeBuilder(10, "Intra Direction Luma") .withDescription("Intra prediction direction luma") .withVectorDataOptions({.scale = 4}) .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(11) - .withTypeName("Intra Direction Chroma") + statisticsData.addStatType(StatisticsTypeBuilder(11, "Intra Direction Chroma") .withDescription("Intra prediction direction chroma") .withVectorDataOptions({.scale = 4}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(12) - .withTypeName("Chroma from Luma Alpha (U)") + StatisticsTypeBuilder(12, "Chroma from Luma Alpha (U)") .withDescription( "CflAlphaU: Contains the signed value of the alpha component for the U component") .withValueDataOptions( @@ -732,9 +706,7 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(13) - .withTypeName("Chroma from Luma Alpha (V)") + StatisticsTypeBuilder(13, "Chroma from Luma Alpha (V)") .withDescription( "CflAlphaV: Contains the signed value of the alpha component for the V component") .withValueDataOptions( @@ -742,25 +714,19 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(14) - .withTypeName("Ref Frame Index 0") + StatisticsTypeBuilder(14, "Ref Frame Index 0") .withDescription("Reference frame index from List 0") .withValueDataOptions({.colorMapper = ColorMapper({0, 7}, PredefinedType::Jet)}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(15) - .withTypeName("Ref Frame Index 1") + StatisticsTypeBuilder(15, "Ref Frame Index 1") .withDescription("Reference frame index from List 1") .withValueDataOptions({.colorMapper = ColorMapper({0, 7}, PredefinedType::Jet)}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(16) - .withTypeName("Compound Prediction Type") + StatisticsTypeBuilder(16, "Compound Prediction Type") .withDescription("The type of compound prediction used") .withValueDataOptions({.colorMapper = ColorMapper({0, 4}, PredefinedType::Jet)}) .withMappingValues({"COMP_INTER_NONE", @@ -771,24 +737,18 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(17) - .withTypeName("Wedge Index") + StatisticsTypeBuilder(17, "Wedge Index") .withValueDataOptions({.colorMapper = ColorMapper({0, 16}, PredefinedType::Jet)}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(18) - .withTypeName("Mask Sign") + StatisticsTypeBuilder(18, "Mask Sign") .withValueDataOptions( {.colorMapper = ColorMapper({0, 1}, Color(0, 0, 0), Color(0, 255, 255))}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(19) - .withTypeName("Inter Mode") + StatisticsTypeBuilder(19, "Inter Mode") .withValueDataOptions({.colorMapper = ColorMapper({0, 7}, PredefinedType::Jet)}) .withMappingValues({"NEARESTMV_NEARESTMV", "NEARMV_NEARMV", @@ -801,25 +761,19 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(20) - .withTypeName("Dynamic Reference List Index") + StatisticsTypeBuilder(20, "Dynamic Reference List Index") .withValueDataOptions( {.colorMapper = ColorMapper({0, 16}, Color(0, 0, 0), Color(0, 255, 255))}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(21) - .withTypeName("Inter-Intra Type") + StatisticsTypeBuilder(21, "Inter-Intra Type") .withValueDataOptions({.colorMapper = ColorMapper({0, 2}, PredefinedType::Jet)}) .withMappingValues({"INTER_INTRA_NONE", "INTER_INTRA_BLEND", "INTER_INTRA_WEDGE"}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(22) - .withTypeName("Inter-Intra Mode") + StatisticsTypeBuilder(22, "Inter-Intra Mode") .withValueDataOptions({.colorMapper = ColorMapper({0, 4}, PredefinedType::Jet)}) .withMappingValues({"II_DC_PRED", "II_VERT_PRED", @@ -829,33 +783,23 @@ void decoderDav1d::fillStatisticList(stats::StatisticsData &statisticsData) cons .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(23) - .withTypeName("Motion Mode") + StatisticsTypeBuilder(23, "Motion Mode") .withValueDataOptions({.colorMapper = ColorMapper({0, 2}, PredefinedType::Jet)}) .withMappingValues({"MM_TRANSLATION", "MM_OBMC", "MM_WARP"}) .build()); - statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(24) - .withTypeName("Motion Vector 0") - .withDescription("The motion vector for component 0") - .withValueDataOptions( - {.colorMapper = ColorMapper({-128, 128}, PredefinedType::Col3_bblg)}) - .build()); + statisticsData.addStatType(StatisticsTypeBuilder(24, "Motion Vector 0") + .withDescription("The motion vector for component 0") + .withVectorDataOptions({.scale = 4}) + .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(25) - .withTypeName("Motion Vector 1") + statisticsData.addStatType(StatisticsTypeBuilder(25, "Motion Vector 1") .withDescription("The motion vector for component 1") .withVectorDataOptions({.scale = 4}) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(26) - .withTypeName("Transform Size") + StatisticsTypeBuilder(26, "Transform Size") .withValueDataOptions({.colorMapper = ColorMapper({0, 19}, PredefinedType::Jet)}) .withMappingValues({"TX_4X4", "TX_8X8", diff --git a/YUViewLib/src/decoder/decoderFFmpeg.cpp b/YUViewLib/src/decoder/decoderFFmpeg.cpp index a383df488..429929a53 100644 --- a/YUViewLib/src/decoder/decoderFFmpeg.cpp +++ b/YUViewLib/src/decoder/decoderFFmpeg.cpp @@ -435,27 +435,17 @@ void decoderFFmpeg::fillStatisticList(stats::StatisticsData &statisticsData) con const auto sourceColorMapper = stats::color::ColorMapper({-2, 2}, stats::color::PredefinedType::Col3_bblg); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(0) - .withTypeName("Source -") + statisticsData.addStatType(StatisticsTypeBuilder(0, "Source -") .withValueDataOptions({.colorMapper = sourceColorMapper}) .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(1) - .withTypeName("Source +") + statisticsData.addStatType(StatisticsTypeBuilder(1, "Source +") .withValueDataOptions({.colorMapper = sourceColorMapper}) .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(2) - .withTypeName("Motion Vector -") - .withVectorDataOptions({.scale = 4}) - .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(3) - .withTypeName("Motion Vector +") - .withVectorDataOptions({.scale = 4}) - .build()); + statisticsData.addStatType( + StatisticsTypeBuilder(2, "Motion Vector -").withVectorDataOptions({.scale = 4}).build()); + statisticsData.addStatType( + StatisticsTypeBuilder(3, "Motion Vector +").withVectorDataOptions({.scale = 4}).build()); } bool decoderFFmpeg::createDecoder(FFmpeg::AVCodecIDWrapper codecID, diff --git a/YUViewLib/src/decoder/decoderHM.cpp b/YUViewLib/src/decoder/decoderHM.cpp index ea0a92ee2..c99717036 100644 --- a/YUViewLib/src/decoder/decoderHM.cpp +++ b/YUViewLib/src/decoder/decoderHM.cpp @@ -535,8 +535,7 @@ void decoderHM::fillStatisticList(stats::StatisticsData &statisticsData) const max = (uMax > INT_MAX) ? INT_MAX : uMax; } - auto typeBuilder = - StatisticsTypeBuilder().withTypeID(i).withTypeName(name).withDescription(description); + auto typeBuilder = StatisticsTypeBuilder(i, name).withDescription(description); if (statType == LIBHMDEC_TYPE_FLAG) { diff --git a/YUViewLib/src/decoder/decoderLibde265.cpp b/YUViewLib/src/decoder/decoderLibde265.cpp index 181997c7d..26da0f18d 100644 --- a/YUViewLib/src/decoder/decoderLibde265.cpp +++ b/YUViewLib/src/decoder/decoderLibde265.cpp @@ -898,17 +898,13 @@ void decoderLibde265::fillStatisticList(stats::StatisticsData &statisticsData) c using namespace stats::color; statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(0) - .withTypeName("Slice Index") + StatisticsTypeBuilder(0, "Slice Index") .withDescription("The slice index reported per CTU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({0, 10}, Color(0, 0, 0), Color(255, 0, 0))})) .build()); - statisticsData.addStatType(StatisticsTypeBuilder() - .withTypeID(1) - .withTypeName("Part Size") + statisticsData.addStatType(StatisticsTypeBuilder(1, "Part Size") .withDescription("The partition size of each CU into PUs") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({0, 7}, PredefinedType::Jet)})) @@ -923,9 +919,7 @@ void decoderLibde265::fillStatisticList(stats::StatisticsData &statisticsData) c .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(2) - .withTypeName("Pred Mode") + StatisticsTypeBuilder(2, "Pred Mode") .withDescription("The internal libde265 prediction mode (intra/inter/skip) per CU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({0, 2}, PredefinedType::Jet)})) @@ -933,53 +927,41 @@ void decoderLibde265::fillStatisticList(stats::StatisticsData &statisticsData) c .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(3) - .withTypeName("PCM flag") + StatisticsTypeBuilder(3, "PCM flag") .withDescription("The PCM flag per CU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({0, 1}, Color(0, 0, 0), Color(255, 0, 0))})) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(4) - .withTypeName("Transquant Bypass Flag") + StatisticsTypeBuilder(4, "Transquant Bypass Flag") .withDescription("The transquant bypass flag per CU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({0, 1}, Color(0, 0, 0), Color(255, 0, 0))})) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(5) - .withTypeName("Ref POC 0") + StatisticsTypeBuilder(5, "Ref POC 0") .withDescription("The reference POC in LIST 0 relative to the current POC per PU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({-16, 16}, PredefinedType::Col3_bblg)})) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(6) - .withTypeName("Ref POC 1") + StatisticsTypeBuilder(6, "Ref POC 1") .withDescription("The reference POC in LIST 1 relative to the current POC per PU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({-16, 16}, PredefinedType::Col3_bblg)})) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(7) - .withTypeName("Motion Vector 0") + StatisticsTypeBuilder(7, "Motion Vector 0") .withDescription("The motion vector in LIST 0 per PU") .withVectorDataOptions(StatisticsType::VectorDataOptions({.scale = 4})) .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(8) - .withTypeName("Motion Vector 1") + StatisticsTypeBuilder(8, "Motion Vector 1") .withDescription("The motion vector in LIST 1 per PU") .withVectorDataOptions(StatisticsType::VectorDataOptions({.scale = 4})) .build()); @@ -996,9 +978,7 @@ void decoderLibde265::fillStatisticList(stats::StatisticsData &statisticsData) c "INTRA_ANGULAR_32", "INTRA_ANGULAR_33", "INTRA_ANGULAR_34"}; statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(9) - .withTypeName("Intra Dir Luma") + StatisticsTypeBuilder(9, "Intra Dir Luma") .withDescription("The intra mode for the luma component per TU (intra prediction is " "performed on a TU level)") .withVectorDataOptions( @@ -1007,9 +987,7 @@ void decoderLibde265::fillStatisticList(stats::StatisticsData &statisticsData) c .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(10) - .withTypeName("Intra Dir Chroma") + StatisticsTypeBuilder(10, "Intra Dir Chroma") .withDescription("The intra mode for the chroma component per TU (intra prediction is " "performed on a TU level)") .withVectorDataOptions( @@ -1018,9 +996,7 @@ void decoderLibde265::fillStatisticList(stats::StatisticsData &statisticsData) c .build()); statisticsData.addStatType( - StatisticsTypeBuilder() - .withTypeID(11) - .withTypeName("Transform Depth") + StatisticsTypeBuilder(11, "Transform Depth") .withDescription("The transform depth within the transform tree per TU") .withValueDataOptions(StatisticsType::ValueDataOptions( {.colorMapper = ColorMapper({0, 3}, Color(0, 0, 0), Color(0, 255, 0))})) diff --git a/YUViewLib/src/statistics/StatisticsData.cpp b/YUViewLib/src/statistics/StatisticsData.cpp index 626de965f..be2237ca0 100644 --- a/YUViewLib/src/statistics/StatisticsData.cpp +++ b/YUViewLib/src/statistics/StatisticsData.cpp @@ -359,13 +359,13 @@ void StatisticsData::addStatType(const StatisticsType &type) void StatisticsData::savePlaylist(YUViewDomElement &root) const { for (const auto &type : this->statsTypes) - type.savePlaylist(root); + type.saveToPlaylist(root); } void StatisticsData::loadPlaylist(const YUViewDomElement &root) { for (auto &type : this->statsTypes) - type.loadPlaylist(root); + type.tryToLoadFromPlaylist(root); } } // namespace stats diff --git a/YUViewLib/src/statistics/StatisticsFileCSV.cpp b/YUViewLib/src/statistics/StatisticsFileCSV.cpp index 29b0ec349..cf42450f4 100644 --- a/YUViewLib/src/statistics/StatisticsFileCSV.cpp +++ b/YUViewLib/src/statistics/StatisticsFileCSV.cpp @@ -32,6 +32,8 @@ #include "StatisticsFileCSV.h" +#include + #include #include @@ -315,9 +317,9 @@ void StatisticsFileCSV::loadStatisticData(StatisticsData &statisticsData, int po this->blockOutsideOfFramePOC = poc; auto &statTypes = statisticsData.getStatisticsTypes(); - auto statIt = std::find_if(statTypes.begin(), statTypes.end(), [type](StatisticsType &t) { - return t.typeID == type; - }); + auto statIt = std::find_if(statTypes.begin(), + statTypes.end(), + [type](StatisticsType &t) { return t.typeID == type; }); Q_ASSERT_X(statIt != statTypes.end(), Q_FUNC_INFO, "Stat type not found."); if (vectorData && statIt->vectorDataOptions) @@ -354,11 +356,16 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) statisticsData.clear(); - // scan header lines first - // also count the lines per Frame for more efficient memory allocation - // if an ID is used twice, the data of the first gets overwritten - bool typeParsingActive = false; - StatisticsType aType; + struct ParsedData + { + int typeID{}; + std::string typeName{}; + + std::optional valueDataOptions; + std::optional vectorDataOptions; + StatisticsType::GridOptions gridOptions; + }; + std::optional type; while (!this->file.atEnd()) { @@ -373,42 +380,43 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) continue; // either a new type or a line which is not header finishes the last type - if (((rowItemList[1] == "type") || (rowItemList[0][0] != '%')) && typeParsingActive) + if (((rowItemList[1] == "type") || (rowItemList[0][0] != '%')) && type) { // Last type is complete. Store this initial state. - aType.setInitialState(); - statisticsData.addStatType(aType); + statisticsData.addStatType(StatisticsTypeBuilder(type->typeID, type->typeName) + .withValueDataOptions(type->valueDataOptions) + .withVectorDataOptions(type->vectorDataOptions) + .withGridOptions(type->gridOptions) + .build()); - // start from scratch for next item - aType = StatisticsType(); - typeParsingActive = false; + type.reset(); // if we found a non-header line, stop here if (rowItemList[0][0] != '%') return; } - if (rowItemList[1] == "type") // new type + if (rowItemList[1] == "type") { - aType.typeID = rowItemList[2].toInt(); - aType.typeName = rowItemList[3].toStdString(); + // Start of a new type + type.emplace(); + type->typeID = rowItemList[2].toInt(); + type->typeName = rowItemList[3].toStdString(); // The next entry (4) is "map", "range", or "vector" if (rowItemList.count() >= 5) { if (rowItemList[4] == "map" || rowItemList[4] == "range") { - aType.valueDataOptions = StatisticsType::ValueDataOptions(); + type->valueDataOptions = StatisticsType::ValueDataOptions(); } else if (rowItemList[4] == "vector" || rowItemList[4] == "line") { - aType.vectorDataOptions = StatisticsType::VectorDataOptions(); + type->vectorDataOptions = StatisticsType::VectorDataOptions(); if (rowItemList[4] == "line") - aType.vectorDataOptions->arrowHead = StatisticsType::ArrowHead::none; + type->vectorDataOptions->arrowHead = StatisticsType::ArrowHead::none; } } - - typeParsingActive = true; } else if (rowItemList[1] == "mapColor") { @@ -420,8 +428,8 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) auto b = (unsigned char)rowItemList[5].toInt(); auto a = (unsigned char)rowItemList[6].toInt(); - aType.valueDataOptions->colorMapper.mappingType = color::MappingType::Map; - aType.valueDataOptions->colorMapper.colorMap[id] = Color(r, g, b, a); + type->valueDataOptions->colorMapper.mappingType = color::MappingType::Map; + type->valueDataOptions->colorMapper.colorMap[id] = Color(r, g, b, a); } else if (rowItemList[1] == "range") { @@ -440,7 +448,7 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) a = rowItemList[11].toInt(); auto maxColor = Color(r, g, b, a); - aType.valueDataOptions->colorMapper = color::ColorMapper({min, max}, minColor, maxColor); + type->valueDataOptions->colorMapper = color::ColorMapper({min, max}, minColor, maxColor); } else if (rowItemList[1] == "defaultRange") { @@ -449,7 +457,7 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) int max = rowItemList[3].toInt(); auto rangeName = rowItemList[4].toStdString(); - aType.valueDataOptions->colorMapper = color::ColorMapper({min, max}, rangeName); + type->valueDataOptions->colorMapper = color::ColorMapper({min, max}, rangeName); } else if (rowItemList[1] == "vectorColor") { @@ -457,7 +465,7 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) auto g = (unsigned char)rowItemList[3].toInt(); auto b = (unsigned char)rowItemList[4].toInt(); auto a = (unsigned char)rowItemList[5].toInt(); - aType.vectorDataOptions->style.color = Color(r, g, b, a); + type->vectorDataOptions->style.color = Color(r, g, b, a); } else if (rowItemList[1] == "gridColor") { @@ -465,15 +473,15 @@ void StatisticsFileCSV::readHeaderFromFile(StatisticsData &statisticsData) auto g = (unsigned char)rowItemList[3].toInt(); auto b = (unsigned char)rowItemList[4].toInt(); auto a = 255; - aType.gridOptions.style.color = Color(r, g, b, a); + type->gridOptions.style.color = Color(r, g, b, a); } else if (rowItemList[1] == "scaleFactor") { - aType.vectorDataOptions->scale = rowItemList[2].toInt(); + type->vectorDataOptions->scale = rowItemList[2].toInt(); } else if (rowItemList[1] == "scaleToBlockSize") { - aType.valueDataOptions->scaleToBlockSize = (rowItemList[2] == "1"); + type->valueDataOptions->scaleToBlockSize = (rowItemList[2] == "1"); } else if (rowItemList[1] == "seq-specs") { diff --git a/YUViewLib/src/statistics/StatisticsType.cpp b/YUViewLib/src/statistics/StatisticsType.cpp index 8d4fa6c3f..9c3d2c44b 100644 --- a/YUViewLib/src/statistics/StatisticsType.cpp +++ b/YUViewLib/src/statistics/StatisticsType.cpp @@ -67,7 +67,7 @@ LineDrawStyle convertStringToPen(const QString &str) return style; } -void addModifiedValuesToElement(YUViewDomElement & element, +void addModifiedValuesToElement(YUViewDomElement &element, const std::optional &options, const std::optional &initOptions) { @@ -86,7 +86,7 @@ std::vector AllArrowHeads = {StatisticsType::ArrowHea StatisticsType::ArrowHead::circle, StatisticsType::ArrowHead::none}; -void addModifiedValuesToElement(YUViewDomElement & element, +void addModifiedValuesToElement(YUViewDomElement &element, const std::optional &options, const std::optional &initOptions) { @@ -112,7 +112,7 @@ void addModifiedValuesToElement(YUViewDomElement & } } -void addModifiedValuesToElement(YUViewDomElement & element, +void addModifiedValuesToElement(YUViewDomElement &element, const StatisticsType::GridOptions &options, const StatisticsType::GridOptions &initOptions) { @@ -136,19 +136,9 @@ bool LineDrawStyle::operator!=(const LineDrawStyle &other) const return !(*this == other); } -void StatisticsType::setInitialState() -{ - this->init.render = this->render; - this->init.alphaFactor = this->alphaFactor; - - this->init.valueDataOptions = this->valueDataOptions; - this->init.vectorDataOptions = this->vectorDataOptions; - this->init.gridOptions = this->gridOptions; -} - /* Save all the settings of the statistics type that have changed from the initial state */ -void StatisticsType::savePlaylist(YUViewDomElement &root) const +void StatisticsType::saveToPlaylist(YUViewDomElement &root) const { bool allValuesIdenticalToInitialValues = (init.render == this->render && // init.alphaFactor == this->alphaFactor && // @@ -175,10 +165,10 @@ void StatisticsType::savePlaylist(YUViewDomElement &root) const root.appendChild(newChild); } -void StatisticsType::loadPlaylist(const YUViewDomElement &root) +void StatisticsType::tryToLoadFromPlaylist(const YUViewDomElement &root) { const auto [name, attributes] = - root.findChildValueWithAttributes(QString("statType%1").arg(typeID)); + root.findChildValueWithAttributes(QString("statType%1").arg(this->typeID)); if (name.toStdString() != this->typeName) // The name of this type with the right ID and the name in the playlist don't match?... @@ -237,6 +227,8 @@ void StatisticsType::loadPlaylist(const YUViewDomElement &root) else if (name == "scaleGridToZoom") this->gridOptions.scaleToZoom = (value != "0"); } + + this->saveInitialState(); } std::string StatisticsType::getValueText(const int val) const @@ -279,4 +271,19 @@ bool StatisticsType::GridOptions::operator==(const GridOptions &rhs) const this->scaleToZoom == rhs.scaleToZoom; } +StatisticsType::StatisticsType(int typeId, std::string typeName) + : typeID(typeId), typeName(std::move(typeName)) +{ +} + +void StatisticsType::saveInitialState() +{ + this->init.render = this->render; + this->init.alphaFactor = this->alphaFactor; + + this->init.valueDataOptions = this->valueDataOptions; + this->init.vectorDataOptions = this->vectorDataOptions; + this->init.gridOptions = this->gridOptions; +} + } // namespace stats diff --git a/YUViewLib/src/statistics/StatisticsType.h b/YUViewLib/src/statistics/StatisticsType.h index 3ec5cbf1a..38216a732 100644 --- a/YUViewLib/src/statistics/StatisticsType.h +++ b/YUViewLib/src/statistics/StatisticsType.h @@ -68,18 +68,12 @@ struct LineDrawStyle */ class StatisticsType { -public: - StatisticsType() = default; - - // Save all the values that the user could change. When saving to playlist we can save only the - // changed values to playlist. - void setInitialState(); + friend class StatisticsTypeBuilder; - // Load/Save status of statistics from playlist file - void savePlaylist(YUViewDomElement &root) const; - void loadPlaylist(const YUViewDomElement &root); +public: + void saveToPlaylist(YUViewDomElement &root) const; + void tryToLoadFromPlaylist(const YUViewDomElement &root); - // Every statistics type has an ID, a name and possibly a description int typeID{}; std::string typeName{}; std::string description{}; @@ -138,9 +132,11 @@ class StatisticsType GridOptions gridOptions; private: + StatisticsType() = delete; + StatisticsType(int typeId, std::string typeName); + std::map valuesToText; - // Backup values for setDefaultState() struct initialState { bool render; @@ -151,6 +147,8 @@ class StatisticsType GridOptions gridOptions; }; initialState init; + + void saveInitialState(); }; } // namespace stats diff --git a/YUViewLib/src/statistics/StatisticsTypeBuilder.h b/YUViewLib/src/statistics/StatisticsTypeBuilder.h index 237e1e04b..6bc77ebf8 100644 --- a/YUViewLib/src/statistics/StatisticsTypeBuilder.h +++ b/YUViewLib/src/statistics/StatisticsTypeBuilder.h @@ -38,16 +38,9 @@ namespace stats class StatisticsTypeBuilder { public: - StatisticsTypeBuilder &withTypeID(const int typeID) + StatisticsTypeBuilder() = delete; + StatisticsTypeBuilder(int typeID, const std::string &typeName) : statisticsType(typeID, typeName) { - this->statisticsType.typeID = typeID; - return *this; - } - - StatisticsTypeBuilder &withTypeName(const std::string &typeName) - { - this->statisticsType.typeName = typeName; - return *this; } StatisticsTypeBuilder &withDescription(const std::string &description) @@ -75,6 +68,13 @@ class StatisticsTypeBuilder return *this; } + StatisticsTypeBuilder + withValueDataOptions(const std::optional &valueDataOptions) + { + this->statisticsType.valueDataOptions = valueDataOptions; + return *this; + } + StatisticsTypeBuilder withVectorDataOptions(const StatisticsType::VectorDataOptions &vectorDataOptions) { @@ -82,6 +82,13 @@ class StatisticsTypeBuilder return *this; } + StatisticsTypeBuilder + withVectorDataOptions(const std::optional &vectorDataOptions) + { + this->statisticsType.vectorDataOptions = vectorDataOptions; + return *this; + } + StatisticsTypeBuilder withGridOptions(const StatisticsType::GridOptions &gridOptions) { this->statisticsType.gridOptions = gridOptions; @@ -96,17 +103,16 @@ class StatisticsTypeBuilder StatisticsTypeBuilder &withMappingValues(const std::initializer_list &mappingValues) { - std::vector values; + int typeId = 0; for (const auto &value : mappingValues) - values.push_back(value); + this->statisticsType.valuesToText[typeId++] = value; - this->statisticsType.setMappingValues(values); return *this; } StatisticsType build() { - this->statisticsType.setInitialState(); + this->statisticsType.saveInitialState(); return this->statisticsType; } diff --git a/YUViewLib/src/ui/views/SplitViewWidget.cpp b/YUViewLib/src/ui/views/SplitViewWidget.cpp index 185817de8..3b59f38a9 100644 --- a/YUViewLib/src/ui/views/SplitViewWidget.cpp +++ b/YUViewLib/src/ui/views/SplitViewWidget.cpp @@ -100,7 +100,7 @@ splitViewWidget::splitViewWidget(QWidget *parent) : MoveAndZoomableView(parent) setContextMenuPolicy(Qt::PreventContextMenu); // No test running yet - connect(&testProgrssUpdateTimer, &QTimer::timeout, this, [=] { updateTestProgress(); }); + connect(&testProgrssUpdateTimer, &QTimer::timeout, this, [this] { this->updateTestProgress(); }); // Initialize the font and the position of the zoom factor indication zoomFactorFont = QFont(SPLITVIEWWIDGET_ZOOMFACTOR_FONT, SPLITVIEWWIDGET_ZOOMFACTOR_FONTSIZE); @@ -235,7 +235,7 @@ void splitViewWidget::paintEvent(QPaintEvent *) // For the zoom box, calculate the pixel position under the cursor for each view. The following // things are calculated in this function: bool pixelPosInItem[2] = {false, - false}; //< Is the pixel position under the cursor within the item? + false}; //< Is the pixel position under the cursor within the item? QRect zoomPixelRect[2]; //< A QRect around the pixel that is under the cursor if (anyItemsSelected && this->drawZoomBox) { @@ -617,7 +617,7 @@ void splitViewWidget::setZoomBoxPixelUnderCursor(QPoint posA, } void splitViewWidget::paintZoomBox(int view, - QPainter & painter, + QPainter &painter, int xSplit, const QPoint &drawArea_botR, playlistItem *item, @@ -803,7 +803,7 @@ void splitViewWidget::paintRegularGrid(QPainter *painter, playlistItem *item) } } -void splitViewWidget::paintPixelRulersX(QPainter & painter, +void splitViewWidget::paintPixelRulersX(QPainter &painter, playlistItem *item, int xPixMin, int xPixMax, @@ -857,7 +857,7 @@ void splitViewWidget::paintPixelRulersX(QPainter & painter, } } -void splitViewWidget::paintPixelRulersY(QPainter & painter, +void splitViewWidget::paintPixelRulersY(QPainter &painter, playlistItem *item, int yPixMax, int xPos, @@ -1605,9 +1605,9 @@ void splitViewWidget::freezeView(bool freeze) } void splitViewWidget::getViewState(QPointF &offset, - double & zoom, - double & splitPoint, - int & mode) const + double &zoom, + double &splitPoint, + int &mode) const { offset = this->moveOffset; zoom = this->zoomFactor; @@ -1657,14 +1657,15 @@ void splitViewWidget::createMenuActions() const bool menuActionsCreatedYet = bool(this->actionSplitViewGroup); Q_ASSERT_X(!menuActionsCreatedYet, Q_FUNC_INFO, "Only call this initialization function once."); - auto configureAction = [this](QAction & action, + auto configureAction = [this](QAction &action, QActionGroup *const actionGroup, - const QString & text, + const QString &text, const bool checkable, const bool checked, void (splitViewWidget::*func)(bool), const QKeySequence &shortcut = {}, - const bool isEnabled = true) { + const bool isEnabled = true) + { action.setParent(this); action.setCheckable(checkable); action.setChecked(checked); diff --git a/YUViewUnitTest/statistics/StatisticsDataTest.cpp b/YUViewUnitTest/statistics/StatisticsDataTest.cpp index 263b384b7..52cf6d1a0 100644 --- a/YUViewUnitTest/statistics/StatisticsDataTest.cpp +++ b/YUViewUnitTest/statistics/StatisticsDataTest.cpp @@ -45,9 +45,7 @@ TEST(StatisticsData, testPixelValueRetrievalInteger) constexpr auto typeID = 0; constexpr auto frameIndex = 0; - data.addStatType(StatisticsTypeBuilder() - .withTypeID(typeID) - .withTypeName("Something") + data.addStatType(StatisticsTypeBuilder(typeID, "Something") .withValueDataOptions({.colorMapper = stats::color::ColorMapper( {0, 10}, stats::color::PredefinedType::Jet)}) .withRender(true) @@ -77,9 +75,7 @@ TEST(StatisticsData, testPixelValueRetrievalVector) constexpr auto typeID = 0; constexpr auto frameIndex = 0; - data.addStatType(StatisticsTypeBuilder() - .withTypeID(typeID) - .withTypeName("Something") + data.addStatType(StatisticsTypeBuilder(typeID, "Something") .withVectorDataOptions({.scale = 4}) .withRender(true) .build()); diff --git a/YUViewUnitTest/statistics/StatisticsTypeBuilderTest.cpp b/YUViewUnitTest/statistics/StatisticsTypeBuilderTest.cpp index ab0a4edae..6cfb32765 100644 --- a/YUViewUnitTest/statistics/StatisticsTypeBuilderTest.cpp +++ b/YUViewUnitTest/statistics/StatisticsTypeBuilderTest.cpp @@ -39,7 +39,7 @@ namespace stats::test TEST(StatisticsTypeBuilderTest, DefaultValues) { - const auto statisticsType = StatisticsTypeBuilder().build(); + const auto statisticsType = StatisticsTypeBuilder(0, "").build(); EXPECT_EQ(statisticsType.typeID, 0); EXPECT_TRUE(statisticsType.typeName.empty()); @@ -55,9 +55,7 @@ TEST(StatisticsTypeBuilderTest, DefaultValues) TEST(StatisticsTypeBuilderTest, SetTypeNameDescriptionAndRenderValues) { - const auto statisticsType = StatisticsTypeBuilder() - .withTypeID(1) - .withTypeName("TestType") + const auto statisticsType = StatisticsTypeBuilder(1, "TestType") .withDescription("TestDescription") .withRender(true) .withAlphaFactor(75) @@ -72,7 +70,8 @@ TEST(StatisticsTypeBuilderTest, SetTypeNameDescriptionAndRenderValues) TEST(StatisticsTypeBuilderTest, SetValueDatDefaultValues) { - const auto statisticsType = StatisticsTypeBuilder().withValueDataOptions({}).build(); + const auto statisticsType = + StatisticsTypeBuilder(0, "").withValueDataOptions(StatisticsType::ValueDataOptions()).build(); EXPECT_TRUE(statisticsType.valueDataOptions); EXPECT_EQ(statisticsType.valueDataOptions->render, true); @@ -85,7 +84,7 @@ TEST(StatisticsTypeBuilderTest, SetValueDataCustomValues) const color::ColorMapper colorMapper({0, 255}, color::PredefinedType::Jet); const auto statisticsType = - stats::StatisticsTypeBuilder() + stats::StatisticsTypeBuilder(0, "") .withValueDataOptions( {.render = false, .scaleToBlockSize = true, .colorMapper = colorMapper}) .build(); @@ -98,7 +97,9 @@ TEST(StatisticsTypeBuilderTest, SetValueDataCustomValues) TEST(StatisticsTypeBuilderTest, SetVectorDataDefaultValues) { - const auto statisticsType = StatisticsTypeBuilder().withVectorDataOptions({}).build(); + const auto statisticsType = StatisticsTypeBuilder(0, "") + .withVectorDataOptions(StatisticsType::VectorDataOptions()) + .build(); EXPECT_TRUE(statisticsType.vectorDataOptions); EXPECT_TRUE(statisticsType.vectorDataOptions->render); @@ -114,7 +115,7 @@ TEST(StatisticsTypeBuilderTest, SetVectorDataCustomValues) { const LineDrawStyle lineDrawStyle({Color(255, 0, 0), 2, Pattern::DashDot}); - const auto statisticsType = StatisticsTypeBuilder() + const auto statisticsType = StatisticsTypeBuilder(0, "") .withVectorDataOptions({ .render = false, .renderDataValues = false, @@ -138,7 +139,7 @@ TEST(StatisticsTypeBuilderTest, SetVectorDataCustomValues) TEST(StatisticsTypeBuilderTest, SetGridOptionsDefaultValues) { - const auto statisticsType = StatisticsTypeBuilder().withGridOptions({}).build(); + const auto statisticsType = StatisticsTypeBuilder(0, "").withGridOptions({}).build(); EXPECT_FALSE(statisticsType.gridOptions.render); EXPECT_EQ(statisticsType.gridOptions.style, LineDrawStyle()); @@ -150,7 +151,7 @@ TEST(StatisticsTypeBuilderTest, SetGridOptionsCustomValues) const LineDrawStyle lineDrawStyle({Color(123, 44, 99), 5, Pattern::DashDot}); const auto statisticsType = - StatisticsTypeBuilder() + StatisticsTypeBuilder(0, "") .withGridOptions({.render = true, .style = lineDrawStyle, .scaleToZoom = true}) .build(); diff --git a/YUViewUnitTest/statistics/StatisticsTypeTest.cpp b/YUViewUnitTest/statistics/StatisticsTypeTest.cpp index 5b05532be..d65c851d6 100644 --- a/YUViewUnitTest/statistics/StatisticsTypeTest.cpp +++ b/YUViewUnitTest/statistics/StatisticsTypeTest.cpp @@ -40,7 +40,7 @@ namespace stats::test TEST(StatisticsTypeTest, GetValueText) { const auto statisticsType = - StatisticsTypeBuilder().withMappingValues({"First", "Second", "Third"}).build(); + StatisticsTypeBuilder(0, "").withMappingValues({"First", "Second", "Third"}).build(); EXPECT_EQ(statisticsType.getValueText(0), "First (0)"); EXPECT_EQ(statisticsType.getValueText(1), "Second (1)"); @@ -51,6 +51,4 @@ TEST(StatisticsTypeTest, GetValueText) EXPECT_EQ(statisticsType.getValueText(-1), "-1"); } - - } // namespace stats::test