annotate data/model/EditableDenseThreeDimensionalModel.cpp @ 392:183ee2a55fc7

* More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui.
author Chris Cannam
date Fri, 14 Mar 2008 17:14:21 +0000
parents 7aa1de571880
children beb2948baa77
rev   line source
Chris@152 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@152 2
Chris@152 3 /*
Chris@152 4 Sonic Visualiser
Chris@152 5 An audio file viewer and annotation editor.
Chris@152 6 Centre for Digital Music, Queen Mary, University of London.
Chris@202 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@152 8
Chris@152 9 This program is free software; you can redistribute it and/or
Chris@152 10 modify it under the terms of the GNU General Public License as
Chris@152 11 published by the Free Software Foundation; either version 2 of the
Chris@152 12 License, or (at your option) any later version. See the file
Chris@152 13 COPYING included with this distribution for more information.
Chris@152 14 */
Chris@152 15
Chris@152 16 #include "EditableDenseThreeDimensionalModel.h"
Chris@152 17
Chris@152 18 #include <QTextStream>
Chris@152 19
Chris@387 20 #include <QStringList>
Chris@387 21
Chris@181 22 #include <iostream>
Chris@181 23
Chris@256 24 #include <cmath>
Chris@256 25
Chris@152 26 EditableDenseThreeDimensionalModel::EditableDenseThreeDimensionalModel(size_t sampleRate,
Chris@152 27 size_t resolution,
Chris@152 28 size_t yBinCount,
Chris@152 29 bool notifyOnAdd) :
Chris@152 30 m_sampleRate(sampleRate),
Chris@152 31 m_resolution(resolution),
Chris@152 32 m_yBinCount(yBinCount),
Chris@152 33 m_minimum(0.0),
Chris@152 34 m_maximum(0.0),
Chris@256 35 m_haveExtents(false),
Chris@152 36 m_notifyOnAdd(notifyOnAdd),
Chris@152 37 m_sinceLastNotifyMin(-1),
Chris@152 38 m_sinceLastNotifyMax(-1),
Chris@152 39 m_completion(100)
Chris@152 40 {
Chris@152 41 }
Chris@152 42
Chris@152 43 bool
Chris@152 44 EditableDenseThreeDimensionalModel::isOK() const
Chris@152 45 {
Chris@152 46 return true;
Chris@152 47 }
Chris@152 48
Chris@152 49 size_t
Chris@152 50 EditableDenseThreeDimensionalModel::getSampleRate() const
Chris@152 51 {
Chris@152 52 return m_sampleRate;
Chris@152 53 }
Chris@152 54
Chris@152 55 size_t
Chris@152 56 EditableDenseThreeDimensionalModel::getStartFrame() const
Chris@152 57 {
Chris@152 58 return 0;
Chris@152 59 }
Chris@152 60
Chris@152 61 size_t
Chris@152 62 EditableDenseThreeDimensionalModel::getEndFrame() const
Chris@152 63 {
Chris@152 64 return m_resolution * m_data.size() + (m_resolution - 1);
Chris@152 65 }
Chris@152 66
Chris@152 67 Model *
Chris@152 68 EditableDenseThreeDimensionalModel::clone() const
Chris@152 69 {
Chris@152 70 EditableDenseThreeDimensionalModel *model =
Chris@152 71 new EditableDenseThreeDimensionalModel
Chris@152 72 (m_sampleRate, m_resolution, m_yBinCount);
Chris@152 73
Chris@152 74 model->m_minimum = m_minimum;
Chris@152 75 model->m_maximum = m_maximum;
Chris@256 76 model->m_haveExtents = m_haveExtents;
Chris@152 77
Chris@152 78 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@182 79 model->setColumn(i, m_data[i]);
Chris@152 80 }
Chris@152 81
Chris@152 82 return model;
Chris@152 83 }
Chris@152 84
Chris@152 85 size_t
Chris@152 86 EditableDenseThreeDimensionalModel::getResolution() const
Chris@152 87 {
Chris@152 88 return m_resolution;
Chris@152 89 }
Chris@152 90
Chris@152 91 void
Chris@152 92 EditableDenseThreeDimensionalModel::setResolution(size_t sz)
Chris@152 93 {
Chris@152 94 m_resolution = sz;
Chris@152 95 }
Chris@152 96
Chris@152 97 size_t
Chris@182 98 EditableDenseThreeDimensionalModel::getWidth() const
Chris@182 99 {
Chris@182 100 return m_data.size();
Chris@182 101 }
Chris@182 102
Chris@182 103 size_t
Chris@182 104 EditableDenseThreeDimensionalModel::getHeight() const
Chris@152 105 {
Chris@152 106 return m_yBinCount;
Chris@152 107 }
Chris@152 108
Chris@152 109 void
Chris@182 110 EditableDenseThreeDimensionalModel::setHeight(size_t sz)
Chris@152 111 {
Chris@152 112 m_yBinCount = sz;
Chris@152 113 }
Chris@152 114
Chris@152 115 float
Chris@152 116 EditableDenseThreeDimensionalModel::getMinimumLevel() const
Chris@152 117 {
Chris@152 118 return m_minimum;
Chris@152 119 }
Chris@152 120
Chris@152 121 void
Chris@152 122 EditableDenseThreeDimensionalModel::setMinimumLevel(float level)
Chris@152 123 {
Chris@152 124 m_minimum = level;
Chris@152 125 }
Chris@152 126
Chris@152 127 float
Chris@152 128 EditableDenseThreeDimensionalModel::getMaximumLevel() const
Chris@152 129 {
Chris@152 130 return m_maximum;
Chris@152 131 }
Chris@152 132
Chris@152 133 void
Chris@152 134 EditableDenseThreeDimensionalModel::setMaximumLevel(float level)
Chris@152 135 {
Chris@152 136 m_maximum = level;
Chris@152 137 }
Chris@152 138
Chris@152 139 void
Chris@182 140 EditableDenseThreeDimensionalModel::getColumn(size_t index,
Chris@182 141 Column &result) const
Chris@152 142 {
Chris@152 143 QMutexLocker locker(&m_mutex);
Chris@152 144
Chris@182 145 if (index < m_data.size()) {
Chris@152 146 result = m_data[index];
Chris@152 147 } else {
Chris@152 148 result.clear();
Chris@152 149 }
Chris@152 150
Chris@152 151 while (result.size() < m_yBinCount) result.push_back(m_minimum);
Chris@152 152 }
Chris@152 153
Chris@152 154 float
Chris@182 155 EditableDenseThreeDimensionalModel::getValueAt(size_t index, size_t n) const
Chris@152 156 {
Chris@152 157 QMutexLocker locker(&m_mutex);
Chris@152 158
Chris@182 159 if (index < m_data.size()) {
Chris@182 160 const Column &s = m_data[index];
Chris@256 161 // std::cerr << "index " << index << ", n " << n << ", res " << m_resolution << ", size " << s.size()
Chris@256 162 // << std::endl;
Chris@152 163 if (n < s.size()) return s[n];
Chris@152 164 }
Chris@152 165
Chris@152 166 return m_minimum;
Chris@152 167 }
Chris@152 168
Chris@152 169 void
Chris@182 170 EditableDenseThreeDimensionalModel::setColumn(size_t index,
Chris@182 171 const Column &values)
Chris@152 172 {
Chris@152 173 QMutexLocker locker(&m_mutex);
Chris@152 174
Chris@182 175 while (index >= m_data.size()) {
Chris@182 176 m_data.push_back(Column());
Chris@152 177 }
Chris@152 178
Chris@152 179 bool allChange = false;
Chris@152 180
Chris@152 181 for (size_t i = 0; i < values.size(); ++i) {
Chris@256 182 float value = values[i];
Chris@257 183 if (std::isnan(value) || std::isinf(value)) {
Chris@256 184 continue;
Chris@256 185 }
Chris@256 186 if (!m_haveExtents || value < m_minimum) {
Chris@256 187 m_minimum = value;
Chris@152 188 allChange = true;
Chris@152 189 }
Chris@256 190 if (!m_haveExtents || value > m_maximum) {
Chris@256 191 m_maximum = value;
Chris@152 192 allChange = true;
Chris@152 193 }
Chris@256 194 m_haveExtents = true;
Chris@152 195 }
Chris@152 196
Chris@152 197 m_data[index] = values;
Chris@152 198
Chris@182 199 long windowStart = index;
Chris@182 200 windowStart *= m_resolution;
Chris@182 201
Chris@152 202 if (m_notifyOnAdd) {
Chris@152 203 if (allChange) {
Chris@152 204 emit modelChanged();
Chris@152 205 } else {
Chris@152 206 emit modelChanged(windowStart, windowStart + m_resolution);
Chris@152 207 }
Chris@152 208 } else {
Chris@152 209 if (allChange) {
Chris@152 210 m_sinceLastNotifyMin = -1;
Chris@152 211 m_sinceLastNotifyMax = -1;
Chris@152 212 emit modelChanged();
Chris@152 213 } else {
Chris@152 214 if (m_sinceLastNotifyMin == -1 ||
Chris@152 215 windowStart < m_sinceLastNotifyMin) {
Chris@152 216 m_sinceLastNotifyMin = windowStart;
Chris@152 217 }
Chris@152 218 if (m_sinceLastNotifyMax == -1 ||
Chris@152 219 windowStart > m_sinceLastNotifyMax) {
Chris@152 220 m_sinceLastNotifyMax = windowStart;
Chris@152 221 }
Chris@152 222 }
Chris@152 223 }
Chris@152 224 }
Chris@152 225
Chris@152 226 QString
Chris@152 227 EditableDenseThreeDimensionalModel::getBinName(size_t n) const
Chris@152 228 {
Chris@152 229 if (m_binNames.size() > n) return m_binNames[n];
Chris@152 230 else return "";
Chris@152 231 }
Chris@152 232
Chris@152 233 void
Chris@152 234 EditableDenseThreeDimensionalModel::setBinName(size_t n, QString name)
Chris@152 235 {
Chris@152 236 while (m_binNames.size() <= n) m_binNames.push_back("");
Chris@152 237 m_binNames[n] = name;
Chris@152 238 emit modelChanged();
Chris@152 239 }
Chris@152 240
Chris@152 241 void
Chris@152 242 EditableDenseThreeDimensionalModel::setBinNames(std::vector<QString> names)
Chris@152 243 {
Chris@152 244 m_binNames = names;
Chris@152 245 emit modelChanged();
Chris@152 246 }
Chris@152 247
Chris@152 248 void
Chris@333 249 EditableDenseThreeDimensionalModel::setCompletion(int completion, bool update)
Chris@152 250 {
Chris@152 251 if (m_completion != completion) {
Chris@152 252 m_completion = completion;
Chris@152 253
Chris@152 254 if (completion == 100) {
Chris@152 255
Chris@152 256 m_notifyOnAdd = true; // henceforth
Chris@152 257 emit modelChanged();
Chris@152 258
Chris@152 259 } else if (!m_notifyOnAdd) {
Chris@152 260
Chris@333 261 if (update &&
Chris@333 262 m_sinceLastNotifyMin >= 0 &&
Chris@152 263 m_sinceLastNotifyMax >= 0) {
Chris@152 264 emit modelChanged(m_sinceLastNotifyMin,
Chris@152 265 m_sinceLastNotifyMax + m_resolution);
Chris@152 266 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
Chris@152 267 } else {
Chris@152 268 emit completionChanged();
Chris@152 269 }
Chris@152 270 } else {
Chris@152 271 emit completionChanged();
Chris@152 272 }
Chris@152 273 }
Chris@152 274 }
Chris@152 275
Chris@318 276 QString
Chris@318 277 EditableDenseThreeDimensionalModel::toDelimitedDataString(QString delimiter) const
Chris@318 278 {
Chris@318 279 QString s;
Chris@318 280 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@318 281 QStringList list;
Chris@318 282 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@318 283 list << QString("%1").arg(m_data[i][j]);
Chris@318 284 }
Chris@318 285 s += list.join(delimiter) + "\n";
Chris@318 286 }
Chris@318 287 return s;
Chris@318 288 }
Chris@318 289
Chris@152 290 void
Chris@152 291 EditableDenseThreeDimensionalModel::toXml(QTextStream &out,
Chris@314 292 QString indent,
Chris@314 293 QString extraAttributes) const
Chris@152 294 {
Chris@152 295 // For historical reasons we read and write "resolution" as "windowSize"
Chris@152 296
Chris@318 297 std::cerr << "EditableDenseThreeDimensionalModel::toXml" << std::endl;
Chris@318 298
Chris@314 299 Model::toXml
Chris@314 300 (out, indent,
Chris@314 301 QString("type=\"dense\" dimensions=\"3\" windowSize=\"%1\" yBinCount=\"%2\" minimum=\"%3\" maximum=\"%4\" dataset=\"%5\" %6")
Chris@152 302 .arg(m_resolution)
Chris@152 303 .arg(m_yBinCount)
Chris@152 304 .arg(m_minimum)
Chris@152 305 .arg(m_maximum)
Chris@152 306 .arg(getObjectExportId(&m_data))
Chris@152 307 .arg(extraAttributes));
Chris@152 308
Chris@152 309 out << indent;
Chris@152 310 out << QString("<dataset id=\"%1\" dimensions=\"3\" separator=\" \">\n")
Chris@152 311 .arg(getObjectExportId(&m_data));
Chris@152 312
Chris@152 313 for (size_t i = 0; i < m_binNames.size(); ++i) {
Chris@152 314 if (m_binNames[i] != "") {
Chris@152 315 out << indent + " ";
Chris@152 316 out << QString("<bin number=\"%1\" name=\"%2\"/>\n")
Chris@152 317 .arg(i).arg(m_binNames[i]);
Chris@152 318 }
Chris@152 319 }
Chris@152 320
Chris@152 321 for (size_t i = 0; i < m_data.size(); ++i) {
Chris@152 322 out << indent + " ";
Chris@152 323 out << QString("<row n=\"%1\">").arg(i);
Chris@152 324 for (size_t j = 0; j < m_data[i].size(); ++j) {
Chris@152 325 if (j > 0) out << " ";
Chris@152 326 out << m_data[i][j];
Chris@152 327 }
Chris@152 328 out << QString("</row>\n");
Chris@318 329 out.flush();
Chris@152 330 }
Chris@152 331
Chris@152 332 out << indent + "</dataset>\n";
Chris@152 333 }
Chris@152 334
Chris@152 335