QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SignalDataTransition.h
Go to the documentation of this file.
1#pragma once
2
4#include "QGCState.h"
5
6#include <QtStateMachine/QStateMachine>
7#include <functional>
8
11template<typename... Args>
13{
14public:
17
18 using Guard = std::function<bool(Args...)>;
19 using Action = std::function<void(Args...)>;
20
27 template<typename Sender, typename Func>
28 SignalDataTransition(const Sender* sender, Func signalFn, QAbstractState* target,
29 Guard guard = nullptr, Action action = nullptr)
30 : QGCSignalTransition(sender, signalFn)
31 , _guard(std::move(guard))
32 , _action(std::move(action))
33 {
34 setTargetState(target);
35 }
36
38 std::tuple<Args...> signalArgs() const { return _lastArgs; }
39
40protected:
41 bool eventTest(QEvent* event) override
42 {
43 if (!QGCSignalTransition::eventTest(event)) {
44 return false;
45 }
46
47 // Extract signal arguments from SignalEvent
48 auto* signalEvent = static_cast<QStateMachine::SignalEvent*>(event);
49 const QList<QVariant>& arguments = signalEvent->arguments();
50
51 // Convert QVariant list to tuple
52 _lastArgs = extractArgs(arguments, std::index_sequence_for<Args...>{});
53
54 if (_guard) {
55 bool allowed = std::apply(_guard, _lastArgs);
56 if (!allowed) {
57 qCDebug(QGCStateMachineLog) << "SignalDataTransition blocked by guard";
58 return false;
59 }
60 }
61
62 return true;
63 }
64
65 void onTransition(QEvent* event) override
66 {
67 Q_UNUSED(event);
68
69 if (_action) {
70 std::apply(_action, _lastArgs);
71 }
72 }
73
74private:
75 template<std::size_t... Is>
76 std::tuple<Args...> extractArgs(const QList<QVariant>& arguments, std::index_sequence<Is...>)
77 {
78 return std::make_tuple(
79 (Is < static_cast<std::size_t>(arguments.size())
80 ? arguments[Is].value<std::tuple_element_t<Is, std::tuple<Args...>>>()
81 : std::tuple_element_t<Is, std::tuple<Args...>>{})...
82 );
83 }
84
85 Guard _guard;
86 Action _action;
87 mutable std::tuple<Args...> _lastArgs;
88};
89
92template<typename... Args, typename Sender, typename Func>
94 const Sender* sender, Func signalFn, QAbstractState* target,
95 typename SignalDataTransition<Args...>::Guard guard = nullptr,
96 typename SignalDataTransition<Args...>::Action action = nullptr)
97{
98 return new SignalDataTransition<Args...>(sender, signalFn, target, std::move(guard), std::move(action));
99}
SignalDataTransition< Args... > * makeSignalDataTransition(const Sender *sender, Func signalFn, QAbstractState *target, typename SignalDataTransition< Args... >::Guard guard=nullptr, typename SignalDataTransition< Args... >::Action action=nullptr)
Base class for signal-based transitions that need access to QGCStateMachine and Vehicle.
SignalDataTransition(const SignalDataTransition &)=delete
SignalDataTransition(const Sender *sender, Func signalFn, QAbstractState *target, Guard guard=nullptr, Action action=nullptr)
std::tuple< Args... > signalArgs() const
Get the arguments from the last matched signal.
std::function< void(Args...)> Action
void onTransition(QEvent *event) override
SignalDataTransition & operator=(const SignalDataTransition &)=delete
std::function< bool(Args...)> Guard
bool eventTest(QEvent *event) override