diff --git a/.clang-format b/.clang-format index 43c7648a3b8b1497c07e324f7d289692fa3ce88c..827c89b435020ccdca9a15eb06a972ac5947c742 100644 --- a/.clang-format +++ b/.clang-format @@ -1,4 +1,13 @@ { BasedOnStyle: Google, + AccessModifierOffset: -4, + AlignConsecutiveAssignments: true, + AllowShortIfStatementsOnASingleLine: false, + AllowShortLoopsOnASingleLine: false, + BreakBeforeBraces: Allman, + ColumnLimit: 80, + ConstructorInitializerAllOnOneLineOrOnePerLine: false, + IndentCaseLabels: true, IndentWidth: 4, + KeepEmptyLinesAtTheStartOfBlocks: true, } diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index c53785838aad821c4a2754227f28eadad970a4ee..49b400525cead1a262a154b7ed0fe83d29c3f5e7 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -4,14 +4,13 @@ "name": "Linux", "includePath": [ "${workspaceFolder}/**", - "~/Qt/5.15.2/gcc_64/include/**", - "/Users/alberton/Qt/5.15.2/clang_64/include/**" + "/Users/alberton/Qt/5.15.2/**" ], "defines": [], - "compilerPath": "/usr/bin/gcc", + "compilerPath": "/usr/bin/clang++", "cStandard": "gnu17", "cppStandard": "gnu++17", - "intelliSenseMode": "linux-gcc-x64" + "intelliSenseMode": "clang-x64" } ], "version": 4 diff --git a/.vscode/settings.json b/.vscode/settings.json index 74d9bae1b0355fa2feef595e842cfb7ee44eaaf3..301582c728fb174400df740c940f7813796cca70 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,7 +10,90 @@ "set": "cpp", "string_view": "cpp", "unordered_map": "cpp", - "locale": "cpp" + "locale": "cpp", + "qlabel": "cpp", + "qwidget": "cpp", + "__hash_table": "cpp", + "__split_buffer": "cpp", + "__tree": "cpp", + "array": "cpp", + "bitset": "cpp", + "deque": "cpp", + "initializer_list": "cpp", + "list": "cpp", + "queue": "cpp", + "random": "cpp", + "stack": "cpp", + "vector": "cpp", + "iterator": "cpp", + "utility": "cpp", + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__nullptr": "cpp", + "__string": "cpp", + "__threading_support": "cpp", + "__tuple": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "fstream": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "numeric": "cpp", + "optional": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "__functional_base": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "*.tcc": "cpp", + "memory_resource": "cpp", + "source_location": "cpp", + "stop_token": "cpp", + "cinttypes": "cpp", + "qformlayout": "cpp", + "qpair": "cpp", + "qstring": "cpp", + "qregularexpression": "cpp", + "qmessagebox": "cpp" }, "editor.defaultFormatter": "chiehyu.vscode-astyle", "[xml]": { diff --git a/Components/SubscriptionsPanel/subscriptionspanel.cpp b/Components/SubscriptionsPanel/subscriptionspanel.cpp index 5dc1139cdd4ba06ff29eaa8cac2059d2f43a0365..17870ac0051c17bae2ac544a1c78114387d0cb0f 100644 --- a/Components/SubscriptionsPanel/subscriptionspanel.cpp +++ b/Components/SubscriptionsPanel/subscriptionspanel.cpp @@ -1,61 +1,65 @@ #include "subscriptionspanel.h" -#include "ui_subscriptionspanel.h" -#include "Components/TopicAndFieldSelector/topicandfieldselector.h" #include <QDebug> -SubscriptionsPanel::SubscriptionsPanel(const QList<TopicAndFieldFilter>* subscriptionsList) : QWidget(nullptr), ui(new Ui::SubscriptionsPanel) { +#include "Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h" +#include "Components/TopicFilterSelector/topicfilterselector.h" +#include "ui_subscriptionspanel.h" + +SubscriptionsPanel::SubscriptionsPanel( + const QList<TopicAndFieldFilter>* subscriptionsList) + : QWidget(nullptr), ui(new Ui::SubscriptionsPanel) +{ ui->setupUi(this); this->setAttribute(Qt::WA_DeleteOnClose, true); - for(auto s : *subscriptionsList) { + for (auto s : *subscriptionsList) + { addSubscription(s); } - connect(ui->button_addTopic, &QPushButton::clicked, this, &SubscriptionsPanel::onAddTopicClicked); - connect(ui->button_addTopicAndField, &QPushButton::clicked, this, &SubscriptionsPanel::onAddTopicAndFieldClicked); - connect(ui->button_remove, &QPushButton::clicked, this, &SubscriptionsPanel::onRemoveClicked); + connect(ui->button_addTopic, &QPushButton::clicked, this, + &SubscriptionsPanel::onAddTopicClicked); + connect(ui->button_addTopicAndField, &QPushButton::clicked, this, + &SubscriptionsPanel::onAddTopicAndFieldClicked); + connect(ui->button_remove, &QPushButton::clicked, this, + &SubscriptionsPanel::onRemoveClicked); } -SubscriptionsPanel::~SubscriptionsPanel() { - delete ui; -} +SubscriptionsPanel::~SubscriptionsPanel() { delete ui; } -void SubscriptionsPanel::addSubscription(const TopicAndFieldFilter& filter) { +void SubscriptionsPanel::addSubscription(const TopicAndFieldFilter& filter) +{ QListWidgetItem* listItem = new QListWidgetItem(filter.toString()); ui->subscriptions_list->addItem(listItem); emit SubscriptionAdded(filter); } -void SubscriptionsPanel::removeSubscription(QListWidgetItem* item) { - emit SubscriptionRemoved(TopicAndFieldFilter::fromStringUnsafe(item->text())); +void SubscriptionsPanel::removeSubscription(QListWidgetItem* item) +{ + emit SubscriptionRemoved( + TopicAndFieldFilter::fromStringUnsafe(item->text())); delete item; } - -void SubscriptionsPanel::onAddTopicClicked() { - TopicAndFieldSelector::selectTopic([this](const TopicAndFieldFilter & topic) { - addSubscription(topic); - }); +void SubscriptionsPanel::onAddTopicClicked() +{ + TopicFilterSelector::selectFilter([this](const TopicFilter& topic) + { addSubscription(topic); }); } -void SubscriptionsPanel::onAddTopicAndFieldClicked() { - TopicAndFieldSelector::selectTopicAndField([this](const TopicAndFieldFilter & filter) { - addSubscription(filter); - }); +void SubscriptionsPanel::onAddTopicAndFieldClicked() +{ + TopicAndFieldFilterSelector::selectFilter( + [this](const TopicAndFieldFilter& filter) { addSubscription(filter); }); } -void SubscriptionsPanel::onRemoveClicked() { +void SubscriptionsPanel::onRemoveClicked() +{ auto items = ui->subscriptions_list->selectedItems(); - for(auto item : items) { + for (auto item : items) + { removeSubscription(item); } } - - - - - - - diff --git a/Components/SubscriptionsPanel/subscriptionspanel.h b/Components/SubscriptionsPanel/subscriptionspanel.h index 61007395615bc4eb5f72e85518d754a26b404f37..a38bf4d4d688db0d685db5d9b02e8d8fc0de8cda 100644 --- a/Components/SubscriptionsPanel/subscriptionspanel.h +++ b/Components/SubscriptionsPanel/subscriptionspanel.h @@ -1,38 +1,40 @@ #ifndef SUBSCRIPTIONSPANEL_H #define SUBSCRIPTIONSPANEL_H -#include <QWidget> -#include <QListWidgetItem> #include <QList> +#include <QListWidgetItem> +#include <QWidget> + #include "Core/Message/topicandfieldfilter.h" -namespace Ui { +namespace Ui +{ class SubscriptionsPanel; } -class SubscriptionsPanel : public QWidget { +class SubscriptionsPanel : public QWidget +{ Q_OBJECT - public: - explicit SubscriptionsPanel(const QList<TopicAndFieldFilter>* subscriptionsList); +public: + explicit SubscriptionsPanel( + const QList<TopicAndFieldFilter>* subscriptionsList); ~SubscriptionsPanel(); void addSubscription(const TopicAndFieldFilter& filter); void removeSubscription(QListWidgetItem* item); - private slots: +private slots: void onAddTopicClicked(); void onAddTopicAndFieldClicked(); void onRemoveClicked(); - signals: +signals: void SubscriptionAdded(const TopicAndFieldFilter&); void SubscriptionRemoved(const TopicAndFieldFilter&); - private: +private: Ui::SubscriptionsPanel* ui; }; -#endif // SUBSCRIPTIONSPANEL_H - - +#endif // SUBSCRIPTIONSPANEL_H diff --git a/Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.cpp b/Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c0365982f913b32ceaf430ecb741fb105049f9a --- /dev/null +++ b/Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.cpp @@ -0,0 +1,74 @@ + +#include "topicandfieldfilterselector.h" + +#include <QFormLayout> +#include <QLineEdit> +#include <QMessageBox> +#include <QPushButton> + +TopicAndFieldFilterSelector::TopicAndFieldFilterSelector( + const TopicAndFieldFilter& filter) +{ + setAttribute(Qt::WA_DeleteOnClose, true); + setWindowTitle("Choose Topic and Field name"); + + QFormLayout* form = new QFormLayout; + form->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); + QLineEdit* topicEdit = new QLineEdit; + topicEdit->setText(filter.getTopicFilter().toString()); + form->addRow("Topic:", topicEdit); + QLineEdit* fieldEdit = new QLineEdit; + fieldEdit->setText(filter.getFieldFilter()); + form->addRow("Field:", fieldEdit); + + QHBoxLayout* buttons = new QHBoxLayout; + QPushButton* cancel = new QPushButton("Cancel"); + buttons->addWidget(cancel); + QPushButton* select = new QPushButton("Select"); + buttons->addWidget(select); + + QVBoxLayout* outer = new QVBoxLayout; + outer->addLayout(form); + outer->addLayout(buttons); + setLayout(outer); + + auto onSelect = [=]() + { + if (topicEdit->text().isEmpty() || fieldEdit->text().isEmpty()) + { + QMessageBox msgBox(nullptr); + msgBox.setText("Cannot accept empty fields"); + msgBox.exec(); + } + else + { + TopicAndFieldFilter newFilter(topicEdit->text(), fieldEdit->text()); + + emit filterSelected(newFilter); + deleteLater(); + } + }; + + connect(cancel, &QPushButton::clicked, [this]() { deleteLater(); }); + connect(select, &QPushButton::clicked, onSelect); + connect(topicEdit, &QLineEdit::returnPressed, onSelect); +} + +void TopicAndFieldFilterSelector::selectFilter( + TopicAndFieldFilterSelector::Handler handler) +{ + TopicAndFieldFilterSelector* selector = new TopicAndFieldFilterSelector({}); + QObject::connect(selector, &TopicAndFieldFilterSelector::filterSelected, + handler); + selector->show(); +} + +void TopicAndFieldFilterSelector::selectFilter( + const TopicAndFieldFilter& filter, Handler handler) +{ + TopicAndFieldFilterSelector* selector = + new TopicAndFieldFilterSelector(filter); + QObject::connect(selector, &TopicAndFieldFilterSelector::filterSelected, + handler); + selector->show(); +} diff --git a/Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h b/Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h new file mode 100644 index 0000000000000000000000000000000000000000..f7eece9796a40bd5ed47babf52bab2a4dea0ccaf --- /dev/null +++ b/Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h @@ -0,0 +1,29 @@ +#ifndef TOPICANDFIELDFILTERSELECTOR_H +#define TOPICANDFIELDFILTERSELECTOR_H + +#include <QPair> +#include <QString> +#include <QWidget> +#include <functional> + +#include "Core/Message/topicandfieldfilter.h" + +class TopicAndFieldFilterSelector : public QWidget +{ + Q_OBJECT + +public: + using Handler = std::function<void(const TopicAndFieldFilter& selector)>; + + static void selectFilter(Handler handler); + static void selectFilter(const TopicAndFieldFilter& filter, + Handler handler); + +private: + TopicAndFieldFilterSelector(const TopicAndFieldFilter& filter); + +signals: + void filterSelected(const TopicAndFieldFilter&); +}; + +#endif // TOPICANDFIELDFILTERSELECTOR_H diff --git a/Components/TopicAndFieldSelector/topicandfieldselector.cpp b/Components/TopicAndFieldSelector/topicandfieldselector.cpp deleted file mode 100644 index 1135c69ea5f167ab0e318c1453375ee79f3cc01c..0000000000000000000000000000000000000000 --- a/Components/TopicAndFieldSelector/topicandfieldselector.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "topicandfieldselector.h" - -#include <QFormLayout> -#include <QLineEdit> -#include <QMessageBox> -#include <QPushButton> - -void TopicAndFieldSelector::selectTopicAndField(TopicAndFieldSelector::Handler func) { - TopicAndFieldSelector* selector = new TopicAndFieldSelector(false); - QObject::connect(selector, &TopicAndFieldSelector::topicAndFieldSelected, func); - selector->show(); -} - -void TopicAndFieldSelector::selectTopic(TopicAndFieldSelector::Handler func) { - TopicAndFieldSelector* selector = new TopicAndFieldSelector(true); - QObject::connect(selector, &TopicAndFieldSelector::topicSelected, func); - selector->show(); -} - -TopicAndFieldSelector::TopicAndFieldSelector(bool justTopic) { - setAttribute(Qt::WA_DeleteOnClose, true); - setWindowTitle(justTopic ? tr("Choose Topic") : tr("Choose Topic and Field name")); - - - QHBoxLayout* buttons = new QHBoxLayout; - QPushButton* cancel = new QPushButton(tr("Cancel")); - QPushButton* select = new QPushButton(tr("Select")); - buttons->addWidget(cancel); - buttons->addWidget(select); - - QFormLayout* form = new QFormLayout; - QLineEdit* topicEdit = new QLineEdit; - form->addRow(tr("Topic:"), topicEdit); - - QVBoxLayout* outer = new QVBoxLayout; - outer->addLayout(form); - outer->addLayout(buttons); - setLayout(outer); - - connect(cancel, &QPushButton::clicked, [this]() { - deleteLater(); - }); - - if(justTopic) { - auto lambda = [ = ]() { - TopicFilter filter(topicEdit->text()); - - if(validityCheck(filter)) { - emit topicSelected({filter}); - deleteLater(); - } - }; - - connect(select, &QPushButton::clicked, lambda); - connect(topicEdit, &QLineEdit::returnPressed, lambda); - } else { - QLineEdit* fieldEdit = new QLineEdit; - form->addRow(tr("Field:"), fieldEdit); - - auto lambda = [ = ]() { - TopicFilter filter(topicEdit->text()); - - if(validityCheck(filter)) { - if(fieldEdit->text().isEmpty()) { - QMessageBox msgBox(nullptr); - msgBox.setText(tr("Cannot accept empty Field name")); - msgBox.exec(); - } else { - emit topicAndFieldSelected({filter, fieldEdit->text()}); - deleteLater(); - } - } - }; - - connect(select, &QPushButton::clicked, lambda); - connect(fieldEdit, &QLineEdit::returnPressed, lambda); - } - -} - -bool TopicAndFieldSelector::validityCheck(const TopicFilter& filter) { - if(!filter.isValid()) { - QMessageBox msgBox(nullptr); - msgBox.setText(tr("Invalid Topic")); - msgBox.exec(); - return false; - } - return true; -} diff --git a/Components/TopicAndFieldSelector/topicandfieldselector.h b/Components/TopicAndFieldSelector/topicandfieldselector.h deleted file mode 100644 index 904b70d29fccbc73278fab425dcb4e31e6025955..0000000000000000000000000000000000000000 --- a/Components/TopicAndFieldSelector/topicandfieldselector.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TOPICANDFIELDSELECTOR_H -#define TOPICANDFIELDSELECTOR_H - -#include <functional> -#include <QWidget> -#include <QString> -#include <QPair> -#include "Core/Message/topicandfieldfilter.h" - -class TopicAndFieldSelector : public QWidget { - Q_OBJECT - public: - using Handler = std::function<void(const TopicAndFieldFilter& selector)>; - - static void selectTopicAndField(Handler func); - static void selectTopic(Handler func); - - private: - TopicAndFieldSelector(bool justTopic); - static bool validityCheck(const TopicFilter&); - - signals: - void topicSelected(const TopicAndFieldFilter&); - void topicAndFieldSelected(const TopicAndFieldFilter&); -}; - -#endif // TOPICANDFIELDSELECTOR_H diff --git a/Components/TopicFilterSelector/topicfilterselector.cpp b/Components/TopicFilterSelector/topicfilterselector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b4aae6c4573ec281358dfbfaf7c2740476dd70f --- /dev/null +++ b/Components/TopicFilterSelector/topicfilterselector.cpp @@ -0,0 +1,65 @@ +#include "topicfilterselector.h" + +#include <QFormLayout> +#include <QLineEdit> +#include <QMessageBox> +#include <QPushButton> + +TopicFilterSelector::TopicFilterSelector(const TopicFilter& filter) +{ + setAttribute(Qt::WA_DeleteOnClose, true); + setWindowTitle("Choose Topic and Field name"); + + QFormLayout* form = new QFormLayout; + form->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow); + QLineEdit* topicEdit = new QLineEdit; + topicEdit->setText(filter.toString()); + form->addRow("Topic:", topicEdit); + + QHBoxLayout* buttons = new QHBoxLayout; + QPushButton* cancel = new QPushButton("Cancel"); + buttons->addWidget(cancel); + QPushButton* select = new QPushButton("Select"); + buttons->addWidget(select); + + QVBoxLayout* outer = new QVBoxLayout; + outer->addLayout(form); + outer->addLayout(buttons); + setLayout(outer); + + auto onSelect = [=]() + { + if (topicEdit->text().isEmpty()) + { + QMessageBox msgBox(nullptr); + msgBox.setText("Cannot accept empty fields"); + msgBox.exec(); + } + else + { + TopicFilter newFilter(topicEdit->text()); + + emit filterSelected(newFilter); + deleteLater(); + } + }; + + connect(cancel, &QPushButton::clicked, [this]() { deleteLater(); }); + connect(select, &QPushButton::clicked, onSelect); + connect(topicEdit, &QLineEdit::returnPressed, onSelect); +} + +void TopicFilterSelector::selectFilter(TopicFilterSelector::Handler handler) +{ + TopicFilterSelector* selector = new TopicFilterSelector({}); + QObject::connect(selector, &TopicFilterSelector::filterSelected, handler); + selector->show(); +} + +void TopicFilterSelector::selectFilter(const TopicFilter& filter, + Handler handler) +{ + TopicFilterSelector* selector = new TopicFilterSelector(filter); + QObject::connect(selector, &TopicFilterSelector::filterSelected, handler); + selector->show(); +} diff --git a/Components/TopicFilterSelector/topicfilterselector.h b/Components/TopicFilterSelector/topicfilterselector.h new file mode 100644 index 0000000000000000000000000000000000000000..f0141055a7c2d83cef003597522f78748e686d60 --- /dev/null +++ b/Components/TopicFilterSelector/topicfilterselector.h @@ -0,0 +1,28 @@ +#ifndef TOPICFILTERSELECTOR_H +#define TOPICFILTERSELECTOR_H + +#include <QPair> +#include <QString> +#include <QWidget> +#include <functional> + +#include "Core/Message/topicfilter.h" + +class TopicFilterSelector : public QWidget +{ + Q_OBJECT + +public: + using Handler = std::function<void(const TopicFilter& selector)>; + + static void selectFilter(Handler handler); + static void selectFilter(const TopicFilter& filter, Handler handler); + +private: + TopicFilterSelector(const TopicFilter& filter); + +signals: + void filterSelected(const TopicFilter&); +}; + +#endif // TOPICANDFIELDFILTERSELECTOR_H diff --git a/Core/Message/modulemessage.cpp b/Core/Message/modulemessage.cpp index d879ad40c4eaf7b02af3b1682ae356fb1996bc81..71742a05adb59a60c585731b1b28d544763eec0e 100644 --- a/Core/Message/modulemessage.cpp +++ b/Core/Message/modulemessage.cpp @@ -1,64 +1,83 @@ #include "modulemessage.h" -ModuleMessage::ModuleMessage() { -} +ModuleMessage::ModuleMessage() {} -ModuleMessage::ModuleMessage(Topic _topic) : topic(_topic) { } +ModuleMessage::ModuleMessage(Topic _topic) : topic(_topic) {} -ModuleMessage::ModuleMessage(const ModuleMessage& rhs) : topic(rhs.topic), fields(rhs.fields) { } +ModuleMessage::ModuleMessage(const ModuleMessage& rhs) + : topic(rhs.topic), fields(rhs.fields) +{ +} -ModuleMessage::ModuleMessage(ModuleMessage&& rhs) : topic(rhs.topic), fields(std::move(rhs.fields)) { } +ModuleMessage::ModuleMessage(ModuleMessage&& rhs) + : topic(rhs.topic), fields(std::move(rhs.fields)) +{ +} -ModuleMessage& ModuleMessage::operator=(const ModuleMessage& rhs) { - topic = rhs.topic; +ModuleMessage& ModuleMessage::operator=(const ModuleMessage& rhs) +{ + topic = rhs.topic; fields = rhs.fields; return *this; } -ModuleMessage& ModuleMessage::operator=(ModuleMessage&& rhs) { - topic = rhs.topic; +ModuleMessage& ModuleMessage::operator=(ModuleMessage&& rhs) +{ + topic = rhs.topic; fields = std::move(rhs.fields); return *this; } -MessageField ModuleMessage::getField(QString key) const { +MessageField ModuleMessage::getField(QString key) const +{ auto it = fields.find(key); - if(it == fields.cend()) { + if (it == fields.cend()) + { return {}; } return *it; } -Topic ModuleMessage::getTopic() const { - return topic; -} +Topic ModuleMessage::getTopic() const { return topic; } -void ModuleMessage::setField(QString key, MessageField field) { +void ModuleMessage::setField(QString key, MessageField field) +{ fields[key] = field; } -void ModuleMessage::setTopic(Topic _topic) { - topic = _topic; -} +void ModuleMessage::setTopic(Topic _topic) { topic = _topic; } -void ModuleMessage::setFields(const QMap<QString, MessageField>& _fields) { +void ModuleMessage::setFields(const QMap<QString, MessageField>& _fields) +{ fields = _fields; } -void ModuleMessage::setFields(QMap<QString, MessageField>&& _fields) { +void ModuleMessage::setFields(QMap<QString, MessageField>&& _fields) +{ fields = std::move(_fields); } -QString ModuleMessage::toString(bool includeTopic) const { +void ModuleMessage::filterFields(const QString& fieldFilter) +{ + for (auto it = fields.begin(); it != fields.end(); it++) + if (it.key() != fieldFilter) + fields.remove(it.key()); +} + +QString ModuleMessage::toString(bool includeTopic) const +{ QString str = "{\n\t"; - if(includeTopic) { + if (includeTopic) + { str.append("<topic>: "); str.append(topic.toString()); } - for(auto it = fields.keyBegin(); it != fields.keyEnd(); ++it) { - if(includeTopic || it != fields.keyBegin()) { + for (auto it = fields.keyBegin(); it != fields.keyEnd(); ++it) + { + if (includeTopic || it != fields.keyBegin()) + { str.append(",\n\t"); } str.append(*it); diff --git a/Core/Message/modulemessage.h b/Core/Message/modulemessage.h index 3f9aa279b4af2e64a49bb2781e90ba4a1eec233d..001b7823144399c90084c44ef482e855b5b0bc2a 100644 --- a/Core/Message/modulemessage.h +++ b/Core/Message/modulemessage.h @@ -1,8 +1,8 @@ #ifndef MODULEMESSAGE_H #define MODULEMESSAGE_H -#include <QTime> #include <QMap> +#include <QTime> #include "messagefield.h" #include "topic.h" @@ -10,9 +10,10 @@ /* * Structure of internal GS Messages. * -*/ -class ModuleMessage { - public: + */ +class ModuleMessage +{ +public: ModuleMessage(); ModuleMessage(Topic topic); @@ -30,11 +31,16 @@ class ModuleMessage { void setFields(const QMap<QString, MessageField>& fields); void setFields(QMap<QString, MessageField>&& fields); + /** + * @brief Removes all the fields that do not match the filter. + */ + void filterFields(const QString& fieldFilter); + QString toString(bool includeTopic = false) const; - private: +private: Topic topic; QMap<QString, MessageField> fields; }; -#endif // MODULEMESSAGE_H +#endif // MODULEMESSAGE_H diff --git a/Core/Message/topicandfieldfilter.cpp b/Core/Message/topicandfieldfilter.cpp index 26ab2ee96835c4f70503bba8b7507558eb2bd8d0..ac0d44647477e2b9f145dec826b82b61e2e337d5 100644 --- a/Core/Message/topicandfieldfilter.cpp +++ b/Core/Message/topicandfieldfilter.cpp @@ -1,53 +1,86 @@ #include "topicandfieldfilter.h" -TopicAndFieldFilter::TopicAndFieldFilter() : topicFilter(TopicFilter::Any), fieldName("") {} -TopicAndFieldFilter::TopicAndFieldFilter(const TopicFilter& _topicFilter, const QString& _fieldName) - : topicFilter(_topicFilter), fieldName(_fieldName) {} +TopicAndFieldFilter::TopicAndFieldFilter() + : topicFilter(TopicFilter::any()), fieldFilter("") +{ +} + +TopicAndFieldFilter::TopicAndFieldFilter(const QString& topicFilter, + const QString& fieldFilter) + : topicFilter(topicFilter), fieldFilter(fieldFilter) +{ +} + +TopicAndFieldFilter::TopicAndFieldFilter(const TopicFilter& topicFilter, + const QString& fieldFilter) + : topicFilter(topicFilter), fieldFilter(fieldFilter) +{ +} -bool TopicAndFieldFilter::operator==(const TopicAndFieldFilter& rhs) const { - return topicFilter == rhs.topicFilter && fieldName == rhs.fieldName; +bool TopicAndFieldFilter::operator==(const TopicAndFieldFilter& rhs) const +{ + return topicFilter == rhs.topicFilter && fieldFilter == rhs.fieldFilter; } -bool TopicAndFieldFilter::matchTopic(const Topic& topic) const { +bool TopicAndFieldFilter::matchTopic(const Topic& topic) const +{ return topicFilter.match(topic); } -bool TopicAndFieldFilter::matchMessage(const ModuleMessage& message, MessageField& extracted) const { - if(!matchTopic(message.getTopic())) { +bool TopicAndFieldFilter::matchMessage(const ModuleMessage& message, + MessageField& field) const +{ + // Check if the message matches the topic + if (!matchTopic(message.getTopic())) return false; - } - if(fieldName.isEmpty()) { - extracted = MessageField(message.toString()); - } else { - extracted = message.getField(fieldName); - } - return true; + // If the field filter is empty, the message is transformed into a single + // string field + if (fieldFilter.isEmpty()) + field = MessageField(message.toString()); + else + field = message.getField(fieldFilter); + return true; } -TopicFilter TopicAndFieldFilter::getTopic() const { - return topicFilter; -} +bool TopicAndFieldFilter::filterMessage(ModuleMessage& message) const +{ + // Check if the message matches the topic + if (!matchTopic(message.getTopic())) + return false; + + // Then filter the message if the field filter is not empty + if (!fieldFilter.isEmpty()) + message.filterFields(fieldFilter); -QString TopicAndFieldFilter::getFieldName() const { - return fieldName; + return true; } -bool TopicAndFieldFilter::isFullFilter() const { - return !fieldName.isEmpty(); +TopicFilter TopicAndFieldFilter::getTopicFilter() const { return topicFilter; } + +QString TopicAndFieldFilter::getFieldFilter() const { return fieldFilter; } + +bool TopicAndFieldFilter::isFullFilter() const +{ + return !fieldFilter.isEmpty(); } -QString TopicAndFieldFilter::toString() const { - return topicFilter.toString() + "." + (fieldName.isEmpty() ? "*" : fieldName); +QString TopicAndFieldFilter::toString() const +{ + return topicFilter.toString() + "." + + (fieldFilter.isEmpty() ? "*" : fieldFilter); } -TopicAndFieldFilter TopicAndFieldFilter::fromStringUnsafe(const QString& str) { +TopicAndFieldFilter TopicAndFieldFilter::fromStringUnsafe(const QString& str) +{ int idx = str.indexOf('.'); - if(idx == -1) { + if (idx == -1) + { return TopicAndFieldFilter(TopicFilter(str)); } QString field = str.mid(idx + 1); - return TopicAndFieldFilter(TopicFilter(str.mid(0, idx)), field == "*" ? "" : field); + return TopicAndFieldFilter(TopicFilter(str.mid(0, idx)), + field == "*" ? "" : field); } diff --git a/Core/Message/topicandfieldfilter.h b/Core/Message/topicandfieldfilter.h index c42fc1bf2ded3d7232744d53b4d4f773d8b93ec7..d40e633d0820e29d11f3df49185528a5b6c44a0c 100644 --- a/Core/Message/topicandfieldfilter.h +++ b/Core/Message/topicandfieldfilter.h @@ -1,42 +1,58 @@ #ifndef TOPICANDFIELDFILTER_H #define TOPICANDFIELDFILTER_H -#include "modulemessage.h" #include "messagefield.h" +#include "modulemessage.h" #include "topicfilter.h" -/* - * TopicAndFieldFilter class represents expressions that can match against Gs message topics, - * and also select a field from that message. - * TopicAndFieldFilter can also not select a certain field, in that case, when matches, - * it returns the entire message converted to string. +/** + * @brief Represents an expressions that can match against topics and fields. * - * See also: Topic, MessageField, ModuleMessage, TopicFilter -*/ -class TopicAndFieldFilter { - public: - - - /* - * fieldName empty -> matchMessage() outputs all the message as a String - */ - TopicAndFieldFilter(const TopicFilter& _topicFilter, const QString& _fieldName = ""); + * It can also not select a certain field, in that case, when matches, it + * returns the entire message converted to string. + * + * TODO: Support multiple filed matching. + */ +class TopicAndFieldFilter +{ +public: TopicAndFieldFilter(); - + TopicAndFieldFilter(const QString& topicFilter, + const QString& fieldFilter = ""); + TopicAndFieldFilter(const TopicFilter& topicFilter, + const QString& fieldFilter = ""); bool operator==(const TopicAndFieldFilter&) const; + + /** + * @brief Check if the given topic is matched by the filter. + */ bool matchTopic(const Topic& topic) const; - bool matchMessage(const ModuleMessage& message, MessageField& extracted) const; - TopicFilter getTopic() const; - QString getFieldName() const; + /** + * @brief Extract the field from a message given the filter. + * + * @returns true if the message contained the filed. + */ + bool matchMessage(const ModuleMessage& message, MessageField& field) const; + + /** + * @brief Removes from the message all the fields that do not match the + * filter. + * + * @warning The provided message is changed if it matched the filter! + */ + bool filterMessage(ModuleMessage& message) const; + + TopicFilter getTopicFilter() const; + QString getFieldFilter() const; bool isFullFilter() const; QString toString() const; static TopicAndFieldFilter fromStringUnsafe(const QString&); - private: +private: TopicFilter topicFilter; - QString fieldName; + QString fieldFilter; }; -#endif // TOPICANDFIELDFILTER_H +#endif // TOPICANDFIELDFILTER_H diff --git a/Core/Message/topicfilter.cpp b/Core/Message/topicfilter.cpp index a4d72b864559b0194e1230e9ade6efab0adfc1d8..313cf56c648df3acf0653e7b29932fb4a7e7c9af 100644 --- a/Core/Message/topicfilter.cpp +++ b/Core/Message/topicfilter.cpp @@ -1,46 +1,54 @@ #include "topicfilter.h" -#include <QRegExp> -#include <QStringRef> - -TopicFilter::TopicFilter(const QString& expr) { - if(expr == '*' || expr == '?' || expr.contains(QRegExp("^[A-Za-z0-9$_]+(\\/[A-Za-z0-9$_]+)*(\\/[*?])?$"))) { - repr = expr; - valid = true; - } else { - valid = false; - } + +TopicFilter::TopicFilter(const QString& expression) +{ + const QRegularExpression validExprRegex = QRegularExpression( + "^(?:([A-Za-z0-9_]+)\\/)?(?:([A-Za-z0-9_]+)\\/?)?([*?]?)$"); + + // Check if the string expression is valid + valid = validExprRegex.match(expression).hasMatch(); + + this->expression = expression; } -bool TopicFilter::operator==(const TopicFilter& rhs) const { - return repr == rhs.repr; +bool TopicFilter::operator==(const TopicFilter& rhs) const +{ + return expression == rhs.expression; } -bool TopicFilter::match(const Topic& topic) const { - if(repr == "*" || repr == "?") +bool TopicFilter::match(const Topic& topic) const +{ + // Always true if the filter is a pure wildcard + if (expression == "*" || expression == "?") return true; - QString str = topic.toString(); + QString topicStr = topic.toString(); - if(!isWildcard()) - return repr == str; + // If the filter doesn't contain a wildcard then the topic must match + if (!isWildcard()) + return expression == topicStr; - QStringRef prefix = repr.midRef(0, repr.lastIndexOf('/')); - if(!str.startsWith(prefix) || (str.size() > prefix.size() && str.at(prefix.size()) != '/')) + // Extract the filter prefix before the last / + QStringRef prefix = expression.midRef(0, expression.lastIndexOf('/')); + + // The topic can match only if it has the same prefix + if (!topicStr.startsWith(prefix) || + (topicStr.size() > prefix.size() && topicStr.at(prefix.size()) != '/')) return false; - return repr.at(repr.size() - 1) != '*' || str.size() > prefix.size(); + return expression.at(expression.size() - 1) != '*' || + topicStr.size() > prefix.size(); } -bool TopicFilter::isWildcard() const { - return !repr.isEmpty() && (repr.at(repr.size() - 1) == '*' || repr.at(repr.size() - 1) == '?'); +bool TopicFilter::isWildcard() const +{ + return !expression.isEmpty() && + (expression.at(expression.size() - 1) == '*' || + expression.at(expression.size() - 1) == '?'); } -bool TopicFilter::isValid() const { - return valid; -} +bool TopicFilter::isValid() const { return valid; } -QString TopicFilter::toString() const { - return repr; -} +QString TopicFilter::toString() const { return expression; } -TopicFilter TopicFilter::Any("*"); +const TopicFilter TopicFilter::any() { return TopicFilter("*"); }; diff --git a/Core/Message/topicfilter.h b/Core/Message/topicfilter.h index 32d4160e2fdee4d1877393db38aa14ce0f3b254d..df70e16bd8f010b590d34bbf98e02895c2c31568 100644 --- a/Core/Message/topicfilter.h +++ b/Core/Message/topicfilter.h @@ -1,39 +1,51 @@ #ifndef TOPICFILTER_H #define TOPICFILTER_H +#include <QRegularExpression> #include <QString> + #include "topic.h" -/* - * TopicFilter class represents expressions that can match against Gs message topics. - * They can contain wildcard symbols * and ? as last token. For example: - * "*" and "?" match with all topics - * "Prefix/?" matchces with "Prefix", "Prefix/A" and "Prefix/A/B" +/** + * @brief Represents expressions that can match against message topics. * - * The difference between * and ? is that the latter also matches when only the predix is present. + * They can contain wildcard symbols * and ? as last token. For example: + * "*" and "?" match with all topics "Prefix/?" matches with "Prefix", + * "Prefix/A" and "Prefix/A/B" * - * See also: Topic -*/ -class TopicFilter { - public: - TopicFilter(const QString& expr); - - TopicFilter(const TopicFilter&) = default; - TopicFilter(TopicFilter&&) = default; + * The difference between * and ? is that the latter also matches when only the + * prefix is present. + */ +class TopicFilter +{ +public: + TopicFilter(const QString& expression = "*"); + bool operator==(const TopicFilter&) const; + + TopicFilter(const TopicFilter&) = default; + TopicFilter(TopicFilter&&) = default; TopicFilter& operator=(const TopicFilter&) = default; - TopicFilter& operator=(TopicFilter&&) = default; + TopicFilter& operator=(TopicFilter&&) = default; - bool operator==(const TopicFilter&) const; + /** + * @brief Returns true if the filter matches the given topic. + */ bool match(const Topic& topic) const; + + /** + * @brief Returns true if the filter contains a wildcard. + */ bool isWildcard() const; + bool isValid() const; + QString toString() const; - static TopicFilter Any; + static const TopicFilter any(); - private: - QString repr; +private: + QString expression; bool valid; }; -#endif // TOPICFILTER_H +#endif // TOPICFILTER_H diff --git a/Core/modulesmanager.cpp b/Core/modulesmanager.cpp index 6c437d965195dc3850890c4859dccf4a9e7b7916..c6bcf08d2741f722db2424b1ea7206c2bc8d1c75 100644 --- a/Core/modulesmanager.cpp +++ b/Core/modulesmanager.cpp @@ -1,71 +1,70 @@ #include "modulesmanager.h" +#include <QDir> #include <QInputDialog> #include <QMessageBox> -#include <QDir> -#include "Core/module.h" -#include "Core/xmlobject.h" #include "Components/ModulesPicker/modulespicker.h" #include "Components/SaveConfigurationDialog/saveconfigurationdialog.h" +#include "Core/module.h" +#include "Core/xmlobject.h" #include "Modules/skywardhubstrings.h" ModulesList ModulesManager::modulesListHandler; -ModulesManager::ModulesManager() { - -} +ModulesManager::ModulesManager() {} ModulesManager::~ModulesManager() { clearPages(); - for(int i = 0; i < menuActions.count(); i++) { + for (int i = 0; i < menuActions.count(); i++) { delete menuActions[i]; } menuActions.clear(); } QString ModulesManager::getModuleName(ModuleId id) { - if(ModulesManager::modulesListHandler.containsId(id)) + if (ModulesManager::modulesListHandler.containsId(id)) return ModulesManager::modulesListHandler.getModuleName(id); return ""; } Module* ModulesManager::instantiateModuleById(ModuleId id) { - if(ModulesManager::modulesListHandler.containsId(id)) + if (ModulesManager::modulesListHandler.containsId(id)) return ModulesManager::modulesListHandler.getFactory(id)(); return nullptr; } -Module* ModulesManager::instantiateModuleById(ModuleId id, const XmlObject& params) { +Module* ModulesManager::instantiateModuleById(ModuleId id, + const XmlObject& params) { Module* m = instantiateModuleById(id); - if(m != nullptr) - m->initialize(params); + if (m != nullptr) m->initialize(params); return m; } Module* ModulesManager::instantiateModuleByName(const QString& moduleName) { - return ModulesManager::modulesListHandler.findFactoryByModuleName(moduleName)(); + return ModulesManager::modulesListHandler.findFactoryByModuleName( + moduleName)(); } -Module* ModulesManager::instantiateModuleByName(const QString& moduleName, const XmlObject& params) { +Module* ModulesManager::instantiateModuleByName(const QString& moduleName, + const XmlObject& params) { Module* m = instantiateModuleByName(moduleName); - if(m != nullptr) - m->initialize(params); + if (m != nullptr) m->initialize(params); return m; } -QList<Module*>ModulesManager::loadModuleFromXml(XmlObject& xml) { +QList<Module*> ModulesManager::loadModuleFromXml(XmlObject& xml) { QList<Module*> windows; - for(int i = 0; i < xml.childCount(); i++) { + for (int i = 0; i < xml.childCount(); i++) { XmlObject* child = xml.getChild(i); QString moduleName = child->getObjectName(); Module* module = ModulesManager::instantiateModuleByName(moduleName); - if(module != nullptr) { + if (module != nullptr) { module->fromXmlObject(*child); windows.append(module); } @@ -76,23 +75,23 @@ QList<Module*>ModulesManager::loadModuleFromXml(XmlObject& xml) { void ModulesManager::setModules(QList<Module*> modules) { int i; - for(i = 0 ; i < pages.count() && i < modules.count(); i++ ) { + for (i = 0; i < pages.count() && i < modules.count(); i++) { Module* old = pages[i]; emit pages[i]->getModuleEventsHandler()->replaceMeWith(old, modules[i]); delete old; } - if(i < pages.count()) { - for(int c = pages.count() - 1; c > i; c-- ) { + if (i < pages.count()) { + for (int c = pages.count() - 1; c > i; c--) { delete pages[c]; } } - for(; i < modules.count(); i++ ) { + for (; i < modules.count(); i++) { addPage(modules[i]); } } void ModulesManager::addModules(QList<Module*> modules) { - for(int i = 0; i < modules.count(); i++) { + for (int i = 0; i < modules.count(); i++) { addPage(modules[i]); } } @@ -105,7 +104,7 @@ void ModulesManager::addPage(Module* module) { void ModulesManager::removePage(Module* module) { int index = pages.indexOf(module); - if(index >= 0) { + if (index >= 0) { pages.removeAt(index); disconnectModule(module); } @@ -122,36 +121,47 @@ Module* ModulesManager::invokeModulesPickerService() { return p->start(); #endif - return nullptr; + return nullptr; } QList<QString> ModulesManager::getModulesNamesList() { return ModulesManager::modulesListHandler.getModulesNamesList(); } - void ModulesManager::connectModule(Module* module) { - if(module) { - connect(module->getModuleEventsHandler(), &ModuleEventsHandler::contextMenuRequest, this, &ModulesManager::onContextMenuRequest); - connect(module->getModuleEventsHandler(), &ModuleEventsHandler::beforeDelete, this, &ModulesManager::onModuleDeleted); - connect(module->getModuleEventsHandler(), &ModuleEventsHandler::replaceMeWith, this, &ModulesManager::onReplaceMeWith); + if (module) { + connect(module->getModuleEventsHandler(), + &ModuleEventsHandler::contextMenuRequest, this, + &ModulesManager::onContextMenuRequest); + connect(module->getModuleEventsHandler(), + &ModuleEventsHandler::beforeDelete, this, + &ModulesManager::onModuleDeleted); + connect(module->getModuleEventsHandler(), + &ModuleEventsHandler::replaceMeWith, this, + &ModulesManager::onReplaceMeWith); } - //connect(module->getModuleEventsHandler(),&ModuleEventsHandler::replaceMeWithModules,this,&ModulesManager::openWindows); + // connect(module->getModuleEventsHandler(),&ModuleEventsHandler::replaceMeWithModules,this,&ModulesManager::openWindows); } void ModulesManager::disconnectModule(Module* module) { - if(module) { - disconnect(module->getModuleEventsHandler(), &ModuleEventsHandler::contextMenuRequest, this, &ModulesManager::onContextMenuRequest); - disconnect(module->getModuleEventsHandler(), &ModuleEventsHandler::beforeDelete, this, &ModulesManager::onModuleDeleted); - disconnect(module->getModuleEventsHandler(), &ModuleEventsHandler::replaceMeWith, this, &ModulesManager::onReplaceMeWith); + if (module) { + disconnect(module->getModuleEventsHandler(), + &ModuleEventsHandler::contextMenuRequest, this, + &ModulesManager::onContextMenuRequest); + disconnect(module->getModuleEventsHandler(), + &ModuleEventsHandler::beforeDelete, this, + &ModulesManager::onModuleDeleted); + disconnect(module->getModuleEventsHandler(), + &ModuleEventsHandler::replaceMeWith, this, + &ModulesManager::onReplaceMeWith); } } void ModulesManager::onModuleDeleted(Module* deletedModule) { int index = pages.indexOf(deletedModule); - if(index == 0) { + if (index == 0) { onFirstPageDeleted(); } else { removePage(deletedModule); @@ -163,27 +173,25 @@ void ModulesManager::openNewEmptyWindow() { } Module* ModulesManager::getModuleAt(int index) { - if(index >= 0 && index < pages.count()) { + if (index >= 0 && index < pages.count()) { return pages.at(index); } return nullptr; } -int ModulesManager::getModuleCount() { - return pages.count(); -} +int ModulesManager::getModuleCount() { return pages.count(); } void ModulesManager::clearPages() { - for(int i = pages.count() - 1; i >= 0; i--) { + for (int i = pages.count() - 1; i >= 0; i--) { delete pages[i]; } pages.clear(); } void ModulesManager::onReplaceMeWith(Module* sender, Module* newModule) { - if(sender != nullptr && newModule != nullptr) { + if (sender != nullptr && newModule != nullptr) { int index = pages.indexOf(sender); - if(index >= 0) { + if (index >= 0) { pages[index] = newModule; connectModule(newModule); disconnectModule(sender); @@ -191,13 +199,9 @@ void ModulesManager::onReplaceMeWith(Module* sender, Module* newModule) { } } -bool ModulesManager::getRebuild() const { - return rebuild; -} +bool ModulesManager::getRebuild() const { return rebuild; } -void ModulesManager::setRebuild(bool value) { - rebuild = value; -} +void ModulesManager::setRebuild(bool value) { rebuild = value; } void ModulesManager::onContextMenuRequest(QMenu& menu, const QPoint& p) { QMenu hubMenu("Hub Menu"); @@ -207,14 +211,16 @@ void ModulesManager::onContextMenuRequest(QMenu& menu, const QPoint& p) { } QList<QAction*> ModulesManager::getHubMenuActions() { - if(menuActions.count() == 0) { + if (menuActions.count() == 0) { QAction* save = new QAction("Save"); menuActions.append(save); - connect(save, &QAction::triggered, this, &ModulesManager::saveConfigurationService); + connect(save, &QAction::triggered, this, + &ModulesManager::saveConfigurationService); QAction* openWindows = new QAction("New Window"); menuActions.append(openWindows); - connect(openWindows, &QAction::triggered, this, &ModulesManager::openNewEmptyWindow); + connect(openWindows, &QAction::triggered, this, + &ModulesManager::openNewEmptyWindow); } return menuActions; @@ -225,7 +231,7 @@ QList<ModuleInfo> ModulesManager::getModulesInfo() { } void ModulesManager::saveConfigurationService() { - if(pages.isEmpty()) { + if (pages.isEmpty()) { QMessageBox errorMsg; errorMsg.setText("No module to be saved found"); errorMsg.exec(); @@ -238,7 +244,8 @@ void ModulesManager::saveConfigurationService() { // Ask configuration data to the user SaveConfigurationDialog* saveDialog = new SaveConfigurationDialog(); saveDialog->setConfigName(SkywardHubStrings::defaultConfigurationFileName); - saveDialog->setConfigIconPath(SkywardHubStrings::defaultConfigurationIconPath); + saveDialog->setConfigIconPath( + SkywardHubStrings::defaultConfigurationIconPath); QString configName; QString configIconPath; QString description; @@ -247,26 +254,30 @@ void ModulesManager::saveConfigurationService() { #endif XmlObject xml(SkywardHubStrings::configurationNameValue); - xml.addAttribute(SkywardHubStrings::configurationIconPathAttribute, configIconPath); - xml.addAttribute(SkywardHubStrings::configurationDescriptionAttribute, description); + xml.addAttribute(SkywardHubStrings::configurationIconPathAttribute, + configIconPath); + xml.addAttribute(SkywardHubStrings::configurationDescriptionAttribute, + description); - if(ok && !configName.isEmpty()) { + if (ok && !configName.isEmpty()) { configName = configName.replace(".xml", ""); - xml.addAttribute(SkywardHubStrings::configurationNameAttribute, configName); - if(configName.indexOf(".xml") < 0 ) { + xml.addAttribute(SkywardHubStrings::configurationNameAttribute, + configName); + if (configName.indexOf(".xml") < 0) { configName.append(".xml"); } - if(!QDir(SkywardHubStrings::defaultPrefabsFolder).exists()) { + if (!QDir(SkywardHubStrings::defaultPrefabsFolder).exists()) { QDir().mkpath(SkywardHubStrings::defaultPrefabsFolder); } - for(Module* module : pages) { + for (Module* module : pages) { xml.addChild(module->toXmlObject()); } QString resultTxt = "Impossible to save"; - if(xml.writeToFile(SkywardHubStrings::defaultPrefabsFolder + configName)) { + if (xml.writeToFile(SkywardHubStrings::defaultPrefabsFolder + + configName)) { resultTxt = "The configuration has been saved in " + configName; } QMessageBox resultMsg; @@ -276,18 +287,17 @@ void ModulesManager::saveConfigurationService() { } void ModulesManager::onFirstPageDeleted() { - if(!rebuild) - return; + if (!rebuild) return; QMessageBox msgBox; msgBox.setWindowTitle("title"); msgBox.setText("Do you want to close the App?"); msgBox.setStandardButtons(QMessageBox::Yes); msgBox.addButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); - if(msgBox.exec() == QMessageBox::No) { - emit pages[0]->getModuleEventsHandler()->replaceMeWith(pages[0], instantiateDefaultModule()); + if (msgBox.exec() == QMessageBox::No) { + emit pages[0]->getModuleEventsHandler()->replaceMeWith( + pages[0], instantiateDefaultModule()); } else { emit appQuitRequested(); } } - diff --git a/Modules/IncomingMessagesViewer/incomingmessagesviewermodule.cpp b/Modules/IncomingMessagesViewer/incomingmessagesviewermodule.cpp index b3b2c10255d7f10ce55f856992d26efa4f03ea17..ddcd2e8298d972291c70e87c907cdb2a8b15fb45 100644 --- a/Modules/IncomingMessagesViewer/incomingmessagesviewermodule.cpp +++ b/Modules/IncomingMessagesViewer/incomingmessagesviewermodule.cpp @@ -1,42 +1,55 @@ +#include "incomingmessagesviewermodule.h" + #include <QHBoxLayout> -#include "incomingmessagesviewermodule.h" #include "Components/SubscriptionsPanel/subscriptionspanel.h" -IncomingMessagesViewerModule::IncomingMessagesViewerModule(QWidget* parent) : DefaultModule(parent) { +IncomingMessagesViewerModule::IncomingMessagesViewerModule(QWidget* parent) + : DefaultModule(parent) +{ setupUi(); defaultContextMenuSetup(); - getCore()->getModuleMessagesBroker()->subscribe({"*"}, this, [this](const ModuleMessage & msg) { - MessageField value; - for(auto it = filters.begin(); it != filters.end(); ++it) { - if(it->matchMessage(msg, value)) { - if(clearEveryMessage) { - edit->setText(""); + getCore()->getModuleMessagesBroker()->subscribe( + {"*"}, this, + [this](const ModuleMessage& msg) + { + MessageField value; + for (auto it = filters.begin(); it != filters.end(); ++it) + { + if (it->matchMessage(msg, value)) + { + if (clearEveryMessage) + { + edit->setText(""); + } + + QString old = edit->toPlainText().mid(0, 10000); + edit->setText(QTime::currentTime().toString("hh.mm.ss") + + " [" + msg.getTopic().toString() + + (it->isFullFilter() + ? (QString(".") + it->getFieldFilter()) + : "") + + "]: " + value.getString() + "\n" + old); } - - QString old = edit->toPlainText().mid(0, 10000); - edit->setText(QTime::currentTime().toString("hh.mm.ss") + " [" - + msg.getTopic().toString() + (it->isFullFilter() ? (QString(".") + it->getFieldName()) : "") - + "]: " + value.getString() + "\n" + old); } - } - }); + }); } -IncomingMessagesViewerModule::~IncomingMessagesViewerModule() { +IncomingMessagesViewerModule::~IncomingMessagesViewerModule() +{ getCore()->getModuleMessagesBroker()->unsubscribe({"*"}, this); } -QWidget* IncomingMessagesViewerModule::toWidget() { - return this; -} +QWidget* IncomingMessagesViewerModule::toWidget() { return this; } -XmlObject IncomingMessagesViewerModule::toXmlObject() { +XmlObject IncomingMessagesViewerModule::toXmlObject() +{ XmlObject obj(getName(ModuleId::INCOMINGMESSAGESVIEWER)); obj.addAttribute("clearEveryMessage", clearEveryMessage ? "1" : "0"); - for(int i = 0; i < filters.count(); i++) { + for (int i = 0; i < filters.count(); i++) + { XmlObject subscription("Subscription"); subscription.addAttribute("Value", filters[i].toString()); obj.addChild(subscription); @@ -45,58 +58,70 @@ XmlObject IncomingMessagesViewerModule::toXmlObject() { return obj; } -void IncomingMessagesViewerModule::fromXmlObject(const XmlObject& xmlObject) { +void IncomingMessagesViewerModule::fromXmlObject(const XmlObject& xmlObject) +{ clearEveryMessage = xmlObject.getAttribute("clearEveryMessage") == "1"; - for(int i = 0; i < xmlObject.childCount(); i++) { + for (int i = 0; i < xmlObject.childCount(); i++) + { XmlObject child = xmlObject.childAt(i); - if(child.getObjectName() == "Subscription") { - auto subscription = TopicAndFieldFilter::fromStringUnsafe(child.getAttribute("Value")); + if (child.getObjectName() == "Subscription") + { + auto subscription = TopicAndFieldFilter::fromStringUnsafe( + child.getAttribute("Value")); addSubscription(subscription); } } } -void IncomingMessagesViewerModule::addSubscription(const TopicAndFieldFilter& filter) { +void IncomingMessagesViewerModule::addSubscription( + const TopicAndFieldFilter& filter) +{ filters.append(filter); } -void IncomingMessagesViewerModule::removeSubscription(const TopicAndFieldFilter& filter) { +void IncomingMessagesViewerModule::removeSubscription( + const TopicAndFieldFilter& filter) +{ filters.removeAll(filter); } -void IncomingMessagesViewerModule::addCustomActionsToMenu() { +void IncomingMessagesViewerModule::addCustomActionsToMenu() +{ QAction* clear = new QAction("Clear"); - connect(clear, &QAction::triggered, this, [this]() { - edit->clear(); - }); + connect(clear, &QAction::triggered, this, [this]() { edit->clear(); }); QAction* manage = new QAction("Manage subscriptions"); - connect(manage, &QAction::triggered, this, [this]() { - auto* panel = new SubscriptionsPanel(&filters); - panel->setWindowTitle("IncomingMessagesViewer subscriptions"); - connect(panel, &SubscriptionsPanel::SubscriptionAdded, this, &IncomingMessagesViewerModule::addSubscription); - connect(panel, &SubscriptionsPanel::SubscriptionRemoved, this, &IncomingMessagesViewerModule::removeSubscription); - panel->show(); - }); + connect(manage, &QAction::triggered, this, + [this]() + { + auto* panel = new SubscriptionsPanel(&filters); + panel->setWindowTitle("IncomingMessagesViewer subscriptions"); + connect(panel, &SubscriptionsPanel::SubscriptionAdded, this, + &IncomingMessagesViewerModule::addSubscription); + connect(panel, &SubscriptionsPanel::SubscriptionRemoved, this, + &IncomingMessagesViewerModule::removeSubscription); + panel->show(); + }); QAction* check = new QAction("Clear every message"); check->setCheckable(true); check->setChecked(clearEveryMessage); - connect(check, &QAction::toggled, this, &IncomingMessagesViewerModule::setClearEveryMessage); + connect(check, &QAction::toggled, this, + &IncomingMessagesViewerModule::setClearEveryMessage); addActionToMenu(clear); addActionToMenu(manage); addActionToMenu(check); } - -void IncomingMessagesViewerModule::setClearEveryMessage(bool val) { +void IncomingMessagesViewerModule::setClearEveryMessage(bool val) +{ clearEveryMessage = val; } - -void IncomingMessagesViewerModule::setupUi() { +void IncomingMessagesViewerModule::setupUi() +{ edit = new QTextEdit(); edit->setReadOnly(true); edit->setContextMenuPolicy(Qt::ContextMenuPolicy::NoContextMenu); diff --git a/Modules/StateViewer/stateviewermodule.cpp b/Modules/StateViewer/stateviewermodule.cpp index 0164c7817aa4b28f4b8e4320c4d0563f0a75a7af..d88b34682f3a16c2d08bd48bd2a186b7ebe4712d 100644 --- a/Modules/StateViewer/stateviewermodule.cpp +++ b/Modules/StateViewer/stateviewermodule.cpp @@ -3,11 +3,12 @@ #include <QInputDialog> #include <QLineEdit> -#include "Components/TopicAndFieldSelector/topicandfieldselector.h" +#include "Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h" #include "Core/modulemessagesbroker.h" #include "ui_stateviewermodule.h" -enum states { +enum states +{ INVALID = 0, INIT, INIT_ERROR, @@ -23,7 +24,8 @@ enum states { }; StateViewerModule::StateViewerModule(QWidget* parent) - : DefaultModule(parent), ui(new Ui::StateViewerModule) { + : DefaultModule(parent), ui(new Ui::StateViewerModule) +{ ui->setupUi(this); defaultContextMenuSetup(); @@ -52,14 +54,17 @@ StateViewerModule::StateViewerModule(QWidget* parent) }; } -StateViewerModule::~StateViewerModule() { - getCore()->getModuleMessagesBroker()->unsubscribe(filter.getTopic(), this); +StateViewerModule::~StateViewerModule() +{ + getCore()->getModuleMessagesBroker()->unsubscribe(filter.getTopicFilter(), + this); delete ui; } QWidget* StateViewerModule::toWidget() { return this; } -XmlObject StateViewerModule::toXmlObject() { +XmlObject StateViewerModule::toXmlObject() +{ XmlObject obj(getName(ModuleId::STATEVIEWER)); obj.addAttribute("filter", filter.toString()); @@ -67,15 +72,18 @@ XmlObject StateViewerModule::toXmlObject() { return obj; } -void StateViewerModule::fromXmlObject(const XmlObject& xmlObject) { - if (xmlObject.getObjectName() == getName(ModuleId::STATEVIEWER)) { +void StateViewerModule::fromXmlObject(const XmlObject& xmlObject) +{ + if (xmlObject.getObjectName() == getName(ModuleId::STATEVIEWER)) + { auto filter = TopicAndFieldFilter::fromStringUnsafe( xmlObject.getAttribute("filter")); setFilter(filter); } } -void StateViewerModule::addCustomActionsToMenu() { +void StateViewerModule::addCustomActionsToMenu() +{ QAction* config = new QAction("Choose input topic and field"); connect(config, &QAction::triggered, this, &StateViewerModule::onConfigureClicked); @@ -83,52 +91,68 @@ void StateViewerModule::addCustomActionsToMenu() { addActionToMenu(config); } -void StateViewerModule::onConfigureClicked() { - TopicAndFieldSelector::selectTopicAndField( +void StateViewerModule::onConfigureClicked() +{ + TopicAndFieldFilterSelector::selectFilter( + filter, [this](const TopicAndFieldFilter& filter) { setFilter(filter); }); } -void StateViewerModule::setFilter(const TopicAndFieldFilter& newFilter) { - getCore()->getModuleMessagesBroker()->unsubscribe(filter.getTopic(), this); +void StateViewerModule::setFilter(const TopicAndFieldFilter& newFilter) +{ + getCore()->getModuleMessagesBroker()->unsubscribe(filter.getTopicFilter(), + this); getCore()->getModuleMessagesBroker()->subscribe( - newFilter.getTopic(), this, + newFilter.getTopicFilter(), this, [this](const ModuleMessage& msg) { onMsgReceived(msg); }); filter = newFilter; } -void StateViewerModule::onMsgReceived(const ModuleMessage& msg) { +void StateViewerModule::onMsgReceived(const ModuleMessage& msg) +{ MessageField field; - if (!filter.matchMessage(msg, field)) return; + if (!filter.matchMessage(msg, field)) + return; int value = (int)field.getUInteger(-1); - if (value != -1) setState(value); + if (value != -1) + setState(value); } -void StateViewerModule::setState(int state) { - if (state != currentState) { +void StateViewerModule::setState(int state) +{ + if (state != currentState) + { currentState = state; updateView(state); } } -void StateViewerModule::updateView(int state) { +void StateViewerModule::updateView(int state) +{ QString currentStateStyle = "background-color:yellow; color:black;"; - QString completedStyle = "background-color:green;"; - QString errorStyle = "background-color:red;"; + QString completedStyle = "background-color:green;"; + QString errorStyle = "background-color:red;"; - if (state == INIT) { + if (state == INIT) + { ui->label_1_INIT->setStyleSheet(currentStateStyle); - } else if (state == INIT_ERROR) { + } + else if (state == INIT_ERROR) + { ui->label_1_INIT->setStyleSheet(errorStyle); - } else if (state > INIT_ERROR && labelsIndexes.contains(state)) { + } + else if (state > INIT_ERROR && labelsIndexes.contains(state)) + { int index = labelsIndexes[state]; if (index < labels.count()) labels[index]->setStyleSheet(currentStateStyle); } - if (labelsIndexes.contains(state)) { + if (labelsIndexes.contains(state)) + { int index = labelsIndexes[state]; // Set as completed every state before the current diff --git a/Modules/StateViewer/stateviewermodule.h b/Modules/StateViewer/stateviewermodule.h index 2b62b6349c9aaef70f39be903f2c23a9550067f8..2e6e5da0d7cd8c9980f9df486a449ab2cee14573 100644 --- a/Modules/StateViewer/stateviewermodule.h +++ b/Modules/StateViewer/stateviewermodule.h @@ -8,14 +8,16 @@ #include "Core/Message/topicandfieldfilter.h" #include "Modules/DefaultModule/defaultmodule.h" -namespace Ui { +namespace Ui +{ class StateViewerModule; } -class StateViewerModule : public DefaultModule { +class StateViewerModule : public DefaultModule +{ Q_OBJECT - public: +public: explicit StateViewerModule(QWidget* parent = nullptr); ~StateViewerModule(); @@ -24,7 +26,7 @@ class StateViewerModule : public DefaultModule { XmlObject toXmlObject() override; void fromXmlObject(const XmlObject& xmlObject) override; - protected: +protected: void addCustomActionsToMenu() override; void onConfigureClicked(); void setFilter(const TopicAndFieldFilter& filter); @@ -32,7 +34,7 @@ class StateViewerModule : public DefaultModule { void setState(int state); void updateView(int state); - private: +private: Ui::StateViewerModule* ui; TopicAndFieldFilter filter; diff --git a/SkywardHub.pro b/SkywardHub.pro index 7d72891ac4668fe8c332a0cdb9b8c62932f00976..40c31260621626001c693ee0ce75fe98dfa1aa74 100644 --- a/SkywardHub.pro +++ b/SkywardHub.pro @@ -17,7 +17,8 @@ SOURCES += \ Components/ToggleButton/togglebutton.cpp \ Components/ErrorDisplayer/error.cpp \ Components/ErrorDisplayer/errordisplayer.cpp \ - Components/TopicAndFieldSelector/topicandfieldselector.cpp \ + Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.cpp \ + Components/TopicFilterSelector/topicfilterselector.cpp \ Core/Message/messagefield.cpp \ Core/Message/modulemessage.cpp \ Core/Message/topic.cpp \ @@ -69,7 +70,8 @@ HEADERS += \ Components/ToggleButton/togglebutton.h \ Components/ErrorDisplayer/error.h \ Components/ErrorDisplayer/errordisplayer.h \ - Components/TopicAndFieldSelector/topicandfieldselector.h \ + Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h \ + Components/TopicFilterSelector/topicfilterselector.h \ Core/Message/messagefield.h \ Core/Message/modulemessage.h \ Core/Message/topic.h \