# HG changeset patch # User Chris Cannam # Date 1552647455 0 # Node ID 86bbccb79c9bcbb59bfdaf557053560322c7d514 # Parent 29a20719796e578564b43db937dcae21167be53c Switch to a single external set of commands for modifying editables with events diff -r 29a20719796e -r 86bbccb79c9b data/model/EventCommands.h --- /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(command); + AddEventCommand *a = + dynamic_cast(*m_commands.rbegin()); + if (r && a) { + if (a->getEvent() == r->getEvent()) { + deleteCommand(a); + return; + } + } + + MacroCommand::addCommand(command); + } + + EventEditable *m_editable; +}; + +#endif diff -r 29a20719796e -r 86bbccb79c9b data/model/NoteModel.h --- a/data/model/NoteModel.h Thu Mar 14 15:31:59 2019 +0000 +++ b/data/model/NoteModel.h Fri Mar 15 10:57:35 2019 +0000 @@ -18,6 +18,7 @@ #include "Model.h" #include "TabularModel.h" +#include "EventCommands.h" #include "base/UnitDatabase.h" #include "base/EventSeries.h" #include "base/NoteData.h" @@ -32,7 +33,8 @@ class NoteModel : public Model, public TabularModel, - public NoteExportable + public NoteExportable, + public EventEditable { Q_OBJECT @@ -192,67 +194,9 @@ } /** - * Editing commands and methods. + * Editing methods. */ - - class EditCommand : public Command - { - public: - //!!! borrowed ptr - EditCommand(NoteModel *model, QString name) : - m_model(model), m_executed(false), m_name(name) { } - - QString getName() const override { - return m_name; - } - - void setName(QString name) { - m_name = name; - } - - void add(Event e) { - m_adding.insert(e); - m_model->add(e); - m_executed = true; - } - - void remove(Event e) { - m_removing.insert(e); - m_model->remove(e); - m_executed = true; - } - - void execute() override { - if (m_executed) return; - for (const Event &e: m_adding) m_model->add(e); - for (const Event &e: m_removing) m_model->remove(e); - m_executed = true; - } - - void unexecute() override { - for (const Event &e: m_removing) m_model->add(e); - for (const Event &e: m_adding) m_model->remove(e); - m_executed = false; - } - - EditCommand *finish() { - if (m_adding.empty() && m_removing.empty()) { - delete this; - return nullptr; - } else { - return this; - } - } - - private: - NoteModel *m_model; - bool m_executed; - std::set m_adding; - std::set m_removing; - QString m_name; - }; - - void add(Event e) { + void add(Event e) override { bool allChange = false; @@ -293,7 +237,7 @@ } } - void remove(Event e) { + void remove(Event e) override { { QMutexLocker locker(&m_mutex); m_events.remove(e); @@ -381,7 +325,8 @@ case 5: e1 = e0.withLabel(value.toString()); break; } - EditCommand *command = new EditCommand(this, tr("Edit Data")); + ChangeEventsCommand *command = + new ChangeEventsCommand(this, tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish(); diff -r 29a20719796e -r 86bbccb79c9b files.pri --- a/files.pri Thu Mar 14 15:31:59 2019 +0000 +++ b/files.pri Fri Mar 15 10:57:35 2019 +0000 @@ -80,6 +80,7 @@ data/model/DenseThreeDimensionalModel.h \ data/model/DenseTimeValueModel.h \ data/model/EditableDenseThreeDimensionalModel.h \ + data/model/EventCommands.h \ data/model/FFTModel.h \ data/model/ImageModel.h \ data/model/IntervalModel.h \