Mercurial > hg > svcore
diff data/model/EventCommands.h @ 1648:86bbccb79c9b single-point
Switch to a single external set of commands for modifying editables with events
author | Chris Cannam |
---|---|
date | Fri, 15 Mar 2019 10:57:35 +0000 |
parents | |
children | 9d82b164f264 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/EventCommands.h Fri Mar 15 10:57:35 2019 +0000 @@ -0,0 +1,140 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006 Chris Cannam. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef SV_EVENT_COMMANDS_H +#define SV_EVENT_COMMANDS_H + +#include "base/Event.h" +#include "base/Command.h" + +/** + * Interface for classes that can be modified through these commands + */ +class EventEditable +{ +public: + virtual void add(Event e) = 0; + virtual void remove(Event e) = 0; +}; + +/** + * Command to add an event to an editable containing events, with undo. + */ +class AddEventCommand : public Command +{ +public: + AddEventCommand(EventEditable *editable, const Event &e, QString name) : + m_editable(editable), m_event(e), m_name(name) { } + + QString getName() const override { return m_name; } + Event getEvent() const { return m_event; } + + void execute() override { m_editable->add(m_event); } + void unexecute() override { m_editable->remove(m_event); } + +private: + EventEditable *m_editable; + Event m_event; + QString m_name; +}; + +/** + * Command to remove an event from an editable containing events, with + * undo. + */ +class RemoveEventCommand : public Command +{ +public: + RemoveEventCommand(EventEditable *editable, const Event &e, QString name) : + m_editable(editable), m_event(e), m_name(name) { } + + QString getName() const override { return m_name; } + Event getEvent() const { return m_event; } + + void execute() override { m_editable->remove(m_event); } + void unexecute() override { m_editable->add(m_event); } + +private: + EventEditable *m_editable; + Event m_event; + QString m_name; +}; + +/** + * Command to add or remove a series of events to or from an editable, + * with undo. Creates and immediately executes a sub-command for each + * add/remove requested. Consecutive add/remove pairs for the same + * point are collapsed. + */ +class ChangeEventsCommand : public MacroCommand +{ +public: + ChangeEventsCommand(EventEditable *editable, QString name) : + MacroCommand(name), m_editable(editable) { } + + void add(Event e) { + addCommand(new AddEventCommand(m_editable, e, getName()), true); + } + void remove(Event e) { + addCommand(new RemoveEventCommand(m_editable, e, getName()), true); + } + + /** + * Stack an arbitrary other command in the same sequence. + */ + void addCommand(Command *command) override { addCommand(command, true); } + + /** + * If any points have been added or deleted, return this + * command (so the caller can add it to the command history). + * Otherwise delete the command and return NULL. + */ + ChangeEventsCommand *finish() { + if (!m_commands.empty()) { + return this; + } else { + delete this; + return nullptr; + } + } + +protected: + virtual void addCommand(Command *command, bool executeFirst) { + + if (executeFirst) command->execute(); + + if (m_commands.empty()) { + MacroCommand::addCommand(command); + return; + } + + RemoveEventCommand *r = + dynamic_cast<RemoveEventCommand *>(command); + AddEventCommand *a = + dynamic_cast<AddEventCommand *>(*m_commands.rbegin()); + if (r && a) { + if (a->getEvent() == r->getEvent()) { + deleteCommand(a); + return; + } + } + + MacroCommand::addCommand(command); + } + + EventEditable *m_editable; +}; + +#endif