Commit e107a34a authored by Valentin Platzgummer's avatar Valentin Platzgummer

temp

parent 40da114d
...@@ -453,6 +453,8 @@ HEADERS += \ ...@@ -453,6 +453,8 @@ HEADERS += \
src/MeasurementComplexItem/geometry/TileDiff.h \ src/MeasurementComplexItem/geometry/TileDiff.h \
src/MeasurementComplexItem/geometry/geometry.h \ src/MeasurementComplexItem/geometry/geometry.h \
src/MeasurementComplexItem/HashFunctions.h \ src/MeasurementComplexItem/HashFunctions.h \
src/MeasurementComplexItem/nemo_interface/Command.h \
src/MeasurementComplexItem/nemo_interface/CommandDispatcher.h \
src/MeasurementComplexItem/nemo_interface/MeasurementTile.h \ src/MeasurementComplexItem/nemo_interface/MeasurementTile.h \
src/QmlControls/QmlUnitsConversion.h \ src/QmlControls/QmlUnitsConversion.h \
src/MeasurementComplexItem/geometry/GeoArea.h \ src/MeasurementComplexItem/geometry/GeoArea.h \
...@@ -534,6 +536,8 @@ SOURCES += \ ...@@ -534,6 +536,8 @@ SOURCES += \
src/MeasurementComplexItem/geometry/SafeArea.cc \ src/MeasurementComplexItem/geometry/SafeArea.cc \
src/MeasurementComplexItem/geometry/geometry.cpp \ src/MeasurementComplexItem/geometry/geometry.cpp \
src/MeasurementComplexItem/HashFunctions.cpp \ src/MeasurementComplexItem/HashFunctions.cpp \
src/MeasurementComplexItem/nemo_interface/Command.cpp \
src/MeasurementComplexItem/nemo_interface/CommandDispatcher.cpp \
src/MeasurementComplexItem/nemo_interface/MeasurementTile.cpp \ src/MeasurementComplexItem/nemo_interface/MeasurementTile.cpp \
src/Vehicle/VehicleEscStatusFactGroup.cc \ src/Vehicle/VehicleEscStatusFactGroup.cc \
src/MeasurementComplexItem/AreaData.cc \ src/MeasurementComplexItem/AreaData.cc \
......
...@@ -40,47 +40,69 @@ using SharedLock = std::shared_lock<std::shared_timed_mutex>; ...@@ -40,47 +40,69 @@ using SharedLock = std::shared_lock<std::shared_timed_mutex>;
using JsonDocUPtr = ros_bridge::com_private::JsonDocUPtr; using JsonDocUPtr = ros_bridge::com_private::JsonDocUPtr;
class NemoInterface::Impl { class NemoInterface::Impl {
using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock>;
public: public:
enum class STATE {
STOPPED,
RUNNING,
WEBSOCKET_DETECTED,
HEARTBEAT_DETECTED,
TRY_TOPIC_SERVICE_SETUP,
READY,
SYNCHRONIZING,
TIMEOUT,
INVALID_HEARTBEAT
}
Impl(NemoInterface *p); Impl(NemoInterface *p);
void start(); void start();
void stop(); void stop();
// Tile editing.
// Functions that require communication to device.
void addTiles(const TilePtrArray &tileArray); void addTiles(const TilePtrArray &tileArray);
void addTiles(const TileArray &tileArray); void addTiles(const TileArray &tileArray);
void removeTiles(const IDArray &idArray); void removeTiles(const IDArray &idArray);
void clearTiles(); void clearTiles();
// Functions that don't require communication to device.
TileArray getTiles(const IDArray &idArray); TileArray getTiles(const IDArray &idArray);
TileArray getAllTiles(); TileArray getAllTiles();
LogicalArray containsTiles(const IDArray &idArray); LogicalArray containsTiles(const IDArray &idArray);
TileArray extractTiles(const IDArray &idArray);
std::size_t size(); std::size_t size();
bool empty(); bool empty();
void publishTileData();
// Progress.
ProgressArray getProgress();
ProgressArray getProgress(const IDArray &idArray);
NemoInterface::STATUS status(); NemoInterface::STATUS status();
bool running(); bool running();
private: private:
typedef std::chrono::time_point<std::chrono::high_resolution_clock> TimePoint;
typedef std::map<long, MeasurementTile> TileMap;
typedef ros_bridge::messages::nemo_msgs::heartbeat::Heartbeat Heartbeat;
void _addTiles(const TileArray &tileArray);
void _removeTiles(const IDArray &idArray);
void _clearTiles();
void doTopicServiceSetup(); void doTopicServiceSetup();
void loop(); void loop();
static STATUS heartbeatToStatus(
const ros_bridge::messages::nemo_msgs::heartbeat::Heartbeat &hb);
bool setStatus(NemoInterface::STATUS s); bool _setState(STATE s);
static bool _running(STATE s);
static void _translate(STATE state, NemoInterface::STATUS &status);
static void _translate(Heartbeat hb, STATE &state);
TimePoint nextTimeout; TimePoint nextTimeout;
mutable std::shared_timed_mutex timeoutMutex; mutable std::shared_timed_mutex timeoutMutex;
std::atomic<NemoInterface::STATUS> status_;
STATE _state;
// Internals ROSBridgePtr _pRosBridge;
std::atomic_bool running_; TileMap _tileMap;
std::atomic_bool topicServiceSetupDone; NemoInterface *_parent;
ROSBridgePtr pRosBridge;
QTimer loopTimer;
NemoInterface *parent;
}; };
using StatusMap = std::map<NemoInterface::STATUS, QString>; using StatusMap = std::map<NemoInterface::STATUS, QString>;
...@@ -98,7 +120,7 @@ static StatusMap statusMap{ ...@@ -98,7 +120,7 @@ static StatusMap statusMap{
NemoInterface::Impl::Impl(NemoInterface *p) NemoInterface::Impl::Impl(NemoInterface *p)
: nextTimeout(TimePoint::max()), status_(STATUS::NOT_CONNECTED), : nextTimeout(TimePoint::max()), status_(STATUS::NOT_CONNECTED),
running_(false), topicServiceSetupDone(false), parent(p) { running_(false), topicServiceSetupDone(false), _parent(p) {
// ROS Bridge. // ROS Bridge.
WimaSettings *wimaSettings = WimaSettings *wimaSettings =
...@@ -114,7 +136,7 @@ NemoInterface::Impl::Impl(NemoInterface *p) ...@@ -114,7 +136,7 @@ NemoInterface::Impl::Impl(NemoInterface *p)
"Websocket connection string possibly invalid: " + connectionString + "Websocket connection string possibly invalid: " + connectionString +
". Trying to connect anyways."); ". Trying to connect anyways.");
} }
this->pRosBridge.reset( this->_pRosBridge.reset(
new ros_bridge::ROSBridge(connectionString.toLocal8Bit().data())); new ros_bridge::ROSBridge(connectionString.toLocal8Bit().data()));
}; };
connect(connectionStringFact, &SettingsFact::rawValueChanged, connect(connectionStringFact, &SettingsFact::rawValueChanged,
...@@ -128,12 +150,73 @@ NemoInterface::Impl::Impl(NemoInterface *p) ...@@ -128,12 +150,73 @@ NemoInterface::Impl::Impl(NemoInterface *p)
void NemoInterface::Impl::start() { void NemoInterface::Impl::start() {
this->running_ = true; this->running_ = true;
emit this->parent->runningChanged(); emit this->_parent->runningChanged();
} }
void NemoInterface::Impl::stop() { void NemoInterface::Impl::stop() {
this->running_ = false; this->running_ = false;
emit this->parent->runningChanged(); emit this->_parent->runningChanged();
}
TileArray NemoInterface::Impl::getTiles(const IDArray &idArray) {
TileArray tileArray;
for (const auto &id : idArray) {
const auto it = _tileMap.find(id);
if (it != _tileMap.end()) {
tileArray.append(it->second);
}
}
return tileArray;
}
TileArray NemoInterface::Impl::getAllTiles() {
TileArray tileArray;
for (const auto &entry : _tileMap) {
tileArray.append(entry.second);
}
return tileArray;
}
LogicalArray NemoInterface::Impl::containsTiles(const IDArray &idArray) {
LogicalArray logicalArray;
for (const auto &id : idArray) {
const auto &it = _tileMap.find(id);
logicalArray.append(it != _tileMap.end());
}
return logicalArray;
}
std::size_t NemoInterface::Impl::size() { return _tileMap.size(); }
bool NemoInterface::Impl::empty() { return _tileMap.empty(); }
ProgressArray NemoInterface::Impl::getProgress() {
ProgressArray progressArray;
for (const auto &entry : _tileMap) {
progressArray.append(TaggedProgress{entry.first, entry.second.progress()});
}
return progressArray;
}
ProgressArray NemoInterface::Impl::getProgress(const IDArray &idArray) {
ProgressArray progressArray;
for (const auto &id : idArray) {
const auto it = _tileMap.find(id);
if (id != _tileMap.end()) {
progressArray.append(TaggedProgress{it->first, it->second.progress()});
}
}
return progressArray;
} }
void NemoInterface::Impl::setTileData(const TileData &tileData) { void NemoInterface::Impl::setTileData(const TileData &tileData) {
...@@ -198,14 +281,16 @@ void NemoInterface::Impl::publishTileData() { ...@@ -198,14 +281,16 @@ void NemoInterface::Impl::publishTileData() {
} }
} }
NemoInterface::STATUS NemoInterface::Impl::status() { return status_.load(); } NemoInterface::STATUS NemoInterface::Impl::status() {
return _translate(this->_state);
}
QVector<int> NemoInterface::Impl::progress() { QVector<int> NemoInterface::Impl::progress() {
SharedLock lk(this->progressMutex); SharedLock lk(this->progressMutex);
return this->qProgress.progress(); return this->qProgress.progress();
} }
bool NemoInterface::Impl::running() { return this->running_.load(); } bool NemoInterface::Impl::running() { return _running(this->_state); }
void NemoInterface::Impl::doTopicServiceSetup() { void NemoInterface::Impl::doTopicServiceSetup() {
using namespace ros_bridge::messages; using namespace ros_bridge::messages;
...@@ -213,7 +298,7 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -213,7 +298,7 @@ void NemoInterface::Impl::doTopicServiceSetup() {
// snake tiles. // snake tiles.
{ {
SharedLock lk(this->tilesENUMutex); SharedLock lk(this->tilesENUMutex);
this->pRosBridge->advertiseTopic( this->_pRosBridge->advertiseTopic(
"/snake/tiles", "/snake/tiles",
jsk_recognition_msgs::polygon_array::messageType().c_str()); jsk_recognition_msgs::polygon_array::messageType().c_str());
} }
...@@ -221,12 +306,12 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -221,12 +306,12 @@ void NemoInterface::Impl::doTopicServiceSetup() {
// snake origin. // snake origin.
{ {
SharedLock lk(this->ENUOriginMutex); SharedLock lk(this->ENUOriginMutex);
this->pRosBridge->advertiseTopic( this->_pRosBridge->advertiseTopic(
"/snake/origin", geographic_msgs::geo_point::messageType().c_str()); "/snake/origin", geographic_msgs::geo_point::messageType().c_str());
} }
// Subscribe nemo progress. // Subscribe nemo progress.
this->pRosBridge->subscribe( this->_pRosBridge->subscribe(
"/nemo/progress", "/nemo/progress",
/* callback */ [this](JsonDocUPtr pDoc) { /* callback */ [this](JsonDocUPtr pDoc) {
std::lock(this->progressMutex, this->tilesENUMutex, std::lock(this->progressMutex, this->tilesENUMutex,
...@@ -244,7 +329,7 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -244,7 +329,7 @@ void NemoInterface::Impl::doTopicServiceSetup() {
qgcApp()->informationMessageBoxOnMainThread( qgcApp()->informationMessageBoxOnMainThread(
"Nemo Interface", "Invalid progress message received."); "Nemo Interface", "Invalid progress message received.");
} }
emit this->parent->progressChanged(); emit this->_parent->progressChanged();
lk1.unlock(); lk1.unlock();
lk2.unlock(); lk2.unlock();
...@@ -252,15 +337,15 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -252,15 +337,15 @@ void NemoInterface::Impl::doTopicServiceSetup() {
}); });
// Subscribe /nemo/heartbeat. // Subscribe /nemo/heartbeat.
this->pRosBridge->subscribe( this->_pRosBridge->subscribe(
"/nemo/heartbeat", "/nemo/heartbeat",
/* callback */ [this](JsonDocUPtr pDoc) { /* callback */ [this](JsonDocUPtr pDoc) {
// auto start = std::chrono::high_resolution_clock::now(); // auto start = std::chrono::high_resolution_clock::now();
nemo_msgs::heartbeat::Heartbeat heartbeatMsg; nemo_msgs::heartbeat::Heartbeat heartbeatMsg;
if (!nemo_msgs::heartbeat::fromJson(*pDoc, heartbeatMsg)) { if (!nemo_msgs::heartbeat::fromJson(*pDoc, heartbeatMsg)) {
this->setStatus(STATUS::INVALID_HEARTBEAT); this->_setState(STATUS::INVALID_HEARTBEAT);
} else { } else {
this->setStatus(heartbeatToStatus(heartbeatMsg)); this->_setState(heartbeatToStatus(heartbeatMsg));
} }
if (this->status_ == STATUS::INVALID_HEARTBEAT) { if (this->status_ == STATUS::INVALID_HEARTBEAT) {
UniqueLock lk(this->timeoutMutex); UniqueLock lk(this->timeoutMutex);
...@@ -280,7 +365,7 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -280,7 +365,7 @@ void NemoInterface::Impl::doTopicServiceSetup() {
}); });
// Advertise /snake/get_origin. // Advertise /snake/get_origin.
this->pRosBridge->advertiseService( this->_pRosBridge->advertiseService(
"/snake/get_origin", "snake_msgs/GetOrigin", "/snake/get_origin", "snake_msgs/GetOrigin",
[this](JsonDocUPtr) -> JsonDocUPtr { [this](JsonDocUPtr) -> JsonDocUPtr {
using namespace ros_bridge::messages; using namespace ros_bridge::messages;
...@@ -305,7 +390,7 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -305,7 +390,7 @@ void NemoInterface::Impl::doTopicServiceSetup() {
}); });
// Advertise /snake/get_tiles. // Advertise /snake/get_tiles.
this->pRosBridge->advertiseService( this->_pRosBridge->advertiseService(
"/snake/get_tiles", "snake_msgs/GetTiles", "/snake/get_tiles", "snake_msgs/GetTiles",
[this](JsonDocUPtr) -> JsonDocUPtr { [this](JsonDocUPtr) -> JsonDocUPtr {
SharedLock lk(this->tilesENUMutex); SharedLock lk(this->tilesENUMutex);
...@@ -331,25 +416,25 @@ void NemoInterface::Impl::doTopicServiceSetup() { ...@@ -331,25 +416,25 @@ void NemoInterface::Impl::doTopicServiceSetup() {
void NemoInterface::Impl::loop() { void NemoInterface::Impl::loop() {
// Check ROS Bridge status and do setup if necessary. // Check ROS Bridge status and do setup if necessary.
if (this->running_) { if (this->running_) {
if (!this->pRosBridge->isRunning()) { if (!this->_pRosBridge->isRunning()) {
this->pRosBridge->start(); this->_pRosBridge->start();
this->loop(); this->loop();
} else if (this->pRosBridge->isRunning() && this->pRosBridge->connected() && } else if (this->_pRosBridge->isRunning() &&
!this->topicServiceSetupDone) { this->_pRosBridge->connected() && !this->topicServiceSetupDone) {
this->doTopicServiceSetup(); this->doTopicServiceSetup();
this->topicServiceSetupDone = true; this->topicServiceSetupDone = true;
this->setStatus(STATUS::WEBSOCKET_DETECTED); this->_setState(STATUS::WEBSOCKET_DETECTED);
} else if (this->pRosBridge->isRunning() && } else if (this->_pRosBridge->isRunning() &&
!this->pRosBridge->connected() && this->topicServiceSetupDone) { !this->_pRosBridge->connected() && this->topicServiceSetupDone) {
this->pRosBridge->reset(); this->_pRosBridge->reset();
this->pRosBridge->start(); this->_pRosBridge->start();
this->topicServiceSetupDone = false; this->topicServiceSetupDone = false;
this->setStatus(STATUS::TIMEOUT); this->_setState(STATUS::TIMEOUT);
} }
} else if (this->pRosBridge->isRunning()) { } else if (this->_pRosBridge->isRunning()) {
this->pRosBridge->reset(); this->_pRosBridge->reset();
this->topicServiceSetupDone = false; this->topicServiceSetupDone = false;
} }
...@@ -359,10 +444,10 @@ void NemoInterface::Impl::loop() { ...@@ -359,10 +444,10 @@ void NemoInterface::Impl::loop() {
if (this->nextTimeout != TimePoint::max() && if (this->nextTimeout != TimePoint::max() &&
this->nextTimeout < std::chrono::high_resolution_clock::now()) { this->nextTimeout < std::chrono::high_resolution_clock::now()) {
lk.unlock(); lk.unlock();
if (this->pRosBridge->isRunning() && this->pRosBridge->connected()) { if (this->_pRosBridge->isRunning() && this->_pRosBridge->connected()) {
this->setStatus(STATUS::WEBSOCKET_DETECTED); this->_setState(STATUS::WEBSOCKET_DETECTED);
} else { } else {
this->setStatus(STATUS::TIMEOUT); this->_setState(STATUS::TIMEOUT);
} }
} }
} }
...@@ -382,7 +467,7 @@ void NemoInterface::Impl::publishTilesENU() { ...@@ -382,7 +467,7 @@ void NemoInterface::Impl::publishTilesENU() {
std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
if (jsk_recognition_msgs::polygon_array::toJson( if (jsk_recognition_msgs::polygon_array::toJson(
this->tilesENU, *jSnakeTiles, jSnakeTiles->GetAllocator())) { this->tilesENU, *jSnakeTiles, jSnakeTiles->GetAllocator())) {
this->pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles"); this->_pRosBridge->publish(std::move(jSnakeTiles), "/snake/tiles");
} else { } else {
qCWarning(NemoInterfaceLog) qCWarning(NemoInterfaceLog)
<< "Impl::publishTilesENU: could not create json document."; << "Impl::publishTilesENU: could not create json document.";
...@@ -395,17 +480,17 @@ void NemoInterface::Impl::publishENUOrigin() { ...@@ -395,17 +480,17 @@ void NemoInterface::Impl::publishENUOrigin() {
std::make_unique<rapidjson::Document>(rapidjson::kObjectType)); std::make_unique<rapidjson::Document>(rapidjson::kObjectType));
if (geographic_msgs::geo_point::toJson(this->ENUOrigin, *jOrigin, if (geographic_msgs::geo_point::toJson(this->ENUOrigin, *jOrigin,
jOrigin->GetAllocator())) { jOrigin->GetAllocator())) {
this->pRosBridge->publish(std::move(jOrigin), "/snake/origin"); this->_pRosBridge->publish(std::move(jOrigin), "/snake/origin");
} else { } else {
qCWarning(NemoInterfaceLog) qCWarning(NemoInterfaceLog)
<< "Impl::publishENUOrigin: could not create json document."; << "Impl::publishENUOrigin: could not create json document.";
} }
} }
bool NemoInterface::Impl::setStatus(NemoInterface::STATUS s) { bool NemoInterface::Impl::_setState(STATE s) {
if (s != this->status_) { if (s != this->status_) {
this->status_ = s; this->status_ = s;
emit this->parent->statusChanged(); emit this->_parent->statusChanged();
return true; return true;
} else { } else {
return false; return false;
...@@ -460,14 +545,18 @@ LogicalArray NemoInterface::containsTiles(const IDArray &idArray) { ...@@ -460,14 +545,18 @@ LogicalArray NemoInterface::containsTiles(const IDArray &idArray) {
return this->pImpl->containsTiles(idArray); return this->pImpl->containsTiles(idArray);
} }
TileArray NemoInterface::extractTiles(const IDArray &idArray) {
return this->pImpl->extractTiles(idArray);
}
std::size_t NemoInterface::size() { return this->pImpl->size(); } std::size_t NemoInterface::size() { return this->pImpl->size(); }
bool NemoInterface::empty() { return this->pImpl->empty(); } bool NemoInterface::empty() { return this->pImpl->empty(); }
ProgressArray NemoInterface::getProgress() {
return this->pImpl->getProgress();
}
ProgressArray NemoInterface::getProgress(const IDArray &idArray) {
return this->pImpl->getProgress(idArray);
}
void NemoInterface::publishTileData() { this->pImpl->publishTileData(); } void NemoInterface::publishTileData() { this->pImpl->publishTileData(); }
void NemoInterface::requestProgress() { void NemoInterface::requestProgress() {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "LogicalArray.h" #include "LogicalArray.h"
#include "TileArray.h" #include "TileArray.h"
#include "TilePtrArray.h" #include "TilePtrArray.h"
#include "geometry/ProgressArray.h"
// Singelton class used to interface measurement devices implementing the nemo // Singelton class used to interface measurement devices implementing the nemo
// interface. // interface.
...@@ -26,11 +27,11 @@ public: ...@@ -26,11 +27,11 @@ public:
static NemoInterface *instance(); static NemoInterface *instance();
enum class STATUS { enum class STATUS {
NOT_CONNECTED = 0, NOT_CONNECTED,
HEARTBEAT_DETECTED = 1, READY,
WEBSOCKET_DETECTED = 2, WEBSOCKET_DETECTED,
TIMEOUT = -1, TIMEOUT,
INVALID_HEARTBEAT = -2 INVALID_HEARTBEAT
}; };
Q_ENUM(STATUS) Q_ENUM(STATUS)
...@@ -39,9 +40,12 @@ public: ...@@ -39,9 +40,12 @@ public:
Q_PROPERTY(QString editorQml READ editorQml CONSTANT) Q_PROPERTY(QString editorQml READ editorQml CONSTANT)
Q_PROPERTY(bool running READ running NOTIFY runningChanged) Q_PROPERTY(bool running READ running NOTIFY runningChanged)
QString editorQml();
Q_INVOKABLE void start(); Q_INVOKABLE void start();
Q_INVOKABLE void stop(); Q_INVOKABLE void stop();
// Tile editing.
void addTiles(const TilePtrArray &tileArray); void addTiles(const TilePtrArray &tileArray);
void addTiles(const TileArray &tileArray); void addTiles(const TileArray &tileArray);
void removeTiles(const IDArray &idArray); void removeTiles(const IDArray &idArray);
...@@ -49,18 +53,22 @@ public: ...@@ -49,18 +53,22 @@ public:
TileArray getTiles(const IDArray &idArray); TileArray getTiles(const IDArray &idArray);
TileArray getAllTiles(); TileArray getAllTiles();
LogicalArray containsTiles(const IDArray &idArray); LogicalArray containsTiles(const IDArray &idArray);
TileArray extractTiles(const IDArray &idArray);
std::size_t size(); std::size_t size();
bool empty(); bool empty();
// Progress.
ProgressArray getProgress();
ProgressArray getProgress(const IDArray &idArray);
// Status.
STATUS status() const; STATUS status() const;
QString statusString() const; QString statusString() const;
QString editorQml();
bool running(); bool running();
signals: signals:
void statusChanged(); void statusChanged();
void progressChanged(); void progressChanged(const ProgressArray &progressArray);
void tilesChanged();
void runningChanged(); void runningChanged();
private: private:
......
#include "Command.h"
namespace nemo_interface {
Command::Command(Functor onExec) : _onExec(onExec) {}
QFuture<Command::ERROR> Command::exec() { return _onExec(); }
} // namespace nemo_interface
#ifndef COMMAND_H
#define COMMAND_H
#include <QFuture>
#include <functional>
namespace nemo_interface {
class Command {
public:
enum class ERROR {
NO_ERROR,
NETWORK_TIMEOUT,
PARAMETER_ERROR,
UNEXPECTED_SERVER_RESPONSE
};
typedef QFuture<ERROR> ReturnType;
typedef std::function<ReturnType()> Functor;
Command(Functor onExec);
QFuture<ERROR> exec();
private:
Functor _onExec;
};
} // namespace nemo_interface
#endif // COMMAND_H
#include "CommandDispatcher.h"
CommandDispatcher::CommandDispatcher()
{
}
#ifndef COMMANDDISPATCHER_H
#define COMMANDDISPATCHER_H
class CommandDispatcher
{
public:
CommandDispatcher();
};
#endif // COMMANDDISPATCHER_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment