diff --git a/delphyne_gui/visualizer/topic_interface_plugin/CMakeLists.txt b/delphyne_gui/visualizer/topic_interface_plugin/CMakeLists.txt index d4d6663f..b23c419f 100644 --- a/delphyne_gui/visualizer/topic_interface_plugin/CMakeLists.txt +++ b/delphyne_gui/visualizer/topic_interface_plugin/CMakeLists.txt @@ -11,7 +11,7 @@ QT5_ADD_RESOURCES(TopicInterfacePlugin_RCC topic_interface_plugin.qrc) add_library(TopicInterfacePlugin ${CMAKE_CURRENT_SOURCE_DIR}/topic_interface_plugin.cc - ${CMAKE_CURRENT_SOURCE_DIR}/message_widget.cc + ${CMAKE_CURRENT_SOURCE_DIR}/message.cc ${TopicInterfacePlugin_MOC} ${TopicInterfacePlugin_RCC} ) diff --git a/delphyne_gui/visualizer/topic_interface_plugin/message_widget.cc b/delphyne_gui/visualizer/topic_interface_plugin/message.cc similarity index 70% rename from delphyne_gui/visualizer/topic_interface_plugin/message_widget.cc rename to delphyne_gui/visualizer/topic_interface_plugin/message.cc index b58ef77e..96145d3c 100644 --- a/delphyne_gui/visualizer/topic_interface_plugin/message_widget.cc +++ b/delphyne_gui/visualizer/topic_interface_plugin/message.cc @@ -1,10 +1,11 @@ // Copyright 2021 Toyota Research Institute -#include "message_widget.h" +#include "message.h" namespace delphyne { namespace gui { +namespace internal { -void MessageWidget::Parse(const std::string& _scopedName, google::protobuf::Message* _msg) { +void Message::Parse(const std::string& _scopedName, google::protobuf::Message* _msg) { constexpr bool kIsRepeated{true}; constexpr bool kIsNotRepeated{!kIsRepeated}; @@ -36,36 +37,36 @@ void MessageWidget::Parse(const std::string& _scopedName, google::protobuf::Mess // Evaluate the type. if (fieldType == google::protobuf::FieldDescriptor::TYPE_MESSAGE) { auto& value = reflection->GetRepeatedMessage(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, &value, kIsRepeated); + children[itemName] = std::make_unique(itemName, &value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_DOUBLE) { const double value = reflection->GetRepeatedDouble(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_FLOAT) { const float value = reflection->GetRepeatedFloat(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_INT64) { const int64_t value = reflection->GetRepeatedInt64(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_INT32) { const int32_t value = reflection->GetRepeatedInt32(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_UINT64) { const uint64_t value = reflection->GetRepeatedUInt64(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_UINT32) { const uint32_t value = reflection->GetRepeatedUInt32(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_BOOL) { const bool value = reflection->GetRepeatedBool(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_STRING) { const std::string value = reflection->GetRepeatedString(*_msg, fieldDescriptor, count); - children[itemName] = std::make_unique(itemName, value, kIsRepeated); + children[itemName] = std::make_unique(itemName, value, kIsRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_ENUM) { auto enumValueDescriptor = reflection->GetRepeatedEnum(*_msg, fieldDescriptor, count); const int enumValue = enumValueDescriptor->number(); const std::string enumName = enumValueDescriptor->name(); - children[itemName] = std::make_unique(itemName, EnumValue{enumValue, enumName}, kIsRepeated); + children[itemName] = std::make_unique(itemName, EnumValue{enumValue, enumName}, kIsRepeated); } else { // Unhandled message type. } @@ -73,37 +74,36 @@ void MessageWidget::Parse(const std::string& _scopedName, google::protobuf::Mess } else { // It's not a repeated message, then we just need to parse them. if (fieldType == google::protobuf::FieldDescriptor::TYPE_MESSAGE) { auto& value = reflection->GetMessage(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, &value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, &value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_DOUBLE) { const double value = reflection->GetDouble(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_FLOAT) { const float value = reflection->GetFloat(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_INT64) { const int64_t value = reflection->GetInt64(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_INT32) { const int32_t value = reflection->GetInt32(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_UINT64) { const uint64_t value = reflection->GetUInt64(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_UINT32) { const uint32_t value = reflection->GetUInt32(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_BOOL) { const bool value = reflection->GetBool(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_STRING) { const std::string value = reflection->GetString(*_msg, fieldDescriptor); - children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, value, kIsNotRepeated); } else if (fieldType == google::protobuf::FieldDescriptor::TYPE_ENUM) { auto enumValueDescriptor = reflection->GetEnum(*_msg, fieldDescriptor); const int enumValue = enumValueDescriptor->number(); const std::string enumName = enumValueDescriptor->name(); - children[scopedName] = - std::make_unique(scopedName, EnumValue{enumValue, enumName}, kIsNotRepeated); + children[scopedName] = std::make_unique(scopedName, EnumValue{enumValue, enumName}, kIsNotRepeated); } else { // Unhandled message type. } @@ -111,5 +111,6 @@ void MessageWidget::Parse(const std::string& _scopedName, google::protobuf::Mess } } +} // namespace internal } // namespace gui } // namespace delphyne diff --git a/delphyne_gui/visualizer/topic_interface_plugin/message.h b/delphyne_gui/visualizer/topic_interface_plugin/message.h new file mode 100644 index 00000000..b8289418 --- /dev/null +++ b/delphyne_gui/visualizer/topic_interface_plugin/message.h @@ -0,0 +1,113 @@ +// Copyright 2021 Toyota Research Institute +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace delphyne { +namespace gui { +namespace internal { + +/// @brief Holds the information of a google::protobuf::Message to be consumed +/// by a Qt widget. +/// @details Holds a variant when it is a leaf node in the message tree +/// ( @see Message::Variant ). Otherwise, when it is a compound type, +/// it populates a dictionary of Messages. +/// See Parse() implementation for a full description of how it uses +/// the reflection API in Google Protobuf Message class to get the +/// information of each field. +class Message { + public: + /// Wraps an enumeration field in Google Protobuf. + struct EnumValue { + int value; ///< The integer value of the enum. + std::string name; ///< The string label the enum has. + }; + + /// It simplifies the operation by consumers when dealing with the type. + /// An instance is well-constructed iff none or just one field has a value. + using Variant = std::variant; + + /// @brief Constructs a Message. + /// + /// @details It is a template constuctor that behaves differently based on T. + /// When T is one of the possible Variant's types, it just stores the + /// value in `variantValue`. When it is a pointer (it'll compile + /// only for google::protobuf::Message*) it'll forward a copy of + /// @p _value to Parse() nodes. + /// @param _name The message name. The fully qualified attribute name will be + /// used when it is recursively built. + /// @param _value The value to hold. When it is a pointer, it is assumed to be + /// a google::protobuf::Message* which will request a recursive + /// introspection via Parse() to populate children. + /// @param _isRepeated Whether or not this message is a repeated field in a + /// google::protobuf::Message definition. + template + Message(const std::string& _name, T _value, bool _isRepeated) { + name = _name; + isRepeated = _isRepeated; + if constexpr (std::is_pointer::value) { + auto msg = _value->New(); + msg->CopyFrom(*_value); + Parse(name, msg); + } else { + typeName = typeid(_value).name(); + variantValue = _value; + } + } + + /// @return The full name of this item in the proto message hierarchy. It + /// uses "::" to separate field names and injects "::X::" where X is + /// a non-negative number to differentiate repeated fields. + std::string Name() const { return name; } + + /// @return The type name of the message. + std::string TypeName() const { return typeName; } + + /// @return Whether this type is compound or not. + bool IsCompound() const { return !children.empty(); } + + /// @return The value this message holds. + Variant Value() const { return variantValue; } + + /// @return Whether the message is a repeated value of a type at the certain + /// level in the hierarchy. + bool IsRepeated() const { return isRepeated; } + + /// @return The children dictionary. + const std::map>& Children() const { return children; } + + private: + /// @brief Parses @p _msg and stores children Message into + /// `variantValue` using @p _scopedName as `name`. + void Parse(const std::string& _scopedName, google::protobuf::Message* _msg); + + /// @brief This message full name. + std::string name{""}; + + /// @brief Holds the type name of the data. + std::string typeName{""}; + + /// @brief Holds the data of a terminal node. + Variant variantValue; + + /// @brief Whether or not this is a repeated field. + bool isRepeated{false}; + + /// @brief Holds the children, nested values. + std::map> children; +}; + +} // namespace internal +} // namespace gui +} // namespace delphyne diff --git a/delphyne_gui/visualizer/topic_interface_plugin/message_widget.h b/delphyne_gui/visualizer/topic_interface_plugin/message_widget.h deleted file mode 100644 index f7081c12..00000000 --- a/delphyne_gui/visualizer/topic_interface_plugin/message_widget.h +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2021 Toyota Research Institute -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -namespace delphyne { -namespace gui { - -/// @brief Holds the information of a google::protobuf::Message to be consumed -/// by a Qt widget. -/// @details Holds a variant like-struct when it is a leaf node in the message -/// tree ( @see MessageWidget::Variant ). Otherwise, when it is a -/// compound type, it populates a dictionary of MessageWidgets. -/// See Parse() implementation for a full description of how it uses -/// the reflection API in Google Protobuf Message class to get the -/// information of each field. -class MessageWidget { - public: - /// Wraps an enumeration field in Google Protobuf. - struct EnumValue { - int value; ///< The integer value of the enum. - std::string name; ///< The string label the enum has. - }; - - /// Operates as a std::variant from optionals. It simplifies the operation by - /// consumers when dealing with the type differences. - /// An instance is well-constructed iff none or just one field has a value. - struct Variant { - std::optional doubleVal{std::nullopt}; - std::optional floatVal{std::nullopt}; - std::optional int64Val{std::nullopt}; - std::optional int32Val{std::nullopt}; - std::optional uInt64Val{std::nullopt}; - std::optional uInt32Val{std::nullopt}; - std::optional boolVal{std::nullopt}; - std::optional stringVal{std::nullopt}; - std::optional enumVal{std::nullopt}; - }; - - /// @{ Multiple constructors for the different types. - /// TODO(#332): Improve this using template constructors. Probably, Variant - /// needs to change to std::variant. - explicit MessageWidget(const std::string& _name, double _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.doubleVal = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, float _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.floatVal = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, int64_t _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.int64Val = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, int32_t _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.int32Val = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, uint64_t _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.uInt64Val = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, uint32_t _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.uInt32Val = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, bool _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.boolVal = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, const std::string& _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.stringVal = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, EnumValue _value, bool _isRepeated) { - name = _name; - typeName = typeid(_value).name(); - variantValue.enumVal = _value; - isRepeated = _isRepeated; - } - explicit MessageWidget(const std::string& _name, const google::protobuf::Message* _msg, bool _isRepeated) { - name = _name; - auto msg = _msg->New(); - msg->CopyFrom(*_msg); - Parse(name, msg); - isRepeated = _isRepeated; - } - /// @} - - /// @return The full name of this item in the proto message hierarchy. It - /// uses "::" to separate field names and injects "::X::" where X is - /// a non-negative number to differentiate repeated fields. - std::string Name() const { return name; } - - /// @return The type name of the message. - std::string TypeName() const { return typeName; } - - /// @return Whether this type is compound or not. - bool IsCompound() const { return !children.empty(); } - - /// @return The value this message holds. - Variant Value() const { return variantValue; } - - /// @return Whether the message is a repeated value of a type at the certain - /// level in the hierarchy. - bool IsRepeated() const { return isRepeated; } - - /// @return The children dictionary. - const std::map>& Children() const { return children; } - - private: - /// @brief Parses @p _msg and stores children MessageWidget into - /// `variantValue` using @p _scopedName as `name`. - void Parse(const std::string& _scopedName, google::protobuf::Message* _msg); - - /// @brief This message full name. - std::string name{""}; - - /// @brief Holds the type name of the data. - std::string typeName{""}; - - /// @brief Holds the data of a terminal node. - Variant variantValue; - - /// @brief Whether or not this is a repeated field. - bool isRepeated{false}; - - /// @brief Holds the children, nested values. - std::map> children; -}; - -} // namespace gui -} // namespace delphyne diff --git a/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.cc b/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.cc index 1b43a5aa..d648496d 100644 --- a/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.cc +++ b/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.cc @@ -18,28 +18,18 @@ namespace delphyne { namespace gui { namespace { -// Serializes a @p value into @p os. -std::ostream& operator<<(std::ostream& os, const MessageWidget::Variant& value) { - if (value.doubleVal.has_value()) { - os << value.doubleVal.value(); - } else if (value.floatVal.has_value()) { - os << value.floatVal.value(); - } else if (value.int64Val.has_value()) { - os << value.int64Val.value(); - } else if (value.int32Val.has_value()) { - os << value.int32Val.value(); - } else if (value.uInt64Val.has_value()) { - os << value.uInt64Val.value(); - } else if (value.uInt32Val.has_value()) { - os << value.uInt32Val.value(); - } else if (value.boolVal.has_value()) { - os << std::boolalpha << value.boolVal.value(); - } else if (value.stringVal.has_value()) { - os << value.stringVal.value(); - } else if (value.enumVal.has_value()) { - os << value.enumVal.value().name; - } - return os; +// Serializes a @p _value into @p _os. Provides a valid operator overload for +// internal::Message::EnumValue so the following function's lambda can be +// resolved. +std::ostream& operator<<(std::ostream& _os, const internal::Message::EnumValue& _value) { + _os << _value.name; + return _os; +} + +// Serializes a @p _value into @p _os. +std::ostream& operator<<(std::ostream& _os, const internal::Message::Variant& _value) { + std::visit([&_os](auto&& arg) { _os << arg; }, _value); + return _os; } // @returns A lower case string with the contents of @p _str. @@ -74,8 +64,6 @@ std::string GetSimpleName(const std::string _fullName) { // When there are none occurrences of "::", this function returns @p _fullName. std::string GetRepeatedName(const std::string _fullName) { auto pos = _fullName.rfind("::"); - // TODO(#332): separator was not found, this is an error when calling this - // function as it assumes the field is repeated. if (pos == std::string::npos) { return _fullName; } @@ -104,8 +92,6 @@ void TopicInterfacePlugin::LoadConfig(const tinyxml2::XMLElement* _pluginElem) { title = "Topic interface"; } - int uiTimerPeriodMs = kUiTimerPerdiodMs; - if (_pluginElem) { // Widget UI title. if (auto xmlTitle = _pluginElem->FirstChildElement("title")) { @@ -120,10 +106,6 @@ void TopicInterfacePlugin::LoadConfig(const tinyxml2::XMLElement* _pluginElem) { xmlHideWidgetElement = xmlHideWidgetElement->NextSiblingElement("hide")) { hideWidgets.push_back(xmlHideWidgetElement->GetText()); } - // UI update period. - if (auto xmlUiUpdatePeriodMs = _pluginElem->FirstChildElement("ui_update_period_ms")) { - xmlUiUpdatePeriodMs->QueryIntText(&uiTimerPeriodMs); - } } // Subscribe @@ -140,16 +122,16 @@ void TopicInterfacePlugin::OnMessageReceived() { // @{ Load the message values. std::lock_guard lock(mutex); - VisitMessageWidgets("", root, messageWidget.get(), true /* top level item */); + VisitMessages("", root, message.get(), true /* top level item */); // @} } -void TopicInterfacePlugin::VisitMessageWidgets(const std::string& _name, QStandardItem* _parent, - MessageWidget* _messageWidget, bool _isTopLevel) { +void TopicInterfacePlugin::VisitMessages(const std::string& _name, QStandardItem* _parent, internal::Message* _message, + bool _isTopLevel) { + // Does not visit blacklisted items. // amendedName is the name of the field but it applies a lower case transformation // and removes the "::X::" of the name when it represents a repeated field. const std::string amendedName = RemoveNumberingField(StringToLowerCase(_name)); - // Does not visit blacklisted items. if (std::find_if(hideWidgets.begin(), hideWidgets.end(), [amendedName](const std::string& hideTopic) { return amendedName == StringToLowerCase(hideTopic); }) != hideWidgets.end()) { @@ -157,8 +139,7 @@ void TopicInterfacePlugin::VisitMessageWidgets(const std::string& _name, QStanda } const QString uniqueName = QString::fromStdString(_name); - const QString name = - QString::fromStdString(_messageWidget->IsRepeated() ? GetRepeatedName(_name) : GetSimpleName(_name)); + const QString name = QString::fromStdString(_message->IsRepeated() ? GetRepeatedName(_name) : GetSimpleName(_name)); QStandardItem* item{nullptr}; bool shouldAppendToParent{false}; @@ -171,21 +152,21 @@ void TopicInterfacePlugin::VisitMessageWidgets(const std::string& _name, QStanda } QString data(""); - if (_messageWidget->IsCompound()) { - for (const auto& name_child : _messageWidget->Children()) { - VisitMessageWidgets(name_child.first, _isTopLevel ? _parent : item, name_child.second.get(), - false /* not a top level element */); + if (_message->IsCompound()) { + for (const auto& name_child : _message->Children()) { + VisitMessages(name_child.first, _isTopLevel ? _parent : item, name_child.second.get(), + false /* not a top level element */); } } else { std::stringstream ss; - ss << _messageWidget->Value(); + ss << _message->Value(); data = QString::fromStdString(ss.str()); } // When the item is a top level message, it is not added to the UI but its // children are. if (!_isTopLevel) { item->setData(QVariant(name), MessageModel::kNameRole); - item->setData(QVariant(QString::fromStdString(_messageWidget->TypeName())), MessageModel::kTypeRole); + item->setData(QVariant(QString::fromStdString(_message->TypeName())), MessageModel::kTypeRole); item->setData(QVariant(data), MessageModel::kDataRole); if (shouldAppendToParent) { _parent->appendRow(item); @@ -195,7 +176,7 @@ void TopicInterfacePlugin::VisitMessageWidgets(const std::string& _name, QStanda void TopicInterfacePlugin::OnMessage(const google::protobuf::Message& _msg) { std::lock_guard lock(mutex); - messageWidget = std::make_unique("", &_msg, false /* is not repeated */); + message = std::make_unique("", &_msg, false /* is not repeated */); emit MessageReceived(); } diff --git a/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.h b/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.h index a1a06554..3fc3f993 100644 --- a/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.h +++ b/delphyne_gui/visualizer/topic_interface_plugin/topic_interface_plugin.h @@ -11,7 +11,7 @@ #include #include -#include "message_widget.h" +#include "message.h" namespace delphyne { namespace gui { @@ -65,7 +65,7 @@ class TopicInterfacePlugin : public ignition::gui::Plugin { /// @brief Callback executed when there is a new message from the topic. /// @details Update the message. - /// @details @p _msg is converted into a MessageWidget and set to be + /// @details @p _msg is converted into a Message and set to be /// displayed. /// @param _msg The received message. void OnMessage(const google::protobuf::Message& _msg); @@ -85,24 +85,20 @@ class TopicInterfacePlugin : public ignition::gui::Plugin { void MessageReceived(); private: - /// @brief Default UI update period in milliseconds. - static constexpr int kUiTimerPerdiodMs{10000}; - - /// @brief Visits nodes in @p _messageWidget and adds them as new rows of a + /// @brief Visits nodes in @p _message and adds them as new rows of a /// @p _parent item when they are not there. /// @details This function implements a visitor pattern and is called - /// recursively over the children nodes of @p _messageWidget. For - /// each node in @p _messageWidget, a new MessageModel is added with + /// recursively over the children nodes of @p _message. For + /// each node in @p _message, a new MessageModel is added with /// the its contents. - /// When @p _messageWidget is a top level message item, its children + /// When @p _message is a top level message item, its children /// will be added to the parent UI element but not itself. - /// @param _name The name of @p _messageWidget node. - /// @param _parent The parent of @p _messageWidget node. - /// @param _messageWidget The message to fill in an UI item. - /// @param _isTopLevel Whether @p _messageWidget is a top level item in the + /// @param _name The name of @p _message node. + /// @param _parent The parent of @p _message node. + /// @param _message The message to fill in an UI item. + /// @param _isTopLevel Whether @p _message is a top level item in the /// tree hierarchy. - void VisitMessageWidgets(const std::string& _name, QStandardItem* _parent, MessageWidget* _messageWidget, - bool _isTopLevel); + void VisitMessages(const std::string& _name, QStandardItem* _parent, internal::Message* _message, bool _isTopLevel); /// @brief The type of the message to receive. std::string msgType{}; @@ -114,7 +110,7 @@ class TopicInterfacePlugin : public ignition::gui::Plugin { std::vector hideWidgets; /// @brief Latest received message - std::unique_ptr messageWidget; + std::unique_ptr message; /// @brief Transport node. ignition::transport::Node node;