-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathFSMScene.h
311 lines (259 loc) · 7.81 KB
/
FSMScene.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#pragma once
#include <QGraphicsScene>
#include <fsm-editor/model/Graph.h>
#include <functional>
class QUndoCommand;
class State;
class Transition;
class FSMElement;
class ExportVisitor;
class QAction;
class QTextStream;
/**
* @brief FSMScene displays the graph.
*
* It manipulates both the graphical components and the model.
* It is bad architecture, but it is the standard one in Qt.
*/
class FSMScene : public QGraphicsScene
{
Q_OBJECT;
using super = QGraphicsScene;
public:
FSMScene();
/**
* Set the custom name validator, passed by the settings.
*/
void setNameValidator(std::function<QString(const QString&)> stateValidator);
/**
* Set the custom code validator, passed by the settings.
*/
void setCodeValidator(std::function<QString(const QString&)> codeValidator);
/**
* Set the writer used by copy method to create string version of clipboard copy.
*/
void setCopyWriter(std::function<void(Graph&&, QTextStream&)> copyWriter);
/**
* Overrides double click handling, to create a state when double clicking.
*/
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
/**
* Push a command in the undo/redo stack.
*/
void pushCommand(QUndoCommand* command);
/**
* Signal emitted when a command was pushed.
*/
Q_SIGNAL void command(QUndoCommand* command);
/**
* Signal emitted when multiple commands are going to be pushed,
* that are going to be squashed together.
*/
Q_SIGNAL void openCommandGroup(const QString& title);
/**
* Signal emitted after multiple commands were pushed,
* that should be squashed together.
*/
Q_SIGNAL void closeCommandGroup();
/**
* Signal emitted when the current code is changed.
*/
Q_SIGNAL void codeChanged(const QString& code, const QString& error);
/**
* Signal emitted when the current code is hidden.
*/
Q_SIGNAL void codeHidden();
/**
* Signal emitted when switching to scroll mode.
*/
Q_SIGNAL void switchScrollMode(bool on);
/**
* Signal emitted when zooming in/out.
*/
Q_SIGNAL void zoomed(int delta);
/**
* Get a state by its name.
*/
State* getState(const QString& name) const;
/**
* Get any graph element by its name.
*/
FSMElement* getElement(const QString& name) const;
/**
* Get a transition by its name.
*/
Transition* getTransition(const QString& name) const;
/**
* Change the name of the state, creating an undo command.
*/
QString renameState(State* state, const QString& newName);
/**
* Sets the current element and its code without triggering the undo/redo stack.
* Used when changing the selection or when undo/redo is already handled otherwise.
*/
void setCode(FSMElement* element, const QString& code);
/**
* Change the code of the selection, passing through the undo/redo stack.
*/
void updateCode(const QString& code);
/**
* Select an element by its name.
*/
void selectElement(const QString& element);
/**
* Sets the selection to this item only and give it focus.
*/
void setSelectedItem(QGraphicsItem* item);
/**
* @return The state the graph starts with.
*/
State* getStartState() const;
/**
* Set the state the graph starts with.
*/
void setStartState(State* start);
/**
* @return An action allowing to set selected state as start state.
*/
QAction* getStartAction() const;
/**
* @return An action deleting the selection.
*/
QAction* getDeleteAction() const;
/**
* @return An action renaming the selection.
*/
QAction* getRenameAction() const;
/**
* Classes outside the QGraphicsScene should handle model objects,
* not directly the graphics item. We want to be able to change the
* architecture in the future.
* @return model version of the graph.
*/
Graph graph() const;
/**
* Replaces current graph with the passed one.
*/
void setNewGraph(Graph&& graph);
/**
* Copy selection to the clipboard both as an internal format graph and
* as a string using the FSMWriter.
*/
Q_SLOT void copy();
/**
* Copy selection to the clipboard both as an internal format graph and
* as a string using the FSMWriter, then delete it from the scene.
*/
Q_SLOT void cut();
/**
* Paste the clipboard content if it contains a graph.
*/
Q_SLOT void paste();
/**
* Delete selected states and transitions.
*/
Q_SLOT void deleteSelection();
/**
* Rename the first selected element.
*/
Q_SLOT void askRenameSelection();
/**
* @return The first element in error if any. nullptr otherwise.
*/
FSMElement* getErrorElement() const;
public:
/**
* Ids used by the QUndoCommands to merge some changes.
*/
enum UNDO_IDS
{
UNDO_MOVE = 1,
UNDO_CODE = 2
};
protected:
virtual void wheelEvent(QGraphicsSceneWheelEvent *event) override;
private:
friend class AddStateCommand;
friend class DeleteStateCommand;
friend class RenameState;
friend class StartStateCommand;
/**
* Method called only by the undo commands, don't call it directly.
* Creates a new state in the scene.
*/
State* addState(const QString& name, const QPointF& pos);
/**
* Method called only by the undo commands, don't call it directly.
* Remove a state by its name.
*/
void removeState(const QString& name);
/**
* Method called only by the undo commands, don't call it directly.
*/
void changeStartState(State* start);
/**
* Method called only by the undo commands, to modify the state name.
*/
void setStateName(State* state, const QString& name);
/**
* Slot method called by start action.
*/
Q_SLOT void setSelectionAsStartState();
/**
* Update internal state on selection change.
*/
Q_SLOT void checkSelection();
/**
* Clear everything in the scene and memory.
*/
void clearAll();
/**
* Read a graph and output it in a output stream.
*/
void writeGraph(QDataStream& out, const Graph& graph);
/**
* Create a subgraph from an input stream.
*/
void readGraph(QDataStream& in);
/**
* Create a transition from an input stream.
*/
void readTransition(QDataStream& in, QMap<QString, QString> &names);
/**
* Replace name if it is contained in the dictionary.
*/
QString replaceNameIfNeeded(QMap<QString, QString>& names, const QString& inputName);
/**
* Create a state from an input stream.
*/
void readState(QDataStream& in, QMap<QString, QString> &names);
/**
* Copy the selection in a model graph.
*/
Graph copyGraph() const;
void copySelectedTransitions(std::list<std::unique_ptr<GraphTransition>> &everyTransitions) const;
void copySelectedStates(std::list<std::unique_ptr<GraphState>> &everyStates) const;
QString copyTextVersion(Graph&& selection);
void fillSelectionLists(QList<State*> &deletedStates, QList<Transition*> &deletedTransitions);
/**
* Open an input dialog and call rename on the state if input text is a valid name.
*/
void askRename(State* state);
void deleteSelectionLists(QList<State*> &deletedStates, QList<Transition*> &deletedTransitions);
private:
static int index;
static const QColor BACKGROUND_COLOR;
static const QString STATE_STR;
static const QString TRANSITION_STR;
private:
std::map<QString, State*> states_;
std::function<QString(const QString&)> stateValidator_;
std::function<void(Graph&&, QTextStream&)> copyWriter_;
std::function<QString(const QString&)> codeValidator_;
State* startingState_;
FSMElement* editingElement_;
QAction* startAct_;
QAction* deleteAct_;
QAction* renameAct_;
QPointF pressPos_;
};