annotate data/model/EventCommands.h @ 1693:718ce5fb9fec single-point

Merge
author Chris Cannam
date Thu, 25 Apr 2019 11:30:51 +0100
parents 86bbccb79c9b
children 9d82b164f264
rev   line source
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