From cef1055d2119e1892c13d2baf3da38062b1d7ff1 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 30 Apr 2021 18:23:13 -0400 Subject: [PATCH] feat: improve plugin parameter specification (helps #84) --- src/hobbits-core/parameterdelegate.cpp | 80 +++++++++++++------ src/hobbits-core/parameterdelegate.h | 39 +++++++-- src/hobbits-plugins/analyzers/Find/find.cpp | 8 +- .../analyzers/Highlight/highlight.cpp | 11 +-- .../analyzers/KaitaiStruct/kaitaistruct.cpp | 9 ++- .../analyzers/Metadata/metadata.cpp | 9 ++- .../analyzers/WidthFramer/widthframer.cpp | 7 +- .../analyzers/WidthFramer/widthframerform.cpp | 2 +- src/hobbits-plugins/displays/Ascii/ascii.cpp | 17 ++-- .../displays/Binary/binary.cpp | 18 +++-- .../displays/BitRaster/bitraster.cpp | 16 ++-- .../displays/ByteRaster/byteraster.cpp | 16 ++-- .../displays/DigraphPlot/digraphplot.cpp | 11 +-- .../displays/DotPlot/dotplot.cpp | 11 +-- .../displays/FrequencyPlot/frequencyplot.cpp | 18 +++-- src/hobbits-plugins/displays/Hex/hex.cpp | 18 +++-- .../displays/HilbertPlot/hilbertplot.cpp | 10 ++- .../displays/Spectrogram/spectrogram.cpp | 28 ++++--- .../displays/SymbolRaster/symbolraster.cpp | 18 +++-- .../DisplayPrint/displayprint.cpp | 15 ++-- .../importerexporters/FileData/filedata.cpp | 2 +- .../importerexporters/HexString/hexstring.cpp | 13 +-- .../importerexporters/HttpData/httpdata.cpp | 20 ++--- .../importerexporters/Lfsr/lfsr.cpp | 6 +- .../PacketCapture/packetcapture.cpp | 23 +++--- .../importerexporters/TcpData/tcpdata.cpp | 22 ++--- .../importerexporters/UdpData/udpdata.cpp | 20 ++--- .../operators/BitsError/bitserror.cpp | 6 +- .../operators/Extractor/extractor.cpp | 15 ++-- .../operators/HeaderFramer/headerframer.cpp | 15 ++-- .../HeaderFramer/headerframerform.cpp | 2 +- .../operators/PythonRunner/pythonrunner.cpp | 7 +- .../SymbolRemapper/symbolremapper.cpp | 13 +-- .../SymbolRemapper/symbolremapperform.cpp | 2 +- .../operators/TakeSkip/takeskip.cpp | 8 +- src/hobbits-python/pythonanalyzer.cpp | 21 +++-- src/hobbits-python/pythonarg.cpp | 12 ++- src/hobbits-python/pythonarg.h | 5 +- src/hobbits-python/pythondisplay.cpp | 22 +++-- src/hobbits-python/pythonexporter.cpp | 21 +++-- src/hobbits-python/pythonimporter.cpp | 21 +++-- src/hobbits-python/pythoninterpreter.cpp | 3 + src/hobbits-python/pythonoperator.cpp | 21 +++-- src/hobbits-python/pythonpluginconfig.cpp | 54 ++++++++----- src/hobbits-python/pythonpluginconfig.h | 7 -- src/hobbits-widgets/displayhelper.cpp | 2 +- src/hobbits-widgets/parameterhelper.cpp | 30 +++++-- src/hobbits-widgets/parameterhelper.h | 3 + src/hobbits-widgets/simpleparametereditor.cpp | 32 ++++++-- 49 files changed, 467 insertions(+), 322 deletions(-) diff --git a/src/hobbits-core/parameterdelegate.cpp b/src/hobbits-core/parameterdelegate.cpp index 1ff9b472..417acadc 100644 --- a/src/hobbits-core/parameterdelegate.cpp +++ b/src/hobbits-core/parameterdelegate.cpp @@ -38,6 +38,25 @@ AbstractParameterEditor* ParameterDelegate::createEditor(QSize targetBounds) return m_editorCreator(sharedFromThis(), targetBounds); } +bool ParameterDelegate::jsonTypeCompatible(QJsonValue::Type jsonType, ParameterDelegate::ParameterType type) { + if (jsonType == QJsonValue::Double) { + return (type == ParameterType::Decimal) || (type == ParameterType::Integer); + } + else if (jsonType == QJsonValue::String) { + return type == ParameterType::String; + } + else if (jsonType == QJsonValue::Bool) { + return type == ParameterType::Boolean; + } + else if (jsonType == QJsonValue::Array) { + return type == ParameterType::Array; + } + else if (jsonType == QJsonValue::Object) { + return type == ParameterType::Object; + } + return false; +} + QList ParameterDelegate::parameterInfos() const { return m_parameterMap.values(); @@ -48,66 +67,81 @@ ParameterDelegate::ParameterInfo ParameterDelegate::getInfo(QString name) const return m_parameterMap.value(name); } -bool ParameterDelegate::validate(const QJsonObject ¶meters) const +QStringList ParameterDelegate::validate(const QJsonObject ¶meters) const { return validateAgainstInfos(parameters, parameterInfos()); } QString ParameterDelegate::actionDescription(const QJsonObject ¶meters) const { - if (!validate(parameters)) { + if (!validate(parameters).isEmpty()) { return QString(); } return m_actionDescriber(parameters); } -bool ParameterDelegate::validateAgainstInfos(const QJsonObject ¶meters, QList infos) +QStringList ParameterDelegate::validateAgainstInfos(const QJsonObject ¶meters, QList infos) { - if (infos.isEmpty()) { - return true; - } + QStringList invalidations; for (auto param : infos) { if (!parameters.contains(param.name)) { if (!param.optional) { - return false; + invalidations.append(QString("Missing required parameter '%1'.").arg(param.name)); + continue; } } - else if (param.type != parameters.value(param.name).type()) { - return false; + else if (!jsonTypeCompatible(parameters.value(param.name).type(), param.type)) { + invalidations.append(QString("Value of provided parameter '%1' is wrong type.").arg(param.name)); + continue; } - if (param.type == QJsonValue::Array) { + if (param.type == ParameterType::Array) { QJsonArray array = parameters.value(param.name).toArray(); if (array.isEmpty() && !param.optional) { - return false; + invalidations.append(QString("Required array parameter '%1' is empty.").arg(param.name)); + continue; } for (QJsonValueRef value: array) { if (!value.isObject()) { - return false; + invalidations.append(QString("Array parameter '%1' has invalid value '%2'.").arg(param.name).arg(value.toString())); } - if (!validateAgainstInfos(value.toObject(), param.subInfos)) { - return false; + else { + invalidations.append(validateAgainstInfos(value.toObject(), param.subInfos)); } } } - else if (param.type == QJsonValue::Object) { + else if (param.type == ParameterType::Object) { QJsonValue val = parameters.value(param.name); if (!val.isObject()) { - return false; + invalidations.append(QString("Object parameter '%1' is not an object.").arg(param.name)); + } + else { + invalidations.append(validateAgainstInfos(val.toObject(), param.subInfos)); } - if (!validateAgainstInfos(val.toObject(), param.subInfos)) { - return false; + } + else if (!param.possibleValues.isEmpty()) { + if (!param.possibleValues.contains(parameters.value(param.name))) { + invalidations.append(QString("Parameter '%1' has invalid value '%2'.").arg(param.name).arg(parameters.value(param.name).toString())); } } - else if (param.type == QJsonValue::Double && param.hasIntLimits) { - int value = parameters.value(param.name).toInt(); - if (value > param.intMax || value < param.intMin) { - return false; + else if (param.type == ParameterType::Integer || param.type == ParameterType::Decimal) { + if (!param.ranges.isEmpty()) { + double value = parameters.value(param.name).toDouble(); + bool within = false; + for (auto range : param.ranges) { + if (value >= range.first && value <= range.second) { + within = true; + break; + } + } + if (!within) { + invalidations.append(QString("Parameter '%1' value '%2' is outside valid range.").arg(param.name).arg(value)); + } } } } - return true; + return invalidations; } diff --git a/src/hobbits-core/parameterdelegate.h b/src/hobbits-core/parameterdelegate.h index a040a5fc..cf4016ee 100644 --- a/src/hobbits-core/parameterdelegate.h +++ b/src/hobbits-core/parameterdelegate.h @@ -27,19 +27,40 @@ class HOBBITSCORESHARED_EXPORT ParameterDelegate : public QEnableSharedFromThis { public: + + /** + * @brief The ParameterType enum provides type classifications for parameters + * + * ParameterType is similar to QJsonValue, but without null or undefined, and with a + * decimal/integer distinction. + */ + enum ParameterType + { + Boolean = 0x1, + Decimal = 0x2, + String = 0x3, + Array = 0x4, + Object = 0x5, + Integer = 0x10 + }; + + /** + * @brief The ParameterInfo struct contains information for a parameter + * + * A parameter's ParameterInfo can be used to provide editors and validation for a parameter. + */ struct HOBBITSCORESHARED_EXPORT ParameterInfo { QString name; - QJsonValue::Type type; + ParameterType type; bool optional; QList subInfos; - bool hasIntLimits; - int intMin; - int intMax; + QList> ranges; + QList possibleValues; - ParameterInfo(QString name, QJsonValue::Type type, bool optional = true, QList subInfos = {}): - name{name}, type{type}, optional{optional}, subInfos{subInfos}, hasIntLimits(false), intMin(0), intMax(INT_MAX) {} + ParameterInfo(QString name, ParameterType type, bool optional = true, QList subInfos = {}): + name{name}, type{type}, optional{optional}, subInfos{subInfos}, ranges(QList>()), possibleValues(QList()) {} ParameterInfo() = default; ParameterInfo(const ParameterInfo&) = default; @@ -56,16 +77,18 @@ class HOBBITSCORESHARED_EXPORT ParameterDelegate : public QEnableSharedFromThis< std::function actionDescriber, std::function, QSize)> editorCreator); + static bool jsonTypeCompatible(QJsonValue::Type jsonType, ParameterType type); + virtual AbstractParameterEditor* createEditor(QSize targetBounds = QSize()); QList parameterInfos() const; ParameterInfo getInfo(QString name) const; - bool validate(const QJsonObject ¶meters) const; + QStringList validate(const QJsonObject ¶meters) const; QString actionDescription(const QJsonObject ¶meters) const; protected: - static bool validateAgainstInfos(const QJsonObject ¶meters, QList infos); + static QStringList validateAgainstInfos(const QJsonObject ¶meters, QList infos); QMap m_parameterMap; std::function m_actionDescriber; std::function, QSize)> m_editorCreator; diff --git a/src/hobbits-plugins/analyzers/Find/find.cpp b/src/hobbits-plugins/analyzers/Find/find.cpp index bfee6899..a8c08802 100644 --- a/src/hobbits-plugins/analyzers/Find/find.cpp +++ b/src/hobbits-plugins/analyzers/Find/find.cpp @@ -5,7 +5,7 @@ Find::Find() { QList infos = { - {"search_string", QJsonValue::String} + {"search_string", ParameterDelegate::ParameterType::String} }; m_delegate = ParameterDelegate::create( @@ -49,9 +49,11 @@ QSharedPointer Find::analyzeBits( const QJsonObject ¶meters, QSharedPointer progress) { - if (!m_delegate->validate(parameters)) { - return AnalyzerResult::error(QString("Invalid parameters passed to %1").arg(name())); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return AnalyzerResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } + auto findBits = BitArray::fromString(parameters.value("search_string").toString()); auto bits = container->bits(); diff --git a/src/hobbits-plugins/analyzers/Highlight/highlight.cpp b/src/hobbits-plugins/analyzers/Highlight/highlight.cpp index 80499d46..c4b01d1e 100644 --- a/src/hobbits-plugins/analyzers/Highlight/highlight.cpp +++ b/src/hobbits-plugins/analyzers/Highlight/highlight.cpp @@ -5,9 +5,9 @@ Highlight::Highlight() { QList infos = { - {"start", QJsonValue::Double}, - {"length", QJsonValue::Double}, - {"color", QJsonValue::Double, true} + {"start", ParameterDelegate::ParameterType::Integer}, + {"length", ParameterDelegate::ParameterType::Integer}, + {"color", ParameterDelegate::ParameterType::Integer, true} }; m_delegate = QSharedPointer( @@ -55,8 +55,9 @@ QSharedPointer Highlight::analyzeBits( QSharedPointer progress) { progress->setProgressPercent(5); - if (!m_delegate->validate(parameters)) { - return AnalyzerResult::error(QString("Invalid parameters passed to %1").arg(name())); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return AnalyzerResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } qint64 start = parameters.value("start").toInt(); diff --git a/src/hobbits-plugins/analyzers/KaitaiStruct/kaitaistruct.cpp b/src/hobbits-plugins/analyzers/KaitaiStruct/kaitaistruct.cpp index f92eaa93..532f10fb 100644 --- a/src/hobbits-plugins/analyzers/KaitaiStruct/kaitaistruct.cpp +++ b/src/hobbits-plugins/analyzers/KaitaiStruct/kaitaistruct.cpp @@ -13,8 +13,8 @@ KaitaiStruct::KaitaiStruct() { QList infos = { - {PARAM_KSY, QJsonValue::String, true}, - {PARAM_PY, QJsonValue::String, true} + {PARAM_KSY, ParameterDelegate::ParameterType::String, true}, + {PARAM_PY, ParameterDelegate::ParameterType::String, true} }; m_delegate = QSharedPointer( @@ -68,8 +68,9 @@ QSharedPointer KaitaiStruct::analyzeBits( const QJsonObject ¶meters, QSharedPointer progress) { - if (!m_delegate->validate(parameters)) { - return AnalyzerResult::error("Invalid parameters given to plugin"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return AnalyzerResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } progress->setProgressPercent(2); diff --git a/src/hobbits-plugins/analyzers/Metadata/metadata.cpp b/src/hobbits-plugins/analyzers/Metadata/metadata.cpp index 220ed340..c1197296 100644 --- a/src/hobbits-plugins/analyzers/Metadata/metadata.cpp +++ b/src/hobbits-plugins/analyzers/Metadata/metadata.cpp @@ -4,8 +4,8 @@ Metadata::Metadata() { QList infos = { - {"label", QJsonValue::String}, - {"contents", QJsonValue::String} + {"label", ParameterDelegate::ParameterType::String}, + {"contents", ParameterDelegate::ParameterType::String} }; m_delegate = ParameterDelegate::create( @@ -51,8 +51,9 @@ QSharedPointer Metadata::analyzeBits( QSharedPointer progress) { Q_UNUSED(progress) - if (!m_delegate->validate(parameters)) { - return AnalyzerResult::error(QString("Invalid parameters passed to %1").arg(name())); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return AnalyzerResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QString label = parameters.value("label").toString(); diff --git a/src/hobbits-plugins/analyzers/WidthFramer/widthframer.cpp b/src/hobbits-plugins/analyzers/WidthFramer/widthframer.cpp index d0a111ba..b2f47a43 100644 --- a/src/hobbits-plugins/analyzers/WidthFramer/widthframer.cpp +++ b/src/hobbits-plugins/analyzers/WidthFramer/widthframer.cpp @@ -7,7 +7,7 @@ WidthFramer::WidthFramer() { QList infos = { - {"width", QJsonValue::Double} + {"width", ParameterDelegate::ParameterType::Integer} }; m_delegate = ParameterDelegate::create( @@ -53,8 +53,9 @@ QSharedPointer WidthFramer::analyzeBits( const QJsonObject ¶meters, QSharedPointer progress) { - if (!m_delegate->validate(parameters)) { - return AnalyzerResult::error("Invalid parameters passed to Width Framer"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return AnalyzerResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } progress->setProgressPercent(10); diff --git a/src/hobbits-plugins/analyzers/WidthFramer/widthframerform.cpp b/src/hobbits-plugins/analyzers/WidthFramer/widthframerform.cpp index 210792a4..f680aac7 100644 --- a/src/hobbits-plugins/analyzers/WidthFramer/widthframerform.cpp +++ b/src/hobbits-plugins/analyzers/WidthFramer/widthframerform.cpp @@ -52,7 +52,7 @@ QString WidthFramerForm::title() bool WidthFramerForm::setParameters(QJsonObject parameters) { - if (!m_delegate->validate(parameters)) { + if (!m_delegate->validate(parameters).isEmpty()) { return false; } diff --git a/src/hobbits-plugins/displays/Ascii/ascii.cpp b/src/hobbits-plugins/displays/Ascii/ascii.cpp index 17ad1520..6b0a78c3 100644 --- a/src/hobbits-plugins/displays/Ascii/ascii.cpp +++ b/src/hobbits-plugins/displays/Ascii/ascii.cpp @@ -13,10 +13,10 @@ Ascii::Ascii() : QList infos = { - {"font_size", QJsonValue::Double}, - {"column_grouping", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool}, - {"encoding", QJsonValue::String} + {"font_size", ParameterDelegate::ParameterType::Integer}, + {"column_grouping", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean}, + {"encoding", ParameterDelegate::ParameterType::String} }; m_delegate = ParameterDelegate::create( @@ -64,7 +64,7 @@ void Ascii::setDisplayHandle(QSharedPointer displayHandle) { m_handle = displayHandle; DisplayHelper::connectHoverUpdates(this, this, m_handle, [this](QPoint& offset, QSize &symbolSize, int &grouping, int &bitsPerSymbol) { - if (!m_delegate->validate(m_lastParams)) { + if (!m_delegate->validate(m_lastParams).isEmpty()) { return false; } offset = headerOffset(m_lastParams); @@ -86,8 +86,9 @@ QSharedPointer Ascii::renderDisplay(QSize viewportSize, const QJs { Q_UNUSED(progress) m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QString encoding = parameters.value("encoding").toString(); @@ -105,7 +106,7 @@ QSharedPointer Ascii::renderDisplay(QSize viewportSize, const QJs QSharedPointer Ascii::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { - if (!m_delegate->validate(m_lastParams)) { + if (!m_delegate->validate(m_lastParams).isEmpty()) { return DisplayResult::nullResult(); } QSize fontSize = DisplayHelper::textSize(DisplayHelper::monoFont(m_lastParams.value("font_size").toInt()), "0"); diff --git a/src/hobbits-plugins/displays/Binary/binary.cpp b/src/hobbits-plugins/displays/Binary/binary.cpp index 7907d23c..f6038eaa 100644 --- a/src/hobbits-plugins/displays/Binary/binary.cpp +++ b/src/hobbits-plugins/displays/Binary/binary.cpp @@ -12,9 +12,9 @@ Binary::Binary() : m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewBitHover); QList infos = { - {"font_size", QJsonValue::Double}, - {"column_grouping", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool} + {"font_size", ParameterDelegate::ParameterType::Integer}, + {"column_grouping", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean} }; m_delegate = ParameterDelegate::create( @@ -62,7 +62,7 @@ void Binary::setDisplayHandle(QSharedPointer displayHandle) { m_handle = displayHandle; DisplayHelper::connectHoverUpdates(this, this, m_handle, [this](QPoint& offset, QSize &symbolSize, int &grouping, int &bitsPerSymbol) { - if (!m_delegate->validate(m_lastParams)) { + if (!m_delegate->validate(m_lastParams).isEmpty()) { return false; } offset = headerOffset(m_lastParams); @@ -84,9 +84,10 @@ QSharedPointer Binary::renderDisplay(QSize viewportSize, const QJ { Q_UNUSED(progress) m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } auto image = DisplayHelper::drawTextRasterFull(viewportSize, headerOffset(parameters), this, m_handle, parameters, 1, @@ -106,8 +107,9 @@ QSharedPointer Binary::renderDisplay(QSize viewportSize, const QJ QSharedPointer Binary::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { - if (!m_delegate->validate(m_lastParams)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QSize fontSize = DisplayHelper::textSize(DisplayHelper::monoFont(m_lastParams.value("font_size").toInt()), "0"); int columnGrouping = m_lastParams.value("column_grouping").toInt(); diff --git a/src/hobbits-plugins/displays/BitRaster/bitraster.cpp b/src/hobbits-plugins/displays/BitRaster/bitraster.cpp index f572743e..a130eda8 100644 --- a/src/hobbits-plugins/displays/BitRaster/bitraster.cpp +++ b/src/hobbits-plugins/displays/BitRaster/bitraster.cpp @@ -12,8 +12,8 @@ BitRaster::BitRaster() : m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewBitHover); QList infos = { - {"scale", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool} + {"scale", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean} }; m_delegate = ParameterDelegate::create( @@ -62,7 +62,7 @@ void BitRaster::setDisplayHandle(QSharedPointer displayHandle) { m_handle = displayHandle; DisplayHelper::connectHoverUpdates(this, this, m_handle, [this](QPoint& offset, QSize &symbolSize, int &grouping, int &bitsPerSymbol) { - if (!m_delegate->validate(m_lastParams)) { + if (!m_delegate->validate(m_lastParams).isEmpty()) { return false; } int scale = m_lastParams.value("scale").toInt(); @@ -84,9 +84,10 @@ QSharedPointer BitRaster::renderDisplay(QSize viewportSize, const Q_UNUSED(progress) m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); @@ -135,8 +136,9 @@ QSharedPointer BitRaster::renderDisplay(QSize viewportSize, const QSharedPointer BitRaster::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { m_lastParams = parameters; - if (!m_delegate->validate(m_lastParams)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } int scale = parameters.value("scale").toInt(); diff --git a/src/hobbits-plugins/displays/ByteRaster/byteraster.cpp b/src/hobbits-plugins/displays/ByteRaster/byteraster.cpp index 8189a66a..5096342c 100644 --- a/src/hobbits-plugins/displays/ByteRaster/byteraster.cpp +++ b/src/hobbits-plugins/displays/ByteRaster/byteraster.cpp @@ -12,8 +12,8 @@ ByteRaster::ByteRaster() : m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewBitHover); QList infos = { - {"scale", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool} + {"scale", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean} }; m_delegate = ParameterDelegate::create( @@ -62,7 +62,7 @@ void ByteRaster::setDisplayHandle(QSharedPointer displayHandle) { m_handle = displayHandle; DisplayHelper::connectHoverUpdates(this, this, m_handle, [this](QPoint& offset, QSize &symbolSize, int &grouping, int &bitsPerSymbol) { - if (!m_delegate->validate(m_lastParams)) { + if (!m_delegate->validate(m_lastParams).isEmpty()) { return false; } int scale = m_lastParams.value("scale").toInt(); @@ -84,9 +84,10 @@ QSharedPointer ByteRaster::renderDisplay(QSize viewportSize, cons Q_UNUSED(progress) m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); @@ -136,8 +137,9 @@ QSharedPointer ByteRaster::renderDisplay(QSize viewportSize, cons QSharedPointer ByteRaster::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { m_lastParams = parameters; - if (!m_delegate->validate(m_lastParams)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } int scale = parameters.value("scale").toInt(); diff --git a/src/hobbits-plugins/displays/DigraphPlot/digraphplot.cpp b/src/hobbits-plugins/displays/DigraphPlot/digraphplot.cpp index 5617b656..1f77eeaf 100644 --- a/src/hobbits-plugins/displays/DigraphPlot/digraphplot.cpp +++ b/src/hobbits-plugins/displays/DigraphPlot/digraphplot.cpp @@ -10,9 +10,9 @@ DigraphPlot::DigraphPlot() : m_renderConfig->setFullRedrawTriggers(DisplayRenderConfig::NewBitOffset | DisplayRenderConfig::NewFrameOffset); QList infos = { - {"scale", QJsonValue::Double}, - {"word_size", QJsonValue::Double}, - {"window_size", QJsonValue::Double} + {"scale", ParameterDelegate::ParameterType::Integer}, + {"word_size", ParameterDelegate::ParameterType::Integer}, + {"window_size", ParameterDelegate::ParameterType::Integer} }; m_delegate = ParameterDelegate::create( @@ -66,9 +66,10 @@ QSharedPointer DigraphPlot::renderDisplay(QSize viewportSize, con { Q_UNUSED(progress) - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); diff --git a/src/hobbits-plugins/displays/DotPlot/dotplot.cpp b/src/hobbits-plugins/displays/DotPlot/dotplot.cpp index d8ceb730..f36fad8a 100644 --- a/src/hobbits-plugins/displays/DotPlot/dotplot.cpp +++ b/src/hobbits-plugins/displays/DotPlot/dotplot.cpp @@ -10,9 +10,9 @@ DotPlot::DotPlot() : m_renderConfig->setFullRedrawTriggers(DisplayRenderConfig::NewBitOffset | DisplayRenderConfig::NewFrameOffset); QList infos = { - {"scale", QJsonValue::Double}, - {"word_size", QJsonValue::Double}, - {"window_size", QJsonValue::Double} + {"scale", ParameterDelegate::ParameterType::Integer}, + {"word_size", ParameterDelegate::ParameterType::Integer}, + {"window_size", ParameterDelegate::ParameterType::Integer} }; m_delegate = ParameterDelegate::create( @@ -66,9 +66,10 @@ QSharedPointer DotPlot::renderDisplay(QSize viewportSize, const Q { Q_UNUSED(progress) - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); diff --git a/src/hobbits-plugins/displays/FrequencyPlot/frequencyplot.cpp b/src/hobbits-plugins/displays/FrequencyPlot/frequencyplot.cpp index ae61a7be..946cd804 100644 --- a/src/hobbits-plugins/displays/FrequencyPlot/frequencyplot.cpp +++ b/src/hobbits-plugins/displays/FrequencyPlot/frequencyplot.cpp @@ -11,9 +11,9 @@ FrequencyPlot::FrequencyPlot() : m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewMouseHover); QList infos = { - {"scale", QJsonValue::Double}, - {"word_size", QJsonValue::Double}, - {"window_size", QJsonValue::Double} + {"scale", ParameterDelegate::ParameterType::Integer}, + {"word_size", ParameterDelegate::ParameterType::Integer}, + {"window_size", ParameterDelegate::ParameterType::Integer} }; m_delegate = ParameterDelegate::create( @@ -69,9 +69,10 @@ QSharedPointer FrequencyPlot::renderDisplay(QSize viewportSize, c m_barMax.clear(); m_barFrequencies.clear(); - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); @@ -161,13 +162,14 @@ QSharedPointer FrequencyPlot::renderDisplay(QSize viewportSize, c QSharedPointer FrequencyPlot::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { - if (!m_delegate->validate(parameters)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QPoint hover = m_handle->mouseHover(this); if (m_handle.isNull() || m_handle->currentContainer().isNull() - || !m_delegate->validate(parameters) + || !m_delegate->validate(parameters).isEmpty() || hover.isNull() || hover.x() < 0 || hover.y() < 0) { diff --git a/src/hobbits-plugins/displays/Hex/hex.cpp b/src/hobbits-plugins/displays/Hex/hex.cpp index eeda7085..bbff3d12 100644 --- a/src/hobbits-plugins/displays/Hex/hex.cpp +++ b/src/hobbits-plugins/displays/Hex/hex.cpp @@ -10,9 +10,9 @@ Hex::Hex() : m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewBitHover); QList infos = { - {"font_size", QJsonValue::Double}, - {"column_grouping", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool} + {"font_size", ParameterDelegate::ParameterType::Integer}, + {"column_grouping", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean} }; m_delegate = ParameterDelegate::create( @@ -60,7 +60,7 @@ void Hex::setDisplayHandle(QSharedPointer displayHandle) { m_handle = displayHandle; DisplayHelper::connectHoverUpdates(this, this, m_handle, [this](QPoint& offset, QSize &symbolSize, int &grouping, int &bitsPerSymbol) { - if (!m_delegate->validate(m_lastParams)) { + if (!m_delegate->validate(m_lastParams).isEmpty()) { return false; } offset = headerOffset(m_lastParams); @@ -83,9 +83,10 @@ QSharedPointer Hex::renderDisplay(QSize viewportSize, const QJson Q_UNUSED(progress) m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); @@ -119,8 +120,9 @@ QSharedPointer Hex::renderDisplay(QSize viewportSize, const QJson QSharedPointer Hex::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { - if (!m_delegate->validate(parameters)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { return DisplayResult::nullResult(); diff --git a/src/hobbits-plugins/displays/HilbertPlot/hilbertplot.cpp b/src/hobbits-plugins/displays/HilbertPlot/hilbertplot.cpp index 32757443..edf4e85d 100644 --- a/src/hobbits-plugins/displays/HilbertPlot/hilbertplot.cpp +++ b/src/hobbits-plugins/displays/HilbertPlot/hilbertplot.cpp @@ -69,8 +69,9 @@ QSharedPointer HilbertPlot::renderDisplay(QSize viewportSize, con { Q_UNUSED(parameters) - if (!m_delegate->validate(parameters)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { return DisplayResult::nullResult(); @@ -140,9 +141,10 @@ QSharedPointer HilbertPlot::renderOverlay(QSize viewportSize, con { Q_UNUSED(viewportSize) Q_UNUSED(parameters) - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); diff --git a/src/hobbits-plugins/displays/Spectrogram/spectrogram.cpp b/src/hobbits-plugins/displays/Spectrogram/spectrogram.cpp index 03cc927e..8f81d880 100644 --- a/src/hobbits-plugins/displays/Spectrogram/spectrogram.cpp +++ b/src/hobbits-plugins/displays/Spectrogram/spectrogram.cpp @@ -17,15 +17,15 @@ Spectrogram::Spectrogram(): m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewMouseHover); QList infos = { - {"sample_format", QJsonValue::String}, - {"fft_overlap", QJsonValue::Double}, - {"fft_size", QJsonValue::Double}, - {"data_type", QJsonValue::Double}, - {"sensitivity", QJsonValue::Double}, - {"sample_rate", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool}, - {"show_slices", QJsonValue::Bool}, - {"logarithmic_scaling", QJsonValue::Bool} + {"sample_format", ParameterDelegate::ParameterType::String}, + {"fft_overlap", ParameterDelegate::ParameterType::Integer}, + {"fft_size", ParameterDelegate::ParameterType::Integer}, + {"data_type", ParameterDelegate::ParameterType::Integer}, + {"sensitivity", ParameterDelegate::ParameterType::Decimal}, + {"sample_rate", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean}, + {"show_slices", ParameterDelegate::ParameterType::Boolean}, + {"logarithmic_scaling", ParameterDelegate::ParameterType::Boolean} }; m_delegate = ParameterDelegate::create( @@ -78,8 +78,9 @@ QSharedPointer Spectrogram::parameterDelegate() QSharedPointer Spectrogram::renderDisplay(QSize viewportSize, const QJsonObject ¶meters, QSharedPointer progress) { - if (!m_delegate->validate(parameters)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QRect spectRect = spectrogramRectangle(viewportSize, m_handle, parameters); @@ -202,9 +203,10 @@ QSharedPointer Spectrogram::renderDisplay(QSize viewportSize, con QSharedPointer Spectrogram::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QRect spectRect = spectrogramRectangle(viewportSize, m_handle, parameters); diff --git a/src/hobbits-plugins/displays/SymbolRaster/symbolraster.cpp b/src/hobbits-plugins/displays/SymbolRaster/symbolraster.cpp index fdc15e11..ac03a599 100644 --- a/src/hobbits-plugins/displays/SymbolRaster/symbolraster.cpp +++ b/src/hobbits-plugins/displays/SymbolRaster/symbolraster.cpp @@ -13,9 +13,9 @@ SymbolRaster::SymbolRaster() : m_renderConfig->setOverlayRedrawTriggers(DisplayRenderConfig::NewBitHover); QList infos = { - {"scale", QJsonValue::Double}, - {"show_headers", QJsonValue::Bool}, - {"color_map", QJsonValue::Array} + {"scale", ParameterDelegate::ParameterType::Integer}, + {"show_headers", ParameterDelegate::ParameterType::Boolean}, + {"color_map", ParameterDelegate::ParameterType::Array} }; m_delegate = ParameterDelegate::create( @@ -64,7 +64,7 @@ void SymbolRaster::setDisplayHandle(QSharedPointer displayHandle) { m_handle = displayHandle; DisplayHelper::connectHoverUpdates(this, this, m_handle, [this](QPoint& offset, QSize &symbolSize, int &grouping, int &bitsPerSymbol) { - if (!m_delegate->validate(m_lastParams) || m_symbolLength < 1) { + if (!m_delegate->validate(m_lastParams).isEmpty() || m_symbolLength < 1) { return false; } int scale = m_lastParams.value("scale").toInt(); @@ -86,9 +86,10 @@ QSharedPointer SymbolRaster::renderDisplay(QSize viewportSize, co Q_UNUSED(progress) m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); @@ -143,8 +144,9 @@ QSharedPointer SymbolRaster::renderDisplay(QSize viewportSize, co QSharedPointer SymbolRaster::renderOverlay(QSize viewportSize, const QJsonObject ¶meters) { m_lastParams = parameters; - if (!m_delegate->validate(parameters)) { - return DisplayResult::error("Invalid parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QJsonArray colorMapValues = parameters.value("color_map").toArray(); diff --git a/src/hobbits-plugins/importerexporters/DisplayPrint/displayprint.cpp b/src/hobbits-plugins/importerexporters/DisplayPrint/displayprint.cpp index e076ddc8..b89a7fe5 100644 --- a/src/hobbits-plugins/importerexporters/DisplayPrint/displayprint.cpp +++ b/src/hobbits-plugins/importerexporters/DisplayPrint/displayprint.cpp @@ -7,11 +7,11 @@ DisplayPrint::DisplayPrint() { QList exportInfos = { - {"plugin_name", QJsonValue::String}, - {"image_width", QJsonValue::Double}, - {"image_height", QJsonValue::Double}, - {"image_filename", QJsonValue::String}, - {"display_params", QJsonValue::Object} + {"plugin_name", ParameterDelegate::ParameterType::String}, + {"image_width", ParameterDelegate::ParameterType::Integer}, + {"image_height", ParameterDelegate::ParameterType::Integer}, + {"image_filename", ParameterDelegate::ParameterType::String}, + {"display_params", ParameterDelegate::ParameterType::Object} }; m_exportDelegate = ParameterDelegate::create( @@ -78,8 +78,9 @@ QSharedPointer DisplayPrint::exportBits(QSharedPointer progress) { - if (!m_exportDelegate->validate(parameters)) { - return ExportResult::error(QString("Invalid parameters passed to %1").arg(name())); + QStringList invalidations = m_exportDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ExportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } int imageWidth = parameters.value("image_width").toInt(); diff --git a/src/hobbits-plugins/importerexporters/FileData/filedata.cpp b/src/hobbits-plugins/importerexporters/FileData/filedata.cpp index ce7c3dd9..cfec8428 100644 --- a/src/hobbits-plugins/importerexporters/FileData/filedata.cpp +++ b/src/hobbits-plugins/importerexporters/FileData/filedata.cpp @@ -10,7 +10,7 @@ FileData::FileData() { QList infos = { - {"filename", QJsonValue::String, false} + {"filename", ParameterDelegate::ParameterType::String, false} }; m_importDelegate = ParameterDelegate::create( diff --git a/src/hobbits-plugins/importerexporters/HexString/hexstring.cpp b/src/hobbits-plugins/importerexporters/HexString/hexstring.cpp index f46c420a..92ace5a1 100644 --- a/src/hobbits-plugins/importerexporters/HexString/hexstring.cpp +++ b/src/hobbits-plugins/importerexporters/HexString/hexstring.cpp @@ -8,9 +8,9 @@ HexString::HexString() { QList importInfos = { - {"filename", QJsonValue::String, true}, - {"hex_string", QJsonValue::String, true}, - {"repeats", QJsonValue::Double, true} + {"filename", ParameterDelegate::ParameterType::String, true}, + {"hex_string", ParameterDelegate::ParameterType::String, true}, + {"repeats", ParameterDelegate::ParameterType::Integer, true} }; m_importDelegate = ParameterDelegate::create( importInfos, @@ -38,7 +38,7 @@ HexString::HexString() QList exportInfos = { - {"filename", QJsonValue::String, false} + {"filename", ParameterDelegate::ParameterType::String, false} }; m_exportDelegate = ParameterDelegate::create( exportInfos, @@ -127,8 +127,9 @@ QSharedPointer HexString::exportBits(QSharedPointer progress) { Q_UNUSED(progress) - if (m_exportDelegate->validate(parameters)) { - ExportResult::error(QString("Invalid parameters passed to '%1'").arg(name())); + QStringList invalidations = m_exportDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ExportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QString fileName; diff --git a/src/hobbits-plugins/importerexporters/HttpData/httpdata.cpp b/src/hobbits-plugins/importerexporters/HttpData/httpdata.cpp index c1078f6f..c6fb0509 100644 --- a/src/hobbits-plugins/importerexporters/HttpData/httpdata.cpp +++ b/src/hobbits-plugins/importerexporters/HttpData/httpdata.cpp @@ -6,8 +6,8 @@ HttpData::HttpData() { QList importInfos = { - {"url", QJsonValue::String}, - {"verb", QJsonValue::String} + {"url", ParameterDelegate::ParameterType::String}, + {"verb", ParameterDelegate::ParameterType::String} }; m_importDelegate = ParameterDelegate::create( @@ -32,9 +32,9 @@ HttpData::HttpData() QList exportInfos = { - {"url", QJsonValue::String}, - {"formdataname", QJsonValue::String}, - {"verb", QJsonValue::String} + {"url", ParameterDelegate::ParameterType::String}, + {"formdataname", ParameterDelegate::ParameterType::String}, + {"verb", ParameterDelegate::ParameterType::String} }; m_exportDelegate = ParameterDelegate::create( exportInfos, @@ -100,8 +100,9 @@ QSharedPointer HttpData::exportParameterDelegate() QSharedPointer HttpData::importBits(QJsonObject parameters, QSharedPointer progress) { - if (!m_importDelegate->validate(parameters)) { - return ImportResult::error("Invalid parameters passed to HTTP Import"); + QStringList invalidations = m_importDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ImportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return HttpImportForm::importData(parameters, progress); @@ -111,8 +112,9 @@ QSharedPointer HttpData::exportBits(QSharedPointer progress) { - if (!m_exportDelegate->validate(parameters)) { - return ExportResult::error("Invalid parameters passed to HTTP Import"); + QStringList invalidations = m_exportDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ExportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return HttpExportForm::exportData(container->bits()->readBytes(0, 25000000), parameters, progress); diff --git a/src/hobbits-plugins/importerexporters/Lfsr/lfsr.cpp b/src/hobbits-plugins/importerexporters/Lfsr/lfsr.cpp index 6d552635..23957c21 100644 --- a/src/hobbits-plugins/importerexporters/Lfsr/lfsr.cpp +++ b/src/hobbits-plugins/importerexporters/Lfsr/lfsr.cpp @@ -11,9 +11,9 @@ Lfsr::Lfsr() { QList importInfos = { - {"polynomial", QJsonValue::String}, - {"taps", QJsonValue::String}, - {"bits_wanted", QJsonValue::Double} + {"polynomial", ParameterDelegate::ParameterType::String}, + {"taps", ParameterDelegate::ParameterType::String}, + {"bits_wanted", ParameterDelegate::ParameterType::Integer} }; m_importDelegate = ParameterDelegate::create( importInfos, diff --git a/src/hobbits-plugins/importerexporters/PacketCapture/packetcapture.cpp b/src/hobbits-plugins/importerexporters/PacketCapture/packetcapture.cpp index 9b0953e3..ed8f3075 100644 --- a/src/hobbits-plugins/importerexporters/PacketCapture/packetcapture.cpp +++ b/src/hobbits-plugins/importerexporters/PacketCapture/packetcapture.cpp @@ -5,15 +5,15 @@ PacketCapture::PacketCapture() { QList importInfos = { - {"device_name", QJsonValue::String}, - {"address", QJsonValue::Double}, - {"max_packets", QJsonValue::Double, true}, - {"max_size", QJsonValue::Double, true}, - {"timeout", QJsonValue::Double}, - {"filter", QJsonValue::String, true}, - {"buffer_size", QJsonValue::Double, true}, - {"packet_size_limit", QJsonValue::Double, true}, - {"promiscuous", QJsonValue::Bool} + {"device_name", ParameterDelegate::ParameterType::String}, + {"address", ParameterDelegate::ParameterType::Integer}, + {"max_packets", ParameterDelegate::ParameterType::Integer, true}, + {"max_size", ParameterDelegate::ParameterType::Integer, true}, + {"timeout", ParameterDelegate::ParameterType::Integer}, + {"filter", ParameterDelegate::ParameterType::String, true}, + {"buffer_size", ParameterDelegate::ParameterType::Integer, true}, + {"packet_size_limit", ParameterDelegate::ParameterType::Integer, true}, + {"promiscuous", ParameterDelegate::ParameterType::Boolean} }; m_importDelegate = QSharedPointer( @@ -74,8 +74,9 @@ QSharedPointer PacketCapture::exportParameterDelegate() QSharedPointer PacketCapture::importBits(QJsonObject parameters, QSharedPointer progress) { - if (!m_importDelegate->validate(parameters)) { - return ImportResult::error("Invalid parameters passed to Packet Capture"); + QStringList invalidations = m_importDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ImportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return PacketCaptureClient::capturePackets(parameters, progress); diff --git a/src/hobbits-plugins/importerexporters/TcpData/tcpdata.cpp b/src/hobbits-plugins/importerexporters/TcpData/tcpdata.cpp index 69fd40c1..bc36ccce 100644 --- a/src/hobbits-plugins/importerexporters/TcpData/tcpdata.cpp +++ b/src/hobbits-plugins/importerexporters/TcpData/tcpdata.cpp @@ -5,9 +5,9 @@ TcpData::TcpData() { QList importInfos = { - {"port", QJsonValue::Double}, - {"max_kb", QJsonValue::Double}, - {"timeout", QJsonValue::Double} + {"port", ParameterDelegate::ParameterType::Integer}, + {"max_kb", ParameterDelegate::ParameterType::Integer}, + {"timeout", ParameterDelegate::ParameterType::Integer} }; m_importDelegate = QSharedPointer( @@ -23,9 +23,9 @@ TcpData::TcpData() QList exportInfos = { - {"host", QJsonValue::String}, - {"port", QJsonValue::Double}, - {"timeout", QJsonValue::Double} + {"host", ParameterDelegate::ParameterType::String}, + {"port", ParameterDelegate::ParameterType::Integer}, + {"timeout", ParameterDelegate::ParameterType::Integer} }; m_exportDelegate = QSharedPointer( new ParameterDelegateUi( @@ -84,8 +84,9 @@ QSharedPointer TcpData::exportParameterDelegate() QSharedPointer TcpData::importBits(QJsonObject parameters, QSharedPointer progress) { - if (!m_importDelegate->validate(parameters)) { - return ImportResult::error("Invalid parameters passed to TCP Import"); + QStringList invalidations = m_importDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ImportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return TcpReceiver::importData(parameters, progress); @@ -95,8 +96,9 @@ QSharedPointer TcpData::exportBits(QSharedPointer progress) { - if (!m_exportDelegate->validate(parameters)) { - return ExportResult::error("Invalid parameters passed to TCP Export"); + QStringList invalidations = m_exportDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ExportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return TcpSender::exportData(container->bits(), parameters, progress); diff --git a/src/hobbits-plugins/importerexporters/UdpData/udpdata.cpp b/src/hobbits-plugins/importerexporters/UdpData/udpdata.cpp index c1740277..d8cd76ee 100644 --- a/src/hobbits-plugins/importerexporters/UdpData/udpdata.cpp +++ b/src/hobbits-plugins/importerexporters/UdpData/udpdata.cpp @@ -6,9 +6,9 @@ UdpData::UdpData() { QList importInfos = { - {"port", QJsonValue::Double}, - {"max_kb", QJsonValue::Double}, - {"timeout", QJsonValue::Double} + {"port", ParameterDelegate::ParameterType::Integer}, + {"max_kb", ParameterDelegate::ParameterType::Integer}, + {"timeout", ParameterDelegate::ParameterType::Integer} }; m_importDelegate = QSharedPointer( @@ -24,8 +24,8 @@ UdpData::UdpData() QList exportInfos = { - {"host", QJsonValue::String}, - {"port", QJsonValue::Double} + {"host", ParameterDelegate::ParameterType::String}, + {"port", ParameterDelegate::ParameterType::Integer} }; m_exportDelegate = QSharedPointer( new ParameterDelegateUi( @@ -84,8 +84,9 @@ QSharedPointer UdpData::exportParameterDelegate() QSharedPointer UdpData::importBits(QJsonObject parameters, QSharedPointer progress) { - if (!m_importDelegate->validate(parameters)) { - return ImportResult::error("Invalid parameters passed to UDP Import"); + QStringList invalidations = m_importDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ImportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return UdpReceiver::importData(parameters, progress); @@ -95,8 +96,9 @@ QSharedPointer UdpData::exportBits(QSharedPointer progress) { - if (!m_exportDelegate->validate(parameters)) { - return ExportResult::error("Invalid parameters passed to UDP Export"); + QStringList invalidations = m_exportDelegate->validate(parameters); + if (!invalidations.isEmpty()) { + return ExportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } return UdpSender::exportData(container->bits(), parameters, progress); diff --git a/src/hobbits-plugins/operators/BitsError/bitserror.cpp b/src/hobbits-plugins/operators/BitsError/bitserror.cpp index e2646258..f4253cb9 100644 --- a/src/hobbits-plugins/operators/BitsError/bitserror.cpp +++ b/src/hobbits-plugins/operators/BitsError/bitserror.cpp @@ -12,9 +12,9 @@ BitsError::BitsError() { QList infos = { - {"error_coeff", QJsonValue::Double}, - {"error_exp", QJsonValue::Double}, - {"error_type", QJsonValue::String} + {"error_coeff", ParameterDelegate::ParameterType::Decimal}, + {"error_exp", ParameterDelegate::ParameterType::Decimal}, + {"error_type", ParameterDelegate::ParameterType::String} }; m_delegate = QSharedPointer( diff --git a/src/hobbits-plugins/operators/Extractor/extractor.cpp b/src/hobbits-plugins/operators/Extractor/extractor.cpp index 4b65e081..7c5edd33 100644 --- a/src/hobbits-plugins/operators/Extractor/extractor.cpp +++ b/src/hobbits-plugins/operators/Extractor/extractor.cpp @@ -5,11 +5,11 @@ Extractor::Extractor() { QList infos = { - {"highlight_category", QJsonValue::String, false}, - {"highlight_label", QJsonValue::String, false}, - {"extract_before", QJsonValue::Bool, true}, - {"extract_highlight", QJsonValue::Bool, true}, - {"extract_after", QJsonValue::Bool, true} + {"highlight_category", ParameterDelegate::ParameterType::String, false}, + {"highlight_label", ParameterDelegate::ParameterType::String, false}, + {"extract_before", ParameterDelegate::ParameterType::Boolean, true}, + {"extract_highlight", ParameterDelegate::ParameterType::Boolean, true}, + {"extract_after", ParameterDelegate::ParameterType::Boolean, true} }; m_delegate = ParameterDelegateUi::create( @@ -87,8 +87,9 @@ QSharedPointer Extractor::operateOnBits( const QJsonObject ¶meters, QSharedPointer progressTracker) { - if (!m_delegate->validate(parameters)) { - return OperatorResult::error("Invalid input parameters"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return OperatorResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (inputContainers.size() != 1) { diff --git a/src/hobbits-plugins/operators/HeaderFramer/headerframer.cpp b/src/hobbits-plugins/operators/HeaderFramer/headerframer.cpp index e43145bb..e5dc7102 100644 --- a/src/hobbits-plugins/operators/HeaderFramer/headerframer.cpp +++ b/src/hobbits-plugins/operators/HeaderFramer/headerframer.cpp @@ -7,11 +7,11 @@ HeaderFramer::HeaderFramer() { QList infos = { - { "headers", QJsonValue::Array, false, { - {"header", QJsonValue::String}, - {"length", QJsonValue::String}, - {"pre-pad", QJsonValue::Double, true}, - {"byte-aligned", QJsonValue::Bool, true} + { "headers", ParameterDelegate::ParameterType::Array, false, { + {"header", ParameterDelegate::ParameterType::String}, + {"length", ParameterDelegate::ParameterType::String}, + {"pre-pad", ParameterDelegate::ParameterType::Integer, true}, + {"byte-aligned", ParameterDelegate::ParameterType::Boolean, true} } } }; @@ -78,8 +78,9 @@ QSharedPointer HeaderFramer::operateOnBits( QSharedPointer result(new OperatorResult()); - if (!m_delegate->validate(parameters)) { - return OperatorResult::error("Invalid parameters given to Header Framer"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return OperatorResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (inputContainers.size() != 1) { diff --git a/src/hobbits-plugins/operators/HeaderFramer/headerframerform.cpp b/src/hobbits-plugins/operators/HeaderFramer/headerframerform.cpp index ddcb62ef..0aaedd22 100644 --- a/src/hobbits-plugins/operators/HeaderFramer/headerframerform.cpp +++ b/src/hobbits-plugins/operators/HeaderFramer/headerframerform.cpp @@ -41,7 +41,7 @@ QString HeaderFramerForm::title() bool HeaderFramerForm::setParameters(QJsonObject parameters) { - if (!m_delegate->validate(parameters)) { + if (!m_delegate->validate(parameters).isEmpty()) { return false; } diff --git a/src/hobbits-plugins/operators/PythonRunner/pythonrunner.cpp b/src/hobbits-plugins/operators/PythonRunner/pythonrunner.cpp index 42c96e3f..b812f108 100644 --- a/src/hobbits-plugins/operators/PythonRunner/pythonrunner.cpp +++ b/src/hobbits-plugins/operators/PythonRunner/pythonrunner.cpp @@ -14,7 +14,7 @@ PythonRunner::PythonRunner() { QList infos = { - { "script", QJsonValue::String } + { "script", ParameterDelegate::ParameterType::String } }; m_delegate = ParameterDelegateUi::create( @@ -75,8 +75,9 @@ QSharedPointer PythonRunner::operateOnBits( if (inputContainers.length() != 1) { return OperatorResult::error("Requires a single input bit container"); } - if (!m_delegate->validate(parameters)) { - return OperatorResult::error("Invalid plugin state"); + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return OperatorResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QTemporaryDir dir; diff --git a/src/hobbits-plugins/operators/SymbolRemapper/symbolremapper.cpp b/src/hobbits-plugins/operators/SymbolRemapper/symbolremapper.cpp index 32e5061f..9798fe3f 100644 --- a/src/hobbits-plugins/operators/SymbolRemapper/symbolremapper.cpp +++ b/src/hobbits-plugins/operators/SymbolRemapper/symbolremapper.cpp @@ -6,9 +6,9 @@ SymbolRemapper::SymbolRemapper() { QList infos = { - { "mappings", QJsonValue::Array, false, { - {"old", QJsonValue::String}, - {"new", QJsonValue::String} + { "mappings", ParameterDelegate::ParameterType::Array, false, { + {"old", ParameterDelegate::ParameterType::String}, + {"new", ParameterDelegate::ParameterType::String} } } }; @@ -71,11 +71,12 @@ QSharedPointer SymbolRemapper::operateOnBits( QSharedPointer nullResult(new OperatorResult()); if (inputContainers.size() != 1) { - return nullResult; + return OperatorResult::error("Invalid input containers - expected 1."); } - if (!m_delegate->validate(parameters)) { - return nullResult; + QStringList invalidations = m_delegate->validate(parameters); + if (!invalidations.isEmpty()) { + return OperatorResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QHash> bitMapping; diff --git a/src/hobbits-plugins/operators/SymbolRemapper/symbolremapperform.cpp b/src/hobbits-plugins/operators/SymbolRemapper/symbolremapperform.cpp index 2faf5c13..c9e6400c 100644 --- a/src/hobbits-plugins/operators/SymbolRemapper/symbolremapperform.cpp +++ b/src/hobbits-plugins/operators/SymbolRemapper/symbolremapperform.cpp @@ -28,7 +28,7 @@ QString SymbolRemapperForm::title() bool SymbolRemapperForm::setParameters(QJsonObject parameters) { - if (!m_delegate->validate((parameters))) { + if (!m_delegate->validate(parameters).isEmpty()) { return false; } diff --git a/src/hobbits-plugins/operators/TakeSkip/takeskip.cpp b/src/hobbits-plugins/operators/TakeSkip/takeskip.cpp index 4f4a6f91..d2ecf353 100644 --- a/src/hobbits-plugins/operators/TakeSkip/takeskip.cpp +++ b/src/hobbits-plugins/operators/TakeSkip/takeskip.cpp @@ -13,10 +13,10 @@ struct OutputHandle { TakeSkip::TakeSkip() { QList infos = { - {"take_skip_string", QJsonValue::String, false}, - {"interleaved", QJsonValue::Bool, true}, - {"frame_based", QJsonValue::Bool, true}, - {"deinterleave_channels", QJsonValue::Double, true} + {"take_skip_string", ParameterDelegate::ParameterType::String, false}, + {"interleaved", ParameterDelegate::ParameterType::Boolean, true}, + {"frame_based", ParameterDelegate::ParameterType::Boolean, true}, + {"deinterleave_channels", ParameterDelegate::ParameterType::Integer, true} }; m_delegate = QSharedPointer( diff --git a/src/hobbits-python/pythonanalyzer.cpp b/src/hobbits-python/pythonanalyzer.cpp index bc1a138b..fea96066 100644 --- a/src/hobbits-python/pythonanalyzer.cpp +++ b/src/hobbits-python/pythonanalyzer.cpp @@ -37,8 +37,9 @@ QSharedPointer PythonAnalyzer::analyzeBits(QSharedPointer< const QJsonObject ¶meters, QSharedPointer progress) { - if (!m_config->delegate()->validate(parameters)) { - return AnalyzerResult::error("Invalid plugin parameters"); + QStringList invalidations = m_config->delegate()->validate(parameters); + if (!invalidations.isEmpty()) { + return AnalyzerResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QTemporaryDir dir; @@ -61,18 +62,16 @@ QSharedPointer PythonAnalyzer::analyzeBits(QSharedPointer< pyRequest->addArg(PythonArg::constBitContainer(container)); pyRequest->addArg(PythonArg::bitInfo(outputInfo)); for (auto param : m_config->parameterInfos()) { - if (param.type == QJsonValue::String) { + if (param.type == ParameterDelegate::ParameterType::String) { pyRequest->addArg(PythonArg::qString(parameters.value(param.name).toString())); } - else if (param.type == QJsonValue::Double) { - if (m_config->parameterNumberType(param.name) == PythonPluginConfig::Integer) { - pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); - } - else { - pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); - } + else if (param.type == ParameterDelegate::ParameterType::Integer) { + pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); } - else if (param.type == QJsonValue::Bool) { + else if (param.type == ParameterDelegate::ParameterType::Decimal) { + pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); + } + else if (param.type == ParameterDelegate::ParameterType::Boolean) { pyRequest->addArg(PythonArg::boolean(parameters.value(param.name).toBool())); } } diff --git a/src/hobbits-python/pythonarg.cpp b/src/hobbits-python/pythonarg.cpp index 87297a79..2b3c221e 100644 --- a/src/hobbits-python/pythonarg.cpp +++ b/src/hobbits-python/pythonarg.cpp @@ -7,6 +7,12 @@ PythonArg::PythonArg() m_stringData = QString(); m_integerData = 0; m_doubleData = 0; + m_boolData = false; +} + +bool PythonArg::boolData() const +{ + return m_boolData; } QSize PythonArg::sizeData() const @@ -159,9 +165,9 @@ PythonArg *PythonArg::number(double n) PythonArg *PythonArg::boolean(bool n) { PythonArg *arg = new PythonArg(); - arg->m_type = Type::Integer; - arg->m_argSymbol = "p"; - arg->m_integerData = n ? 1 : 0; + arg->m_type = Type::Boolean; + arg->m_argSymbol = "O"; + arg->m_boolData = n; return arg; } diff --git a/src/hobbits-python/pythonarg.h b/src/hobbits-python/pythonarg.h index 0258bb94..f91343cf 100644 --- a/src/hobbits-python/pythonarg.h +++ b/src/hobbits-python/pythonarg.h @@ -17,7 +17,8 @@ class HOBBITSPYTHONSHARED_EXPORT PythonArg Integer = 0x3, Double = 0x4, ByteBuffer = 0x5, - ImageBuffer = 0x6 + ImageBuffer = 0x6, + Boolean = 0x7 }; static PythonArg* bitArray(QSharedPointer bitArray); @@ -43,6 +44,7 @@ class HOBBITSPYTHONSHARED_EXPORT PythonArg int integerData() const; double doubleData() const; QSize sizeData() const; + bool boolData() const; private: PythonArg(); @@ -55,6 +57,7 @@ class HOBBITSPYTHONSHARED_EXPORT PythonArg int m_integerData; double m_doubleData; QSize m_sizeData; + bool m_boolData; }; #endif // PYTHONARG_H diff --git a/src/hobbits-python/pythondisplay.cpp b/src/hobbits-python/pythondisplay.cpp index d63a6f7a..01525446 100644 --- a/src/hobbits-python/pythondisplay.cpp +++ b/src/hobbits-python/pythondisplay.cpp @@ -49,10 +49,10 @@ QSharedPointer PythonDisplay::parameterDelegate() QSharedPointer PythonDisplay::renderDisplay(QSize viewportSize, const QJsonObject ¶meters, QSharedPointer progress) { - - if (!m_config->delegate()->validate(parameters)) { + QStringList invalidations = m_config->delegate()->validate(parameters); + if (!invalidations.isEmpty()) { m_handle->setRenderedRange(this, Range()); - return DisplayResult::error("Invalid parameters"); + return DisplayResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } if (m_handle.isNull() || m_handle->currentContainer().isNull()) { m_handle->setRenderedRange(this, Range()); @@ -80,18 +80,16 @@ QSharedPointer PythonDisplay::renderDisplay(QSize viewportSize, c pyRequest->addArg(PythonArg::displayHandle(m_handle)); pyRequest->addArg(PythonArg::imageBuffer(byteBuffer, viewportSize)); for (auto param : m_config->parameterInfos()) { - if (param.type == QJsonValue::String) { + if (param.type == ParameterDelegate::ParameterType::String) { pyRequest->addArg(PythonArg::qString(parameters.value(param.name).toString())); } - else if (param.type == QJsonValue::Double) { - if (m_config->parameterNumberType(param.name) == PythonPluginConfig::Integer) { - pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); - } - else { - pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); - } + else if (param.type == ParameterDelegate::ParameterType::Integer) { + pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); + } + else if (param.type == ParameterDelegate::ParameterType::Decimal) { + pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); } - else if (param.type == QJsonValue::Bool) { + else if (param.type == ParameterDelegate::ParameterType::Boolean) { pyRequest->addArg(PythonArg::boolean(parameters.value(param.name).toBool())); } } diff --git a/src/hobbits-python/pythonexporter.cpp b/src/hobbits-python/pythonexporter.cpp index 0a794a76..f6002360 100644 --- a/src/hobbits-python/pythonexporter.cpp +++ b/src/hobbits-python/pythonexporter.cpp @@ -57,8 +57,9 @@ QSharedPointer PythonExporter::importBits(QJsonObject parameters, QSharedPointer PythonExporter::exportBits(QSharedPointer container, QJsonObject parameters, QSharedPointer progress) { - if (!m_config->delegate()->validate(parameters)) { - return ExportResult::error("Invalid plugin parameters"); + QStringList invalidations = m_config->delegate()->validate(parameters); + if (!invalidations.isEmpty()) { + return ExportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QTemporaryDir dir; @@ -81,18 +82,16 @@ QSharedPointer PythonExporter::exportBits(QSharedPointeraddArg(PythonArg::constBitContainer(container)); for (auto param : m_config->parameterInfos()) { - if (param.type == QJsonValue::String) { + if (param.type == ParameterDelegate::ParameterType::String) { pyRequest->addArg(PythonArg::qString(parameters.value(param.name).toString())); } - else if (param.type == QJsonValue::Double) { - if (m_config->parameterNumberType(param.name) == PythonPluginConfig::Integer) { - pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); - } - else { - pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); - } + else if (param.type == ParameterDelegate::ParameterType::Integer) { + pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); } - else if (param.type == QJsonValue::Bool) { + else if (param.type == ParameterDelegate::ParameterType::Decimal) { + pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); + } + else if (param.type == ParameterDelegate::ParameterType::Boolean) { pyRequest->addArg(PythonArg::boolean(parameters.value(param.name).toBool())); } } diff --git a/src/hobbits-python/pythonimporter.cpp b/src/hobbits-python/pythonimporter.cpp index 23c8de0d..040d64cc 100644 --- a/src/hobbits-python/pythonimporter.cpp +++ b/src/hobbits-python/pythonimporter.cpp @@ -50,8 +50,9 @@ QSharedPointer PythonImporter::exportParameterDelegate() QSharedPointer PythonImporter::importBits(QJsonObject parameters, QSharedPointer progress) { - if (!m_config->delegate()->validate(parameters)) { - return ImportResult::error("Invalid plugin parameters"); + QStringList invalidations = m_config->delegate()->validate(parameters); + if (!invalidations.isEmpty()) { + return ImportResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QTemporaryDir dir; @@ -75,18 +76,16 @@ QSharedPointer PythonImporter::importBits(QJsonObject parameters, pyRequest->addArg(PythonArg::bitArray(outputBits)); pyRequest->addArg(PythonArg::bitInfo(outputInfo)); for (auto param : m_config->parameterInfos()) { - if (param.type == QJsonValue::String) { + if (param.type == ParameterDelegate::ParameterType::String) { pyRequest->addArg(PythonArg::qString(parameters.value(param.name).toString())); } - else if (param.type == QJsonValue::Double) { - if (m_config->parameterNumberType(param.name) == PythonPluginConfig::Integer) { - pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); - } - else { - pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); - } + else if (param.type == ParameterDelegate::ParameterType::Integer) { + pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); } - else if (param.type == QJsonValue::Bool) { + else if (param.type == ParameterDelegate::ParameterType::Decimal) { + pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); + } + else if (param.type == ParameterDelegate::ParameterType::Boolean) { pyRequest->addArg(PythonArg::boolean(parameters.value(param.name).toBool())); } } diff --git a/src/hobbits-python/pythoninterpreter.cpp b/src/hobbits-python/pythoninterpreter.cpp index 715a015f..b77f8b6a 100644 --- a/src/hobbits-python/pythoninterpreter.cpp +++ b/src/hobbits-python/pythoninterpreter.cpp @@ -222,6 +222,9 @@ PyObject* parseArg(PyObject *hobbitsModule, PythonArg *arg) else if (arg->type() == PythonArg::Double) { return Py_BuildValue(arg->argSymbol().toStdString().c_str(), arg->doubleData()); } + else if (arg->type() == PythonArg::Boolean) { + return Py_BuildValue(arg->argSymbol().toStdString().c_str(), arg->boolData() ? Py_True : Py_False); + } else if (arg->type() == PythonArg::ByteBuffer) { return PyMemoryView_FromMemory(reinterpret_cast(arg->pointer()), arg->integerData(), PyBUF_WRITE); } diff --git a/src/hobbits-python/pythonoperator.cpp b/src/hobbits-python/pythonoperator.cpp index eb8dd5fe..c38b0e0c 100644 --- a/src/hobbits-python/pythonoperator.cpp +++ b/src/hobbits-python/pythonoperator.cpp @@ -52,8 +52,9 @@ QSharedPointer PythonOperator::operateOnBits(QListdelegate()->validate(parameters)) { - return OperatorResult::error("Invalid plugin parameters"); + QStringList invalidations = m_config->delegate()->validate(parameters); + if (!invalidations.isEmpty()) { + return OperatorResult::error(QString("Invalid parameters passed to %1:\n%2").arg(name()).arg(invalidations.join("\n"))); } QTemporaryDir dir; @@ -78,18 +79,16 @@ QSharedPointer PythonOperator::operateOnBits(QListaddArg(PythonArg::bitArray(outputBits)); pyRequest->addArg(PythonArg::bitInfo(outputInfo)); for (auto param : m_config->parameterInfos()) { - if (param.type == QJsonValue::String) { + if (param.type == ParameterDelegate::ParameterType::String) { pyRequest->addArg(PythonArg::qString(parameters.value(param.name).toString())); } - else if (param.type == QJsonValue::Double) { - if (m_config->parameterNumberType(param.name) == PythonPluginConfig::Integer) { - pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); - } - else { - pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); - } + else if (param.type == ParameterDelegate::ParameterType::Integer) { + pyRequest->addArg(PythonArg::integer(parameters.value(param.name).toInt())); } - else if (param.type == QJsonValue::Bool) { + else if (param.type == ParameterDelegate::ParameterType::Decimal) { + pyRequest->addArg(PythonArg::number(parameters.value(param.name).toDouble())); + } + else if (param.type == ParameterDelegate::ParameterType::Boolean) { pyRequest->addArg(PythonArg::boolean(parameters.value(param.name).toBool())); } } diff --git a/src/hobbits-python/pythonpluginconfig.cpp b/src/hobbits-python/pythonpluginconfig.cpp index 1723d4cc..73705b22 100644 --- a/src/hobbits-python/pythonpluginconfig.cpp +++ b/src/hobbits-python/pythonpluginconfig.cpp @@ -198,32 +198,49 @@ QStringList PythonPluginConfig::configure(QString configFolder, auto param = value.toObject(); QString name = param.value("name").toString(); QString type = param.value("type").toString(); + + ParameterDelegate::ParameterInfo info; if (type == "string") { - m_parameterInfos.append({name, QJsonValue::String}); + info = {name, ParameterDelegate::ParameterType::String}; } else if (type == "integer") { - ParameterDelegate::ParameterInfo info = {name, QJsonValue::Double}; + info = {name, ParameterDelegate::ParameterType::Integer}; if (param.contains("min") || param.contains("max")) { - info.hasIntLimits = true; - info.intMax = INT_MAX; - info.intMin = INT_MIN; - } - if (param.contains("min")) { - info.intMin = param.value("min").toInt(); - } - if (param.contains("max")) { - info.intMax = param.value("max").toInt(); + QPair range = {INT_MIN, INT_MAX}; + if (param.contains("min")) { + range.first = param.value("min").toDouble(); + } + if (param.contains("max")) { + range.second = param.value("max").toDouble(); + } + info.ranges.append(range); } - m_parameterInfos.append(info); - m_paramNumberTypes.insert(name, NumberType::Integer); } else if (type == "decimal") { - m_parameterInfos.append({name, QJsonValue::Double}); - m_paramNumberTypes.insert(name, NumberType::Decimal); + info = {name, ParameterDelegate::ParameterType::Decimal}; + if (param.contains("min") || param.contains("max")) { + QPair range = {INT_MIN, INT_MAX}; + if (param.contains("min")) { + range.first = param.value("min").toDouble(); + } + if (param.contains("max")) { + range.second = param.value("max").toDouble(); + } + info.ranges.append(range); + } } else if (type == "boolean") { - m_parameterInfos.append({name, QJsonValue::Bool}); + info = {name, ParameterDelegate::ParameterType::Boolean}; + } + + if (param.contains("possible_values") && param.value("possible_values").isArray()) { + auto values = param.value("possible_values").toArray(); + for (auto value : values) { + info.possibleValues.append(value); + } } + + m_parameterInfos.append(info); } if (!config.contains("script")) { @@ -324,8 +341,3 @@ QSharedPointer PythonPluginConfig::renderConfig() const { return m_renderConfig; } - -PythonPluginConfig::NumberType PythonPluginConfig::parameterNumberType(QString paramName) -{ - return m_paramNumberTypes.value(paramName, NumberType::Decimal); -} diff --git a/src/hobbits-python/pythonpluginconfig.h b/src/hobbits-python/pythonpluginconfig.h index a6f56f9b..490929b4 100644 --- a/src/hobbits-python/pythonpluginconfig.h +++ b/src/hobbits-python/pythonpluginconfig.h @@ -12,11 +12,6 @@ class HOBBITSPYTHONSHARED_EXPORT PythonPluginConfig public: PythonPluginConfig(); - enum NumberType { - Integer = 1, - Decimal = 2 - }; - static QStringList loadPythonPlugins(QString path, QSharedPointer pluginManager, std::function, QSize)> editorCreator); @@ -52,7 +47,6 @@ class HOBBITSPYTHONSHARED_EXPORT PythonPluginConfig QString type() const; QStringList extraPaths() const; QSharedPointer renderConfig() const; - NumberType parameterNumberType(QString paramName); private: QString m_name; @@ -60,7 +54,6 @@ class HOBBITSPYTHONSHARED_EXPORT PythonPluginConfig QStringList m_tags; QSharedPointer m_delegate; QList m_parameterInfos; - QMap m_paramNumberTypes; QString m_script; QString m_type; QStringList m_extraPaths; diff --git a/src/hobbits-widgets/displayhelper.cpp b/src/hobbits-widgets/displayhelper.cpp index fa90927c..a11f2465 100644 --- a/src/hobbits-widgets/displayhelper.cpp +++ b/src/hobbits-widgets/displayhelper.cpp @@ -509,7 +509,7 @@ QImage DisplayHelper::drawTextRasterFull(QSize viewportSize, int bitsPerChar, std::function textConverter) { - if (handle.isNull() || handle->currentContainer().isNull() || !display->parameterDelegate()->validate(parameters)) { + if (handle.isNull() || handle->currentContainer().isNull() || !display->parameterDelegate()->validate(parameters).isEmpty()) { return QImage(); } diff --git a/src/hobbits-widgets/parameterhelper.cpp b/src/hobbits-widgets/parameterhelper.cpp index 7587fdec..546d4d71 100644 --- a/src/hobbits-widgets/parameterhelper.cpp +++ b/src/hobbits-widgets/parameterhelper.cpp @@ -33,6 +33,16 @@ void ParameterHelper::addSpinBoxIntParameter(QString name, QSpinBox* spinBox) }); } +void ParameterHelper::addSpinBoxDoubleParameter(QString name, QDoubleSpinBox* spinBox) +{ + addParameter(name, [spinBox](QJsonValue value) { + spinBox->setValue(value.toDouble()); + return true; + }, [spinBox]() { + return QJsonValue(spinBox->value()); + }); +} + void ParameterHelper::addSliderIntParameter(QString name, QAbstractSlider *slider) { addParameter(name, [slider](QJsonValue value) { @@ -69,37 +79,43 @@ void ParameterHelper::addComboBoxParameter(QString name, QComboBox* comboBox, in auto type = m_delegate->getInfo(name).type; addParameter(name, [comboBox, type, role](QJsonValue value) { int index = -1; - if (type == QJsonValue::Bool) { + if (type == ParameterDelegate::ParameterType::Boolean) { index = comboBox->findData(value.toBool(), role); } - else if (type == QJsonValue::String) { + else if (type == ParameterDelegate::ParameterType::String) { index = comboBox->findData(value.toString(), role); } - else if (type == QJsonValue::Double) { + else if (type == ParameterDelegate::ParameterType::Decimal) { index = comboBox->findData(value.toDouble(), role); } + else if (type == ParameterDelegate::ParameterType::Integer) { + index = comboBox->findData(value.toInt(), role); + } if (index < 0) { return false; } comboBox->setCurrentIndex(index); return true; }, [comboBox, type, role]() { - if (type == QJsonValue::Bool) { + if (type == ParameterDelegate::ParameterType::Boolean) { return QJsonValue(comboBox->currentData(role).toBool()); } - else if (type == QJsonValue::String) { + else if (type == ParameterDelegate::ParameterType::String) { return QJsonValue(comboBox->currentData(role).toString()); } - else if (type == QJsonValue::Double) { + else if (type == ParameterDelegate::ParameterType::Decimal) { return QJsonValue(comboBox->currentData(role).toDouble()); } + else if (type == ParameterDelegate::ParameterType::Integer) { + return QJsonValue(comboBox->currentData(role).toInt()); + } return QJsonValue(); }); } bool ParameterHelper::applyParametersToUi(const QJsonObject ¶meters) { - if (!m_delegate->validate(parameters)) { + if (!m_delegate->validate(parameters).isEmpty()) { return false; } diff --git a/src/hobbits-widgets/parameterhelper.h b/src/hobbits-widgets/parameterhelper.h index a28c2f33..c6335f55 100644 --- a/src/hobbits-widgets/parameterhelper.h +++ b/src/hobbits-widgets/parameterhelper.h @@ -27,6 +27,9 @@ class HOBBITSWIDGETSSHARED_EXPORT ParameterHelper void addSpinBoxIntParameter(QString name, QSpinBox* spinBox); + void addSpinBoxDoubleParameter(QString name, + QDoubleSpinBox* spinBox); + void addSliderIntParameter(QString name, QAbstractSlider* slider); diff --git a/src/hobbits-widgets/simpleparametereditor.cpp b/src/hobbits-widgets/simpleparametereditor.cpp index 84d59e0c..b4370265 100644 --- a/src/hobbits-widgets/simpleparametereditor.cpp +++ b/src/hobbits-widgets/simpleparametereditor.cpp @@ -2,6 +2,7 @@ #include "ui_simpleparametereditor.h" #include #include +#include #include #include @@ -13,23 +14,42 @@ SimpleParameterEditor::SimpleParameterEditor(QSharedPointer d ui->setupUi(this); for (auto param: delegate->parameterInfos()) { - if (param.type == QJsonValue::String) { + if (!param.possibleValues.isEmpty()) { + auto comboBox = new QComboBox(); + for (auto value : param.possibleValues) { + comboBox->addItem(value.toVariant().toString(), value.toVariant()); + } + ui->formLayout->addRow(param.name, comboBox); + m_stateHelper->addComboBoxParameter(param.name, comboBox); + connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed())); + } + else if (param.type == ParameterDelegate::ParameterType::String) { auto lineEdit = new QLineEdit(); ui->formLayout->addRow(param.name, lineEdit); m_stateHelper->addLineEditStringParameter(param.name, lineEdit); connect(lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); } - else if (param.type == QJsonValue::Double) { + else if (param.type == ParameterDelegate::ParameterType::Decimal) { + auto spinBox = new QDoubleSpinBox(); + spinBox->setRange(0.0, 9000000.0); + if (param.ranges.size() == 1) { + spinBox->setRange(param.ranges.first().first, param.ranges.first().second); + } + ui->formLayout->addRow(param.name, spinBox); + m_stateHelper->addSpinBoxDoubleParameter(param.name, spinBox); + connect(spinBox, SIGNAL(valueChanged(double)), this, SIGNAL(changed())); + } + else if (param.type == ParameterDelegate::ParameterType::Integer) { auto spinBox = new QSpinBox(); - spinBox->setRange(0, 0x7fffffff); - if (param.hasIntLimits) { - spinBox->setRange(param.intMin, param.intMax); + spinBox->setRange(0, INT_MAX); + if (param.ranges.size() == 1) { + spinBox->setRange(param.ranges.first().first, param.ranges.first().second); } ui->formLayout->addRow(param.name, spinBox); m_stateHelper->addSpinBoxIntParameter(param.name, spinBox); connect(spinBox, SIGNAL(valueChanged(int)), this, SIGNAL(changed())); } - else if (param.type == QJsonValue::Bool) { + else if (param.type == ParameterDelegate::ParameterType::Boolean) { auto checkBox = new QCheckBox(param.name); ui->formLayout->addRow("", checkBox); m_stateHelper->addCheckBoxBoolParameter(param.name, checkBox);