diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 52eb58314fa5c7fbb7bb84546f4b18e851530f68..7c8dbf1e9859f75dcf7efa4518385241ad909715 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,7 +3,7 @@ { "name": "Linux", "includePath": [ - "${workspaceFolder}/src/", + "${workspaceFolder}/src/shared", "~/Qt/5.15.2/**" ], "defines": [], diff --git a/CMakeLists.txt b/CMakeLists.txt index 47030a51ce84881356bc5f2aff850b036d081c80..cb0d44cca0b7815810b5c0a9f4c67aa9fe1e5ae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ add_executable(groundstation src/shared/Modules/CommandPad/MessageFormElement.cpp src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp src/shared/Modules/CompactCommandPad/CommandSelector.cpp + src/shared/Modules/CompactCommandPad/SendThread.cpp src/shared/Modules/DefaultModule/defaultmodule.cpp src/shared/Modules/Empty/emptymodule.cpp src/shared/Modules/FileStream/filestreammodule.cpp diff --git a/src/shared/Components/ModulesPicker/modulespicker.ui b/src/shared/Components/ModulesPicker/modulespicker.ui index c1faf6a182a502dbaca18447f42ba180e685985e..9006776718f89d360de950401f3f76e07a8298e2 100644 --- a/src/shared/Components/ModulesPicker/modulespicker.ui +++ b/src/shared/Components/ModulesPicker/modulespicker.ui @@ -104,8 +104,8 @@ </property> <property name="icon"> <iconset resource="../../application.qrc"> - <normaloff>:/Resources/Icons/splitter_vertical.png</normaloff> - :/Resources/Icons/splitter_vertical.png + <normaloff>:/assets/icons/splitter_horizontal.png</normaloff> + :/assets/icons/splitter_vertical.png </iconset> </property> <property name="iconSize"> diff --git a/src/shared/Components/SubscriptionsPanel/subscriptionspanel.cpp b/src/shared/Components/SubscriptionsPanel/subscriptionspanel.cpp index 2b5225dcdb8c2e2a63d81382e0cc4ec63812e517..4db9d323fc6ed90086d3af0a73f6f04a66aface1 100644 --- a/src/shared/Components/SubscriptionsPanel/subscriptionspanel.cpp +++ b/src/shared/Components/SubscriptionsPanel/subscriptionspanel.cpp @@ -3,7 +3,6 @@ #include <QDebug> #include <functional> -#include "Components/TopicAndFieldFilterSelector/topicandfieldfilterselector.h" #include "Components/TopicFilterSelector/topicfilterselector.h" #include "ui_subscriptionspanel.h" @@ -60,6 +59,7 @@ void SubscriptionsPanel::onAddTopicClicked() void SubscriptionsPanel::onAddTopicAndFieldClicked() { + // TODO: Fix // TopicFilterSelector::selectFilter([&](const TopicAndFieldFilter& filter) // { addTopicAndFieldFilter(filter); }); } diff --git a/src/shared/Core/Message/topic.cpp b/src/shared/Core/Message/topic.cpp index 2c08e1a06566eae6779c3139a651fc8a529e121e..820ff406f00df6eb9ede6bae817e2150e4dee81f 100644 --- a/src/shared/Core/Message/topic.cpp +++ b/src/shared/Core/Message/topic.cpp @@ -2,13 +2,13 @@ #include <QRegExp> -Topic::Topic() : repr(""), valid(true) {} +Topic::Topic() : topic(""), valid(true) {} Topic::Topic(QString str) { if (str.contains(QRegExp("^[A-Za-z0-9$_]+(\\/[A-Za-z0-9$_]+)*$"))) { - repr = str; + topic = str; valid = true; } else @@ -19,16 +19,16 @@ Topic::Topic(QString str) Topic Topic::getParent() const { - int idx = repr.lastIndexOf('/'); - return idx == -1 ? Topic(repr) : Topic(repr.left(idx)); + int idx = topic.lastIndexOf('/'); + return idx == -1 ? Topic(topic) : Topic(topic.left(idx)); } Topic Topic::getRoot() const { - int idx = repr.indexOf('/'); - return idx == -1 ? Topic(repr) : Topic(repr.left(idx)); + int idx = topic.indexOf('/'); + return idx == -1 ? Topic(topic) : Topic(topic.left(idx)); } bool Topic::isValid() const { return valid; } -QString Topic::toString() const { return repr; } +QString Topic::toString() const { return topic; } diff --git a/src/shared/Core/Message/topic.h b/src/shared/Core/Message/topic.h index 5e763c8d2297a5ee88ba55eea9cf14f85f420840..5c1e72d3de273b1390fc71c0b9c87186907e4c39 100644 --- a/src/shared/Core/Message/topic.h +++ b/src/shared/Core/Message/topic.h @@ -1,5 +1,4 @@ -#ifndef TOPIC_H -#define TOPIC_H +#pragma once #include <QString> @@ -17,10 +16,10 @@ public: Topic(); explicit Topic(QString str); - Topic(const Topic&) = default; - Topic(Topic&&) = default; + Topic(const Topic&) = default; + Topic(Topic&&) = default; Topic& operator=(const Topic&) = default; - Topic& operator=(Topic&&) = default; + Topic& operator=(Topic&&) = default; // Exact match bool operator==(const Topic& topic) const; @@ -32,8 +31,6 @@ public: QString toString() const; private: - QString repr; + QString topic; bool valid; }; - -#endif // TOPIC_H diff --git a/src/shared/Core/Message/topicfilter.h b/src/shared/Core/Message/topicfilter.h index af1d353feacee992268faedac4776b105f4abf5e..32c67c9f108885ed16c667d6ed1e95e45e044632 100644 --- a/src/shared/Core/Message/topicfilter.h +++ b/src/shared/Core/Message/topicfilter.h @@ -1,5 +1,4 @@ -#ifndef TOPICFILTER_H -#define TOPICFILTER_H +#pragma once #include <QRegularExpression> #include <QString> @@ -22,10 +21,10 @@ public: TopicFilter(const QString& expression = "*"); bool operator==(const TopicFilter&) const; - TopicFilter(const TopicFilter&) = default; - TopicFilter(TopicFilter&&) = default; + TopicFilter(const TopicFilter&) = default; + TopicFilter(TopicFilter&&) = default; TopicFilter& operator=(const TopicFilter&) = default; - TopicFilter& operator=(TopicFilter&&) = default; + TopicFilter& operator=(TopicFilter&&) = default; /** * @brief Returns true if the filter matches the given topic. @@ -47,5 +46,3 @@ private: QString expression; bool valid; }; - -#endif // TOPICFILTER_H diff --git a/src/shared/Core/QCustomPlot/QCustomPlot.cpp b/src/shared/Core/QCustomPlot/QCustomPlot.cpp index fc161301e77ff213b353754a7ed432d09bdbf7de..90676021b46966a86aee1dcf8c6d95c2bcb5c931 100644 --- a/src/shared/Core/QCustomPlot/QCustomPlot.cpp +++ b/src/shared/Core/QCustomPlot/QCustomPlot.cpp @@ -5795,8 +5795,8 @@ void QCPLineEnding::draw(QCPPainter *painter, const QCPVector2D &pos, { QCPVector2D widthVecPerp = widthVec.perpendicular(); QPointF points[4] = { - (pos - widthVecPerp).toPointF(), (pos - widthVec).toPointF(), - (pos + widthVecPerp).toPointF(), (pos + widthVec).toPointF()}; + (pos - widthVecPerp).toPointF(), (pos - widthVec).toPointF(), + (pos + widthVecPerp).toPointF(), (pos + widthVec).toPointF()}; painter->setPen(miterPen); painter->setBrush(brush); painter->drawConvexPolygon(points, 4); diff --git a/src/shared/Modules/CompactCommandPad/CommandSelector.cpp b/src/shared/Modules/CompactCommandPad/CommandSelector.cpp index 06efd3c8fd677fbf08dfb869b08fe60532486153..644574f35a150f1fa4bddfe86e98311d7967e5b8 100644 --- a/src/shared/Modules/CompactCommandPad/CommandSelector.cpp +++ b/src/shared/Modules/CompactCommandPad/CommandSelector.cpp @@ -4,7 +4,11 @@ #include <QDebug> -CommandSelector::CommandSelector() : QDialog() { setupUi(); } +CommandSelector::CommandSelector(DefaultModule* _parent) + : QDialog(), parent(_parent) +{ + setupUi(); +} CommandSelector::~CommandSelector() { @@ -14,6 +18,11 @@ CommandSelector::~CommandSelector() XmlObject CommandSelector::toXmlObject(XmlObject& obj) { + bool ok; + long timeout = continuosTimeoutEdit->text().toUInt(&ok); + if (ok) + obj.addAttribute("timeout", QString() + timeout); + auto key = messagesListComboBox->currentText(); if (formElements.contains(key)) { @@ -27,6 +36,14 @@ XmlObject CommandSelector::toXmlObject(XmlObject& obj) void CommandSelector::fromXmlObject(const XmlObject& obj) { + QString str = obj.getAttribute("timeout", "0"); + long timeout; + bool ok; + timeout = str.toUInt(&ok); + + if (ok) + continuosTimeoutEdit->setText(QString() + timeout); + if (obj.hasAttribute("message_id")) { auto key = obj.getAttribute("message_id"); @@ -44,10 +61,14 @@ void CommandSelector::fromXmlObject(const XmlObject& obj) } } -bool CommandSelector::getSelection(QString& label, ModuleMessage& message) +bool CommandSelector::getSelection(QString& label, ModuleMessage& message, + long& continuosSendTimeout) { - message = selectedMessage; - label = selectedLabel; + message = selectedMessage; + label = selectedLabel; + continuosSendTimeout = continuosCheck->isChecked() + ? continuosTimeoutEdit->text().toUInt(nullptr) + : 0; return selected; } @@ -60,6 +81,19 @@ void CommandSelector::setupUi() lineEdit->setPlaceholderText("Write the button label"); outerLayout->addWidget(lineEdit); + continuosCheck = new QCheckBox; + continuosCheck->setText("Continuos Send"); + outerLayout->addWidget(continuosCheck); + QObject::connect( + continuosCheck, &QCheckBox::stateChanged, + [this]() + { continuosTimeoutEdit->setHidden(!continuosCheck->isChecked()); }); + + continuosTimeoutEdit = new QLineEdit(); + continuosTimeoutEdit->setPlaceholderText("Choose resend timeout in ms"); + continuosTimeoutEdit->setHidden(true); + outerLayout->addWidget(continuosTimeoutEdit); + messagesListComboBox = new QComboBox; messagesListComboBox->setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); @@ -97,6 +131,25 @@ void CommandSelector::setupUi() connect(sendButton, &QPushButton::clicked, [=]() { + if (continuosCheck->isChecked()) + { + bool ok; + continuosTimeoutEdit->text().toUInt(&ok); + if (!ok) + { + parent->error("Invalid Input", + "Please enter a valid unsigned integer."); + return; + } + } + + if (lineEdit->text().isEmpty()) + { + parent->error("Invalid Input", + "Please enter a name for the button."); + return; + } + auto key = messagesListComboBox->currentText(); if (formElements.contains(key)) { diff --git a/src/shared/Modules/CompactCommandPad/CommandSelector.h b/src/shared/Modules/CompactCommandPad/CommandSelector.h index 3fa838b5c99f150d56ecfddc0bdb4ede5710636b..1215f0f780ae99b1cf63e42fa27331c9b535ed32 100644 --- a/src/shared/Modules/CompactCommandPad/CommandSelector.h +++ b/src/shared/Modules/CompactCommandPad/CommandSelector.h @@ -2,8 +2,10 @@ #include <Core/xmlobject.h> #include <Modules/CommandPad/MessageFormElement.h> +#include <Modules/DefaultModule/defaultmodule.h> #include <QBoxLayout> +#include <QCheckBox> #include <QComboBox> #include <QDialog> #include <QGridLayout> @@ -17,26 +19,30 @@ class CommandSelector : public QDialog Q_OBJECT public: - explicit CommandSelector(); + explicit CommandSelector(DefaultModule* _parent); ~CommandSelector(); XmlObject toXmlObject(XmlObject& obj); void fromXmlObject(const XmlObject& xmlObject); - bool getSelection(QString& label, ModuleMessage& message); + bool getSelection(QString& label, ModuleMessage& message, + long& continuosSendTimeout); private: void setupUi(); QString currentMessage; QVBoxLayout* outerLayout; - QLineEdit* lineEdit; + QLineEdit *lineEdit, *continuosTimeoutEdit; QComboBox* messagesListComboBox; QMap<QString, MessageFormElement*> formElements; QGridLayout* formGridLayout; QPushButton* sendButton; + QCheckBox* continuosCheck; bool selected = false; QString selectedLabel; ModuleMessage selectedMessage; -}; \ No newline at end of file + + DefaultModule* parent; +}; diff --git a/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp b/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp index 1b50605b276719151ccbbc620e8512644748a66e..5094fbadda4c13b66804430faee4252386baa51e 100644 --- a/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp +++ b/src/shared/Modules/CompactCommandPad/CompactCommandPad.cpp @@ -1,6 +1,7 @@ #include "CompactCommandPad.h" -CompactCommandPad::CompactCommandPad(QWidget* parent) : DefaultModule(parent) +CompactCommandPad::CompactCommandPad(QWidget* parent) + : DefaultModule(parent), timer(nullptr), continuosSendTimeout(false) { setupUi(); defaultContextMenuSetup(); @@ -13,9 +14,7 @@ QWidget* CompactCommandPad::toWidget() { return this; } XmlObject CompactCommandPad::toXmlObject() { XmlObject obj = XmlObject("compact_command_pad"); - selector->toXmlObject(obj); - return obj; } @@ -25,21 +24,38 @@ void CompactCommandPad::fromXmlObject(const XmlObject& obj) selector->fromXmlObject(obj); QString label; - selected = selector->getSelection(label, selectedMessage); + selected = + selector->getSelection(label, selectedMessage, continuosSendTimeout); if (selected) + { + if (continuosSendTimeout != 0) + button->setText(label + " [Start]"); + button->setText(label); + } } void CompactCommandPad::buttonEditActionTriggered() { selector->exec(); + selected = + selector->getSelection(label, selectedMessage, continuosSendTimeout); - QString label; - selected = selector->getSelection(label, selectedMessage); + if (timer) + { + timer->stop(); + timer->deleteLater(); + timer = nullptr; + } if (selected) - button->setText(label); + { + if (continuosSendTimeout != 0) + button->setText(label + " [Start]"); + else + button->setText(label); + } } void CompactCommandPad::setupUi() @@ -49,17 +65,46 @@ void CompactCommandPad::setupUi() button = new QPushButton("Edit me"); outerLayout->addWidget(button); - connect( - button, &QPushButton::clicked, - [=]() - { - if (selected) - getCore()->getModuleMessagesBroker()->publish(selectedMessage); - }); + connect(button, &QPushButton::clicked, + [=]() + { + if (timer) + { + timer->stop(); + timer->deleteLater(); + timer = nullptr; + button->setText(label + " [Start]"); + } + else + { + if (selected) + { + if (continuosSendTimeout == 0) + { + send(); + } + else + { + button->setText(label + " [Stop]"); + + send(); + timer = new QTimer(this); + connect(timer, &QTimer::timeout, this, + &CompactCommandPad::send); + timer->start(continuosSendTimeout); + } + } + } + }); setLayout(outerLayout); - selector = new CommandSelector; + selector = new CommandSelector(this); +} + +void CompactCommandPad::send() +{ + getCore()->getModuleMessagesBroker()->publish(selectedMessage); } void CompactCommandPad::addCustomActionsToMenu() @@ -68,4 +113,4 @@ void CompactCommandPad::addCustomActionsToMenu() addActionToMenu(edit); connect(edit, &QAction::triggered, this, &CompactCommandPad::buttonEditActionTriggered); -} \ No newline at end of file +} diff --git a/src/shared/Modules/CompactCommandPad/CompactCommandPad.h b/src/shared/Modules/CompactCommandPad/CompactCommandPad.h index 69993d2f7e456889102ff6490144f65d0a6bc46c..95da8691dfac82f8dfd20df35691a1237182047e 100644 --- a/src/shared/Modules/CompactCommandPad/CompactCommandPad.h +++ b/src/shared/Modules/CompactCommandPad/CompactCommandPad.h @@ -3,6 +3,8 @@ #include <Modules/CompactCommandPad/CommandSelector.h> #include <Modules/DefaultModule/defaultmodule.h> +#include <QTimer> + class CompactCommandPad : public DefaultModule { Q_OBJECT @@ -18,6 +20,7 @@ public: private slots: void buttonEditActionTriggered(); + void send(); private: void setupUi(); @@ -25,7 +28,10 @@ private: CommandSelector* selector; QPushButton* button; + QTimer* timer; + QString label; bool selected; + long continuosSendTimeout; ModuleMessage selectedMessage; }; diff --git a/src/shared/Modules/CompactCommandPad/SendThread.cpp b/src/shared/Modules/CompactCommandPad/SendThread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89bab6c5d2e0bb749a74660806c0af70035b6a33 --- /dev/null +++ b/src/shared/Modules/CompactCommandPad/SendThread.cpp @@ -0,0 +1,20 @@ +#include "SendThread.h" + +SendThread::SendThread(ModuleMessagesBroker* broker, const ModuleMessage& msg, + long timeout) + : broker(broker), msg(msg), timeout(timeout), toStop(false) +{ + connect(this, &SendThread::finished, this, &SendThread::deleteLater); + start(); +} + +void SendThread::requestStop() { toStop = true; } + +void SendThread::run() +{ + while (!toStop) + { + broker->publish(msg); + QThread::sleep(timeout); + } +} diff --git a/src/shared/Modules/CompactCommandPad/SendThread.h b/src/shared/Modules/CompactCommandPad/SendThread.h new file mode 100644 index 0000000000000000000000000000000000000000..4252e2cb3b722e2edf795d6721d49fcc1ef20416 --- /dev/null +++ b/src/shared/Modules/CompactCommandPad/SendThread.h @@ -0,0 +1,22 @@ +#pragma once + +#include <QThread> + +#include "Core/modulemessagesbroker.h" + +class SendThread : public QThread +{ +public: + SendThread(ModuleMessagesBroker* broker, const ModuleMessage& msg, + long timeout); + void requestStop(); + +protected: + void run() override; + +private: + ModuleMessagesBroker* broker; + ModuleMessage msg; + long timeout; + bool toStop; +}; diff --git a/src/shared/Modules/Mavlink/mavlinkmodule.cpp b/src/shared/Modules/Mavlink/mavlinkmodule.cpp index 49a624ad5d898b545f7d37e422421f4ad8093618..7d7bd59c09868bdaf8a287f81f697eae060cc045 100644 --- a/src/shared/Modules/Mavlink/mavlinkmodule.cpp +++ b/src/shared/Modules/Mavlink/mavlinkmodule.cpp @@ -143,7 +143,7 @@ void MavlinkModule::onCommandReceived(const ModuleMessage &msg) mavlinkCommandAdapter.send(encoded_mvl_msg); ModuleMessage confirmationMsg( - Topic(SkywardHubStrings::logCommandsTopic)); + Topic((QString)SkywardHubStrings::logCommandsTopic)); auto nameField = MessageField(msg.getTopic().toString().replace( SkywardHubStrings::commandsTopic + "/", "")); @@ -219,8 +219,6 @@ void MavlinkModule::initializeSerialPortView() for (auto serialPortInfo : serialPortInfos) portsComboBox->addItem(serialPortInfo.portName()); - // portsComboBox->setCurrentIndex(0); - baudrateComboBox->addItem("115200", QSerialPort::Baud115200); baudrateComboBox->addItem("19200", QSerialPort::Baud19200); baudrateComboBox->addItem("9600", QSerialPort::Baud9600);