annotate data/model/SparseOneDimensionalModel.h @ 1455:ec9e65fcf749

The use of the begin/end pairs here just seems to cause too many rows to be deleted (from the visual representation, not the underlying model). Things apparently work better if we just modify the underlying model and let the change signals percolate back up again. To that end, update the change handlers so as to cover their proper ranges with dataChanged signals.
author Chris Cannam
date Mon, 23 Apr 2018 16:03:35 +0100
parents 48e9f538e6e9
children c01cbe41aeb5
rev   line source
Chris@147 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@147 2
Chris@147 3 /*
Chris@147 4 Sonic Visualiser
Chris@147 5 An audio file viewer and annotation editor.
Chris@147 6 Centre for Digital Music, Queen Mary, University of London.
Chris@147 7 This file copyright 2006 Chris Cannam.
Chris@147 8
Chris@147 9 This program is free software; you can redistribute it and/or
Chris@147 10 modify it under the terms of the GNU General Public License as
Chris@147 11 published by the Free Software Foundation; either version 2 of the
Chris@147 12 License, or (at your option) any later version. See the file
Chris@147 13 COPYING included with this distribution for more information.
Chris@147 14 */
Chris@147 15
Chris@147 16 #ifndef _SPARSE_ONE_DIMENSIONAL_MODEL_H_
Chris@147 17 #define _SPARSE_ONE_DIMENSIONAL_MODEL_H_
Chris@147 18
Chris@147 19 #include "SparseModel.h"
Chris@852 20 #include "NoteData.h"
Chris@150 21 #include "base/PlayParameterRepository.h"
Chris@147 22 #include "base/RealTime.h"
Chris@147 23
Chris@387 24 #include <QStringList>
Chris@387 25
Chris@147 26 struct OneDimensionalPoint
Chris@147 27 {
Chris@147 28 public:
Chris@1038 29 OneDimensionalPoint(sv_frame_t _frame) : frame(_frame) { }
Chris@1038 30 OneDimensionalPoint(sv_frame_t _frame, QString _label) : frame(_frame), label(_label) { }
Chris@147 31
Chris@147 32 int getDimensions() const { return 1; }
Chris@147 33
Chris@1038 34 sv_frame_t frame;
Chris@147 35 QString label;
Chris@338 36
Chris@338 37 QString getLabel() const { return label; }
Chris@338 38
Chris@314 39 void toXml(QTextStream &stream,
Chris@314 40 QString indent = "",
Chris@314 41 QString extraAttributes = "") const
Chris@147 42 {
Chris@314 43 stream << QString("%1<point frame=\"%2\" label=\"%3\" %4/>\n")
Chris@1429 44 .arg(indent).arg(frame).arg(XmlExportable::encodeEntities(label))
Chris@603 45 .arg(extraAttributes);
Chris@147 46 }
Chris@147 47
Chris@1060 48 QString toDelimitedDataString(QString delimiter, DataExportOptions, sv_samplerate_t sampleRate) const
Chris@147 49 {
Chris@147 50 QStringList list;
Chris@147 51 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@318 52 if (label != "") list << label;
Chris@147 53 return list.join(delimiter);
Chris@147 54 }
Chris@147 55
Chris@147 56 struct Comparator {
Chris@1429 57 bool operator()(const OneDimensionalPoint &p1,
Chris@1429 58 const OneDimensionalPoint &p2) const {
Chris@1429 59 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@1429 60 return p1.label < p2.label;
Chris@1429 61 }
Chris@147 62 };
Chris@147 63
Chris@147 64 struct OrderComparator {
Chris@1429 65 bool operator()(const OneDimensionalPoint &p1,
Chris@1429 66 const OneDimensionalPoint &p2) const {
Chris@1429 67 return p1.frame < p2.frame;
Chris@1429 68 }
Chris@147 69 };
Chris@147 70 };
Chris@147 71
Chris@147 72
Chris@852 73 class SparseOneDimensionalModel : public SparseModel<OneDimensionalPoint>,
Chris@852 74 public NoteExportable
Chris@147 75 {
Chris@423 76 Q_OBJECT
Chris@423 77
Chris@147 78 public:
Chris@1040 79 SparseOneDimensionalModel(sv_samplerate_t sampleRate, int resolution,
Chris@1429 80 bool notifyOnAdd = true) :
Chris@1429 81 SparseModel<OneDimensionalPoint>(sampleRate, resolution, notifyOnAdd)
Chris@147 82 {
Chris@1429 83 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@391 84 }
Chris@391 85
Chris@391 86 virtual ~SparseOneDimensionalModel()
Chris@391 87 {
Chris@391 88 PlayParameterRepository::getInstance()->removePlayable(this);
Chris@391 89 }
Chris@391 90
Chris@391 91 virtual bool canPlay() const { return true; }
Chris@391 92
Chris@866 93 virtual QString getDefaultPlayClipId() const
Chris@391 94 {
Chris@864 95 return "tap";
Chris@147 96 }
Chris@147 97
Chris@420 98 int getIndexOf(const Point &point)
Chris@420 99 {
Chris@1429 100 // slow
Chris@1429 101 int i = 0;
Chris@1429 102 Point::Comparator comparator;
Chris@1429 103 for (PointList::const_iterator j = m_points.begin();
Chris@1429 104 j != m_points.end(); ++j, ++i) {
Chris@1429 105 if (!comparator(*j, point) && !comparator(point, *j)) return i;
Chris@1429 106 }
Chris@1429 107 return -1;
Chris@147 108 }
Chris@345 109
Chris@345 110 QString getTypeName() const { return tr("Sparse 1-D"); }
Chris@420 111
Chris@420 112 /**
Chris@420 113 * TabularModel methods.
Chris@420 114 */
Chris@420 115
Chris@420 116 virtual int getColumnCount() const
Chris@420 117 {
Chris@420 118 return 3;
Chris@420 119 }
Chris@420 120
Chris@420 121 virtual QString getHeading(int column) const
Chris@420 122 {
Chris@420 123 switch (column) {
Chris@420 124 case 0: return tr("Time");
Chris@420 125 case 1: return tr("Frame");
Chris@420 126 case 2: return tr("Label");
Chris@420 127 default: return tr("Unknown");
Chris@420 128 }
Chris@420 129 }
Chris@420 130
Chris@420 131 virtual QVariant getData(int row, int column, int role) const
Chris@420 132 {
Chris@425 133 if (column < 2) {
Chris@425 134 return SparseModel<OneDimensionalPoint>::getData
Chris@425 135 (row, column, role);
Chris@425 136 }
Chris@425 137
Chris@606 138 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@420 139 if (i == m_points.end()) return QVariant();
Chris@420 140
Chris@420 141 switch (column) {
Chris@422 142 case 2: return i->label;
Chris@420 143 default: return QVariant();
Chris@420 144 }
Chris@420 145 }
Chris@420 146
Chris@424 147 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@424 148 {
Chris@425 149 if (column < 2) {
Chris@425 150 return SparseModel<OneDimensionalPoint>::getSetDataCommand
Chris@425 151 (row, column, value, role);
Chris@425 152 }
Chris@425 153
Chris@740 154 if (role != Qt::EditRole) return 0;
Chris@606 155 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@740 156 if (i == m_points.end()) return 0;
Chris@424 157 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@424 158
Chris@424 159 Point point(*i);
Chris@424 160 command->deletePoint(point);
Chris@424 161
Chris@424 162 switch (column) {
Chris@424 163 case 2: point.label = value.toString(); break;
Chris@424 164 }
Chris@424 165
Chris@424 166 command->addPoint(point);
Chris@424 167 return command->finish();
Chris@424 168 }
Chris@424 169
Chris@427 170
Chris@420 171 virtual bool isColumnTimeValue(int column) const
Chris@420 172 {
Chris@420 173 return (column < 2);
Chris@420 174 }
Chris@422 175
Chris@422 176 virtual SortType getSortType(int column) const
Chris@422 177 {
Chris@422 178 if (column == 2) return SortAlphabetical;
Chris@422 179 return SortNumeric;
Chris@422 180 }
Chris@852 181
Chris@852 182 /**
Chris@852 183 * NoteExportable methods.
Chris@852 184 */
Chris@852 185
Chris@852 186 NoteList getNotes() const {
Chris@929 187 return getNotesWithin(getStartFrame(), getEndFrame());
Chris@852 188 }
Chris@852 189
Chris@1038 190 NoteList getNotesWithin(sv_frame_t startFrame, sv_frame_t endFrame) const {
Chris@852 191
Chris@1429 192 PointList points = getPoints(startFrame, endFrame);
Chris@852 193 NoteList notes;
Chris@852 194
Chris@1429 195 for (PointList::iterator pli =
Chris@1429 196 points.begin(); pli != points.end(); ++pli) {
Chris@852 197
Chris@852 198 notes.push_back
Chris@852 199 (NoteData(pli->frame,
Chris@1040 200 sv_frame_t(getSampleRate() / 6), // arbitrary short duration
Chris@852 201 64, // default pitch
Chris@852 202 100)); // default velocity
Chris@852 203 }
Chris@852 204
Chris@852 205 return notes;
Chris@852 206 }
Chris@147 207 };
Chris@147 208
Chris@147 209 #endif
Chris@147 210
Chris@147 211
Chris@147 212