diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt b/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt index 9450ff9ebb1ace95ca7a96d8bc631ecde8a2a145..749f70029b0271c47594e703193e1f49f725d261 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt @@ -11,13 +11,15 @@ set(SOURCES aronTreeWidget/visitors/AronTreeWidgetModalCreator.cpp aronTreeWidget/visitors/AronTreeWidgetContextMenu.cpp aronTreeWidget/Data.cpp - aronTreeWidget/NDArrayHelper.cpp - aronTreeWidget/EditMatrixWidget.cpp - aronTreeWidget/QuaternionWidget.cpp + aronTreeWidget/widgets/EditMatrixWidget.cpp + aronTreeWidget/widgets/IntEnumWidget.cpp + aronTreeWidget/ListDictHelper.cpp + aronTreeWidget/widgets/QuaternionWidget.cpp aronTreeWidget/AronTreeWidgetItem.cpp aronTreeWidget/AronTreeWidgetController.cpp aronTreeWidget/modal/text/AronTreeWidgetTextInputModalController.cpp aronTreeWidget/modal/AronTreeWidgetModal.cpp + ColorPalettes.cpp SkillManagerMonitorWidgetController.cpp ) @@ -28,13 +30,16 @@ set(HEADERS aronTreeWidget/visitors/AronTreeWidgetModalCreator.h aronTreeWidget/visitors/AronTreeWidgetContextMenu.h aronTreeWidget/Data.h - aronTreeWidget/NDArrayHelper.h - aronTreeWidget/EditMatrixWidget.h - aronTreeWidget/QuaternionWidget.h + aronTreeWidget/widgets/NDArrayHelper.h + aronTreeWidget/widgets/EditMatrixWidget.h + aronTreeWidget/widgets/IntEnumWidget.h + aronTreeWidget/ListDictHelper.h + aronTreeWidget/widgets/QuaternionWidget.h aronTreeWidget/AronTreeWidgetItem.h aronTreeWidget/AronTreeWidgetController.h aronTreeWidget/modal/AronTreeWidgetModal.h aronTreeWidget/modal/text/AronTreeWidgetTextInputModalController.h + ColorPalettes.h SkillManagerMonitorWidgetController.h ) diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/ColorPalettes.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/ColorPalettes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d263456d71c8fbfb2179b9ca6fbabb963699fa7a --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/ColorPalettes.cpp @@ -0,0 +1,23 @@ +#include "ColorPalettes.h" + +namespace armarx::gui_color_palette +{ + QPalette + getErrorPalette() + { + QPalette errorPalette; + errorPalette.setColor(QPalette::Base, Qt::red); + errorPalette.setColor(QPalette::Text, Qt::black); + return errorPalette; + } + QPalette + getNormalPalette() + { + + QPalette normalPalette; + + normalPalette.setColor(QPalette::Base, Qt::white); + normalPalette.setColor(QPalette::Text, Qt::black); + return normalPalette; + } +} // namespace armarx::gui_color_palette diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/ColorPalettes.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/ColorPalettes.h new file mode 100644 index 0000000000000000000000000000000000000000..ade58f4319d6c65db21ae66895a4ec758d113d7e --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/ColorPalettes.h @@ -0,0 +1,9 @@ +#pragma once +#include <QPalette> + +namespace armarx::gui_color_palette +{ + QPalette getNormalPalette(); + + QPalette getErrorPalette(); +} // namespace armarx::gui_color_palette diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/ListDictHelper.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/ListDictHelper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9866e8bc9f8c35a00e6411331461511e4c031e9f --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/ListDictHelper.cpp @@ -0,0 +1,28 @@ +#include "ListDictHelper.h" + +namespace armarx::misc +{ + QString + generateNumElementsText(int num) + { + QString numElemsText = "<"; + if (num == 0) + { + numElemsText.append("no"); + } + else + { + numElemsText.append(QString::number(num)); + } + if (num > 1 || num == 0) + { + numElemsText.append(" elements>"); + } + else + { + numElemsText.append(" element>"); + } + return numElemsText; + } + +} // namespace armarx::misc diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/ListDictHelper.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/ListDictHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..c5d991ad2861aef5c32fc82c033c9090070f13b5 --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/ListDictHelper.h @@ -0,0 +1,8 @@ +#include <QString> + + +namespace armarx::misc +{ + // helper that generates a string on how many items are available + QString generateNumElementsText(int num); +} // namespace armarx::misc diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.cpp index 76c38e9a27d686d40e7dce7d29380074957f5dde..e7843221f89365ff113e3eb0cc444bb9aa7ed812 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.cpp @@ -6,6 +6,7 @@ #include <QTreeWidgetItem> #include "../AronTreeWidgetItem.h" +#include "../ListDictHelper.h" #include "AronTreeWidgetCreator.h" namespace armarx @@ -19,29 +20,6 @@ namespace armarx { } - QString - AronTreeWidgetContextMenuVisitor::generateNumElementsText(int num) - { - QString numElemsText = "<"; - if (num == 0) - { - numElemsText.append("no"); - } - else - { - numElemsText.append(QString::number(num)); - } - if (num > 1 || num == 0) - { - numElemsText.append(" elements>"); - } - else - { - numElemsText.append(" element>"); - } - return numElemsText; - } - void AronTreeWidgetContextMenuVisitor::addDeleteAction() { @@ -78,7 +56,7 @@ namespace armarx castedContainer->child(i)->setText(0, numberString.c_str()); } // This displays the number of children also when the list is collapsed - QString numElemsText = generateNumElementsText(castedContainer->childCount()); + QString numElemsText = misc::generateNumElementsText(castedContainer->childCount()); containerPtr->setText(1, numElemsText); // set italic auto currFont = castedContainer->font(1); @@ -126,7 +104,7 @@ namespace armarx castedContainer->aronType->getDescriptor() == aron::type::Descriptor::LIST) { // This displays the number of children also when the list is collapsed - auto numElemsText = generateNumElementsText(castedContainer->childCount()); + auto numElemsText = misc::generateNumElementsText(castedContainer->childCount()); castedContainer->setText(1, numElemsText); // set italic auto currFont = castedContainer->font(1); diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.h index bc35df3cb66a78a97640f0b29ae945d59697c9d6..510f68292b91bf9934dcecd4300d698e64d516b3 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.h +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetContextMenu.h @@ -15,17 +15,17 @@ namespace armarx class AronTreeWidgetItem; + // Visitor on aron types. It creates a context menu dependent on the type of the AronTreeWidgetItem. + // Its only used for Lists and Dicts. class AronTreeWidgetContextMenuVisitor : public armarx::aron::type::ConstVariantVisitor { - public: + AronTreeWidgetItem* parentItem; QTreeWidget* contextMenuParent; const QPoint& pos; int index; - // helper that generates a string on how many items are available - // its used most often in this class, that's why its defined here - static QString generateNumElementsText(int num); + public: AronTreeWidgetContextMenuVisitor() = delete; AronTreeWidgetContextMenuVisitor(AronTreeWidgetItem* i, const QPoint& pos, diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetConverter.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetConverter.cpp index 10fa387251f71fefbacfd95b39d1510ce7163db7..d390959415dc319ee5f63786573f52951c6ee5dd 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetConverter.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetConverter.cpp @@ -35,8 +35,9 @@ // qt #include <QTreeWidgetItem> -#include "../EditMatrixWidget.h" -#include "../QuaternionWidget.h" +#include "../widgets/EditMatrixWidget.h" +#include "../widgets/IntEnumWidget.h" +#include "../widgets/QuaternionWidget.h" namespace armarx @@ -269,42 +270,17 @@ namespace armarx void AronTreeWidgetConverterVisitor::visitAronVariant(const aron::type::IntEnumPtr& i) { - auto crAron = std::make_shared<aron::data::Int>(i->getPath()); - createdAron = crAron; - auto valueMap = i->getAcceptedValueMap(); QTreeWidgetItem* el = parentItem->child(index); - std::string toParse = el->text(1).toStdString(); - auto searchRes = valueMap.find(toParse); - if (searchRes != valueMap.end()) + auto* genericWidget = el->treeWidget()->itemWidget(el, 1); + auto* intEnumWidget = IntEnumWidget::DynamicCastAndCheck(genericWidget); + if (!intEnumWidget) { - crAron->setValue(searchRes->second); + // already reporting error; continue here return; } - // maybe its the number directly - auto accVals = i->getAcceptedValues(); - int res; - try - { - res = simox::alg::to_<int>(toParse); - } - catch (const simox::error::SimoxError& err) - { - errorOccured = true; - ARMARX_VERBOSE << "Failed to parse IntEnum: Could not convert \'" << toParse - << "\' to an int. It also was not one of the accepted strings."; - return; - } - if (std::find(accVals.begin(), accVals.end(), res) != accVals.end()) - { - - crAron->setValue(res); - } - else - { - errorOccured = true; - ARMARX_VERBOSE << "Parsed int " << res - << "but this int is not part of the accepted values."; - } + bool success; + std::tie(success, createdAron) = intEnumWidget->parseToAron(); + errorOccured &= success; } void diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetCreator.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetCreator.cpp index e7dde099a79a7bab378e82b71270e8ec090dcee2..02abb5c7ac440e7f5b0508c2004425aa724fb3bf 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetCreator.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetCreator.cpp @@ -22,15 +22,19 @@ #include <string> -#include "../EditMatrixWidget.h" -#include "../QuaternionWidget.h" +#include "../widgets/EditMatrixWidget.h" +#include "../widgets/IntEnumWidget.h" +#include "../widgets/QuaternionWidget.h" // base class #include "AronTreeWidgetCreator.h" // data +#include <QComboBox> + #include "../AronTreeWidgetItem.h" #include "../Data.h" +#include "../ListDictHelper.h" #include "AronTreeWidgetContextMenu.h" namespace armarx @@ -186,7 +190,7 @@ namespace armarx { insertNewTreeViewWidget(i, ""); // TODO: Move to external helper class - auto txt = AronTreeWidgetContextMenuVisitor::generateNumElementsText(0); + auto txt = misc::generateNumElementsText(0); createdQWidgetItem->setText(1, txt); } void @@ -235,7 +239,11 @@ namespace armarx ARMARX_CHECK_NOT_NULL(i); ARMARX_CHECK_GREATER(i->getAcceptedValueNames().size(), 0); - insertNewTreeViewWidget(i, i->getAcceptedValueNames()[0]); + insertNewTreeViewWidget(i, ""); + // TODO set combobox widget with correct content + IntEnumWidget* widget = new IntEnumWidget(i); + //widget->postCtorCall(); + createdQWidgetItem->treeWidget()->setItemWidget(createdQWidgetItem, 1, widget); } void AronTreeWidgetCreatorVisitor::visitAronVariant(const aron::type::IntPtr& i) diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetSetter.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetSetter.cpp index 6c03126d63948bd1f89446dc6fabea89755d25e5..279e8bf0870704623f58a3a9ef4b988686f8bd65 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetSetter.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/visitors/AronTreeWidgetSetter.cpp @@ -24,8 +24,10 @@ #include <string> -#include "../EditMatrixWidget.h" -#include "../QuaternionWidget.h" +#include "../ListDictHelper.h" +#include "../widgets/EditMatrixWidget.h" +#include "../widgets/IntEnumWidget.h" +#include "../widgets/QuaternionWidget.h" #include "AronTreeWidgetContextMenu.h" #include "AronTreeWidgetCreator.h" @@ -145,8 +147,7 @@ namespace armarx ++x; } // This displays the number of children also when the list is collapsed - QString numElemsText = - AronTreeWidgetContextMenuVisitor::generateNumElementsText(i->getElements().size()); + QString numElemsText = misc::generateNumElementsText(i->getElements().size()); aronTreeWidget->setText(1, numElemsText); // set italic auto currFont = aronTreeWidget->font(1); @@ -157,107 +158,121 @@ namespace armarx void - AronTreeWidgetSetterVisitor::visitAronVariant(const aron::data::NDArrayPtr& arr) + visitMatrix(EditMatrixWidget* matrixWidget, + const std::shared_ptr<armarx::aron::type::Matrix>& matrixType, + const aron::data::NDArrayPtr& arr) { - // Matrices are handled as NDArray. Raw ndarrays cannot be created currently - auto* castedEl = AronTreeWidgetItem::DynamicCast(parentItem->child(index)); - ARMARX_CHECK(castedEl); - auto matrixCast = aron::type::Matrix::DynamicCast(castedEl->aronType); - auto quaternionCast = aron::type::Quaternion::DynamicCast(castedEl->aronType); - auto* rootWidget = castedEl->treeWidget(); - ARMARX_CHECK(rootWidget); - EditMatrixWidget* matrixWidget = - EditMatrixWidget::DynamicCast(rootWidget->itemWidget(castedEl, 1)); - QuaternionWidget* quaternionWidget = - QuaternionWidget::DynamicCast(rootWidget->itemWidget(castedEl, 1)); - - if (matrixCast && matrixWidget) + auto elemType = matrixType->getElementType(); + auto* rawData = arr->getData(); + // string can convert any item + auto toString = [elemType, rawData](size_t elementNr) -> std::string { - auto elemType = matrixCast->getElementType(); - auto* rawData = arr->getData(); - // string can convert any item - auto toString = [elemType, rawData](size_t elementNr) -> std::string + switch (elemType) { - switch (elemType) + case aron::type::matrix::ElementType::FLOAT32: + { + static_assert(sizeof(float) == 4); + float* interpreted = reinterpret_cast<float*>(rawData); + float laundered = std::launder(interpreted)[elementNr]; + return usString<float>(laundered); + } + case aron::type::matrix::ElementType::FLOAT64: + { + static_assert(sizeof(double) == 8); + double* interpreted = reinterpret_cast<double*>(rawData); + float laundered = std::launder(interpreted)[elementNr]; + return usString<double>(laundered); + } + case aron::type::matrix::ElementType::INT16: { - case aron::type::matrix::ElementType::FLOAT32: - { - static_assert(sizeof(float) == 4); - float* interpreted = reinterpret_cast<float*>(rawData); - float laundered = std::launder(interpreted)[elementNr]; - return usString<float>(laundered); - } - case aron::type::matrix::ElementType::FLOAT64: - { - static_assert(sizeof(double) == 8); - double* interpreted = reinterpret_cast<double*>(rawData); - float laundered = std::launder(interpreted)[elementNr]; - return usString<double>(laundered); - } - case aron::type::matrix::ElementType::INT16: - { - int16_t* interpreted = reinterpret_cast<int16_t*>(rawData); - int16_t laudered = std::launder(interpreted)[elementNr]; - return usString<int16_t>(laudered); - } - case aron::type::matrix::ElementType::INT32: - { - int32_t* interpreted = reinterpret_cast<int32_t*>(rawData); - int32_t laudered = std::launder(interpreted)[elementNr]; - return usString<int32_t>(laudered); - } - case aron::type::matrix::ElementType::INT64: - { - int64_t* interpreted = reinterpret_cast<int64_t*>(rawData); - int64_t laudered = std::launder(interpreted)[elementNr]; - return usString<int64_t>(laudered); - } + int16_t* interpreted = reinterpret_cast<int16_t*>(rawData); + int16_t laudered = std::launder(interpreted)[elementNr]; + return usString<int16_t>(laudered); } - return "Error!"; - }; + case aron::type::matrix::ElementType::INT32: + { + int32_t* interpreted = reinterpret_cast<int32_t*>(rawData); + int32_t laudered = std::launder(interpreted)[elementNr]; + return usString<int32_t>(laudered); + } + case aron::type::matrix::ElementType::INT64: + { + int64_t* interpreted = reinterpret_cast<int64_t*>(rawData); + int64_t laudered = std::launder(interpreted)[elementNr]; + return usString<int64_t>(laudered); + } + } + return "Error!"; + }; - for (size_t row = 0; (int)row < matrixCast->getRows(); ++row) + for (size_t row = 0; (int)row < matrixType->getRows(); ++row) + { + for (size_t col = 0; (int)col < matrixType->getCols(); ++col) { - for (size_t col = 0; (int)col < matrixCast->getCols(); ++col) - { - matrixWidget->setText(row, col, toString(col * matrixCast->getRows() + row)); - } + matrixWidget->setText(row, col, toString(col * matrixType->getRows() + row)); } } - else if (quaternionCast && quaternionWidget) + } + void + visitQuaternion(QuaternionWidget* quatWidget, + std::shared_ptr<armarx::aron::type::Quaternion>& quatType, + const aron::data::NDArrayPtr& arr) + { + auto elemType = quatType->getElementType(); + auto rawData = arr->getData(); + auto shape = arr->getShape(); + // string can convert any item + auto toString = [elemType, rawData](size_t elementNr) -> std::string { - auto elemType = quaternionCast->getElementType(); - auto rawData = arr->getData(); - auto shape = arr->getShape(); - // string can convert any item - auto toString = [elemType, rawData](size_t elementNr) -> std::string + switch (elemType) { - switch (elemType) + case aron::type::quaternion::ElementType::FLOAT32: { - case aron::type::quaternion::ElementType::FLOAT32: - { - static_assert(sizeof(float) == 4); - float* interpreted = reinterpret_cast<float*>(rawData); - float laundered = std::launder(interpreted)[elementNr]; - return usString<float>(laundered); - } - case aron::type::quaternion::ElementType::FLOAT64: - { - static_assert(sizeof(double) == 8); - double* interpreted = reinterpret_cast<double*>(rawData); - //TODO: Note to future Tobi: Fix pls. Does not find correct number. May also be export error from component! - // also: skill execution crashes. See into Skill provider - float laundered = std::launder(interpreted)[elementNr]; - return usString<double>(laundered); - } + static_assert(sizeof(float) == 4); + float* interpreted = reinterpret_cast<float*>(rawData); + float laundered = std::launder(interpreted)[elementNr]; + return usString<float>(laundered); + } + case aron::type::quaternion::ElementType::FLOAT64: + { + static_assert(sizeof(double) == 8); + double* interpreted = reinterpret_cast<double*>(rawData); + + float laundered = std::launder(interpreted)[elementNr]; + return usString<double>(laundered); } - return "Error!"; - }; - for (size_t i = 0; i < 4; ++i) - { - quaternionWidget->setText((QuaternionWidget::QuaternionComponents)i, toString(i)); } + return "Error!"; + }; + for (size_t i = 0; i < 4; ++i) + { + quatWidget->setText((QuaternionWidget::QuaternionComponents)i, toString(i)); + } + } + + void + AronTreeWidgetSetterVisitor::visitAronVariant(const aron::data::NDArrayPtr& arr) + { + // Matrices are handled as NDArray. Raw ndarrays cannot be created currently + auto* castedEl = AronTreeWidgetItem::DynamicCast(parentItem->child(index)); + ARMARX_CHECK(castedEl); + + auto matrixCast = aron::type::Matrix::DynamicCast(castedEl->aronType); + auto quaternionCast = aron::type::Quaternion::DynamicCast(castedEl->aronType); + + auto* rootWidget = castedEl->treeWidget(); + ARMARX_CHECK(rootWidget); + auto* matrixWidget = EditMatrixWidget::DynamicCast(rootWidget->itemWidget(castedEl, 1)); + auto* quaternionWidget = QuaternionWidget::DynamicCast(rootWidget->itemWidget(castedEl, 1)); + + if (matrixCast && matrixWidget) + { + visitMatrix(matrixWidget, matrixCast, arr); + } + else if (quaternionCast && quaternionWidget) + { + visitQuaternion(quaternionWidget, quaternionCast, arr); } else { @@ -272,7 +287,18 @@ namespace armarx if (checkTreeWidgetItemForSimilarName(i->getPath().getLastElement())) { QTreeWidgetItem* el = parentItem->child(index); - el->setText(1, QString::fromStdString(usString<int>(i->getValue()))); + auto* enumWidget = IntEnumWidget::DynamicCast(el->treeWidget()->itemWidget(el, 1)); + auto newText = QString::fromStdString(usString<int>(i->getValue())); + if (enumWidget) + { + // Its an IntEnum! -> Ask the custom widget + enumWidget->setText(newText); + } + else + { + // Its just an int. -> do the QTreeWidgetItem call + el->setText(1, newText); + } } } diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/EditMatrixWidget.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/EditMatrixWidget.cpp similarity index 93% rename from source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/EditMatrixWidget.cpp rename to source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/EditMatrixWidget.cpp index 223e5e8d9f71bfa03938c87d20862d1c58c1959a..de5f5c3314b61f0beadeada4a4c0a00f03dcf85a 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/EditMatrixWidget.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/EditMatrixWidget.cpp @@ -6,8 +6,9 @@ #include "ArmarXCore/core/exceptions/local/ExpressionException.h" #include "ArmarXCore/core/logging/Logging.h" +#include "../../ColorPalettes.h" +#include "../visitors/AronTreeWidgetCreator.h" #include "NDArrayHelper.h" -#include "visitors/AronTreeWidgetCreator.h" namespace armarx { @@ -147,14 +148,6 @@ namespace armarx void EditMatrixWidget::highlightUnparsableEntries() { - QPalette normalPalette; - normalPalette.setColor(QPalette::Base, Qt::white); - normalPalette.setColor(QPalette::Text, Qt::black); - - QPalette errorPalette; - errorPalette.setColor(QPalette::Base, Qt::red); - errorPalette.setColor(QPalette::Text, Qt::black); - auto dispRows = getDisplayedRows(); auto dispCols = getDisplayedCols(); for (size_t row = 0; row < dispRows; ++row) @@ -164,11 +157,13 @@ namespace armarx auto parsed = parseElement(row, col); if (parsed.empty()) { - dispElements.at(row * dispCols + col)->setPalette(errorPalette); + dispElements.at(row * dispCols + col) + ->setPalette(gui_color_palette::getErrorPalette()); } else { - dispElements.at(row * dispCols + col)->setPalette(normalPalette); + dispElements.at(row * dispCols + col) + ->setPalette(gui_color_palette::getNormalPalette()); } } } diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/EditMatrixWidget.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/EditMatrixWidget.h similarity index 83% rename from source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/EditMatrixWidget.h rename to source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/EditMatrixWidget.h index 3c3f9f5140d4a9820cc964fd98acf36927d9806b..5948d0c27f990c7e3a0edbbd2c74cb5546f202d4 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/EditMatrixWidget.h +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/EditMatrixWidget.h @@ -11,6 +11,9 @@ namespace armarx { + // Custom Widget used to display Matrices + // MAX_ROWS_DISPLAY and MAX_COLS_DISPLAY are the maximal number of elements displayable + // everything else will not be displayed. However, there can still be made changes to this data with setText() class EditMatrixWidget : public QWidget { Q_OBJECT @@ -20,12 +23,12 @@ namespace armarx static EditMatrixWidget* DynamicCast(QWidget*); static EditMatrixWidget* DynamicCastAndCheck(QWidget*); - // Sets the text on all visible rows and cols. Does nothing for invisible ones. + // Sets the text on all visible rows and cols. void setText(size_t row, size_t col, const std::string& str); std::string getText(size_t row, size_t col); void highlightUnparsableEntries(); bool hasParseErrors(); - // returns an empty vector if parsing failed. else, contains the individual bytes. + // returns an empty vector if parsing failed. Else, contains the individual bytes. std::vector<unsigned char> parseElement(size_t row, size_t col); private: diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/IntEnumWidget.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/IntEnumWidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..578a65acb51696dbafc815e576c92021127371f1 --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/IntEnumWidget.cpp @@ -0,0 +1,133 @@ +#include "IntEnumWidget.h" + +#include <QHBoxLayout> + +#include "RobotAPI/libraries/aron/core/type/variant/All.h" + +#include "../../ColorPalettes.h" +#include "../visitors/AronTreeWidgetConverter.h" + +namespace armarx +{ + IntEnumWidget::IntEnumWidget(const aron::type::IntEnumPtr& enumPtr) : element_type(enumPtr) + { + auto names = enumPtr->getAcceptedValueNames(); + auto outerLayout = new QHBoxLayout(); + outerLayout->setContentsMargins(0, 0, 0, 0); + innerWidget = new QComboBox(); + outerLayout->addWidget(innerWidget); + + for (const auto& n : names) + { + innerWidget->addItem(n.c_str()); + } + innerWidget->setInsertPolicy(QComboBox::NoInsert); + innerWidget->setEditable(true); + innerWidget->setCurrentIndex(0); + + setLayout(outerLayout); + ARMARX_CHECK(connect(innerWidget, + SIGNAL(currentTextChanged(const QString&)), + this, + SLOT(textChanged(const QString&)))); + } + + IntEnumWidget* + IntEnumWidget::DynamicCast(QWidget* widget) + { + return dynamic_cast<IntEnumWidget*>(widget); + } + + IntEnumWidget* + IntEnumWidget::DynamicCastAndCheck(QWidget* elem) + { + if (!elem) + { + return nullptr; + } + auto* casted = DynamicCast(elem); + ARMARX_CHECK_NOT_NULL(casted); + return casted; + } + + bool + IntEnumWidget::hasParseErrors() + { + return parseToAron().first; + } + + void + IntEnumWidget::setText(const QString& text) + { + innerWidget->setEditText(text); + highlightUnparsableEntries(); + } + + QString + IntEnumWidget::getText() + { + return innerWidget->currentText(); + } + + std::pair<bool, aron::data::IntPtr> + IntEnumWidget::parseToAron() + { + auto crAron = std::make_shared<aron::data::Int>(element_type->getPath()); + + // first look for strings in value map + auto valueMap = element_type->getAcceptedValueMap(); + std::string toParse = getText().toStdString(); + + auto searchRes = valueMap.find(toParse); + if (searchRes != valueMap.end()) + { + crAron->setValue(searchRes->second); + return {true, crAron}; + } + // maybe its the number directly + auto accVals = element_type->getAcceptedValues(); + int res; + try + { + res = simox::alg::to_<int>(toParse); + } + catch (const simox::error::SimoxError& err) + { + ARMARX_VERBOSE << "Failed to parse IntEnum: Could not convert \'" << toParse + << "\' to an int. It also was not one of the accepted strings."; + return {false, nullptr}; + } + if (std::find(accVals.begin(), accVals.end(), res) != accVals.end()) + { + + crAron->setValue(res); + } + else + { + ARMARX_VERBOSE << "Parsed int " << res + << "but this int is not part of the accepted values."; + return {false, nullptr}; + } + return {true, crAron}; + } + + void + IntEnumWidget::highlightUnparsableEntries() + { + auto parsed = parseToAron().first; + if (parsed) + { + innerWidget->setPalette(gui_color_palette::getNormalPalette()); + } + else + { + innerWidget->setPalette(gui_color_palette::getErrorPalette()); + } + } + + void + IntEnumWidget::textChanged(const QString&) + { + highlightUnparsableEntries(); + } +} // namespace armarx diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/IntEnumWidget.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/IntEnumWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..72e568f2a645a2e5e18d0ab3f013110bc280dad5 --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/IntEnumWidget.h @@ -0,0 +1,41 @@ +#pragma once + +#include <QComboBox> +#include <QWidget> + +#include "RobotAPI/libraries/aron/core/data/variant/primitive/Int.h" +#include "RobotAPI/libraries/aron/core/type/variant/forward_declarations.h" + +#include "../AronTreeWidgetItem.h" + +namespace armarx +{ + // Custom wrapper around the QComboBox widget to represent IntEnums + // This class handles parsing once the user edited the field and is also responsible + // to parse the according aron data from text + class IntEnumWidget : public QWidget + { + Q_OBJECT + public: + IntEnumWidget(const aron::type::IntEnumPtr&); + // needs to be called after the constructor, because qt needs the meta object to be fully constructed at this point + void postCtorCall(); + + static IntEnumWidget* DynamicCast(QWidget*); + static IntEnumWidget* DynamicCastAndCheck(QWidget*); + + bool hasParseErrors(); + void setText(const QString& text); + QString getText(); + std::pair<bool, aron::data::IntPtr> parseToAron(); + + private: + const aron::type::IntEnumPtr element_type; + QComboBox* innerWidget; + bool noParseErrors = true; + + void highlightUnparsableEntries(); + private slots: + void textChanged(const QString&); + }; +} // namespace armarx diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/NDArrayHelper.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/NDArrayHelper.h new file mode 100644 index 0000000000000000000000000000000000000000..ed91b874cc5f91ee24cf95eb6b46013da7b9d590 --- /dev/null +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/NDArrayHelper.h @@ -0,0 +1,30 @@ +#pragma once +#include <string> +#include <vector> + +#include <SimoxUtility/algorithm/string.h> + +class NDArrayHelper +{ +public: + // Uses the simox utility to parse floatingpoint and fixed precision types + // it then writes the result into a byte vector + // an empty byte vector encodes a parsing error. + template <typename T> + std::vector<unsigned char> static toByteVector(const std::string& str) + { + try + { + auto val = simox::alg::to_<T>(str); + std::vector<unsigned char> res(sizeof(val), 0); + T* reinterpPtr = reinterpret_cast<T*>(res.data()); + T* laundered = std::launder(reinterpPtr); + *laundered = val; + return res; + } + catch (const simox::error::SimoxError& err) + { + return {}; + } + } +}; diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/QuaternionWidget.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/QuaternionWidget.cpp similarity index 90% rename from source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/QuaternionWidget.cpp rename to source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/QuaternionWidget.cpp index 67a5a62a19c25f2c3b15058f8e3b0e9472fad1c5..39f80e503b264008a4a07bd206101ff7c7f1f652 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/QuaternionWidget.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/QuaternionWidget.cpp @@ -4,6 +4,7 @@ #include <QLabel> #include <QLineEdit> +#include "../../ColorPalettes.h" #include "NDArrayHelper.h" namespace armarx { @@ -85,14 +86,6 @@ namespace armarx void QuaternionWidget::highlightUnparsableEntries() { - QPalette normalPalette; - normalPalette.setColor(QPalette::Base, Qt::white); - normalPalette.setColor(QPalette::Text, Qt::black); - - QPalette errorPalette; - errorPalette.setColor(QPalette::Base, Qt::red); - errorPalette.setColor(QPalette::Text, Qt::black); - noParseErrors = true; for (size_t i = 0; i < 4; ++i) { @@ -115,11 +108,11 @@ namespace armarx } if (ok) { - xyzw_components.at(i)->setPalette(normalPalette); + xyzw_components.at(i)->setPalette(gui_color_palette::getNormalPalette()); } else { - xyzw_components.at(i)->setPalette(errorPalette); + xyzw_components.at(i)->setPalette(gui_color_palette::getErrorPalette()); noParseErrors = false; } } diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/QuaternionWidget.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/QuaternionWidget.h similarity index 88% rename from source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/QuaternionWidget.h rename to source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/QuaternionWidget.h index c75e0fad87b50c8a1225dbdcc4fc901b7c088650..869ff7ce76319f5c98a8a7877744c65b74e139b9 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/QuaternionWidget.h +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/aronTreeWidget/widgets/QuaternionWidget.h @@ -11,6 +11,8 @@ namespace armarx { + // Custom Widget which represents a Quaternion - This class does not normalize the inputs + // It can parse its data to NDArray and also handles user edit signals itself. (And also the highlighting if errors occur) class QuaternionWidget : public QWidget { Q_OBJECT