1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qeventtransition.h" |
5 | #include "qeventtransition_p.h" |
6 | #include "qstate.h" |
7 | #include "qstate_p.h" |
8 | #include "qstatemachine.h" |
9 | #include "qstatemachine_p.h" |
10 | #include <qdebug.h> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | /*! |
15 | \class QEventTransition |
16 | \inmodule QtStateMachine |
17 | |
18 | \brief The QEventTransition class provides a QObject-specific transition for Qt events. |
19 | |
20 | \since 4.6 |
21 | \ingroup statemachine |
22 | |
23 | A QEventTransition object binds an event to a particular QObject. |
24 | QEventTransition is part of \l{Qt State Machine Overview}{Qt State Machine Framework}. |
25 | |
26 | Example: |
27 | |
28 | \code |
29 | QPushButton *button = ...; |
30 | QState *s1 = ...; |
31 | QState *s2 = ...; |
32 | // If in s1 and the button receives an Enter event, transition to s2 |
33 | QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter); |
34 | enterTransition->setTargetState(s2); |
35 | s1->addTransition(enterTransition); |
36 | // If in s2 and the button receives an Exit event, transition back to s1 |
37 | QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave); |
38 | leaveTransition->setTargetState(s1); |
39 | s2->addTransition(leaveTransition); |
40 | \endcode |
41 | |
42 | \section1 Subclassing |
43 | |
44 | When reimplementing the eventTest() function, you should first call the base |
45 | implementation to verify that the event is a QStateMachine::WrappedEvent for |
46 | the proper object and event type. You may then cast the event to a |
47 | QStateMachine::WrappedEvent and get the original event by calling |
48 | QStateMachine::WrappedEvent::event(), and perform additional checks on that |
49 | object. |
50 | |
51 | \sa QState::addTransition() |
52 | */ |
53 | |
54 | /*! |
55 | \property QEventTransition::eventSource |
56 | |
57 | \brief the event source that this event transition is associated with |
58 | */ |
59 | |
60 | /*! |
61 | \property QEventTransition::eventType |
62 | |
63 | \brief the type of event that this event transition is associated with |
64 | */ |
65 | |
66 | QEventTransitionPrivate::~QEventTransitionPrivate() |
67 | { |
68 | } |
69 | |
70 | void QEventTransitionPrivate::unregister() |
71 | { |
72 | Q_Q(QEventTransition); |
73 | if (!registered || !machine()) |
74 | return; |
75 | QStateMachinePrivate::get(q: machine())->unregisterEventTransition(transition: q); |
76 | } |
77 | |
78 | void QEventTransitionPrivate::maybeRegister() |
79 | { |
80 | Q_Q(QEventTransition); |
81 | if (QStateMachine *mach = machine()) |
82 | QStateMachinePrivate::get(q: mach)->maybeRegisterEventTransition(transition: q); |
83 | } |
84 | |
85 | /*! |
86 | Constructs a new QEventTransition object with the given \a sourceState. |
87 | */ |
88 | QEventTransition::QEventTransition(QState *sourceState) |
89 | : QAbstractTransition(*new QEventTransitionPrivate, sourceState) |
90 | { |
91 | } |
92 | |
93 | /*! |
94 | Constructs a new QEventTransition object associated with events of the given |
95 | \a type for the given \a object, and with the given \a sourceState. |
96 | */ |
97 | QEventTransition::QEventTransition(QObject *object, QEvent::Type type, |
98 | QState *sourceState) |
99 | : QAbstractTransition(*new QEventTransitionPrivate, sourceState) |
100 | { |
101 | Q_D(QEventTransition); |
102 | d->registered = false; |
103 | d->object.setValueBypassingBindings(object); |
104 | d->eventType.setValueBypassingBindings(type); |
105 | d->maybeRegister(); |
106 | } |
107 | |
108 | /*! |
109 | \internal |
110 | */ |
111 | QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) |
112 | : QAbstractTransition(dd, parent) |
113 | { |
114 | } |
115 | |
116 | /*! |
117 | \internal |
118 | */ |
119 | QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, |
120 | QEvent::Type type, QState *parent) |
121 | : QAbstractTransition(dd, parent) |
122 | { |
123 | Q_D(QEventTransition); |
124 | d->registered = false; |
125 | d->object.setValueBypassingBindings(object); |
126 | d->eventType.setValueBypassingBindings(type); |
127 | d->maybeRegister(); |
128 | } |
129 | |
130 | /*! |
131 | Destroys this QObject event transition. |
132 | */ |
133 | QEventTransition::~QEventTransition() |
134 | { |
135 | } |
136 | |
137 | /*! |
138 | Returns the event type that this event transition is associated with. |
139 | */ |
140 | QEvent::Type QEventTransition::eventType() const |
141 | { |
142 | Q_D(const QEventTransition); |
143 | return d->eventType; |
144 | } |
145 | |
146 | /*! |
147 | Sets the event \a type that this event transition is associated with. |
148 | */ |
149 | void QEventTransition::setEventType(QEvent::Type type) |
150 | { |
151 | Q_D(QEventTransition); |
152 | if (d->eventType.value() == type) { |
153 | d->eventType.removeBindingUnlessInWrapper(); |
154 | return; |
155 | } |
156 | d->unregister(); |
157 | d->eventType = type; |
158 | d->maybeRegister(); |
159 | d->eventType.notify(); |
160 | } |
161 | |
162 | QBindable<QEvent::Type> QEventTransition::bindableEventType() |
163 | { |
164 | Q_D(QEventTransition); |
165 | return &d->eventType; |
166 | } |
167 | |
168 | /*! |
169 | Returns the event source associated with this event transition. |
170 | */ |
171 | QObject *QEventTransition::eventSource() const |
172 | { |
173 | Q_D(const QEventTransition); |
174 | return d->object; |
175 | } |
176 | |
177 | /*! |
178 | Sets the event source associated with this event transition to be the given |
179 | \a object. |
180 | */ |
181 | void QEventTransition::setEventSource(QObject *object) |
182 | { |
183 | Q_D(QEventTransition); |
184 | if (d->object.value() == object) { |
185 | d->object.removeBindingUnlessInWrapper(); |
186 | return; |
187 | } |
188 | d->unregister(); |
189 | d->object = object; |
190 | d->maybeRegister(); |
191 | d->object.notify(); |
192 | } |
193 | |
194 | QBindable<QObject*> QEventTransition::bindableEventSource() |
195 | { |
196 | Q_D(QEventTransition); |
197 | return &d->object; |
198 | } |
199 | |
200 | /*! |
201 | \reimp |
202 | */ |
203 | bool QEventTransition::eventTest(QEvent *event) |
204 | { |
205 | Q_D(const QEventTransition); |
206 | if (event->type() == QEvent::StateMachineWrapped) { |
207 | QStateMachine::WrappedEvent *we = static_cast<QStateMachine::WrappedEvent*>(event); |
208 | return (we->object() == d->object) |
209 | && (we->event()->type() == d->eventType.value()); |
210 | } |
211 | return false; |
212 | } |
213 | |
214 | /*! |
215 | \reimp |
216 | */ |
217 | void QEventTransition::onTransition(QEvent *event) |
218 | { |
219 | Q_UNUSED(event); |
220 | } |
221 | |
222 | /*! |
223 | \reimp |
224 | */ |
225 | bool QEventTransition::event(QEvent *e) |
226 | { |
227 | return QAbstractTransition::event(e); |
228 | } |
229 | |
230 | QT_END_NAMESPACE |
231 | |
232 | #include "moc_qeventtransition.cpp" |
233 | |