Mercurial > hg > svcore
changeset 1741:9d82b164f264 by-id
Work on commands, and some other model updates
author | Chris Cannam |
---|---|
date | Thu, 27 Jun 2019 13:08:10 +0100 |
parents | fe3f7f8df3a3 |
children | 52705a328b34 |
files | data/model/EventCommands.h data/model/ImageModel.h data/model/Labeller.h data/model/Model.h data/model/NoteModel.h data/model/Path.h data/model/RegionModel.h data/model/SparseOneDimensionalModel.h data/model/SparseTimeValueModel.h data/model/TextModel.h data/model/test/TestSparseModels.h |
diffstat | 11 files changed, 113 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/data/model/EventCommands.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/EventCommands.h Thu Jun 27 13:08:10 2019 +0100 @@ -18,6 +18,7 @@ #include "base/Event.h" #include "base/Command.h" +#include "base/ById.h" /** * Interface for classes that can be modified through these commands @@ -29,66 +30,111 @@ virtual void remove(Event e) = 0; }; +template <typename Base> +class WithEditable +{ + typedef typename Base::Id Id; + Id m_id; + +protected: + WithEditable(Id id) : m_id(id) { } + + std::shared_ptr<EventEditable> getEditable() { + auto base = StaticById<Base, Id>::get(m_id); + if (!base) return {}; // acceptable - item has expired + auto editable = std::dynamic_pointer_cast<EventEditable>(base); + if (!editable) { + SVCERR << "WARNING: Id passed to EventEditable command is not that of an EventEditable" << endl; + } + return editable; + } +}; + /** - * Command to add an event to an editable containing events, with undo. + * Command to add an event to an editable containing events, with + * undo. The template parameter must be a type that can be + * dynamic_cast to EventEditable and that has a ById store. */ -class AddEventCommand : public Command +template <typename Base> +class AddEventCommand : public Command, + public WithEditable<Base> { public: - AddEventCommand(EventEditable *editable, const Event &e, QString name) : - m_editable(editable), m_event(e), m_name(name) { } + AddEventCommand(typename Base::Id editable, const Event &e, QString name) : + WithEditable<Base>(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); } + void execute() override { + auto editable = getEditable(); + if (editable) editable->add(m_event); + } + void unexecute() override { + auto editable = getEditable(); + if (editable) editable->remove(m_event); + } private: - EventEditable *m_editable; Event m_event; QString m_name; + using WithEditable<Base>::getEditable; }; /** * Command to remove an event from an editable containing events, with - * undo. + * undo. The template parameter must be a type that implements + * EventBase and that has a ById store. */ -class RemoveEventCommand : public Command +template <typename Base> +class RemoveEventCommand : public Command, + public WithEditable<Base> { public: - RemoveEventCommand(EventEditable *editable, const Event &e, QString name) : - m_editable(editable), m_event(e), m_name(name) { } + RemoveEventCommand(typename Base::Id editable, const Event &e, QString name) : + WithEditable<Base>(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); } + void execute() override { + auto editable = getEditable(); + if (editable) editable->remove(m_event); + } + void unexecute() override { + auto editable = getEditable(); + if (editable) editable->add(m_event); + } private: - EventEditable *m_editable; Event m_event; QString m_name; + using WithEditable<Base>::getEditable; }; /** * 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. + * point are collapsed. The template parameter must be a type that + * implements EventBase and that has a ById store. */ +template <typename Base> class ChangeEventsCommand : public MacroCommand { + typedef typename Base::Id Id; + public: - ChangeEventsCommand(EventEditable *editable, QString name) : + ChangeEventsCommand(Id editable, QString name) : MacroCommand(name), m_editable(editable) { } void add(Event e) { - addCommand(new AddEventCommand(m_editable, e, getName()), true); + addCommand(new AddEventCommand<Base>(m_editable, e, getName()), + true); } void remove(Event e) { - addCommand(new RemoveEventCommand(m_editable, e, getName()), true); + addCommand(new RemoveEventCommand<Base>(m_editable, e, getName()), + true); } /** @@ -120,10 +166,10 @@ return; } - RemoveEventCommand *r = - dynamic_cast<RemoveEventCommand *>(command); - AddEventCommand *a = - dynamic_cast<AddEventCommand *>(*m_commands.rbegin()); + RemoveEventCommand<Base> *r = + dynamic_cast<RemoveEventCommand<Base> *>(command); + AddEventCommand<Base> *a = + dynamic_cast<AddEventCommand<Base> *>(*m_commands.rbegin()); if (r && a) { if (a->getEvent() == r->getEvent()) { deleteCommand(a); @@ -134,7 +180,7 @@ MacroCommand::addCommand(command); } - EventEditable *m_editable; + Id m_editable; }; #endif
--- a/data/model/ImageModel.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/ImageModel.h Thu Jun 27 13:08:10 2019 +0100 @@ -231,8 +231,7 @@ case 3: e1 = e0.withLabel(value.toString()); break; } - ChangeEventsCommand *command = - new ChangeEventsCommand(this, tr("Edit Data")); + auto command = new ChangeEventsCommand<Model>(getId(), tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish();
--- a/data/model/Labeller.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/Labeller.h Thu Jun 27 13:08:10 2019 +0100 @@ -225,13 +225,16 @@ * Relabel all events in the given event vector that lie within * the given multi-selection, according to the labelling * properties of this labeller. Return a command that has been - * executed but not yet added to the history. + * executed but not yet added to the history. The template + * parameter must be a type that can be dynamic_cast to + * EventEditable and that has a ById store. */ - Command *labelAll(EventEditable *editable, + template <typename EditableBase> + Command *labelAll(typename EditableBase::Id editable, MultiSelection *ms, const EventVector &allEvents) { - ChangeEventsCommand *command = new ChangeEventsCommand + auto command = new ChangeEventsCommand<EditableBase> (editable, tr("Label Points")); Event prev; @@ -270,14 +273,17 @@ * that event lies within the given multi-selection, add n-1 new * events at equally spaced intervals between it and the following * event. Return a command that has been executed but not yet - * added to the history. + * added to the history. The template parameter must be a type + * that can be dynamic_cast to EventEditable and that has a ById + * store. */ - Command *subdivide(EventEditable *editable, + template <typename EditableBase> + Command *subdivide(typename EditableBase::Id editable, MultiSelection *ms, const EventVector &allEvents, int n) { - ChangeEventsCommand *command = new ChangeEventsCommand + auto command = new ChangeEventsCommand<EditableBase> (editable, tr("Subdivide Points")); for (auto i = allEvents.begin(); i != allEvents.end(); ++i) { @@ -319,14 +325,17 @@ * multi-selection, and a number n, remove all but every nth event * from the vector within the extents of the multi-selection. * Return a command that has been executed but not yet added to - * the history. + * the history. The template parameter must be a type + * that can be dynamic_cast to EventEditable and that has a ById + * store. */ - Command *winnow(EventEditable *editable, + template <typename EditableBase> + Command *winnow(typename EditableBase::Id editable, MultiSelection *ms, const EventVector &allEvents, int n) { - ChangeEventsCommand *command = new ChangeEventsCommand + auto command = new ChangeEventsCommand<EditableBase> (editable, tr("Winnow Points")); int counter = 0;
--- a/data/model/Model.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/Model.h Thu Jun 27 13:08:10 2019 +0100 @@ -362,7 +362,7 @@ sv_frame_t m_extendTo; }; -typedef Model::ModelId ModelId; -typedef StaticById<Model, ModelId> ModelById; +typedef Model::Id ModelId; +typedef StaticById<Model, Model::Id> ModelById; #endif
--- a/data/model/NoteModel.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/NoteModel.h Thu Jun 27 13:08:10 2019 +0100 @@ -308,8 +308,7 @@ case 5: e1 = e0.withLabel(value.toString()); break; } - ChangeEventsCommand *command = - new ChangeEventsCommand(this, tr("Edit Data")); + auto command = new ChangeEventsCommand<Model>(getId(), tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish();
--- a/data/model/Path.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/Path.h Thu Jun 27 13:08:10 2019 +0100 @@ -96,6 +96,16 @@ // For historical reasons we serialise a Path as a model, // although the class itself no longer is. + + // We also write start and end frames - which our API no + // longer exposes - just for backward compatibility + + sv_frame_t start = 0; + sv_frame_t end = 0; + if (!m_points.empty()) { + start = m_points.begin()->frame; + end = m_points.rbegin()->frame + m_resolution; + } // Our dataset doesn't have its own export ID, we just use // ours. Actually any model could do that, since datasets @@ -104,11 +114,14 @@ out << indent; out << QString("<model id=\"%1\" name=\"\" sampleRate=\"%2\" " - "type=\"sparse\" dimensions=\"2\" resolution=\"%3\" " - "notifyOnAdd=\"true\" dataset=\"%4\" " - "subtype=\"path\" %5/>\n") + "start=\"%3\" end=\"%4\" type=\"sparse\" " + "dimensions=\"2\" resolution=\"%5\" " + "notifyOnAdd=\"true\" dataset=\"%6\" " + "subtype=\"path\" %7/>\n") .arg(getExportId()) .arg(m_sampleRate) + .arg(start) + .arg(end) .arg(m_resolution) .arg(getExportId()) .arg(extraAttributes);
--- a/data/model/RegionModel.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/RegionModel.h Thu Jun 27 13:08:10 2019 +0100 @@ -291,8 +291,7 @@ case 4: e1 = e0.withLabel(value.toString()); break; } - ChangeEventsCommand *command = - new ChangeEventsCommand(this, tr("Edit Data")); + auto command = new ChangeEventsCommand<Model>(getId(), tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish();
--- a/data/model/SparseOneDimensionalModel.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/SparseOneDimensionalModel.h Thu Jun 27 13:08:10 2019 +0100 @@ -239,8 +239,7 @@ case 2: e1 = e0.withLabel(value.toString()); break; } - ChangeEventsCommand *command = - new ChangeEventsCommand(this, tr("Edit Data")); + auto command = new ChangeEventsCommand<Model>(getId(), tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish();
--- a/data/model/SparseTimeValueModel.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/SparseTimeValueModel.h Thu Jun 27 13:08:10 2019 +0100 @@ -289,8 +289,7 @@ case 3: e1 = e0.withLabel(value.toString()); break; } - ChangeEventsCommand *command = - new ChangeEventsCommand(this, tr("Edit Data")); + auto command = new ChangeEventsCommand<Model>(getId(), tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish();
--- a/data/model/TextModel.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/TextModel.h Thu Jun 27 13:08:10 2019 +0100 @@ -226,8 +226,7 @@ case 3: e1 = e0.withLabel(value.toString()); break; } - ChangeEventsCommand *command = - new ChangeEventsCommand(this, tr("Edit Data")); + auto command = new ChangeEventsCommand<Model>(getId(), tr("Edit Data")); command->remove(e0); command->add(e1); return command->finish();
--- a/data/model/test/TestSparseModels.h Wed Jun 26 17:25:20 2019 +0100 +++ b/data/model/test/TestSparseModels.h Thu Jun 27 13:08:10 2019 +0100 @@ -18,7 +18,7 @@ #include "../SparseOneDimensionalModel.h" #include "../NoteModel.h" #include "../TextModel.h" -#include "../PathModel.h" +#include "../Path.h" #include "../ImageModel.h" #include <QObject> @@ -252,7 +252,7 @@ } void path_xml() { - PathModel m(100, 10, false); + Path m(100, 10); PathPoint p1(20, 30); PathPoint p2(40, 60); PathPoint p3(50, 49);