SparseOneDimensionalModel.h
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 #ifndef SV_SPARSE_ONE_DIMENSIONAL_MODEL_H
16 #define SV_SPARSE_ONE_DIMENSIONAL_MODEL_H
17 
18 #include "EventCommands.h"
19 #include "TabularModel.h"
20 #include "Model.h"
21 #include "DeferredNotifier.h"
22 
23 #include "base/NoteData.h"
24 #include "base/EventSeries.h"
25 #include "base/NoteExportable.h"
27 #include "base/RealTime.h"
28 
29 #include "system/System.h"
30 
31 #include <QStringList>
32 
38  public TabularModel,
39  public EventEditable,
40  public NoteExportable
41 {
42  Q_OBJECT
43 
44 public:
46  int resolution,
47  bool notifyOnAdd = true) :
48  m_sampleRate(sampleRate),
49  m_resolution(resolution),
50  m_haveTextLabels(false),
51  m_notifier(this,
52  getId(),
53  notifyOnAdd ?
54  DeferredNotifier::NOTIFY_ALWAYS :
55  DeferredNotifier::NOTIFY_DEFERRED),
56  m_completion(100) {
58  (getId().untyped, this);
59  }
60 
63  (getId().untyped);
64  }
65 
66  QString getTypeName() const override { return tr("Sparse 1-D"); }
67  bool isSparse() const override { return true; }
68  bool isOK() const override { return true; }
69 
70  sv_frame_t getStartFrame() const override {
71  return m_events.getStartFrame();
72  }
73  sv_frame_t getTrueEndFrame() const override {
74  if (m_events.isEmpty()) return 0;
76  if (e % m_resolution == 0) return e;
77  else return (e / m_resolution + 1) * m_resolution;
78  }
79 
80  sv_samplerate_t getSampleRate() const override { return m_sampleRate; }
81  int getResolution() const { return m_resolution; }
82 
83  bool canPlay() const override { return true; }
84  QString getDefaultPlayClipId() const override { return "tap"; }
85 
86  bool hasTextLabels() const { return m_haveTextLabels; }
87 
88  int getCompletion() const override { return m_completion; }
89 
90  void setCompletion(int completion, bool update = true) {
91 
92  if (m_completion == completion) return;
93  m_completion = completion;
94 
95  if (update) {
97  }
98 
99  emit completionChanged(getId());
100 
101  if (completion == 100) {
102  // henceforth:
104  emit modelChanged(getId());
105  }
106  }
107 
112  int getEventCount() const {
113  return m_events.count();
114  }
115  bool isEmpty() const {
116  return m_events.isEmpty();
117  }
118  bool containsEvent(const Event &e) const {
119  return m_events.contains(e);
120  }
122  return m_events.getAllEvents();
123  }
125  return m_events.getEventsSpanning(f, duration);
126  }
128  return m_events.getEventsCovering(f);
129  }
131  int overspill = 0) const {
132  return m_events.getEventsWithin(f, duration, overspill);
133  }
135  return m_events.getEventsStartingWithin(f, duration);
136  }
138  return m_events.getEventsStartingAt(f);
139  }
141  std::function<bool(Event)> predicate,
142  EventSeries::Direction direction,
143  Event &found) const {
145  (startSearchAt, predicate, direction, found);
146  }
147 
151  void add(Event e) override {
152 
154 
155  if (e.getLabel() != "") {
156  m_haveTextLabels = true;
157  }
158 
160  }
161 
162  void remove(Event e) override {
163  m_events.remove(e);
164  emit modelChangedWithin(getId(),
165  e.getFrame(), e.getFrame() + m_resolution);
166  }
167 
172  int getRowCount() const override {
173  return m_events.count();
174  }
175 
176  int getColumnCount() const override {
177  return 3;
178  }
179 
180  bool isColumnTimeValue(int column) const override {
181  return (column < 2);
182  }
183 
184  sv_frame_t getFrameForRow(int row) const override {
185  if (row < 0 || row >= m_events.count()) {
186  return 0;
187  }
188  Event e = m_events.getEventByIndex(row);
189  return e.getFrame();
190  }
191 
192  int getRowForFrame(sv_frame_t frame) const override {
193  return m_events.getIndexForEvent(Event(frame));
194  }
195 
196  QString getHeading(int column) const override {
197  switch (column) {
198  case 0: return tr("Time");
199  case 1: return tr("Frame");
200  case 2: return tr("Label");
201  default: return tr("Unknown");
202  }
203  }
204 
205  SortType getSortType(int column) const override {
206  if (column == 2) return SortAlphabetical;
207  return SortNumeric;
208  }
209 
210  QVariant getData(int row, int column, int role) const override {
211 
212  if (row < 0 || row >= m_events.count()) {
213  return QVariant();
214  }
215 
216  Event e = m_events.getEventByIndex(row);
217 
218  switch (column) {
219  case 0: return adaptFrameForRole(e.getFrame(), getSampleRate(), role);
220  case 1: return int(e.getFrame());
221  case 2: return e.getLabel();
222  default: return QVariant();
223  }
224  }
225 
226  Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override {
227  if (row < 0 || row >= m_events.count()) return nullptr;
228  if (role != Qt::EditRole) return nullptr;
229 
230  Event e0 = m_events.getEventByIndex(row);
231  Event e1;
232 
233  switch (column) {
234  case 0: e1 = e0.withFrame(sv_frame_t(round(value.toDouble() *
235  getSampleRate()))); break;
236  case 1: e1 = e0.withFrame(value.toInt()); break;
237  case 2: e1 = e0.withLabel(value.toString()); break;
238  }
239 
240  auto command = new ChangeEventsCommand(getId().untyped, tr("Edit Data"));
241  command->remove(e0);
242  command->add(e1);
243  return command->finish();
244  }
245 
246  bool isEditable() const override { return true; }
247 
248  Command *getInsertRowCommand(int row) override {
249  if (row < 0 || row >= m_events.count()) return nullptr;
250  auto command = new ChangeEventsCommand(getId().untyped,
251  tr("Add Point"));
252  Event e = m_events.getEventByIndex(row);
253  command->add(e);
254  return command->finish();
255  }
256 
257  Command *getRemoveRowCommand(int row) override {
258  if (row < 0 || row >= m_events.count()) return nullptr;
259  auto command = new ChangeEventsCommand(getId().untyped,
260  tr("Delete Point"));
261  Event e = m_events.getEventByIndex(row);
262  command->remove(e);
263  return command->finish();
264  }
265 
270  NoteList getNotes() const override {
272  getEndFrame() - getStartFrame());
273  }
274 
275  NoteList getNotesActiveAt(sv_frame_t frame) const override {
276  return getNotesStartingWithin(frame, 1);
277  }
278 
280  sv_frame_t duration) const override {
281 
282  NoteList notes;
283  EventVector ee = m_events.getEventsStartingWithin(startFrame, duration);
284  for (const auto &e: ee) {
285  notes.push_back(e.toNoteData(getSampleRate(), true));
286  }
287  return notes;
288  }
289 
293  void toXml(QTextStream &out,
294  QString indent = "",
295  QString extraAttributes = "") const override {
296 
298  (out,
299  indent,
300  QString("type=\"sparse\" dimensions=\"1\" resolution=\"%1\" "
301  "notifyOnAdd=\"%2\" dataset=\"%3\" %4")
302  .arg(m_resolution)
303  .arg("true") // always true after model reaches 100% -
304  // subsequent events are always notified
305  .arg(m_events.getExportId())
306  .arg(extraAttributes));
307 
308  m_events.toXml(out, indent, QString("dimensions=\"1\""));
309  }
310 
311  QVector<QString>
312  getStringExportHeaders(DataExportOptions options) const override {
313  return m_events.getStringExportHeaders(options, {});
314  }
315 
316  QVector<QVector<QString>>
318  sv_frame_t startFrame,
319  sv_frame_t duration) const override {
320  return m_events.toStringExportRows(options,
321  startFrame,
322  duration,
323  m_sampleRate,
324  m_resolution,
325  {});
326  }
327 
328 protected:
331 
332  std::atomic<bool> m_haveTextLabels;
334  std::atomic<int> m_completion;
335 
337 };
338 
339 #endif
340 
341 
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const override
Stream this exportable object out to XML on a text stream.
Definition: Model.cpp:204
static PlayParameterRepository * getInstance()
int getColumnCount() const override
Return the number of columns (values/labels/etc per item).
SparseOneDimensionalModel(sv_samplerate_t sampleRate, int resolution, bool notifyOnAdd=true)
bool contains(const Event &e) const
EventVector getEventsStartingAt(sv_frame_t f) const
SortType getSortType(int column) const override
Return the sort type (numeric or alphabetical) for the column.
int count() const
Definition: EventSeries.cpp:79
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
int getRowCount() const override
TabularModel methods.
void add(const Event &e)
Definition: EventSeries.cpp:89
bool getNearestEventMatching(sv_frame_t startSearchAt, std::function< bool(Event)> predicate, EventSeries::Direction direction, Event &found) const
EventVector getEventsStartingAt(sv_frame_t frame) const
Retrieve all events starting at exactly the given frame.
Definition: EventSeries.h:143
static QVariant adaptFrameForRole(sv_frame_t frame, sv_samplerate_t rate, int role)
Definition: TabularModel.h:124
Event getEventByIndex(int index) const
Return the event at the given numerical index in the series, where 0 = the first event and count()-1 ...
void update(sv_frame_t frame, sv_frame_t duration)
EventVector getAllEvents() const
Retrieve all events, in their natural order.
EventVector getEventsWithin(sv_frame_t f, sv_frame_t duration, int overspill=0) const
sv_frame_t getStartFrame() const
Return the frame of the first event in the series.
QVector< QVector< QString > > toStringExportRows(DataExportOptions options, sv_frame_t startFrame, sv_frame_t duration, sv_samplerate_t sampleRate, sv_frame_t resolution, Event fillEvent) const
Emit events starting within the given range as string rows ready for conversion to an e...
void makeDeferredNotifications()
QVector< QString > getStringExportHeaders(DataExportOptions options, Event::ExportNameOptions) const
Return a label for each column that would be written by toStringExportRows.
EventVector getEventsSpanning(sv_frame_t f, sv_frame_t duration) const
QVariant getData(int row, int column, int role) const override
Get the value in the given cell, for the given role.
Id getId() const
Return an id for this object.
Definition: ById.h:193
int getIndexForEvent(const Event &e) const
Return the index of the first event in the series that does not compare inferior to the given event...
sv_frame_t getEndFrame() const
Return the audio frame at the end of the model, i.e.
Definition: Model.h:87
Event withLabel(QString label) const
Definition: Event.h:160
void toXml(QTextStream &out, QString indent, QString extraAttributes) const override
Emit to XML as a dataset element.
EventVector getEventsStartingWithin(sv_frame_t f, sv_frame_t duration) const
bool isEmpty() const
Definition: EventSeries.cpp:72
int getCompletion() const override
Return an estimated percentage value showing how far through any background operation used to calcula...
EventVector getEventsCovering(sv_frame_t frame) const
Retrieve all events that cover the given frame.
NoteList getNotesActiveAt(sv_frame_t frame) const override
Get notes that are active at the given frame, i.e.
EventVector getEventsSpanning(sv_frame_t frame, sv_frame_t duration) const
Retrieve all events any part of which falls within the range in frames defined by the given frame f a...
int getRowForFrame(sv_frame_t frame) const override
Return the number of the first row whose frame time is not less than the given one.
EventVector getEventsCovering(sv_frame_t f) const
Command * getSetDataCommand(int row, int column, const QVariant &value, int role) override
Return a command to set the value in the given cell, for the given role, to the contents of the suppl...
NoteList getNotes() const override
NoteExportable methods.
static QString notes[]
Definition: Pitch.cpp:91
Model is the base class for all data models that represent any sort of data on a time scale based on ...
Definition: Model.h:51
TabularModel is an abstract base class for models that support direct access to data in a tabular for...
Definition: TabularModel.h:35
void completionChanged(ModelId myId)
Emitted when some internal processing has advanced a stage, but the model has not changed externally...
Event withoutDuration() const
Definition: Event.h:150
bool containsEvent(const Event &e) const
bool isOK() const override
Return true if the model was constructed successfully.
sv_frame_t getStartFrame() const override
Return the first audio frame spanned by the model.
sv_frame_t getEndFrame() const
Return the frame plus duration of the event in the series that ends last.
void removePlayable(int id)
Unregister a playable.
Event withFrame(sv_frame_t frame) const
Definition: Event.h:115
void remove(const Event &e)
QString getDefaultPlayClipId() const override
ExportId getExportId() const
Return the numerical export identifier for this object.
void setCompletion(int completion, bool update=true)
bool getNearestEventMatching(sv_frame_t startSearchAt, std::function< bool(const Event &)> predicate, Direction direction, Event &found) const
Return the first event for which the given predicate returns true, searching events with start frames...
void modelChangedWithin(ModelId myId, sv_frame_t startFrame, sv_frame_t endFrame)
Emitted when a model has been edited (or more data retrieved from cache, in the case of a cached mode...
EventVector getEventsWithin(sv_frame_t frame, sv_frame_t duration, int overspill=0) const
Retrieve all events falling wholly within the range in frames defined by the given frame f and durati...
QString getHeading(int column) const override
Return the heading for a given column, e.g.
sv_samplerate_t getSampleRate() const override
Return the frame rate in frames per second.
std::vector< NoteData > NoteList
Definition: NoteData.h:48
QVector< QVector< QString > > toStringExportRows(DataExportOptions options, sv_frame_t startFrame, sv_frame_t duration) const override
Emit events starting within the given range as string rows ready for conversion to an e...
Command * getRemoveRowCommand(int row) override
Return a command to delete the row with the given index.
An immutable(-ish) type used for point and event representation in sparse models, as well as for inte...
Definition: Event.h:55
void addPlayable(int id, const Playable *)
Register a playable.
sv_frame_t getFrame() const
Definition: Event.h:113
Command * getInsertRowCommand(int row) override
Return a command to insert a new row before the row with the given index.
Container storing a series of events, with or without durations, and supporting the ability to query ...
Definition: EventSeries.h:49
void add(Event e) override
Editing methods.
QString getTypeName() const override
Return the type of the model.
A model representing a series of time instants with optional labels but without values.
sv_frame_t getTrueEndFrame() const override
Return the audio frame at the end of the model.
void switchMode(Mode newMode)
std::vector< Event > EventVector
Definition: Event.h:494
bool isColumnTimeValue(int column) const override
Return true if the column is the frame time of the item, or an alternative representation of it (i...
bool isSparse() const override
Return true if this is a sparse model.
Interface for classes that can be modified through these commands.
Definition: EventCommands.h:26
QString getLabel() const
Definition: Event.h:158
int getEventCount() const
Query methods.
NoteList getNotesStartingWithin(sv_frame_t startFrame, sv_frame_t duration) const override
Get notes that start within the range in frames defined by the given start frame and duration...
EventVector getEventsStartingWithin(sv_frame_t frame, sv_frame_t duration) const
Retrieve all events starting within the range in frames defined by the given frame f and duration d...
bool isEditable() const override
Return true if the model is user-editable, false otherwise.
void modelChanged(ModelId myId)
Emitted when a model has been edited (or more data retrieved from cache, in the case of a cached mode...
QVector< QString > getStringExportHeaders(DataExportOptions options) const override
Return a label for each column that would be written by toStringExportRows.
Command to add or remove a series of events to or from an editable, with undo.
void toXml(QTextStream &out, QString indent="", QString extraAttributes="") const override
XmlExportable methods.
sv_frame_t getFrameForRow(int row) const override
Return the frame time for the given row.
int DataExportOptions
Event withoutValue() const
Definition: Event.h:130