ImageModel.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  This file copyright 2006-2007 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #ifndef SV_IMAGE_MODEL_H
17 #define SV_IMAGE_MODEL_H
18 
19 #include "EventCommands.h"
20 #include "TabularModel.h"
21 #include "Model.h"
22 #include "DeferredNotifier.h"
23 
24 #include "base/EventSeries.h"
25 #include "base/XmlExportable.h"
26 #include "base/RealTime.h"
27 
28 #include "system/System.h"
29 
30 #include <QStringList>
31 
38 class ImageModel : public Model,
39  public TabularModel,
40  public EventEditable
41 {
42  Q_OBJECT
43 
44 public:
46  int resolution,
47  bool notifyOnAdd = true) :
48  m_sampleRate(sampleRate),
49  m_resolution(resolution),
50  m_notifier(this,
51  getId(),
52  notifyOnAdd ?
53  DeferredNotifier::NOTIFY_ALWAYS :
54  DeferredNotifier::NOTIFY_DEFERRED),
55  m_completion(100) {
56  }
57 
58  QString getTypeName() const override { return tr("Image"); }
59  bool isSparse() const override { return true; }
60  bool isOK() const override { return true; }
61 
62  sv_frame_t getStartFrame() const override {
63  return m_events.getStartFrame();
64  }
65  sv_frame_t getTrueEndFrame() const override {
66  if (m_events.isEmpty()) return 0;
68  if (e % m_resolution == 0) return e;
69  else return (e / m_resolution + 1) * m_resolution;
70  }
71 
72  sv_samplerate_t getSampleRate() const override { return m_sampleRate; }
73  int getResolution() const { return m_resolution; }
74 
75  int getCompletion() const override { return m_completion; }
76 
77  void setCompletion(int completion, bool update = true) {
78 
79  if (m_completion == completion) return;
80  m_completion = completion;
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 
102  int getEventCount() const {
103  return m_events.count();
104  }
105  bool isEmpty() const {
106  return m_events.isEmpty();
107  }
108  bool containsEvent(const Event &e) const {
109  return m_events.contains(e);
110  }
112  return m_events.getAllEvents();
113  }
115  return m_events.getEventsSpanning(f, duration);
116  }
118  return m_events.getEventsCovering(f);
119  }
121  int overspill = 0) const {
122  return m_events.getEventsWithin(f, duration, overspill);
123  }
125  return m_events.getEventsStartingWithin(f, duration);
126  }
128  return m_events.getEventsStartingAt(f);
129  }
131  std::function<bool(Event)> predicate,
132  EventSeries::Direction direction,
133  Event &found) const {
135  (startSearchAt, predicate, direction, found);
136  }
137 
141  void add(Event e) override {
144  }
145 
146  void remove(Event e) override {
147  m_events.remove(e);
148  emit modelChangedWithin(getId(),
149  e.getFrame(), e.getFrame() + m_resolution);
150  }
151 
156  int getRowCount() const override {
157  return m_events.count();
158  }
159 
160  int getColumnCount() const override {
161  return 4;
162  }
163 
164  bool isColumnTimeValue(int column) const override {
165  return (column < 2);
166  }
167 
168  sv_frame_t getFrameForRow(int row) const override {
169  if (row < 0 || row >= m_events.count()) {
170  return 0;
171  }
172  Event e = m_events.getEventByIndex(row);
173  return e.getFrame();
174  }
175 
176  int getRowForFrame(sv_frame_t frame) const override {
177  return m_events.getIndexForEvent(Event(frame));
178  }
179 
180  QString getHeading(int column) const override {
181  switch (column) {
182  case 0: return tr("Time");
183  case 1: return tr("Frame");
184  case 2: return tr("Image");
185  case 3: return tr("Label");
186  default: return tr("Unknown");
187  }
188  }
189 
190  SortType getSortType(int column) const override {
191  if (column >= 2) return SortAlphabetical;
192  return SortNumeric;
193  }
194 
195  QVariant getData(int row, int column, int role) const override {
196 
197  if (row < 0 || row >= m_events.count()) {
198  return QVariant();
199  }
200 
201  Event e = m_events.getEventByIndex(row);
202 
203  switch (column) {
204  case 0: return adaptFrameForRole(e.getFrame(), getSampleRate(), role);
205  case 1: return int(e.getFrame());
206  case 2: return e.getURI();
207  case 3: return e.getLabel();
208  default: return QVariant();
209  }
210  }
211 
212  Command *getSetDataCommand(int row, int column, const QVariant &value, int role) override {
213 
214  if (row < 0 || row >= m_events.count()) return nullptr;
215  if (role != Qt::EditRole) return nullptr;
216 
217  Event e0 = m_events.getEventByIndex(row);
218  Event e1;
219 
220  switch (column) {
221  case 0: e1 = e0.withFrame(sv_frame_t(round(value.toDouble() *
222  getSampleRate()))); break;
223  case 1: e1 = e0.withFrame(value.toInt()); break;
224  case 2: e1 = e0.withURI(value.toString()); break;
225  case 3: e1 = e0.withLabel(value.toString()); break;
226  }
227 
228  auto command = new ChangeEventsCommand(getId().untyped, tr("Edit Data"));
229  command->remove(e0);
230  command->add(e1);
231  return command->finish();
232  }
233 
234  bool isEditable() const override { return true; }
235 
236  Command *getInsertRowCommand(int row) override {
237  if (row < 0 || row >= m_events.count()) return nullptr;
238  auto command = new ChangeEventsCommand(getId().untyped,
239  tr("Add Image"));
240  Event e = m_events.getEventByIndex(row);
241  command->add(e);
242  return command->finish();
243  }
244 
245  Command *getRemoveRowCommand(int row) override {
246  if (row < 0 || row >= m_events.count()) return nullptr;
247  auto command = new ChangeEventsCommand(getId().untyped,
248  tr("Delete Image"));
249  Event e = m_events.getEventByIndex(row);
250  command->remove(e);
251  return command->finish();
252  }
253 
257  void toXml(QTextStream &out,
258  QString indent = "",
259  QString extraAttributes = "") const override {
260 
262  (out,
263  indent,
264  QString("type=\"sparse\" dimensions=\"1\" resolution=\"%1\" "
265  "notifyOnAdd=\"%2\" dataset=\"%3\" subtype=\"image\" %4")
266  .arg(m_resolution)
267  .arg("true") // always true after model reaches 100% -
268  // subsequent events are always notified
269  .arg(m_events.getExportId())
270  .arg(extraAttributes));
271 
272  Event::ExportNameOptions options;
273  options.uriAttributeName = "image";
274 
275  m_events.toXml(out, indent, QString("dimensions=\"1\""), options);
276  }
277 
278  QVector<QString>
279  getStringExportHeaders(DataExportOptions options) const override {
280  Event::ExportNameOptions nameOpts;
281  nameOpts.uriAttributeName = "image";
282  return m_events.getStringExportHeaders(options, nameOpts);
283  }
284 
285  QVector<QVector<QString>>
287  sv_frame_t startFrame,
288  sv_frame_t duration) const override {
289  return m_events.toStringExportRows(options,
290  startFrame,
291  duration,
292  m_sampleRate,
293  m_resolution,
294  Event().withValue(0.f));
295  }
296 
297 protected:
300 
302  std::atomic<int> m_completion;
303 
305 };
306 
307 
308 #endif
309 
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
EventVector getEventsSpanning(sv_frame_t f, sv_frame_t duration) const
Definition: ImageModel.h:114
bool isOK() const override
Return true if the model was constructed successfully.
Definition: ImageModel.h:60
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
void add(Event e) override
Editing methods.
Definition: ImageModel.h:141
bool contains(const Event &e) const
Event withURI(QString uri) const
Definition: Event.h:169
SortType getSortType(int column) const override
Return the sort type (numeric or alphabetical) for the column.
Definition: ImageModel.h:190
QString getHeading(int column) const override
Return the heading for a given column, e.g.
Definition: ImageModel.h:180
int count() const
Definition: EventSeries.cpp:79
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
Command * getRemoveRowCommand(int row) override
Return a command to delete the row with the given index.
Definition: ImageModel.h:245
sv_frame_t getFrameForRow(int row) const override
Return the frame time for the given row.
Definition: ImageModel.h:168
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
sv_samplerate_t getSampleRate() const override
Return the frame rate in frames per second.
Definition: ImageModel.h:72
static QVariant adaptFrameForRole(sv_frame_t frame, sv_samplerate_t rate, int role)
Definition: TabularModel.h:124
int getCompletion() const override
Return an estimated percentage value showing how far through any background operation used to calcula...
Definition: ImageModel.h:75
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: ImageModel.h:286
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.
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...
QVector< QString > getStringExportHeaders(DataExportOptions options) const override
Return a label for each column that would be written by toStringExportRows.
Definition: ImageModel.h:279
void makeDeferredNotifications()
DeferredNotifier m_notifier
Definition: ImageModel.h:301
QVector< QString > getStringExportHeaders(DataExportOptions options, Event::ExportNameOptions) const
Return a label for each column that would be written by toStringExportRows.
Id getId() const
Return an id for this object.
Definition: ById.h:193
bool isEmpty() const
Definition: ImageModel.h:105
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...
Command * getInsertRowCommand(int row) override
Return a command to insert a new row before the row with the given index.
Definition: ImageModel.h:236
EventVector getAllEvents() const
Definition: ImageModel.h:111
sv_frame_t getTrueEndFrame() const override
Return the audio frame at the end of the model.
Definition: ImageModel.h:65
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.
sv_frame_t getStartFrame() const override
Return the first audio frame spanned by the model.
Definition: ImageModel.h:62
int getColumnCount() const override
Return the number of columns (values/labels/etc per item).
Definition: ImageModel.h:160
bool isEditable() const override
Return true if the model is user-editable, false otherwise.
Definition: ImageModel.h:234
QVariant getData(int row, int column, int role) const override
Get the value in the given cell, for the given role.
Definition: ImageModel.h:195
QString uriAttributeName
Definition: Event.h:291
sv_samplerate_t m_sampleRate
Definition: ImageModel.h:298
bool isEmpty() const
Definition: EventSeries.cpp:72
void setCompletion(int completion, bool update=true)
Definition: ImageModel.h:77
EventVector getEventsCovering(sv_frame_t frame) const
Retrieve all events that cover the given frame.
EventVector getEventsStartingWithin(sv_frame_t f, sv_frame_t duration) const
Definition: ImageModel.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
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)
void toXml(QTextStream &out, QString indent="", QString extraAttributes="") const override
XmlExportable methods.
Definition: ImageModel.h:257
ExportId getExportId() const
Return the numerical export identifier for this object.
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...
int m_resolution
Definition: ImageModel.h:299
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...
int getEventCount() const
Query methods.
Definition: ImageModel.h:102
bool containsEvent(const Event &e) const
Definition: ImageModel.h:108
EventSeries m_events
Definition: ImageModel.h:304
An immutable(-ish) type used for point and event representation in sparse models, as well as for inte...
Definition: Event.h:55
EventVector getEventsWithin(sv_frame_t f, sv_frame_t duration, int overspill=0) const
Definition: ImageModel.h:120
int getResolution() const
Definition: ImageModel.h:73
sv_frame_t getFrame() const
Definition: Event.h:113
QString getURI() const
Definition: Event.h:167
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: ImageModel.h:164
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: ImageModel.h:212
Container storing a series of events, with or without durations, and supporting the ability to query ...
Definition: EventSeries.h:49
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: ImageModel.h:176
bool getNearestEventMatching(sv_frame_t startSearchAt, std::function< bool(Event)> predicate, EventSeries::Direction direction, Event &found) const
Definition: ImageModel.h:130
bool isSparse() const override
Return true if this is a sparse model.
Definition: ImageModel.h:59
void switchMode(Mode newMode)
int getRowCount() const override
TabularModel methods.
Definition: ImageModel.h:156
std::vector< Event > EventVector
Definition: Event.h:494
QString getTypeName() const override
Return the type of the model.
Definition: ImageModel.h:58
Interface for classes that can be modified through these commands.
Definition: EventCommands.h:26
std::atomic< int > m_completion
Definition: ImageModel.h:302
QString getLabel() const
Definition: Event.h:158
A model representing image annotations, identified by filename or URI, at a given time...
Definition: ImageModel.h:38
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...
ImageModel(sv_samplerate_t sampleRate, int resolution, bool notifyOnAdd=true)
Definition: ImageModel.h:45
EventVector getEventsStartingAt(sv_frame_t f) const
Definition: ImageModel.h:127
Command to add or remove a series of events to or from an editable, with undo.
EventVector getEventsCovering(sv_frame_t f) const
Definition: ImageModel.h:117
int DataExportOptions
Event withoutValue() const
Definition: Event.h:130