From 5c2fc0d8cbbacc1cc9665759f723150b8e67085c Mon Sep 17 00:00:00 2001 From: Hoop77 <p.badenhoop@gmx.de> Date: Wed, 16 May 2018 14:53:07 +0200 Subject: [PATCH] MessageGui still crashes when showing most recent messages; CommandGui ready --- .../catkin_ws/src/MessageLib/src/Client.cpp | 2 +- .../catkin_ws/src/PC2CarLib/CMakeLists.txt | 8 +- .../src/PC2CarLib/test/DisplayCommands.cpp | 59 ++++++++ .../src/PC2CarLib/test/{Main.cpp => Test.cpp} | 0 .../catkin_ws/src/PCGui/PCGui/CMakeLists.txt | 26 ++-- .../catkin_ws/src/PCGui/PCGui/CommandGui.qml | 136 +++++++++++++++++- .../catkin_ws/src/PCGui/PCGui/MessageGui.qml | 97 ++++++++++--- .../PCGui/include/CommandGui/SignalConsumer.h | 63 ++++++++ .../PCGui/PCGui/include/MessageGui/Message.h | 25 ++++ .../include/MessageGui/MessageCollection.h | 42 ++++++ .../PCGui/include/MessageGui/MessageList.h | 32 +++++ .../include/{ => MessageGui}/MessageModel.h | 15 +- .../PCGui/include/MessageGui/MessageRole.h | 33 +++++ .../MostRecentMessageFiltertProxyModel.h | 91 ++++++++++++ .../PCGui/include/MessageGui/SignalConsumer.h | 47 ++++++ .../PCGui/include/MessageGui/SignalProducer.h | 36 +++++ .../{ => MessageGui}/SortFilterProxyModel.h | 0 .../PCGui/PCGui/include/MessageGui/Utils.h | 31 ++++ .../src/PCGui/PCGui/include/MessageList.h | 32 ----- .../src/PCGui/PCGui/include/MessageProducer.h | 23 --- .../src/PCGui/PCGui/src/CommandGui.cpp | 14 -- .../PCGui/PCGui/src/CommandGui/CommandGui.cpp | 97 +++++++++++++ .../src/PCGui/PCGui/src/MessageGui.cpp | 54 ------- .../PCGui/PCGui/src/MessageGui/MessageGui.cpp | 119 +++++++++++++++ .../PCGui/src/MessageGui/MessageList.cpp | 33 +++++ .../PCGui/src/MessageGui/MessageModel.cpp | 87 +++++++++++ .../MostRecentMessageFilterProxyModel.cpp | 103 +++++++++++++ .../{ => MessageGui}/SortFilterProxyModel.cpp | 2 +- .../src/PCGui/PCGui/src/MessageList.cpp | 21 --- .../src/PCGui/PCGui/src/MessageModel.cpp | 78 ---------- .../src/car/src/ultrasonic/Ultrasonic.cpp | 6 +- 31 files changed, 1142 insertions(+), 270 deletions(-) create mode 100644 modules/catkin_ws/src/PC2CarLib/test/DisplayCommands.cpp rename modules/catkin_ws/src/PC2CarLib/test/{Main.cpp => Test.cpp} (100%) create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/CommandGui/SignalConsumer.h create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Message.h create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageCollection.h create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageList.h rename modules/catkin_ws/src/PCGui/PCGui/include/{ => MessageGui}/MessageModel.h (62%) create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageRole.h create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MostRecentMessageFiltertProxyModel.h create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalConsumer.h create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalProducer.h rename modules/catkin_ws/src/PCGui/PCGui/include/{ => MessageGui}/SortFilterProxyModel.h (100%) create mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Utils.h delete mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageList.h delete mode 100644 modules/catkin_ws/src/PCGui/PCGui/include/MessageProducer.h delete mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/CommandGui.cpp create mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/CommandGui/CommandGui.cpp delete mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageGui.cpp create mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageGui.cpp create mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageList.cpp create mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageModel.cpp create mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MostRecentMessageFilterProxyModel.cpp rename modules/catkin_ws/src/PCGui/PCGui/src/{ => MessageGui}/SortFilterProxyModel.cpp (96%) delete mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageList.cpp delete mode 100644 modules/catkin_ws/src/PCGui/PCGui/src/MessageModel.cpp diff --git a/modules/catkin_ws/src/MessageLib/src/Client.cpp b/modules/catkin_ws/src/MessageLib/src/Client.cpp index a00ef36c..38eb532b 100644 --- a/modules/catkin_ws/src/MessageLib/src/Client.cpp +++ b/modules/catkin_ws/src/MessageLib/src/Client.cpp @@ -78,7 +78,7 @@ void Client::nextRequest(PeriodicAsyncState::Ptr state) return; std::string emptyRequest; - net.waitWhileBusy(*(state->self->client)); + net.waitWhileBusy(*(client)); client->asyncCall( emptyRequest, state->host, state->self->port, state->retryInterval, [state](const auto & error, const auto & responseMessage) diff --git a/modules/catkin_ws/src/PC2CarLib/CMakeLists.txt b/modules/catkin_ws/src/PC2CarLib/CMakeLists.txt index f2b61086..15a3de67 100644 --- a/modules/catkin_ws/src/PC2CarLib/CMakeLists.txt +++ b/modules/catkin_ws/src/PC2CarLib/CMakeLists.txt @@ -114,12 +114,12 @@ endif() ####### # Test ####### -set(TEST_SOURCE_FILES ${SOURCE_FILES} test/Main.cpp) -add_executable(PC2CarTest ${TEST_SOURCE_FILES}) +add_executable(PC2CarTest ${SOURCE_FILES} test/Test.cpp) +add_executable(DisplayCommands ${SOURCE_FILES} test/DisplayCommands.cpp) # NetworkingLib target_include_directories(PC2CarTest PUBLIC ${NetworkingLib_INCLUDE_DIRS}) target_link_libraries(PC2CarTest NetworkingLib) -# For debugging -target_compile_options(PC2CarTest PUBLIC -fopenmp -fPIC -O0 -g3 -ggdb) \ No newline at end of file +target_include_directories(DisplayCommands PUBLIC ${NetworkingLib_INCLUDE_DIRS}) +target_link_libraries(DisplayCommands NetworkingLib) \ No newline at end of file diff --git a/modules/catkin_ws/src/PC2CarLib/test/DisplayCommands.cpp b/modules/catkin_ws/src/PC2CarLib/test/DisplayCommands.cpp new file mode 100644 index 00000000..a40c8a20 --- /dev/null +++ b/modules/catkin_ws/src/PC2CarLib/test/DisplayCommands.cpp @@ -0,0 +1,59 @@ +// +// Created by philipp on 16.05.18. +// + +#include <iostream> +#include "../include/PC2CarLib/CommandSender.h" +#include "../include/PC2CarLib/CommandReceiver.h" + +int main(int argc, char ** argv) +{ + using namespace pc2car; + + networking::Networking net; + CommandSender sender{net, "127.0.0.1"}; + auto receiver = CommandReceiver::create(net); + + receiver->receiveCommands( + [receiver](CommandCode code) + { + using namespace commandCodes; + std::cout << "code: " << code << "\n"; + switch (code) + { + case ENABLE_LOGGING: + std::cout << "ENABLE_LOGGING\n"; + std::cout << receiver->isLoggingEnabled().get() << "\n"; + break; + + case ENABLE_PLATOON: + std::cout << "ENABLE_PLATOON\n"; + std::cout << receiver->isPlatoonEnabled().get() << "\n"; + break; + + case ENABLE_RC_MODE: + std::cout << "ENABLE_RC_MODE\n"; + std::cout << receiver->isRcModeEnabled().get() << "\n"; + break; + + case SET_PS: + std::cout << "SET_PS\n"; + std::cout << receiver->getPlatoonSpeed().get() << "\n"; + break; + + case SET_IPD: + std::cout << "SET_IPD\n"; + std::cout << receiver->getInnerPlatoonDistance().get() << "\n"; + break; + + case SET_SPEED: + std::cout << "SET_SPEED\n"; + std::cout << receiver->getSpeed().get() << "\n"; + break; + } + std::cout << std::flush; + }); + + while (1); + return 0; +} \ No newline at end of file diff --git a/modules/catkin_ws/src/PC2CarLib/test/Main.cpp b/modules/catkin_ws/src/PC2CarLib/test/Test.cpp similarity index 100% rename from modules/catkin_ws/src/PC2CarLib/test/Main.cpp rename to modules/catkin_ws/src/PC2CarLib/test/Test.cpp diff --git a/modules/catkin_ws/src/PCGui/PCGui/CMakeLists.txt b/modules/catkin_ws/src/PCGui/PCGui/CMakeLists.txt index ac4fc842..abe911b5 100644 --- a/modules/catkin_ws/src/PCGui/PCGui/CMakeLists.txt +++ b/modules/catkin_ws/src/PCGui/PCGui/CMakeLists.txt @@ -36,17 +36,25 @@ set(SOURCE_FILES qml.qrc) add_executable(CommandGui ${SOURCE_FILES} - src/CommandGui.cpp) + include/CommandGui/SignalConsumer.h + src/CommandGui/CommandGui.cpp) add_executable(MessageGui ${SOURCE_FILES} - include/SortFilterProxyModel.h - include/MessageModel.h - include/MessageList.h - include/MessageProducer.h - src/MessageGui.cpp - src/MessageModel.cpp - src/MessageList.cpp - src/SortFilterProxyModel.cpp) + include/MessageGui/SortFilterProxyModel.h + include/MessageGui/MessageModel.h + include/MessageGui/MessageCollection.h + include/MessageGui/MessageList.h + include/MessageGui/SignalProducer.h + include/MessageGui/SignalConsumer.h + include/MessageGui/Utils.h + include/MessageGui/MostRecentMessageFiltertProxyModel.h + include/MessageGui/MessageRole.h + include/MessageGui/Message.h + src/MessageGui/MessageGui.cpp + src/MessageGui/MessageModel.cpp + src/MessageGui/MessageList.cpp + src/MessageGui/MostRecentMessageFilterProxyModel.cpp + src/MessageGui/SortFilterProxyModel.cpp) target_link_libraries(CommandGui ${LIBS}) target_link_libraries(MessageGui ${LIBS}) diff --git a/modules/catkin_ws/src/PCGui/PCGui/CommandGui.qml b/modules/catkin_ws/src/PCGui/PCGui/CommandGui.qml index 9a40ba2d..ca724ffb 100644 --- a/modules/catkin_ws/src/PCGui/PCGui/CommandGui.qml +++ b/modules/catkin_ws/src/PCGui/PCGui/CommandGui.qml @@ -1,9 +1,139 @@ import QtQuick 2.5 import QtQuick.Window 2.2 +import QtQuick.Controls 1.2 -Window { +ApplicationWindow { visible: true - width: 640 - height: 480 + width: 500 + height: 250 title: qsTr("Command Gui") + + // --- host --- + Label { + id: hostLabel + text: "Host:" + + anchors.left: parent.left + anchors.leftMargin: 30 + anchors.top: parent.top + anchors.topMargin: 30 + } + + TextField { + id: hostTextField + objectName: "hostTextField" + text: "127.0.0.1" + + anchors.left: hostLabel.right + anchors.leftMargin: 150 + anchors.verticalCenter: hostLabel.verticalCenter + } + + Button { + id: setHostButton + objectName: "setHostButton" + text: "set" + + anchors.left: hostTextField.right + anchors.leftMargin: 10 + anchors.verticalCenter: hostTextField.verticalCenter + } + + // --- enablePlatoon --- + CheckBox { + id: enablePlatoonCheckbox + objectName: "enablePlatoonCheckbox" + text: "Platoon enabled" + + anchors.left: hostLabel.left + anchors.top: hostLabel.bottom + anchors.topMargin: 20 + } + + // --- platoonSpeed --- + Label { + id: platoonSpeedLabel + text: "Platoon Speed:" + + anchors.left: hostLabel.left + anchors.top: enablePlatoonCheckbox.bottom + anchors.topMargin: 20 + } + + TextField { + id: platoonSpeedTextField + objectName: "platoonSpeedTextField" + text: "0" + + anchors.left: hostTextField.left + anchors.verticalCenter: platoonSpeedLabel.verticalCenter + } + + Button { + id: setPlatoonSpeedButton + objectName: "setPlatoonSpeedButton" + text: "set" + + anchors.left: platoonSpeedTextField.right + anchors.leftMargin: 10 + anchors.verticalCenter: platoonSpeedTextField.verticalCenter + } + + // --- innerPlatoonDistance --- + Label { + id: innerPlatoonDistanceLabel + text: "Inner Platoon Distance:" + + anchors.left: hostLabel.left + anchors.top: platoonSpeedLabel.bottom + anchors.topMargin: 20 + } + + TextField { + id: innerPlatoonDistanceTextField + objectName: "innerPlatoonDistanceTextField" + text: "0" + + anchors.left: hostTextField.left + anchors.verticalCenter: innerPlatoonDistanceLabel.verticalCenter + } + + Button { + id: setInnerPlatoonDistanceButton + objectName: "setInnerPlatoonDistanceButton" + text: "set" + + anchors.left: innerPlatoonDistanceTextField.right + anchors.leftMargin: 10 + anchors.verticalCenter: innerPlatoonDistanceTextField.verticalCenter + } + + // --- speed --- + Label { + id: speedLabel + text: "Platoon Speed:" + + anchors.left: hostLabel.left + anchors.top: innerPlatoonDistanceLabel.bottom + anchors.topMargin: 20 + } + + TextField { + id: speedTextField + objectName: "speedTextField" + text: "0" + + anchors.left: hostTextField.left + anchors.verticalCenter: speedLabel.verticalCenter + } + + Button { + id: setPlatoonButton + objectName: "setSpeedButton" + text: "set" + + anchors.left: speedTextField.right + anchors.leftMargin: 10 + anchors.verticalCenter: speedTextField.verticalCenter + } } diff --git a/modules/catkin_ws/src/PCGui/PCGui/MessageGui.qml b/modules/catkin_ws/src/PCGui/PCGui/MessageGui.qml index 45d0b62e..08350fbc 100644 --- a/modules/catkin_ws/src/PCGui/PCGui/MessageGui.qml +++ b/modules/catkin_ws/src/PCGui/PCGui/MessageGui.qml @@ -62,22 +62,66 @@ ApplicationWindow { anchors.topMargin: 20 } + Button { + id: clearButton + text: "Clear" + onClicked: { + messageList_.clear(); + } + + anchors.left: mostRecentCheckBox.right + anchors.leftMargin: 20 + anchors.verticalCenter: mostRecentCheckBox.verticalCenter + } + Label { - id: statusLabel - text: "Status:" + id: hostLabel + text: "Host:" anchors.left: moduleLabel.left anchors.top: mostRecentCheckBox.bottom anchors.topMargin: 20 } + TextField { + id: hostTextField + objectName: "hostTextField" + text: "127.0.0.1" + + anchors.left: hostLabel.right + anchors.leftMargin: 20 + anchors.verticalCenter: hostLabel.verticalCenter + } + + Button { + id: connectButton + objectName: "connectButton" + text: "Connect" + + anchors.left: hostTextField.right + anchors.leftMargin: 20 + anchors.verticalCenter: hostTextField.verticalCenter + } + + Label { + id: statusLabel + text: "Status:" + + anchors.left: connectButton.right + anchors.leftMargin: 20 + anchors.verticalCenter: connectButton.verticalCenter + } + Label { - id: status + id: statusTextLabel + objectName: "statusTextLabel" + text: "Disconnected" color: "red" - anchors.left: moduleSearchBox.left - anchors.top: statusLabel.top + anchors.left: statusLabel.right + anchors.leftMargin: 20 + anchors.verticalCenter: statusLabel.verticalCenter } } @@ -121,22 +165,41 @@ ApplicationWindow { width: tableView.viewport.width / 3 } - // model: SortFilterProxyModel { - // id: proxyModel - // source: sourceModel.count > 0 ? sourceModel : null + model: SortFilterProxyModel { + id: filterKeyModel + source: filterModuleModel - // sortOrder: tableView.sortIndicatorOrder - // sortCaseSensitivity: Qt.CaseInsensitive - // sortRole: sourceModel.count > 0 ? tableView.getColumn(tableView.sortIndicatorColumn).role : "" + //sortOrder: tableView.sortIndicatorOrder + sortCaseSensitivity: Qt.CaseInsensitive + sortRole: "key" - // filterString: moduleSearchBox.text - // filterSyntax: SortFilterProxyModel.FixedString - // filterCaseSensitivity: Qt.CaseInsensitive - // } + filterString: "*" + keySearchBox.text + "*" + filterSyntax: SortFilterProxyModel.Wildcard + filterCaseSensitivity: Qt.CaseInsensitive + } + + SortFilterProxyModel { + id: filterModuleModel + source: mostRecentModel + + //sortOrder: tableView.sortIndicatorOrder + sortCaseSensitivity: Qt.CaseInsensitive + sortRole: "module" + + filterString: "*" + moduleSearchBox.text + "*" + filterSyntax: SortFilterProxyModel.Wildcard + filterCaseSensitivity: Qt.CaseInsensitive + } + + MostRecentMessageFilterProxyModel { + id: mostRecentModel + source: messageModel + enabled: mostRecentCheckBox.checked + } - model: MessageModel { + MessageModel { id: messageModel - messageList: messages + messageCollection: messageList_ } } } diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/CommandGui/SignalConsumer.h b/modules/catkin_ws/src/PCGui/PCGui/include/CommandGui/SignalConsumer.h new file mode 100644 index 00000000..efefa1ea --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/CommandGui/SignalConsumer.h @@ -0,0 +1,63 @@ +// +// Created by philipp on 16.05.18. +// + +#ifndef PCGUI_SIGNALCONSUMER_H +#define PCGUI_SIGNALCONSUMER_H + +#include <QObject> +#include <functional> + +class SignalConsumer : public QObject +{ +Q_OBJECT + +public: + + using Callback = std::function<void()>; + + explicit SignalConsumer(QObject * parent = nullptr) : QObject(parent) + {} + + void setOnHostChanged(const Callback & callback) + { onHostChanged = callback; } + + void setOnEnablePlatoonChanged(const Callback & callback) + { onEnablePlatoonChanged = callback; } + + void setOnPlatoonSpeedChanged(const Callback & callback) + { onPlatoonSpeedChanged = callback; } + + void setOnInnerPlatoonDistanceChanged(const Callback & callback) + { onInnerPlatoonDistanceChanged = callback; } + + void setOnSpeedChanged(const Callback & callback) + { onSpeedChanged = callback; } + +public slots: + + void hostChanged() + { onHostChanged(); }; + + void enablePlatoonChanged() + { onEnablePlatoonChanged(); } + + void platoonSpeedChanged() + { onPlatoonSpeedChanged(); } + + void innerPlatoonDistanceChanged() + { onInnerPlatoonDistanceChanged(); } + + void speedChanged() + { onSpeedChanged(); } + +private: + + Callback onHostChanged = [] {}; + Callback onEnablePlatoonChanged = [] {}; + Callback onPlatoonSpeedChanged = [] {}; + Callback onInnerPlatoonDistanceChanged = [] {}; + Callback onSpeedChanged = [] {}; +}; + +#endif //PCGUI_SIGNALCONSUMER_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Message.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Message.h new file mode 100644 index 00000000..f93ce811 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Message.h @@ -0,0 +1,25 @@ +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_MESSAGE_H +#define PCGUI_MESSAGE_H + +#include "MessageLib/Message.h" +#include <QMetaType> + +struct Message +{ + Message() = default; + + Message(int id, const message::Message & data) + : id(id), data(data) + {} + + int id; + message::Message data; +}; + +Q_DECLARE_METATYPE(Message); + +#endif //PCGUI_MESSAGE_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageCollection.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageCollection.h new file mode 100644 index 00000000..20e8d8be --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageCollection.h @@ -0,0 +1,42 @@ + +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_MESSAGECOLLECTION_H +#define PCGUI_MESSAGECOLLECTION_H + +#include <QObject> +#include "Message.h" + +class MessageCollection : public QObject +{ +Q_OBJECT + +public: + explicit MessageCollection(QObject * parent = nullptr) : QObject(parent) + {} + + virtual Message & getItem(int index) = 0; + + virtual int getSize() const noexcept = 0; + +signals: + + void preMessageInserted(); + + void postMessageInserted(); + + void preMessagesCleared(); + + void postMessagesCleared(); + +public slots: + + virtual void insert(const Message & message) = 0; + + virtual void clear() = 0; + +}; + +#endif //PCGUI_MESSAGECOLLECTION_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageList.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageList.h new file mode 100644 index 00000000..456a768c --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageList.h @@ -0,0 +1,32 @@ +// +// Created by philipp on 13.05.18. +// + +#ifndef PCGUI_MESSAGELIST_H +#define PCGUI_MESSAGELIST_H + +#include "MessageCollection.h" +#include <QtCore/QVector> + +class MessageList : public MessageCollection +{ +Q_OBJECT + +public: + explicit MessageList(QObject * parent = nullptr); + + Message & getItem(int index) override; + + int getSize() const noexcept override; + +public slots: + + void insert(const Message & message) override; + + void clear() override; + +private: + QVector<Message> items; +}; + +#endif //PCGUI_MESSAGELIST_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageModel.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageModel.h similarity index 62% rename from modules/catkin_ws/src/PCGui/PCGui/include/MessageModel.h rename to modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageModel.h index 3434974b..18961fd9 100644 --- a/modules/catkin_ws/src/PCGui/PCGui/include/MessageModel.h +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageModel.h @@ -9,30 +9,23 @@ class MessageModel : public QAbstractListModel { Q_OBJECT -Q_PROPERTY(MessageList * messageList READ getMessageList WRITE setMessageList) +Q_PROPERTY(MessageCollection * messageCollection READ getMessageCollection WRITE setMessageCollection) public: explicit MessageModel(QObject * parent = nullptr); - enum - { - ModuleRole = Qt::UserRole, - KeyRole, - ValueRole - }; - int rowCount(const QModelIndex & parent = QModelIndex()) const override; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; QHash<int, QByteArray> roleNames() const override; - MessageList * getMessageList() const noexcept; + MessageCollection * getMessageCollection() const noexcept; - void setMessageList(MessageList * newMessageList); + void setMessageCollection(MessageCollection * newMessageCollection); private: - MessageList * messageList; + MessageCollection * messageCollection; }; #endif // MESSAGEMODEL_H \ No newline at end of file diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageRole.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageRole.h new file mode 100644 index 00000000..e76c0e10 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MessageRole.h @@ -0,0 +1,33 @@ +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_MESSAGEROLES_H +#define PCGUI_MESSAGEROLES_H + +#include <QHash> + +namespace messageRole +{ + +enum +{ + id = Qt::UserRole, + module, + key, + value +}; + +inline QHash<int, QByteArray> roleNames() +{ + QHash<int, QByteArray> names; + names[id] = "id"; + names[module] = "module"; + names[key] = "key"; + names[value] = "value"; + return names; +} + +} + +#endif //PCGUI_MESSAGEROLES_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MostRecentMessageFiltertProxyModel.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MostRecentMessageFiltertProxyModel.h new file mode 100644 index 00000000..58c137a3 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/MostRecentMessageFiltertProxyModel.h @@ -0,0 +1,91 @@ +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_MOSTRECENTFILTERTPROXYMODEL_H +#define PCGUI_MOSTRECENTFILTERTPROXYMODEL_H + +#include <QtCore/QSortFilterProxyModel> +#include <unordered_map> +#include "MessageLib/Message.h" + +struct MessageKey +{ + MessageKey(const std::string & module, const std::string & key) + : module(module), key(key) + {} + + std::string module; + std::string key; +}; + +namespace std +{ + +template<> +struct hash<MessageKey> +{ + std::size_t operator()(const MessageKey & key) const + { + return std::hash<std::string>{}(key.module + "#" + key.key); + } +}; + +template<> +struct equal_to<MessageKey> +{ + bool operator()(const MessageKey & lhs, const MessageKey & rhs) const noexcept + { + return lhs.module == rhs.module && lhs.key == rhs.key; + } +}; + +} + +class MostRecentMessageFilterProxyModel : public QSortFilterProxyModel +{ +Q_OBJECT + + Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(QObject * source READ source WRITE setSource) + Q_PROPERTY(bool enabled READ enabled WRITE enable ) + +public: + explicit MostRecentMessageFilterProxyModel(QObject * parent = nullptr); + + QObject * source() const; + + void setSource(QObject * source); + + int count() const; + + void enable(bool flag); + + bool enabled() const noexcept; + +signals: + + void countChanged(); + +protected slots: + + void onRowsInserted(const QModelIndex & parent, int first, int last); + + void onRowsRemoved(const QModelIndex & parent, int first, int last); + +protected: + QHash<int, QByteArray> roleNames() const; + + bool filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const override; + +private: + + MessageKey messageKeyFromRow(int row, const QModelIndex & parent) const; + + int idFromRow(int row, const QModelIndex & parent) const; + + std::unordered_map<MessageKey, int> mostRecent; + bool enabledFlag{false}; +}; + +#endif //PCGUI_MOSTRECENTFILTERTPROXYMODEL_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalConsumer.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalConsumer.h new file mode 100644 index 00000000..c49f3f11 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalConsumer.h @@ -0,0 +1,47 @@ +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_SIGNALCONSUMER_H +#define PCGUI_SIGNALCONSUMER_H + +#include <QObject> +#include <functional> + +class SignalConsumer : public QObject +{ +Q_OBJECT + +public: + using Callback = std::function<void()>; + + SignalConsumer(QObject * parent = nullptr) + {} + + void setOnShowConnected(const Callback & callback) + { onShowConnected = callback; } + + void setOnShowDisconnected(const Callback & callback) + { onShowDisconnected = callback; } + + void setOnDoConnect(const Callback & callback) + { onDoConnect = callback; } + +public slots: + + void showConnected() + { onShowConnected(); }; + + void showDisconnected() + { onShowDisconnected(); } + + void doConnect() + { onDoConnect(); } + +private: + Callback onShowConnected = [] {}; + Callback onShowDisconnected = [] {}; + Callback onDoConnect = [] {}; +}; + +#endif //PCGUI_SIGNALCONSUMER_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalProducer.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalProducer.h new file mode 100644 index 00000000..3cf62a56 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SignalProducer.h @@ -0,0 +1,36 @@ +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_SIGNALPRODUCER_H +#define PCGUI_SIGNALPRODUCER_H + +#include <QObject> + +class SignalProducer : public QObject +{ +Q_OBJECT + +public: + SignalProducer(QObject * parent = nullptr) + {} + + void emitConnected() + { emit connected(); } + + void emitDisconnected() + { emit disconnected(); } + + void emitMessageProduced(const Message & message) + { emit messageProduced(message); } + +signals: + + void connected(); + + void disconnected(); + + void messageProduced(Message); +}; + +#endif //PCGUI_SIGNALPRODUCER_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/SortFilterProxyModel.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SortFilterProxyModel.h similarity index 100% rename from modules/catkin_ws/src/PCGui/PCGui/include/SortFilterProxyModel.h rename to modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/SortFilterProxyModel.h diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Utils.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Utils.h new file mode 100644 index 00000000..f74c5a18 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/include/MessageGui/Utils.h @@ -0,0 +1,31 @@ +// +// Created by philipp on 15.05.18. +// + +#ifndef PCGUI_UTILS_H +#define PCGUI_UTILS_H + +#include <unordered_map> +#include <vector> + +namespace utils +{ + +template<template<typename...> class Map, typename Key, typename Value> +std::vector<Key> keys(const Map<Key, Value> & map) +{ + std::vector<Key> mapKeys; + for (const auto & i : map) + mapKeys.emplace_back(i.first); + return mapKeys; +}; + +template<typename Container, typename Key> +bool contains(const Container & container, const Key & key) +{ + return container.find(key) != container.end(); +}; + +} + +#endif //PCGUI_UTILS_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageList.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageList.h deleted file mode 100644 index 06ada7ef..00000000 --- a/modules/catkin_ws/src/PCGui/PCGui/include/MessageList.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by philipp on 13.05.18. -// - -#ifndef PCGUI_MESSAGELIST_H -#define PCGUI_MESSAGELIST_H - -#include <QObject> -#include <MessageLib/Message.h> -#include <QtCore/QVector> - -class MessageList : public QObject -{ - Q_OBJECT - -public: - explicit MessageList(QObject * parent = nullptr); - - const QVector<message::Message> & getItems() const noexcept; - -signals: - void preMessageAppended(); - void postMessageAppended(); - -public slots: - void appendMessage(const message::Message & message); - -private: - QVector<message::Message> items; -}; - -#endif //PCGUI_MESSAGELIST_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/include/MessageProducer.h b/modules/catkin_ws/src/PCGui/PCGui/include/MessageProducer.h deleted file mode 100644 index 04d36010..00000000 --- a/modules/catkin_ws/src/PCGui/PCGui/include/MessageProducer.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Created by philipp on 14.05.18. -// - -#ifndef PCGUI_MESSAGEPRODUCER_H -#define PCGUI_MESSAGEPRODUCER_H - -#include <QObject> -#include "MessageLib/Message.h" - -class MessageProducer : public QObject -{ -Q_OBJECT - -public: - void produceMessage(const message::Message & message) - { emit messageProduced(message); } - -signals: - void messageProduced(message::Message); -}; - -#endif //PCGUI_MESSAGEPRODUCER_H diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/CommandGui.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/CommandGui.cpp deleted file mode 100644 index 04741d3d..00000000 --- a/modules/catkin_ws/src/PCGui/PCGui/src/CommandGui.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include <QGuiApplication> -#include <QQmlApplicationEngine> - -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/CommandGui.qml"))); - if (engine.rootObjects().isEmpty()) - return -1; - - return app.exec(); -} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/CommandGui/CommandGui.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/CommandGui/CommandGui.cpp new file mode 100644 index 00000000..2f81c9cf --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/src/CommandGui/CommandGui.cpp @@ -0,0 +1,97 @@ +#include "include/QtQuickControlsApplication.h" +#include <QQmlApplicationEngine> +#include <QtGui/qsurfaceformat.h> +#include <QtQml/qqml.h> +#include <QtQml/QQmlContext> +#include <NetworkingLib/Networking.h> +#include "../include/CommandGui/SignalConsumer.h" +#include "PC2CarLib/CommandSender.h" + +void registerTypes() +{ + qmlRegisterUncreatableType<SignalConsumer>( + "car.pcgui", 1, 0, "SignalConsumer", QStringLiteral("SignalConsumer should not be created in QML")); +} + +void configureSurfaceFormat() +{ + if (QCoreApplication::arguments().contains(QLatin1String("--coreprofile"))) + { + QSurfaceFormat fmt; + fmt.setVersion(4, 4); + fmt.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(fmt); + } +} + +int main(int argc, char * argv[]) +{ + SignalConsumer consumer; + networking::Networking net; + pc2car::CommandSender commandSender{net, "127.0.0.1"}; + + registerTypes(); + QtQuickControlsApplication app{argc, argv}; + configureSurfaceFormat(); + QQmlApplicationEngine engine{}; + + engine.rootContext()->setContextProperty(QStringLiteral("consumer"), &consumer); + + engine.load(QUrl("qrc:/CommandGui.qml")); + if (engine.rootObjects().isEmpty()) + return -1; + + auto root = engine.rootObjects()[0]; + auto hostTextField = root->findChild<QObject *>("hostTextField"); + auto setHostButton = root->findChild<QObject *>("setHostButton"); + auto enablePlatoonCheckBox = root->findChild<QObject *>("enablePlatoonCheckbox"); + auto platoonSpeedTextField = root->findChild<QObject *>("platoonSpeedTextField"); + auto setPlatoonSpeedButton = root->findChild<QObject *>("setPlatoonSpeedButton"); + auto innerPlatoonDistanceTextField = root->findChild<QObject *>("innerPlatoonDistanceTextField"); + auto setInnerPlatoonDistanceButton = root->findChild<QObject *>("setInnerPlatoonDistanceButton"); + auto speedTextField = root->findChild<QObject *>("speedTextField"); + auto setSpeedButton = root->findChild<QObject *>("setSpeedButton"); + + QObject::connect(setHostButton, SIGNAL(clicked()), &consumer, SLOT(hostChanged())); + QObject::connect(enablePlatoonCheckBox, SIGNAL(clicked()), &consumer, SLOT(enablePlatoonChanged())); + QObject::connect(setPlatoonSpeedButton, SIGNAL(clicked()), &consumer, SLOT(platoonSpeedChanged())); + QObject::connect(setInnerPlatoonDistanceButton, SIGNAL(clicked()), &consumer, SLOT(innerPlatoonDistanceChanged())); + QObject::connect(setSpeedButton, SIGNAL(clicked()), &consumer, SLOT(speedChanged())); + + consumer.setOnHostChanged( + [&commandSender, &hostTextField] + { + auto host = hostTextField->property("text").toString().toStdString(); + commandSender.setHost(host); + }); + + consumer.setOnEnablePlatoonChanged( + [&commandSender, &enablePlatoonCheckBox] + { + auto checked = enablePlatoonCheckBox->property("checked").toBool(); + commandSender.enablePlatoon(checked); + }); + + consumer.setOnPlatoonSpeedChanged( + [&commandSender, &platoonSpeedTextField] + { + auto platoonSpeed = platoonSpeedTextField->property("text").toFloat(); + commandSender.setPlatoonSpeed(platoonSpeed); + }); + + consumer.setOnInnerPlatoonDistanceChanged( + [&commandSender, &innerPlatoonDistanceTextField] + { + auto innerPlatoonDistance = innerPlatoonDistanceTextField->property("text").toFloat(); + commandSender.setInnerPlatoonDistance(innerPlatoonDistance); + }); + + consumer.setOnSpeedChanged( + [&commandSender, &speedTextField] + { + auto speed = speedTextField->property("text").toFloat(); + commandSender.setSpeed(speed); + }); + + return app.exec(); +} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui.cpp deleted file mode 100644 index 7dcf04af..00000000 --- a/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "../include/QtQuickControlsApplication.h" -#include "../include/SortFilterProxyModel.h" -#include <QtQml/qqmlapplicationengine.h> -#include <QtGui/qsurfaceformat.h> -#include <QtQml/qqml.h> -#include <QtQml/QQmlContext> -#include <include/MessageModel.h> -#include "NetworkingLib/Networking.h" -#include "MessageLib/Client.h" -#include <chrono> -#include <iostream> -#include <include/MessageProducer.h> - -Q_DECLARE_METATYPE(message::Message); - -int main(int argc, char * argv[]) -{ - using namespace std::chrono_literals; - - qmlRegisterType<SortFilterProxyModel>("car.pcgui", 1, 0, "SortFilterProxyModel"); - qmlRegisterType<MessageModel>("car.pcgui", 1, 0, "MessageModel"); - qRegisterMetaType<message::Message>(); - qmlRegisterUncreatableType<MessageList>( - "car.pcgui", 1, 0, "MessageList", QStringLiteral("MessageList should not be created in QML")); - - networking::Networking net; - auto messageClient = message::Client::create(net, 10207); - MessageList messages; - MessageProducer producer; - QObject::connect(&producer, SIGNAL(messageProduced(message::Message)), - &messages, SLOT(appendMessage(const message::Message &))); - - QtQuickControlsApplication app(argc, argv); - if (QCoreApplication::arguments().contains(QLatin1String("--coreprofile"))) - { - QSurfaceFormat fmt; - fmt.setVersion(4, 4); - fmt.setProfile(QSurfaceFormat::CoreProfile); - QSurfaceFormat::setDefaultFormat(fmt); - } - - QQmlApplicationEngine engine{}; - engine.rootContext()->setContextProperty(QStringLiteral("messages"), &messages); - engine.load(QUrl("qrc:/MessageGui.qml")); - if (engine.rootObjects().isEmpty()) - return -1; - - messageClient->requestMessagesPeriodically( - "127.0.0.1", 10ms, 3s, - [&producer](const auto & message) - { producer.produceMessage(message); }); - - return app.exec(); -} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageGui.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageGui.cpp new file mode 100644 index 00000000..4db67206 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageGui.cpp @@ -0,0 +1,119 @@ +#include "include/QtQuickControlsApplication.h" +#include "include/MessageGui/SortFilterProxyModel.h" +#include <QtQml/qqmlapplicationengine.h> +#include <QtGui/qsurfaceformat.h> +#include <QtQml/qqml.h> +#include <QtQml/QQmlContext> +#include <include/MessageGui/MessageModel.h> +#include "NetworkingLib/Networking.h" +#include "MessageLib/Client.h" +#include "include/MessageGui/SignalProducer.h" +#include "include/MessageGui/SignalConsumer.h" +#include <QDebug> +#include "include/MessageGui/MostRecentMessageFiltertProxyModel.h" + +static int currId = 0; + +void registerTypes() +{ + qmlRegisterType<SortFilterProxyModel>("car.pcgui", 1, 0, "SortFilterProxyModel"); + qmlRegisterType<MostRecentMessageFilterProxyModel>("car.pcgui", 1, 0, "MostRecentMessageFilterProxyModel"); + qmlRegisterType<MessageModel>("car.pcgui", 1, 0, "MessageModel"); + qRegisterMetaType<Message>(); + qmlRegisterUncreatableType<MessageCollection>( + "car.pcgui", 1, 0, "MessageCollection", QStringLiteral("MessageCollection should not be created in QML")); + qmlRegisterUncreatableType<MessageList>( + "car.pcgui", 1, 0, "MessageList", QStringLiteral("MessageList should not be created in QML")); + qmlRegisterUncreatableType<SignalConsumer>( + "car.pcgui", 1, 0, "SignalConsumer", QStringLiteral("SignalConsumer should not be created in QML")); +} + +void configureSurfaceFormat() +{ + if (QCoreApplication::arguments().contains(QLatin1String("--coreprofile"))) + { + QSurfaceFormat fmt; + fmt.setVersion(4, 4); + fmt.setProfile(QSurfaceFormat::CoreProfile); + QSurfaceFormat::setDefaultFormat(fmt); + } +} + +void requestMessages(message::Client::Ptr & messageClient, + SignalProducer & producer, + const std::string & host) +{ + using namespace std::chrono_literals; + messageClient->requestMessagesPeriodically( + host, 10ms, 3s, + [&producer](const auto & message) + { + producer.emitMessageProduced(Message{currId++, message}); + }, + [&producer](const auto & error) + { + if (error) + producer.emitDisconnected(); + else + producer.emitConnected(); + }); +} + +int main(int argc, char * argv[]) +{ + networking::Networking net; + auto messageClient = message::Client::create(net, 10207); + MessageList messageList; + SignalProducer producer; + SignalConsumer consumer; + + registerTypes(); + QtQuickControlsApplication app{argc, argv}; + configureSurfaceFormat(); + QQmlApplicationEngine engine{}; + + engine.rootContext()->setContextProperty(QStringLiteral("messageList_"), &messageList); + engine.rootContext()->setContextProperty(QStringLiteral("consumer"), &consumer); + + engine.load(QUrl("qrc:/MessageGui.qml")); + if (engine.rootObjects().isEmpty()) + return -1; + + auto root = engine.rootObjects()[0]; + auto hostTextField = root->findChild<QObject *>("hostTextField"); + auto connectButton = root->findChild<QObject *>("connectButton"); + auto statusTextLabel = root->findChild<QObject *>("statusTextLabel"); + + QObject::connect(&producer, SIGNAL(messageProduced(Message)), + &messageList, SLOT(insert(const Message &))); + QObject::connect(&producer, SIGNAL(connected()), &consumer, SLOT(showConnected())); + QObject::connect(&producer, SIGNAL(disconnected()), &consumer, SLOT(showDisconnected())); + QObject::connect(connectButton, SIGNAL(clicked()), &consumer, SLOT(doConnect())); + + consumer.setOnShowConnected( + [statusTextLabel] + { + statusTextLabel->setProperty("text", QStringLiteral("Connected")); + statusTextLabel->setProperty("color", QStringLiteral("green")); + }); + + consumer.setOnShowDisconnected( + [statusTextLabel] + { + statusTextLabel->setProperty("text", QStringLiteral("Disconnected")); + statusTextLabel->setProperty("color", QStringLiteral("red")); + }); + + consumer.setOnDoConnect( + [hostTextField, &messageClient, &producer, &net] + { + auto host = hostTextField->property("text").toString().toStdString(); + messageClient->stop(); + net.waitWhileBusy(*messageClient); + requestMessages(messageClient, producer, host); + }); + + requestMessages(messageClient, producer, "127.0.0.1"); + + return app.exec(); +} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageList.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageList.cpp new file mode 100644 index 00000000..770c9809 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageList.cpp @@ -0,0 +1,33 @@ +// +// Created by philipp on 13.05.18. +// + +#include "include/MessageGui/MessageList.h" + +MessageList::MessageList(QObject * parent) : MessageCollection(parent) +{ +} + +Message & MessageList::getItem(int index) +{ + return items[index]; +} + +int MessageList::getSize() const noexcept +{ + return items.size(); +} + +void MessageList::insert(const Message & message) +{ + emit preMessageInserted(); + items.append(message); + emit postMessageInserted(); +} + +void MessageList::clear() +{ + emit preMessagesCleared(); + items.clear(); + emit postMessagesCleared(); +} \ No newline at end of file diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageModel.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageModel.cpp new file mode 100644 index 00000000..c7b6ffc8 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MessageModel.cpp @@ -0,0 +1,87 @@ +#include "include/MessageGui/MessageModel.h" +#include "include/MessageGui/MessageRole.h" + +MessageModel::MessageModel(QObject * parent) + : QAbstractListModel(parent) + , messageCollection(nullptr) +{ +} + +int MessageModel::rowCount(const QModelIndex & parent) const +{ + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid() || !messageCollection) + return 0; + + return messageCollection->getSize(); +} + +QVariant MessageModel::data(const QModelIndex & index, int role) const +{ + if (!index.isValid() || !messageCollection) + return QVariant{}; + + auto message = messageCollection->getItem(index.row()); + switch (role) + { + case messageRole::id: + return QVariant{message.id}; + + case messageRole::module: + return QVariant{QString::fromStdString(message.data.module)}; + + case messageRole::key: + return QVariant{QString::fromStdString(message.data.key)}; + + case messageRole::value: + return QVariant{QString::fromStdString(message.data.value)}; + } + + return QVariant{}; +} + +QHash<int, QByteArray> MessageModel::roleNames() const +{ + return messageRole::roleNames(); +} + +MessageCollection * MessageModel::getMessageCollection() const noexcept +{ + return messageCollection; +} + +void MessageModel::setMessageCollection(MessageCollection * newMessageCollection) +{ + beginResetModel(); + + if (messageCollection) + { + messageCollection->disconnect(this); + removeRows(0, rowCount()); + } + + messageCollection = newMessageCollection; + + if (messageCollection) + { + insertRows(0, messageCollection->getSize()); + + connect(messageCollection, &MessageCollection::preMessageInserted, this, [this] + { + int index = messageCollection->getSize(); + beginInsertRows(QModelIndex{}, index, index); + }); + + connect(messageCollection, &MessageCollection::postMessageInserted, this, [this] + { endInsertRows(); }); + + connect(messageCollection, &MessageCollection::preMessagesCleared, this, [this]() + { beginRemoveRows(QModelIndex{}, 0, rowCount()); }); + + connect(messageCollection, &MessageCollection::postMessagesCleared, this, [this] + { endRemoveRows(); }); + } + + endResetModel(); +} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MostRecentMessageFilterProxyModel.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MostRecentMessageFilterProxyModel.cpp new file mode 100644 index 00000000..e135b950 --- /dev/null +++ b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/MostRecentMessageFilterProxyModel.cpp @@ -0,0 +1,103 @@ +// +// Created by philipp on 15.05.18. +// + +#include "include/MessageGui/MostRecentMessageFiltertProxyModel.h" +#include "include/MessageGui/MessageRole.h" + +MostRecentMessageFilterProxyModel::MostRecentMessageFilterProxyModel(QObject * parent) + : QSortFilterProxyModel(parent) +{ + connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SIGNAL(countChanged())); + connect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SIGNAL(countChanged())); +} + +QObject * MostRecentMessageFilterProxyModel::source() const +{ + return sourceModel(); +} + +void MostRecentMessageFilterProxyModel::setSource(QObject * source) +{ + beginResetModel(); + + if (this->source()) + disconnect(this->source()); + + setSourceModel(qobject_cast<QAbstractItemModel *>(source)); + + connect(this, SIGNAL(rowsInserted(QModelIndex, int, int)), + this, SLOT(onRowsInserted(const QModelIndex &, int, int))); + connect(this, SIGNAL(rowsRemoved(QModelIndex, int, int)), + this, SLOT(onRowsRemoved(const QModelIndex &, int, int))); + + endResetModel(); +} + +int MostRecentMessageFilterProxyModel::count() const +{ + return rowCount(); +} + +void MostRecentMessageFilterProxyModel::enable(bool flag) +{ + enabledFlag = flag; + invalidateFilter(); +} + +bool MostRecentMessageFilterProxyModel::enabled() const noexcept +{ + return enabledFlag; +} + +QHash<int, QByteArray> MostRecentMessageFilterProxyModel::roleNames() const +{ + return messageRole::roleNames(); +} + +void MostRecentMessageFilterProxyModel::onRowsInserted(const QModelIndex & parent, int first, int last) +{ + for (int i = first; i <= last; i++) + { + auto key = messageKeyFromRow(i, parent); + mostRecent[key] = idFromRow(i, parent); + } + invalidateFilter(); +} + +#include <QDebug> + +void MostRecentMessageFilterProxyModel::onRowsRemoved(const QModelIndex & parent, int first, int last) +{ + for (int i = first; i <= last; i++) + qDebug() << "ID to remove: " << idFromRow(i, parent); +} + +MessageKey MostRecentMessageFilterProxyModel::messageKeyFromRow(int row, const QModelIndex & parent) const +{ + auto model = sourceModel(); + auto module = model->data(model->index(row, 0, parent), messageRole::module).toString().toStdString(); + auto key = model->data(model->index(row, 0, parent), messageRole::key).toString().toStdString(); + return MessageKey{module, key}; +} + +int MostRecentMessageFilterProxyModel::idFromRow(int row, const QModelIndex & parent) const +{ + auto model = sourceModel(); + return model->data(model->index(row, 0, parent), messageRole::id).toInt(); +} + +bool MostRecentMessageFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const +{ + if (!enabled() || !sourceModel()->index(sourceRow, 0, sourceParent).isValid() || + sourceRow < 0 || sourceRow >= rowCount()) + return true; + + auto key = messageKeyFromRow(sourceRow, sourceParent); + auto id = idFromRow(sourceRow, sourceParent); + + if (id != mostRecent.at(key)) + qDebug() << "ID not accepted: " << id; + + return id == mostRecent.at(key); +} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/SortFilterProxyModel.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/SortFilterProxyModel.cpp similarity index 96% rename from modules/catkin_ws/src/PCGui/PCGui/src/SortFilterProxyModel.cpp rename to modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/SortFilterProxyModel.cpp index 4baa931f..5d688ef7 100644 --- a/modules/catkin_ws/src/PCGui/PCGui/src/SortFilterProxyModel.cpp +++ b/modules/catkin_ws/src/PCGui/PCGui/src/MessageGui/SortFilterProxyModel.cpp @@ -48,7 +48,7 @@ ** ****************************************************************************/ -#include "../include/SortFilterProxyModel.h" +#include "include/MessageGui/SortFilterProxyModel.h" #include <QtDebug> #include <QtQml> diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageList.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageList.cpp deleted file mode 100644 index 9fc693b9..00000000 --- a/modules/catkin_ws/src/PCGui/PCGui/src/MessageList.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by philipp on 13.05.18. -// - -#include "../include/MessageList.h" - -MessageList::MessageList(QObject * parent) : QObject(parent) -{ -} - -const QVector<message::Message> & MessageList::getItems() const noexcept -{ - return items; -} - -void MessageList::appendMessage(const message::Message & message) -{ - emit preMessageAppended(); - items.append(message); - emit postMessageAppended(); -} diff --git a/modules/catkin_ws/src/PCGui/PCGui/src/MessageModel.cpp b/modules/catkin_ws/src/PCGui/PCGui/src/MessageModel.cpp deleted file mode 100644 index b305119a..00000000 --- a/modules/catkin_ws/src/PCGui/PCGui/src/MessageModel.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "../include/MessageModel.h" - -MessageModel::MessageModel(QObject * parent) - : QAbstractListModel(parent) - , messageList(nullptr) -{ -} - -int MessageModel::rowCount(const QModelIndex & parent) const -{ - // For list models only the root node (an invalid parent) should return the list's size. For all - // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. - if (parent.isValid() || !messageList) - return 0; - - return messageList->getItems().size(); -} - -QVariant MessageModel::data(const QModelIndex & index, int role) const -{ - if (!index.isValid() || !messageList) - return QVariant{}; - - auto message = messageList->getItems().at(index.row()); - switch (role) - { - case ModuleRole: - return QVariant{QString::fromStdString(message.module)}; - - case KeyRole: - return QVariant{QString::fromStdString(message.key)}; - - case ValueRole: - return QVariant{QString::fromStdString(message.value)}; - } - - return QVariant{}; -} - -QHash<int, QByteArray> MessageModel::roleNames() const -{ - QHash<int, QByteArray> names; - names[ModuleRole] = "module"; - names[KeyRole] = "key"; - names[ValueRole] = "value"; - return names; -} - -MessageList * MessageModel::getMessageList() const noexcept -{ - return messageList; -} - -void MessageModel::setMessageList(MessageList * newMessageList) -{ - beginResetModel(); - - if (messageList) - messageList->disconnect(this); - - messageList = newMessageList; - - if (messageList) - { - connect(messageList, &MessageList::preMessageAppended, this, [this] - { - int index = messageList->getItems().size(); - beginInsertRows(QModelIndex{}, index, index); - }); - - connect(messageList, &MessageList::postMessageAppended, this, [this] - { - endInsertRows(); - }); - } - - endResetModel(); -} diff --git a/modules/catkin_ws/src/car/src/ultrasonic/Ultrasonic.cpp b/modules/catkin_ws/src/car/src/ultrasonic/Ultrasonic.cpp index 847e7b17..4137e638 100644 --- a/modules/catkin_ws/src/car/src/ultrasonic/Ultrasonic.cpp +++ b/modules/catkin_ws/src/car/src/ultrasonic/Ultrasonic.cpp @@ -22,14 +22,16 @@ void Ultrasonic::onInit() messageOStream.write("onInit", "START"); ussData = nh.advertise<ussDataMsg>("ussData", 1); - sensor.init(); + //sensor.init(); timer = networking::time::Timer::create(net); timer->startPeriodicTimeout( std::chrono::milliseconds(UltrasonicSensor::DELAY), [&] { ussDataMsg msg; - auto distance = streamMedianFilter.moveWindow(sensor.getDistance()); + //auto distance = streamMedianFilter.moveWindow(sensor.getDistance()); + static int distance = 0; + distance++; msg.distance = distance; msg.timestamp = ros::Time::now(); ussData.publish(msg); -- GitLab