TextModel.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_TEXT_MODEL_H
16 #define SV_TEXT_MODEL_H
17 
18 #include "EventCommands.h"
19 #include "TabularModel.h"
20 #include "Model.h"
21 #include "DeferredNotifier.h"
22 
23 #include "base/EventSeries.h"
24 #include "base/XmlExportable.h"
25 #include "base/RealTime.h"
26 
27 #include "system/System.h"
28 
29 #include <QStringList>
30 
36 class TextModel : public Model,
37  public TabularModel,
38  public EventEditable
39 {
40  Q_OBJECT
41 
42 public:
44  int resolution,
45  bool notifyOnAdd = true) :
46  m_sampleRate(sampleRate),
47  m_resolution(resolution),
48  m_notifier(this,
49  getId(),
50  notifyOnAdd ?
51  DeferredNotifier::NOTIFY_ALWAYS :
52  DeferredNotifier::NOTIFY_DEFERRED),
53  m_completion(100) {
54  }
55 
56  QString getTypeName() const override { return tr("Text"); }
57  bool isSparse() const override { return true; }
58  bool isOK() const override { return true; }
59 
60  sv_frame_t getStartFrame() const override {
61  return m_events.getStartFrame();
62  }
63  sv_frame_t getTrueEndFrame() const override {
64  if (m_events.isEmpty()) return 0;
66  if (e % m_resolution == 0) return e;
67  else return (e / m_resolution + 1) * m_resolution;
68  }
69 
70  sv_samplerate_t getSampleRate() const override { return m_sampleRate; }
71  int getResolution() const { return m_resolution; }
72 
73  int getCompletion() const override { return m_completion; }
74 
75  void setCompletion(int completion, bool update = true) {
76 
77  { QMutexLocker locker(&m_mutex);
78  if (m_completion == completion) return;
79  m_completion = completion;
80  }
81 
82  if (update) {
84  }
85 
86  emit completionChanged(getId());
87 
88  if (completion == 100) {
89  // henceforth:
91  emit modelChanged(getId());
92  }
93  }
94 
99  int getEventCount() const {
100  return m_events.count();
101  }
102  bool isEmpty() const {
103  return m_events.isEmpty();
104  }
105  bool containsEvent(const Event &e) const {
106  return m_events.contains(e);
107  }
109  return m_events.getAllEvents();
110  }
112  return m_events.getEventsSpanning(f, duration);
113  }
115  return m_events.getEventsCovering(f);
116  }
118  int overspill = 0) const {
119  return m_events.getEventsWithin(f, duration, overspill);
120  }
122  return m_events.getEventsStartingWithin(f, duration);
123  }
125  return m_events.getEventsStartingAt(f);
126  }
128  std::function<bool(Event)> predicate,
129  EventSeries::Direction direction,
130  Event &found) const {
132  (startSearchAt, predicate, direction, found);
133  }
134 
138  void add(Event e) override {
139 
140  { QMutexLocker locker(&m_mutex);
142  }
143 
145  }
146 
147  void remove(Event e) override {
148  { QMutexLocker locker(&m_mutex);
149  m_events.remove(e);
150  }
151  emit modelChangedWithin(getId(),
152  e.getFrame(), e.getFrame() + m_resolution);
153  }
154 
159  int getRowCount() const override {
160  return m_events.count();
161  }
162 
163  int getColumnCount() const override {
164  return 4;
165  }
166 
167  bool isColumnTimeValue(int column) const override {
168  return (column < 2);
169  }
170 
171  sv_frame_t getFrameForRow(int row) const override {
172  if (row < 0 || row >= m_events.count()) {
173  return 0;
174  }
175  Event e = m_events.getEventByIndex(row);
176  return e.getFrame();
177  }
178 
179  int getRowForFrame(sv_frame_t frame) const override {
180  return m_events.getIndexForEvent(Event(frame));
181  }
182 
183  QString getHeading(int column) const override {
184  switch (column) {
185  case 0: return tr("Time");
186  case 1: return tr("Frame");
187  case 2: return tr("Height");
188  case 3: return tr("Label");
189  default: return tr("Unknown");
190  }
191  }
192 
193  SortType getSortType(int column) const override {
194  if (column == 3) return SortAlphabetical;
195  return SortNumeric;
196  }
197 
198  QVariant getData(int row, int column, int role) const override {
199 
200  if (row < 0 || row >= m_events.count()) {
201  return QVariant();
202  }
203 
204  Event e = m_events.getEventByIndex(row);
205 
206  switch (column) {
207  case 0: return adaptFrameForRole(e.getFrame(), getSampleRate(), role);
208  case 1: return int(e.getFrame());
209  case 2: return e.getValue();
210  case 3: return e.getLabel();
211  default: return QVariant();
212  }
213  }
214 
215  Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override {
216 
217  if (row < 0 || row >= m_events.count()) return nullptr;
218  if (role != Qt::EditRole) return nullptr;
219 
220  Event e0 = m_events.getEventByIndex(row);
221  Event e1;
222 
223  switch (column) {
224  case 0: e1 = e0.withFrame(sv_frame_t(round(value.toDouble() *
225  getSampleRate()))); break;
226  case 1: e1 = e0.withFrame(value.toInt()); break;
227  case 2: e1 = e0.withValue(float(value.toDouble())); break;
228  case 3: e1 = e0.withLabel(value.toString()); break;
229  }
230 
231  auto command = new ChangeEventsCommand(getId().untyped, tr("Edit Data"));
232  command->remove(e0);
233  command->add(e1);
234  return command->finish();
235  }
236 
237  bool isEditable() const override { return true; }
238 
239  Command *getInsertRowCommand(int row) override {
240  if (row < 0 || row >= m_events.count()) return nullptr;
241  auto command = new ChangeEventsCommand(getId().untyped,
242  tr("Add Label"));
243  Event e = m_events.getEventByIndex(row);
244  command->add(e);
245  return command->finish();
246  }
247 
248  Command *getRemoveRowCommand(int row) override {
249  if (row < 0 || row >= m_events.count()) return nullptr;
250  auto command = new ChangeEventsCommand(getId().untyped,
251  tr("Delete Label"));
252  Event e = m_events.getEventByIndex(row);
253  command->remove(e);
254  return command->finish();
255  }
256 
260  void toXml(QTextStream &out,
261  QString indent = "",
262  QString extraAttributes = "") const override {
263 
265  (out,
266  indent,
267  QString("type=\"sparse\" dimensions=\"2\" resolution=\"%1\" "
268  "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"text\" %4")
269  .arg(m_resolution)
270  .arg("true") // always true after model reaches 100% -
271  // subsequent events are always notified
272  .arg(m_events.getExportId())
273  .arg(extraAttributes));
274 
275  Event::ExportNameOptions options;
276  options.valueAttributeName = "height";
277 
278  m_events.toXml(out, indent, QString("dimensions=\"2\""), options);
279  }
280 
281  QVector<QString>
282  getStringExportHeaders(DataExportOptions options) const override {
283  Event::ExportNameOptions nameOpts;
284  nameOpts.valueAttributeName = "height";
285  return m_events.getStringExportHeaders(options, nameOpts);
286  }
287 
288  QVector<QVector<QString>>
290  sv_frame_t startFrame,
291  sv_frame_t duration) const override {
292  return m_events.toStringExportRows(options,
293  startFrame,
294  duration,
295  m_sampleRate,
296  m_resolution,
297  Event().withValue(0.f));
298  }
299 
300 protected:
303 
306 
308 
309  mutable QMutex m_mutex;
310 
311 };
312 
313 
314 #endif
315 
316 
317 
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
bool contains(const Event &e) 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...
Definition: TextModel.h:215
float getValue() const
Definition: Event.h:122
EventVector getEventsStartingWithin(sv_frame_t f, sv_frame_t duration) const
Definition: TextModel.h:121
int m_resolution
Definition: TextModel.h:302
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 getRowForFrame(sv_frame_t frame) const override
Return the number of the first row whose frame time is not less than the given one.
Definition: TextModel.h:179
int getCompletion() const override
Return an estimated percentage value showing how far through any background operation used to calcula...
Definition: TextModel.h:73
void add(const Event &e)
Definition: EventSeries.cpp:89
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
EventVector getAllEvents() const
Definition: TextModel.h:108
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...
Definition: TextModel.h:167
QVariant getData(int row, int column, int role) const override
Get the value in the given cell, for the given role.
Definition: TextModel.h:198
bool isEmpty() const
Definition: TextModel.h:102
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.
int getColumnCount() const override
Return the number of columns (values/labels/etc per item).
Definition: TextModel.h:163
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...
A model representing casual textual annotations.
Definition: TextModel.h:36
void makeDeferredNotifications()
QMutex m_mutex
Definition: TextModel.h:309
QVector< QString > getStringExportHeaders(DataExportOptions options, Event::ExportNameOptions) const
Return a label for each column that would be written by toStringExportRows.
QString getTypeName() const override
Return the type of the model.
Definition: TextModel.h:56
Id getId() const
Return an id for this object.
Definition: ById.h:193
QString valueAttributeName
Definition: Event.h:289
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...
void toXml(QTextStream &out, QString indent="", QString extraAttributes="") const override
XmlExportable methods.
Definition: TextModel.h:260
bool isSparse() const override
Return true if this is a sparse model.
Definition: TextModel.h:57
Event withLabel(QString label) const
Definition: Event.h:160
sv_samplerate_t getSampleRate() const override
Return the frame rate in frames per second.
Definition: TextModel.h:70
void toXml(QTextStream &out, QString indent, QString extraAttributes) const override
Emit to XML as a dataset element.
Command * getRemoveRowCommand(int row) override
Return a command to delete the row with the given index.
Definition: TextModel.h:248
bool isEmpty() const
Definition: EventSeries.cpp:72
EventVector getEventsCovering(sv_frame_t frame) const
Retrieve all events that cover the given frame.
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...
Definition: TextModel.h:289
EventVector getEventsStartingAt(sv_frame_t f) const
Definition: TextModel.h:124
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...
Event withoutLevel() const
Definition: Event.h:184
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
Event withValue(float value) const
Definition: Event.h:124
sv_frame_t getEndFrame() const
Return the frame plus duration of the event in the series that ends last.
Event withFrame(sv_frame_t frame) const
Definition: Event.h:115
void remove(const Event &e)
sv_samplerate_t m_sampleRate
Definition: TextModel.h:301
ExportId getExportId() const
Return the numerical export identifier for this object.
EventSeries m_events
Definition: TextModel.h:307
int m_completion
Definition: TextModel.h:305
QString getHeading(int column) const override
Return the heading for a given column, e.g.
Definition: TextModel.h:183
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...
bool isOK() const override
Return true if the model was constructed successfully.
Definition: TextModel.h:58
void setCompletion(int completion, bool update=true)
Definition: TextModel.h:75
void add(Event e) override
Editing methods.
Definition: TextModel.h:138
An immutable(-ish) type used for point and event representation in sparse models, as well as for inte...
Definition: Event.h:55
sv_frame_t getTrueEndFrame() const override
Return the audio frame at the end of the model.
Definition: TextModel.h:63
sv_frame_t getFrameForRow(int row) const override
Return the frame time for the given row.
Definition: TextModel.h:171
bool getNearestEventMatching(sv_frame_t startSearchAt, std::function< bool(Event)> predicate, EventSeries::Direction direction, Event &found) const
Definition: TextModel.h:127
EventVector getEventsWithin(sv_frame_t f, sv_frame_t duration, int overspill=0) const
Definition: TextModel.h:117
bool containsEvent(const Event &e) const
Definition: TextModel.h:105
sv_frame_t getFrame() const
Definition: Event.h:113
Container storing a series of events, with or without durations, and supporting the ability to query ...
Definition: EventSeries.h:49
bool isEditable() const override
Return true if the model is user-editable, false otherwise.
Definition: TextModel.h:237
EventVector getEventsCovering(sv_frame_t f) const
Definition: TextModel.h:114
void switchMode(Mode newMode)
std::vector< Event > EventVector
Definition: Event.h:494
Interface for classes that can be modified through these commands.
Definition: EventCommands.h:26
QString getLabel() const
Definition: Event.h:158
Command * getInsertRowCommand(int row) override
Return a command to insert a new row before the row with the given index.
Definition: TextModel.h:239
DeferredNotifier m_notifier
Definition: TextModel.h:304
sv_frame_t getStartFrame() const override
Return the first audio frame spanned by the model.
Definition: TextModel.h:60
int getEventCount() const
Query methods.
Definition: TextModel.h:99
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...
void modelChanged(ModelId myId)
Emitted when a model has been edited (or more data retrieved from cache, in the case of a cached mode...
int getRowCount() const override
TabularModel methods.
Definition: TextModel.h:159
int getResolution() const
Definition: TextModel.h:71
SortType getSortType(int column) const override
Return the sort type (numeric or alphabetical) for the column.
Definition: TextModel.h:193
Command to add or remove a series of events to or from an editable, with undo.
EventVector getEventsSpanning(sv_frame_t f, sv_frame_t duration) const
Definition: TextModel.h:111
TextModel(sv_samplerate_t sampleRate, int resolution, bool notifyOnAdd=true)
Definition: TextModel.h:43
QVector< QString > getStringExportHeaders(DataExportOptions options) const override
Return a label for each column that would be written by toStringExportRows.
Definition: TextModel.h:282
int DataExportOptions