annotate data/model/SparseTimeValueModel.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_TIME_VALUE_MODEL_H_
Chris@147 17 #define _SPARSE_TIME_VALUE_MODEL_H_
Chris@147 18
Chris@147 19 #include "SparseValueModel.h"
Chris@150 20 #include "base/PlayParameterRepository.h"
Chris@147 21 #include "base/RealTime.h"
Chris@147 22
Chris@147 23 /**
Chris@147 24 * Time/value point type for use in a SparseModel or SparseValueModel.
Chris@147 25 * With this point type, the model basically represents a wiggly-line
Chris@147 26 * plot with points at arbitrary intervals of the model resolution.
Chris@147 27 */
Chris@147 28
Chris@147 29 struct TimeValuePoint
Chris@147 30 {
Chris@147 31 public:
Chris@1110 32 TimeValuePoint(sv_frame_t _frame) : frame(_frame), value(0.0f) { }
Chris@1110 33 TimeValuePoint(sv_frame_t _frame, float _value, QString _label) :
Chris@1429 34 frame(_frame), value(_value), label(_label) { }
Chris@147 35
Chris@147 36 int getDimensions() const { return 2; }
Chris@147 37
Chris@1110 38 sv_frame_t frame;
Chris@147 39 float value;
Chris@147 40 QString label;
Chris@338 41
Chris@338 42 QString getLabel() const { return label; }
Chris@147 43
Chris@314 44 void toXml(QTextStream &stream, QString indent = "",
Chris@314 45 QString extraAttributes = "") const
Chris@147 46 {
Chris@314 47 stream << QString("%1<point frame=\"%2\" value=\"%3\" label=\"%4\" %5/>\n")
Chris@1429 48 .arg(indent).arg(frame).arg(value).arg(XmlExportable::encodeEntities(label))
Chris@603 49 .arg(extraAttributes);
Chris@147 50 }
Chris@147 51
Chris@1060 52 QString toDelimitedDataString(QString delimiter, DataExportOptions, sv_samplerate_t sampleRate) const
Chris@147 53 {
Chris@147 54 QStringList list;
Chris@147 55 list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
Chris@147 56 list << QString("%1").arg(value);
Chris@318 57 if (label != "") list << label;
Chris@147 58 return list.join(delimiter);
Chris@147 59 }
Chris@147 60
Chris@147 61 struct Comparator {
Chris@1429 62 bool operator()(const TimeValuePoint &p1,
Chris@1429 63 const TimeValuePoint &p2) const {
Chris@1429 64 if (p1.frame != p2.frame) return p1.frame < p2.frame;
Chris@1429 65 if (p1.value != p2.value) return p1.value < p2.value;
Chris@1429 66 return p1.label < p2.label;
Chris@1429 67 }
Chris@147 68 };
Chris@147 69
Chris@147 70 struct OrderComparator {
Chris@1429 71 bool operator()(const TimeValuePoint &p1,
Chris@1429 72 const TimeValuePoint &p2) const {
Chris@1429 73 return p1.frame < p2.frame;
Chris@1429 74 }
Chris@147 75 };
Chris@147 76 };
Chris@147 77
Chris@147 78
Chris@147 79 class SparseTimeValueModel : public SparseValueModel<TimeValuePoint>
Chris@147 80 {
Chris@423 81 Q_OBJECT
Chris@423 82
Chris@147 83 public:
Chris@1040 84 SparseTimeValueModel(sv_samplerate_t sampleRate, int resolution,
Chris@1429 85 bool notifyOnAdd = true) :
Chris@1429 86 SparseValueModel<TimeValuePoint>(sampleRate, resolution,
Chris@1429 87 notifyOnAdd)
Chris@256 88 {
Chris@868 89 // Model is playable, but may not sound (if units not Hz or
Chris@868 90 // range unsuitable)
Chris@1429 91 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@256 92 }
Chris@256 93
Chris@1040 94 SparseTimeValueModel(sv_samplerate_t sampleRate, int resolution,
Chris@1429 95 float valueMinimum, float valueMaximum,
Chris@1429 96 bool notifyOnAdd = true) :
Chris@1429 97 SparseValueModel<TimeValuePoint>(sampleRate, resolution,
Chris@1429 98 valueMinimum, valueMaximum,
Chris@1429 99 notifyOnAdd)
Chris@147 100 {
Chris@868 101 // Model is playable, but may not sound (if units not Hz or
Chris@868 102 // range unsuitable)
Chris@1429 103 PlayParameterRepository::getInstance()->addPlayable(this);
Chris@868 104 }
Chris@868 105
Chris@868 106 virtual ~SparseTimeValueModel()
Chris@868 107 {
Chris@1429 108 PlayParameterRepository::getInstance()->removePlayable(this);
Chris@147 109 }
Chris@345 110
Chris@345 111 QString getTypeName() const { return tr("Sparse Time-Value"); }
Chris@420 112
Chris@868 113 virtual bool canPlay() const { return true; }
Chris@952 114 virtual bool getDefaultPlayAudible() const { return false; } // user must unmute
Chris@868 115
Chris@420 116 /**
Chris@420 117 * TabularModel methods.
Chris@420 118 */
Chris@420 119
Chris@420 120 virtual int getColumnCount() const
Chris@420 121 {
Chris@420 122 return 4;
Chris@420 123 }
Chris@420 124
Chris@420 125 virtual QString getHeading(int column) const
Chris@420 126 {
Chris@420 127 switch (column) {
Chris@420 128 case 0: return tr("Time");
Chris@420 129 case 1: return tr("Frame");
Chris@420 130 case 2: return tr("Value");
Chris@420 131 case 3: return tr("Label");
Chris@420 132 default: return tr("Unknown");
Chris@420 133 }
Chris@420 134 }
Chris@420 135
Chris@420 136 virtual QVariant getData(int row, int column, int role) const
Chris@420 137 {
Chris@425 138 if (column < 2) {
Chris@425 139 return SparseValueModel<TimeValuePoint>::getData
Chris@425 140 (row, column, role);
Chris@425 141 }
Chris@425 142
Chris@606 143 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@420 144 if (i == m_points.end()) return QVariant();
Chris@420 145
Chris@420 146 switch (column) {
Chris@420 147 case 2:
Chris@422 148 if (role == Qt::EditRole || role == SortRole) return i->value;
Chris@420 149 else return QString("%1 %2").arg(i->value).arg(getScaleUnits());
Chris@420 150 case 3: return i->label;
Chris@420 151 default: return QVariant();
Chris@420 152 }
Chris@420 153 }
Chris@420 154
Chris@424 155 virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
Chris@420 156 {
Chris@425 157 if (column < 2) {
Chris@425 158 return SparseValueModel<TimeValuePoint>::getSetDataCommand
Chris@425 159 (row, column, value, role);
Chris@425 160 }
Chris@425 161
Chris@740 162 if (role != Qt::EditRole) return 0;
Chris@606 163 PointListConstIterator i = getPointListIteratorForRow(row);
Chris@740 164 if (i == m_points.end()) return 0;
Chris@420 165 EditCommand *command = new EditCommand(this, tr("Edit Data"));
Chris@420 166
Chris@420 167 Point point(*i);
Chris@420 168 command->deletePoint(point);
Chris@420 169
Chris@420 170 switch (column) {
Chris@1038 171 case 2: point.value = float(value.toDouble()); break;
Chris@420 172 case 3: point.label = value.toString(); break;
Chris@420 173 }
Chris@420 174
Chris@420 175 command->addPoint(point);
Chris@420 176 return command->finish();
Chris@420 177 }
Chris@420 178
Chris@420 179 virtual bool isColumnTimeValue(int column) const
Chris@420 180 {
Chris@420 181 return (column < 2);
Chris@420 182 }
Chris@422 183
Chris@422 184 virtual SortType getSortType(int column) const
Chris@422 185 {
Chris@422 186 if (column == 3) return SortAlphabetical;
Chris@422 187 return SortNumeric;
Chris@422 188 }
Chris@147 189 };
Chris@147 190
Chris@147 191
Chris@147 192 #endif
Chris@147 193
Chris@147 194
Chris@147 195