annotate data/model/SparseModel.h @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents fc9323a41f5a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #ifndef _SPARSE_MODEL_H_
lbajardsilogic@0 17 #define _SPARSE_MODEL_H_
lbajardsilogic@0 18
lbajardsilogic@0 19 #include "Model.h"
lbajardsilogic@0 20 #include "base/Command.h"
lbajardsilogic@0 21 #include "base/CommandHistory.h"
lbajardsilogic@0 22
lbajardsilogic@0 23 #include <iostream>
lbajardsilogic@0 24
lbajardsilogic@0 25 #include <set>
lbajardsilogic@0 26 #include <QMutex>
lbajardsilogic@0 27 #include <QTextStream>
lbajardsilogic@0 28
lbajardsilogic@0 29
lbajardsilogic@0 30 /**
lbajardsilogic@0 31 * Model containing sparse data (points with some properties). The
lbajardsilogic@0 32 * properties depend on the point type.
lbajardsilogic@0 33 */
lbajardsilogic@0 34
lbajardsilogic@0 35 template <typename PointType>
lbajardsilogic@0 36 class SparseModel : public Model
lbajardsilogic@0 37 {
lbajardsilogic@0 38 public:
lbajardsilogic@0 39 SparseModel(size_t sampleRate, size_t resolution,
lbajardsilogic@0 40 bool notifyOnAdd = true);
lbajardsilogic@0 41 virtual ~SparseModel() { }
lbajardsilogic@0 42
lbajardsilogic@0 43 virtual bool isOK() const { return true; }
lbajardsilogic@0 44 virtual size_t getStartFrame() const;
lbajardsilogic@0 45 virtual size_t getEndFrame() const;
lbajardsilogic@0 46 virtual size_t getSampleRate() const { return m_sampleRate; }
lbajardsilogic@0 47
lbajardsilogic@0 48 virtual Model *clone() const;
lbajardsilogic@0 49
lbajardsilogic@0 50 // Number of frames of the underlying sample rate that this model
lbajardsilogic@0 51 // is capable of resolving to. For example, if m_resolution == 10
lbajardsilogic@0 52 // then every point in this model will be at a multiple of 10
lbajardsilogic@0 53 // sample frames and should be considered to cover a window ending
lbajardsilogic@0 54 // 10 sample frames later.
lbajardsilogic@0 55 virtual size_t getResolution() const {
lbajardsilogic@0 56 return m_resolution ? m_resolution : 1;
lbajardsilogic@0 57 }
lbajardsilogic@0 58 virtual void setResolution(size_t resolution);
lbajardsilogic@0 59
lbajardsilogic@0 60 typedef PointType Point;
lbajardsilogic@0 61 typedef std::multiset<PointType,
lbajardsilogic@0 62 typename PointType::OrderComparator> PointList;
lbajardsilogic@0 63 typedef typename PointList::iterator PointListIterator;
lbajardsilogic@0 64 typedef typename PointList::const_iterator PointListConstIterator;
lbajardsilogic@0 65
lbajardsilogic@0 66 /**
lbajardsilogic@0 67 * Return whether the model is empty or not.
lbajardsilogic@0 68 */
lbajardsilogic@0 69 virtual bool isEmpty() const;
lbajardsilogic@0 70
lbajardsilogic@0 71 /**
lbajardsilogic@0 72 * Get the total number of points in the model.
lbajardsilogic@0 73 */
lbajardsilogic@0 74 virtual size_t getPointCount() const;
lbajardsilogic@0 75
lbajardsilogic@0 76 /**
lbajardsilogic@0 77 * Get all of the points in this model between the given
lbajardsilogic@0 78 * boundaries (in frames), as well as up to two points before and
lbajardsilogic@0 79 * after the boundaries. If you need exact boundaries, check the
lbajardsilogic@0 80 * point coordinates in the returned list.
lbajardsilogic@0 81 */
lbajardsilogic@0 82 virtual PointList getPoints(long start, long end) const;
lbajardsilogic@0 83
lbajardsilogic@0 84 /**
lbajardsilogic@0 85 * Get all points that cover the given frame number, taking the
lbajardsilogic@0 86 * resolution of the model into account.
lbajardsilogic@0 87 */
lbajardsilogic@0 88 virtual PointList getPoints(long frame) const;
lbajardsilogic@0 89
lbajardsilogic@0 90 /**
lbajardsilogic@0 91 * Return all points that share the nearest frame number prior to
lbajardsilogic@0 92 * the given one at which there are any points.
lbajardsilogic@0 93 */
lbajardsilogic@0 94 virtual PointList getPreviousPoints(long frame) const;
lbajardsilogic@0 95
lbajardsilogic@0 96 /**
lbajardsilogic@0 97 * Return all points that share the nearest frame number
lbajardsilogic@0 98 * subsequent to the given one at which there are any points.
lbajardsilogic@0 99 */
lbajardsilogic@0 100 virtual PointList getNextPoints(long frame) const;
lbajardsilogic@0 101
lbajardsilogic@0 102 /**
lbajardsilogic@0 103 * Remove all points.
lbajardsilogic@0 104 */
lbajardsilogic@0 105 virtual void clear();
lbajardsilogic@0 106
lbajardsilogic@0 107 /**
lbajardsilogic@0 108 * Add a point.
lbajardsilogic@0 109 */
lbajardsilogic@0 110 virtual void addPoint(const PointType &point);
lbajardsilogic@0 111
lbajardsilogic@0 112 /**
lbajardsilogic@0 113 * Remove a point. Points are not necessarily unique, so this
lbajardsilogic@0 114 * function will remove the first point that compares equal to the
lbajardsilogic@0 115 * supplied one using Point::Comparator. Other identical points
lbajardsilogic@0 116 * may remain in the model.
lbajardsilogic@0 117 */
lbajardsilogic@0 118 virtual void deletePoint(const PointType &point);
lbajardsilogic@0 119
lbajardsilogic@0 120 virtual void setCompletion(int completion);
lbajardsilogic@0 121 virtual int getCompletion() const { return m_completion; }
lbajardsilogic@0 122
lbajardsilogic@0 123 virtual bool hasTextLabels() const { return m_hasTextLabels; }
lbajardsilogic@0 124
lbajardsilogic@0 125 virtual void toXml(QTextStream &out,
lbajardsilogic@0 126 QString indent = "",
lbajardsilogic@0 127 QString extraAttributes = "") const;
lbajardsilogic@0 128
lbajardsilogic@0 129 virtual QString toXmlString(QString indent = "",
lbajardsilogic@0 130 QString extraAttributes = "") const;
lbajardsilogic@0 131
lbajardsilogic@0 132 virtual QString toDelimitedDataString(QString delimiter) const
lbajardsilogic@0 133 {
lbajardsilogic@0 134 QString s;
lbajardsilogic@0 135 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) {
lbajardsilogic@0 136 s += i->toDelimitedDataString(delimiter, m_sampleRate) + "\n";
lbajardsilogic@0 137 }
lbajardsilogic@0 138 return s;
lbajardsilogic@0 139 }
lbajardsilogic@0 140
lbajardsilogic@0 141 /**
lbajardsilogic@0 142 * Command to add a point, with undo.
lbajardsilogic@0 143 */
lbajardsilogic@0 144 class AddPointCommand : public Command
lbajardsilogic@0 145 {
lbajardsilogic@0 146 public:
lbajardsilogic@0 147 AddPointCommand(SparseModel<PointType> *model,
lbajardsilogic@0 148 const PointType &point,
lbajardsilogic@0 149 QString name = "") :
lbajardsilogic@0 150 m_model(model), m_point(point), m_name(name) { }
lbajardsilogic@0 151
lbajardsilogic@0 152 virtual QString getName() const {
lbajardsilogic@0 153 return (m_name == "" ? tr("Add Point") : m_name);
lbajardsilogic@0 154 }
lbajardsilogic@0 155
lbajardsilogic@0 156 virtual void execute() { m_model->addPoint(m_point); }
lbajardsilogic@0 157 virtual void unexecute() { m_model->deletePoint(m_point); }
lbajardsilogic@0 158
lbajardsilogic@0 159 const PointType &getPoint() const { return m_point; }
lbajardsilogic@0 160
lbajardsilogic@0 161 private:
lbajardsilogic@0 162 SparseModel<PointType> *m_model;
lbajardsilogic@0 163 PointType m_point;
lbajardsilogic@0 164 QString m_name;
lbajardsilogic@0 165 };
lbajardsilogic@0 166
lbajardsilogic@0 167
lbajardsilogic@0 168 /**
lbajardsilogic@0 169 * Command to remove a point, with undo.
lbajardsilogic@0 170 */
lbajardsilogic@0 171 class DeletePointCommand : public Command
lbajardsilogic@0 172 {
lbajardsilogic@0 173 public:
lbajardsilogic@0 174 DeletePointCommand(SparseModel<PointType> *model,
lbajardsilogic@0 175 const PointType &point) :
lbajardsilogic@0 176 m_model(model), m_point(point) { }
lbajardsilogic@0 177
lbajardsilogic@0 178 virtual QString getName() const { return tr("Delete Point"); }
lbajardsilogic@0 179
lbajardsilogic@0 180 virtual void execute() { m_model->deletePoint(m_point); }
lbajardsilogic@0 181 virtual void unexecute() { m_model->addPoint(m_point); }
lbajardsilogic@0 182
lbajardsilogic@0 183 const PointType &getPoint() const { return m_point; }
lbajardsilogic@0 184
lbajardsilogic@0 185 private:
lbajardsilogic@0 186 SparseModel<PointType> *m_model;
lbajardsilogic@0 187 PointType m_point;
lbajardsilogic@0 188 };
lbajardsilogic@0 189
lbajardsilogic@0 190
lbajardsilogic@0 191 /**
lbajardsilogic@0 192 * Command to add or remove a series of points, with undo.
lbajardsilogic@0 193 * Consecutive add/remove pairs for the same point are collapsed.
lbajardsilogic@0 194 */
lbajardsilogic@0 195 class EditCommand : public MacroCommand
lbajardsilogic@0 196 {
lbajardsilogic@0 197 public:
lbajardsilogic@0 198 EditCommand(SparseModel<PointType> *model, QString commandName);
lbajardsilogic@0 199
lbajardsilogic@0 200 virtual void addPoint(const PointType &point);
lbajardsilogic@0 201 virtual void deletePoint(const PointType &point);
lbajardsilogic@0 202
lbajardsilogic@0 203 /**
lbajardsilogic@0 204 * Stack an arbitrary other command in the same sequence.
lbajardsilogic@0 205 */
lbajardsilogic@0 206 virtual void addCommand(Command *command) { addCommand(command, true); }
lbajardsilogic@0 207
lbajardsilogic@0 208 /**
lbajardsilogic@0 209 * If any points have been added or deleted, add this command
lbajardsilogic@0 210 * to the command history. Otherwise delete the command.
lbajardsilogic@0 211 */
lbajardsilogic@0 212 virtual void finish();
lbajardsilogic@0 213
lbajardsilogic@0 214 protected:
lbajardsilogic@0 215 virtual void addCommand(Command *command, bool executeFirst);
lbajardsilogic@0 216
lbajardsilogic@0 217 SparseModel<PointType> *m_model;
lbajardsilogic@0 218 };
lbajardsilogic@0 219
lbajardsilogic@0 220
lbajardsilogic@0 221 /**
lbajardsilogic@0 222 * Command to relabel a point.
lbajardsilogic@0 223 */
lbajardsilogic@0 224 class RelabelCommand : public Command
lbajardsilogic@0 225 {
lbajardsilogic@0 226 public:
lbajardsilogic@0 227 RelabelCommand(SparseModel<PointType> *model,
lbajardsilogic@0 228 const PointType &point,
lbajardsilogic@0 229 QString newLabel) :
lbajardsilogic@0 230 m_model(model), m_oldPoint(point), m_newPoint(point) {
lbajardsilogic@0 231 m_newPoint.label = newLabel;
lbajardsilogic@0 232 }
lbajardsilogic@0 233
lbajardsilogic@0 234 virtual QString getName() const { return tr("Re-Label Point"); }
lbajardsilogic@0 235
lbajardsilogic@0 236 virtual void execute() {
lbajardsilogic@0 237 m_model->deletePoint(m_oldPoint);
lbajardsilogic@0 238 m_model->addPoint(m_newPoint);
lbajardsilogic@0 239 std::swap(m_oldPoint, m_newPoint);
lbajardsilogic@0 240 }
lbajardsilogic@0 241
lbajardsilogic@0 242 virtual void unexecute() { execute(); }
lbajardsilogic@0 243
lbajardsilogic@0 244 private:
lbajardsilogic@0 245 SparseModel<PointType> *m_model;
lbajardsilogic@0 246 PointType m_oldPoint;
lbajardsilogic@0 247 PointType m_newPoint;
lbajardsilogic@0 248 };
lbajardsilogic@0 249
lbajardsilogic@0 250
lbajardsilogic@0 251
lbajardsilogic@0 252 protected:
lbajardsilogic@0 253 size_t m_sampleRate;
lbajardsilogic@0 254 size_t m_resolution;
lbajardsilogic@0 255 bool m_notifyOnAdd;
lbajardsilogic@0 256 long m_sinceLastNotifyMin;
lbajardsilogic@0 257 long m_sinceLastNotifyMax;
lbajardsilogic@0 258 bool m_hasTextLabels;
lbajardsilogic@0 259
lbajardsilogic@0 260 PointList m_points;
lbajardsilogic@0 261 size_t m_pointCount;
lbajardsilogic@0 262 mutable QMutex m_mutex;
lbajardsilogic@0 263 int m_completion;
lbajardsilogic@0 264 };
lbajardsilogic@0 265
lbajardsilogic@0 266
lbajardsilogic@0 267 template <typename PointType>
lbajardsilogic@0 268 SparseModel<PointType>::SparseModel(size_t sampleRate,
lbajardsilogic@0 269 size_t resolution,
lbajardsilogic@0 270 bool notifyOnAdd) :
lbajardsilogic@0 271 m_sampleRate(sampleRate),
lbajardsilogic@0 272 m_resolution(resolution),
lbajardsilogic@0 273 m_notifyOnAdd(notifyOnAdd),
lbajardsilogic@0 274 m_sinceLastNotifyMin(-1),
lbajardsilogic@0 275 m_sinceLastNotifyMax(-1),
lbajardsilogic@0 276 m_hasTextLabels(false),
lbajardsilogic@0 277 m_pointCount(0),
lbajardsilogic@0 278 m_completion(100)
lbajardsilogic@0 279 {
lbajardsilogic@0 280 }
lbajardsilogic@0 281
lbajardsilogic@0 282 template <typename PointType>
lbajardsilogic@0 283 size_t
lbajardsilogic@0 284 SparseModel<PointType>::getStartFrame() const
lbajardsilogic@0 285 {
lbajardsilogic@0 286 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 287 size_t f = 0;
lbajardsilogic@0 288 if (!m_points.empty()) {
lbajardsilogic@0 289 f = m_points.begin()->frame;
lbajardsilogic@0 290 }
lbajardsilogic@0 291 return f;
lbajardsilogic@0 292 }
lbajardsilogic@0 293
lbajardsilogic@0 294 template <typename PointType>
lbajardsilogic@0 295 size_t
lbajardsilogic@0 296 SparseModel<PointType>::getEndFrame() const
lbajardsilogic@0 297 {
lbajardsilogic@0 298 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 299 size_t f = 0;
lbajardsilogic@0 300 if (!m_points.empty()) {
lbajardsilogic@0 301 PointListConstIterator i(m_points.end());
lbajardsilogic@0 302 f = (--i)->frame;
lbajardsilogic@0 303 }
lbajardsilogic@0 304 return f;
lbajardsilogic@0 305 }
lbajardsilogic@0 306
lbajardsilogic@0 307 template <typename PointType>
lbajardsilogic@0 308 Model *
lbajardsilogic@0 309 SparseModel<PointType>::clone() const
lbajardsilogic@0 310 {
lbajardsilogic@0 311 SparseModel<PointType> *model =
lbajardsilogic@0 312 new SparseModel<PointType>(m_sampleRate, m_resolution, m_notifyOnAdd);
lbajardsilogic@0 313 model->m_points = m_points;
lbajardsilogic@0 314 model->m_pointCount = m_pointCount;
lbajardsilogic@0 315 return model;
lbajardsilogic@0 316 }
lbajardsilogic@0 317
lbajardsilogic@0 318 template <typename PointType>
lbajardsilogic@0 319 bool
lbajardsilogic@0 320 SparseModel<PointType>::isEmpty() const
lbajardsilogic@0 321 {
lbajardsilogic@0 322 return m_pointCount == 0;
lbajardsilogic@0 323 }
lbajardsilogic@0 324
lbajardsilogic@0 325 template <typename PointType>
lbajardsilogic@0 326 size_t
lbajardsilogic@0 327 SparseModel<PointType>::getPointCount() const
lbajardsilogic@0 328 {
lbajardsilogic@0 329 return m_pointCount;
lbajardsilogic@0 330 }
lbajardsilogic@0 331
lbajardsilogic@0 332 template <typename PointType>
lbajardsilogic@0 333 typename SparseModel<PointType>::PointList
lbajardsilogic@0 334 SparseModel<PointType>::getPoints(long start, long end) const
lbajardsilogic@0 335 {
lbajardsilogic@0 336 if (start > end) return PointList();
lbajardsilogic@0 337 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 338
lbajardsilogic@0 339 PointType startPoint(start), endPoint(end);
lbajardsilogic@0 340
lbajardsilogic@0 341 PointListConstIterator startItr = m_points.lower_bound(startPoint);
lbajardsilogic@0 342 PointListConstIterator endItr = m_points.upper_bound(endPoint);
lbajardsilogic@0 343
lbajardsilogic@0 344 if (startItr != m_points.begin()) --startItr;
lbajardsilogic@0 345 if (startItr != m_points.begin()) --startItr;
lbajardsilogic@0 346 if (endItr != m_points.end()) ++endItr;
lbajardsilogic@0 347 if (endItr != m_points.end()) ++endItr;
lbajardsilogic@0 348
lbajardsilogic@0 349 PointList rv;
lbajardsilogic@0 350
lbajardsilogic@0 351 for (PointListConstIterator i = startItr; i != endItr; ++i) {
lbajardsilogic@0 352 rv.insert(*i);
lbajardsilogic@0 353 }
lbajardsilogic@0 354
lbajardsilogic@0 355 return rv;
lbajardsilogic@0 356 }
lbajardsilogic@0 357
lbajardsilogic@0 358 template <typename PointType>
lbajardsilogic@0 359 typename SparseModel<PointType>::PointList
lbajardsilogic@0 360 SparseModel<PointType>::getPoints(long frame) const
lbajardsilogic@0 361 {
lbajardsilogic@0 362 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 363
lbajardsilogic@0 364 if (m_resolution == 0) return PointList();
lbajardsilogic@0 365
lbajardsilogic@0 366 long start = (frame / m_resolution) * m_resolution;
lbajardsilogic@0 367 long end = start + m_resolution;
lbajardsilogic@0 368
lbajardsilogic@0 369 PointType startPoint(start), endPoint(end);
lbajardsilogic@0 370
lbajardsilogic@0 371 PointListConstIterator startItr = m_points.lower_bound(startPoint);
lbajardsilogic@0 372 PointListConstIterator endItr = m_points.upper_bound(endPoint);
lbajardsilogic@0 373
lbajardsilogic@0 374 PointList rv;
lbajardsilogic@0 375
lbajardsilogic@0 376 for (PointListConstIterator i = startItr; i != endItr; ++i) {
lbajardsilogic@0 377 rv.insert(*i);
lbajardsilogic@0 378 }
lbajardsilogic@0 379
lbajardsilogic@0 380 return rv;
lbajardsilogic@0 381 }
lbajardsilogic@0 382
lbajardsilogic@0 383 template <typename PointType>
lbajardsilogic@0 384 typename SparseModel<PointType>::PointList
lbajardsilogic@0 385 SparseModel<PointType>::getPreviousPoints(long originFrame) const
lbajardsilogic@0 386 {
lbajardsilogic@0 387 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 388
lbajardsilogic@0 389 PointType lookupPoint(originFrame);
lbajardsilogic@0 390 PointList rv;
lbajardsilogic@0 391
lbajardsilogic@0 392 PointListConstIterator i = m_points.lower_bound(lookupPoint);
lbajardsilogic@0 393 if (i == m_points.begin()) return rv;
lbajardsilogic@0 394
lbajardsilogic@0 395 --i;
lbajardsilogic@0 396 long frame = i->frame;
lbajardsilogic@0 397 while (i->frame == frame) {
lbajardsilogic@0 398 rv.insert(*i);
lbajardsilogic@0 399 if (i == m_points.begin()) break;
lbajardsilogic@0 400 --i;
lbajardsilogic@0 401 }
lbajardsilogic@0 402
lbajardsilogic@0 403 return rv;
lbajardsilogic@0 404 }
lbajardsilogic@0 405
lbajardsilogic@0 406 template <typename PointType>
lbajardsilogic@0 407 typename SparseModel<PointType>::PointList
lbajardsilogic@0 408 SparseModel<PointType>::getNextPoints(long originFrame) const
lbajardsilogic@0 409 {
lbajardsilogic@0 410 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 411
lbajardsilogic@0 412 PointType lookupPoint(originFrame);
lbajardsilogic@0 413 PointList rv;
lbajardsilogic@0 414
lbajardsilogic@0 415 PointListConstIterator i = m_points.upper_bound(lookupPoint);
lbajardsilogic@0 416 if (i == m_points.end()) return rv;
lbajardsilogic@0 417
lbajardsilogic@0 418 long frame = i->frame;
lbajardsilogic@0 419 while (i != m_points.end() && i->frame == frame) {
lbajardsilogic@0 420 rv.insert(*i);
lbajardsilogic@0 421 ++i;
lbajardsilogic@0 422 }
lbajardsilogic@0 423
lbajardsilogic@0 424 return rv;
lbajardsilogic@0 425 }
lbajardsilogic@0 426
lbajardsilogic@0 427 template <typename PointType>
lbajardsilogic@0 428 void
lbajardsilogic@0 429 SparseModel<PointType>::setResolution(size_t resolution)
lbajardsilogic@0 430 {
lbajardsilogic@0 431 {
lbajardsilogic@0 432 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 433 m_resolution = resolution;
lbajardsilogic@0 434 }
lbajardsilogic@0 435 emit modelChanged();
lbajardsilogic@0 436 }
lbajardsilogic@0 437
lbajardsilogic@0 438 template <typename PointType>
lbajardsilogic@0 439 void
lbajardsilogic@0 440 SparseModel<PointType>::clear()
lbajardsilogic@0 441 {
lbajardsilogic@0 442 {
lbajardsilogic@0 443 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 444 m_points.clear();
lbajardsilogic@0 445 m_pointCount = 0;
lbajardsilogic@0 446 }
lbajardsilogic@0 447 emit modelChanged();
lbajardsilogic@0 448 }
lbajardsilogic@0 449
lbajardsilogic@0 450 template <typename PointType>
lbajardsilogic@0 451 void
lbajardsilogic@0 452 SparseModel<PointType>::addPoint(const PointType &point)
lbajardsilogic@0 453 {
lbajardsilogic@0 454 // std::cout << "SparseModel<Point>::addPoint(" << point.frame << ", "
lbajardsilogic@0 455 // << point.value << ")" << std::endl;
lbajardsilogic@0 456
lbajardsilogic@0 457 {
lbajardsilogic@0 458 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 459 m_points.insert(point);
lbajardsilogic@0 460 m_pointCount++;
lbajardsilogic@0 461 if (point.label != "") m_hasTextLabels = true;
lbajardsilogic@0 462 }
lbajardsilogic@0 463
lbajardsilogic@0 464 // Even though this model is nominally sparse, there may still be
lbajardsilogic@0 465 // too many signals going on here (especially as they'll probably
lbajardsilogic@0 466 // be queued from one thread to another), which is why we need the
lbajardsilogic@0 467 // notifyOnAdd as an option rather than a necessity (the
lbajardsilogic@0 468 // alternative is to notify on setCompletion).
lbajardsilogic@0 469
lbajardsilogic@0 470 if (m_notifyOnAdd) {
lbajardsilogic@0 471 emit modelChanged(point.frame, point.frame + m_resolution);
lbajardsilogic@0 472 } else {
lbajardsilogic@0 473 if (m_sinceLastNotifyMin == -1 ||
lbajardsilogic@0 474 point.frame < m_sinceLastNotifyMin) {
lbajardsilogic@0 475 m_sinceLastNotifyMin = point.frame;
lbajardsilogic@0 476 }
lbajardsilogic@0 477 if (m_sinceLastNotifyMax == -1 ||
lbajardsilogic@0 478 point.frame > m_sinceLastNotifyMax) {
lbajardsilogic@0 479 m_sinceLastNotifyMax = point.frame;
lbajardsilogic@0 480 }
lbajardsilogic@0 481 }
lbajardsilogic@0 482 }
lbajardsilogic@0 483
lbajardsilogic@0 484 template <typename PointType>
lbajardsilogic@0 485 void
lbajardsilogic@0 486 SparseModel<PointType>::deletePoint(const PointType &point)
lbajardsilogic@0 487 {
lbajardsilogic@0 488 {
lbajardsilogic@0 489 QMutexLocker locker(&m_mutex);
lbajardsilogic@0 490
lbajardsilogic@0 491 PointListIterator i = m_points.lower_bound(point);
lbajardsilogic@0 492 typename PointType::Comparator comparator;
lbajardsilogic@0 493 while (i != m_points.end()) {
lbajardsilogic@0 494 if (i->frame > point.frame) break;
lbajardsilogic@0 495 if (!comparator(*i, point) && !comparator(point, *i)) {
lbajardsilogic@0 496 m_points.erase(i);
lbajardsilogic@0 497 m_pointCount--;
lbajardsilogic@0 498 break;
lbajardsilogic@0 499 }
lbajardsilogic@0 500 ++i;
lbajardsilogic@0 501 }
lbajardsilogic@0 502 }
lbajardsilogic@0 503 // std::cout << "SparseOneDimensionalModel: emit modelChanged("
lbajardsilogic@0 504 // << point.frame << ")" << std::endl;
lbajardsilogic@0 505 emit modelChanged(point.frame, point.frame + m_resolution);
lbajardsilogic@0 506 }
lbajardsilogic@0 507
lbajardsilogic@0 508 template <typename PointType>
lbajardsilogic@0 509 void
lbajardsilogic@0 510 SparseModel<PointType>::setCompletion(int completion)
lbajardsilogic@0 511 {
lbajardsilogic@0 512 // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl;
lbajardsilogic@0 513
lbajardsilogic@0 514 if (m_completion != completion) {
lbajardsilogic@0 515 m_completion = completion;
lbajardsilogic@0 516
lbajardsilogic@0 517 if (completion == 100) {
lbajardsilogic@0 518
lbajardsilogic@0 519 m_notifyOnAdd = true; // henceforth
lbajardsilogic@0 520 emit modelChanged();
lbajardsilogic@0 521
lbajardsilogic@0 522 } else if (!m_notifyOnAdd) {
lbajardsilogic@0 523
lbajardsilogic@0 524 if (m_sinceLastNotifyMin >= 0 &&
lbajardsilogic@0 525 m_sinceLastNotifyMax >= 0) {
lbajardsilogic@0 526 emit modelChanged(m_sinceLastNotifyMin, m_sinceLastNotifyMax);
lbajardsilogic@0 527 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
lbajardsilogic@0 528 } else {
lbajardsilogic@0 529 emit completionChanged();
lbajardsilogic@0 530 }
lbajardsilogic@0 531 } else {
lbajardsilogic@0 532 emit completionChanged();
lbajardsilogic@0 533 }
lbajardsilogic@0 534 }
lbajardsilogic@0 535 }
lbajardsilogic@0 536
lbajardsilogic@0 537 template <typename PointType>
lbajardsilogic@0 538 void
lbajardsilogic@0 539 SparseModel<PointType>::toXml(QTextStream &out,
lbajardsilogic@0 540 QString indent,
lbajardsilogic@0 541 QString extraAttributes) const
lbajardsilogic@0 542 {
lbajardsilogic@0 543 Model::toXml
lbajardsilogic@0 544 (out,
lbajardsilogic@0 545 indent,
lbajardsilogic@0 546 QString("type=\"sparse\" dimensions=\"%1\" resolution=\"%2\" notifyOnAdd=\"%3\" dataset=\"%4\" %5")
lbajardsilogic@0 547 .arg(PointType(0).getDimensions())
lbajardsilogic@0 548 .arg(m_resolution)
lbajardsilogic@0 549 .arg(m_notifyOnAdd ? "true" : "false")
lbajardsilogic@0 550 .arg(getObjectExportId(&m_points))
lbajardsilogic@0 551 .arg(extraAttributes));
lbajardsilogic@0 552
lbajardsilogic@0 553 out << indent;
lbajardsilogic@0 554 out << QString("<dataset id=\"%1\" dimensions=\"%2\">\n")
lbajardsilogic@0 555 .arg(getObjectExportId(&m_points))
lbajardsilogic@0 556 .arg(PointType(0).getDimensions());
lbajardsilogic@0 557
lbajardsilogic@0 558 for (PointListConstIterator i = m_points.begin(); i != m_points.end(); ++i) {
lbajardsilogic@0 559 out << i->toXmlString(indent + " ");
lbajardsilogic@0 560 }
lbajardsilogic@0 561
lbajardsilogic@0 562 out << indent;
lbajardsilogic@0 563 out << "</dataset>\n";
lbajardsilogic@0 564 }
lbajardsilogic@0 565
lbajardsilogic@0 566 template <typename PointType>
lbajardsilogic@0 567 QString
lbajardsilogic@0 568 SparseModel<PointType>::toXmlString(QString indent,
lbajardsilogic@0 569 QString extraAttributes) const
lbajardsilogic@0 570 {
lbajardsilogic@0 571 QString s;
lbajardsilogic@0 572
lbajardsilogic@0 573 {
lbajardsilogic@0 574 QTextStream out(&s);
lbajardsilogic@0 575 toXml(out, indent, extraAttributes);
lbajardsilogic@0 576 }
lbajardsilogic@0 577
lbajardsilogic@0 578 return s;
lbajardsilogic@0 579 }
lbajardsilogic@0 580
lbajardsilogic@0 581 template <typename PointType>
lbajardsilogic@0 582 SparseModel<PointType>::EditCommand::EditCommand(SparseModel *model,
lbajardsilogic@0 583 QString commandName) :
lbajardsilogic@0 584 MacroCommand(commandName),
lbajardsilogic@0 585 m_model(model)
lbajardsilogic@0 586 {
lbajardsilogic@0 587 }
lbajardsilogic@0 588
lbajardsilogic@0 589 template <typename PointType>
lbajardsilogic@0 590 void
lbajardsilogic@0 591 SparseModel<PointType>::EditCommand::addPoint(const PointType &point)
lbajardsilogic@0 592 {
lbajardsilogic@0 593 addCommand(new AddPointCommand(m_model, point), true);
lbajardsilogic@0 594 }
lbajardsilogic@0 595
lbajardsilogic@0 596 template <typename PointType>
lbajardsilogic@0 597 void
lbajardsilogic@0 598 SparseModel<PointType>::EditCommand::deletePoint(const PointType &point)
lbajardsilogic@0 599 {
lbajardsilogic@0 600 addCommand(new DeletePointCommand(m_model, point), true);
lbajardsilogic@0 601 }
lbajardsilogic@0 602
lbajardsilogic@0 603 template <typename PointType>
lbajardsilogic@0 604 void
lbajardsilogic@0 605 SparseModel<PointType>::EditCommand::finish()
lbajardsilogic@0 606 {
lbajardsilogic@0 607 if (!m_commands.empty()) {
lbajardsilogic@0 608 CommandHistory::getInstance()->addCommand(this, false);
lbajardsilogic@0 609 } else {
lbajardsilogic@0 610 delete this;
lbajardsilogic@0 611 }
lbajardsilogic@0 612 }
lbajardsilogic@0 613
lbajardsilogic@0 614 template <typename PointType>
lbajardsilogic@0 615 void
lbajardsilogic@0 616 SparseModel<PointType>::EditCommand::addCommand(Command *command,
lbajardsilogic@0 617 bool executeFirst)
lbajardsilogic@0 618 {
lbajardsilogic@0 619 if (executeFirst) command->execute();
lbajardsilogic@0 620
lbajardsilogic@0 621 if (!m_commands.empty()) {
lbajardsilogic@0 622 DeletePointCommand *dpc = dynamic_cast<DeletePointCommand *>(command);
lbajardsilogic@0 623 if (dpc) {
lbajardsilogic@0 624 AddPointCommand *apc = dynamic_cast<AddPointCommand *>
lbajardsilogic@0 625 (m_commands[m_commands.size() - 1]);
lbajardsilogic@0 626 typename PointType::Comparator comparator;
lbajardsilogic@0 627 if (apc) {
lbajardsilogic@0 628 if (!comparator(apc->getPoint(), dpc->getPoint()) &&
lbajardsilogic@0 629 !comparator(dpc->getPoint(), apc->getPoint())) {
lbajardsilogic@0 630 deleteCommand(apc);
lbajardsilogic@0 631 return;
lbajardsilogic@0 632 }
lbajardsilogic@0 633 }
lbajardsilogic@0 634 }
lbajardsilogic@0 635 }
lbajardsilogic@0 636
lbajardsilogic@0 637 MacroCommand::addCommand(command);
lbajardsilogic@0 638 }
lbajardsilogic@0 639
lbajardsilogic@0 640
lbajardsilogic@0 641 #endif
lbajardsilogic@0 642
lbajardsilogic@0 643
lbajardsilogic@0 644