Chris@1648
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@1648
|
2
|
Chris@1648
|
3 /*
|
Chris@1648
|
4 Sonic Visualiser
|
Chris@1648
|
5 An audio file viewer and annotation editor.
|
Chris@1648
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@1648
|
7 This file copyright 2006 Chris Cannam.
|
Chris@1648
|
8
|
Chris@1648
|
9 This program is free software; you can redistribute it and/or
|
Chris@1648
|
10 modify it under the terms of the GNU General Public License as
|
Chris@1648
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@1648
|
12 License, or (at your option) any later version. See the file
|
Chris@1648
|
13 COPYING included with this distribution for more information.
|
Chris@1648
|
14 */
|
Chris@1648
|
15
|
Chris@1648
|
16 #ifndef SV_EVENT_COMMANDS_H
|
Chris@1648
|
17 #define SV_EVENT_COMMANDS_H
|
Chris@1648
|
18
|
Chris@1648
|
19 #include "base/Event.h"
|
Chris@1648
|
20 #include "base/Command.h"
|
Chris@1648
|
21
|
Chris@1648
|
22 /**
|
Chris@1648
|
23 * Interface for classes that can be modified through these commands
|
Chris@1648
|
24 */
|
Chris@1648
|
25 class EventEditable
|
Chris@1648
|
26 {
|
Chris@1648
|
27 public:
|
Chris@1648
|
28 virtual void add(Event e) = 0;
|
Chris@1648
|
29 virtual void remove(Event e) = 0;
|
Chris@1648
|
30 };
|
Chris@1648
|
31
|
Chris@1648
|
32 /**
|
Chris@1648
|
33 * Command to add an event to an editable containing events, with undo.
|
Chris@1648
|
34 */
|
Chris@1648
|
35 class AddEventCommand : public Command
|
Chris@1648
|
36 {
|
Chris@1648
|
37 public:
|
Chris@1648
|
38 AddEventCommand(EventEditable *editable, const Event &e, QString name) :
|
Chris@1648
|
39 m_editable(editable), m_event(e), m_name(name) { }
|
Chris@1648
|
40
|
Chris@1648
|
41 QString getName() const override { return m_name; }
|
Chris@1648
|
42 Event getEvent() const { return m_event; }
|
Chris@1648
|
43
|
Chris@1648
|
44 void execute() override { m_editable->add(m_event); }
|
Chris@1648
|
45 void unexecute() override { m_editable->remove(m_event); }
|
Chris@1648
|
46
|
Chris@1648
|
47 private:
|
Chris@1648
|
48 EventEditable *m_editable;
|
Chris@1648
|
49 Event m_event;
|
Chris@1648
|
50 QString m_name;
|
Chris@1648
|
51 };
|
Chris@1648
|
52
|
Chris@1648
|
53 /**
|
Chris@1648
|
54 * Command to remove an event from an editable containing events, with
|
Chris@1648
|
55 * undo.
|
Chris@1648
|
56 */
|
Chris@1648
|
57 class RemoveEventCommand : public Command
|
Chris@1648
|
58 {
|
Chris@1648
|
59 public:
|
Chris@1648
|
60 RemoveEventCommand(EventEditable *editable, const Event &e, QString name) :
|
Chris@1648
|
61 m_editable(editable), m_event(e), m_name(name) { }
|
Chris@1648
|
62
|
Chris@1648
|
63 QString getName() const override { return m_name; }
|
Chris@1648
|
64 Event getEvent() const { return m_event; }
|
Chris@1648
|
65
|
Chris@1648
|
66 void execute() override { m_editable->remove(m_event); }
|
Chris@1648
|
67 void unexecute() override { m_editable->add(m_event); }
|
Chris@1648
|
68
|
Chris@1648
|
69 private:
|
Chris@1648
|
70 EventEditable *m_editable;
|
Chris@1648
|
71 Event m_event;
|
Chris@1648
|
72 QString m_name;
|
Chris@1648
|
73 };
|
Chris@1648
|
74
|
Chris@1648
|
75 /**
|
Chris@1648
|
76 * Command to add or remove a series of events to or from an editable,
|
Chris@1648
|
77 * with undo. Creates and immediately executes a sub-command for each
|
Chris@1648
|
78 * add/remove requested. Consecutive add/remove pairs for the same
|
Chris@1648
|
79 * point are collapsed.
|
Chris@1648
|
80 */
|
Chris@1648
|
81 class ChangeEventsCommand : public MacroCommand
|
Chris@1648
|
82 {
|
Chris@1648
|
83 public:
|
Chris@1648
|
84 ChangeEventsCommand(EventEditable *editable, QString name) :
|
Chris@1648
|
85 MacroCommand(name), m_editable(editable) { }
|
Chris@1648
|
86
|
Chris@1648
|
87 void add(Event e) {
|
Chris@1648
|
88 addCommand(new AddEventCommand(m_editable, e, getName()), true);
|
Chris@1648
|
89 }
|
Chris@1648
|
90 void remove(Event e) {
|
Chris@1648
|
91 addCommand(new RemoveEventCommand(m_editable, e, getName()), true);
|
Chris@1648
|
92 }
|
Chris@1648
|
93
|
Chris@1648
|
94 /**
|
Chris@1648
|
95 * Stack an arbitrary other command in the same sequence.
|
Chris@1648
|
96 */
|
Chris@1648
|
97 void addCommand(Command *command) override { addCommand(command, true); }
|
Chris@1648
|
98
|
Chris@1648
|
99 /**
|
Chris@1648
|
100 * If any points have been added or deleted, return this
|
Chris@1648
|
101 * command (so the caller can add it to the command history).
|
Chris@1648
|
102 * Otherwise delete the command and return NULL.
|
Chris@1648
|
103 */
|
Chris@1648
|
104 ChangeEventsCommand *finish() {
|
Chris@1648
|
105 if (!m_commands.empty()) {
|
Chris@1648
|
106 return this;
|
Chris@1648
|
107 } else {
|
Chris@1648
|
108 delete this;
|
Chris@1648
|
109 return nullptr;
|
Chris@1648
|
110 }
|
Chris@1648
|
111 }
|
Chris@1648
|
112
|
Chris@1648
|
113 protected:
|
Chris@1648
|
114 virtual void addCommand(Command *command, bool executeFirst) {
|
Chris@1648
|
115
|
Chris@1648
|
116 if (executeFirst) command->execute();
|
Chris@1648
|
117
|
Chris@1648
|
118 if (m_commands.empty()) {
|
Chris@1648
|
119 MacroCommand::addCommand(command);
|
Chris@1648
|
120 return;
|
Chris@1648
|
121 }
|
Chris@1648
|
122
|
Chris@1648
|
123 RemoveEventCommand *r =
|
Chris@1648
|
124 dynamic_cast<RemoveEventCommand *>(command);
|
Chris@1648
|
125 AddEventCommand *a =
|
Chris@1648
|
126 dynamic_cast<AddEventCommand *>(*m_commands.rbegin());
|
Chris@1648
|
127 if (r && a) {
|
Chris@1648
|
128 if (a->getEvent() == r->getEvent()) {
|
Chris@1648
|
129 deleteCommand(a);
|
Chris@1648
|
130 return;
|
Chris@1648
|
131 }
|
Chris@1648
|
132 }
|
Chris@1648
|
133
|
Chris@1648
|
134 MacroCommand::addCommand(command);
|
Chris@1648
|
135 }
|
Chris@1648
|
136
|
Chris@1648
|
137 EventEditable *m_editable;
|
Chris@1648
|
138 };
|
Chris@1648
|
139
|
Chris@1648
|
140 #endif
|