comparison data/model/SparseModel.h @ 420:50a956688baa

* reorganise tabular data editor model support
author Chris Cannam
date Wed, 11 Jun 2008 16:13:25 +0000
parents a00902d5f0ab
children 4caa28a0a8a2
comparison
equal deleted inserted replaced
419:64e7bbb255d3 420:50a956688baa
15 15
16 #ifndef _SPARSE_MODEL_H_ 16 #ifndef _SPARSE_MODEL_H_
17 #define _SPARSE_MODEL_H_ 17 #define _SPARSE_MODEL_H_
18 18
19 #include "Model.h" 19 #include "Model.h"
20 #include "TabularModel.h"
20 #include "base/Command.h" 21 #include "base/Command.h"
21 22
22 #include <iostream> 23 #include <iostream>
23 24
24 #include <set> 25 #include <set>
26 #include <vector>
27 #include <algorithm>
28
25 #include <QMutex> 29 #include <QMutex>
26 #include <QTextStream> 30 #include <QTextStream>
27
28 31
29 /** 32 /**
30 * Model containing sparse data (points with some properties). The 33 * Model containing sparse data (points with some properties). The
31 * properties depend on the point type. 34 * properties depend on the point type.
32 */ 35 */
33 36
34 template <typename PointType> 37 template <typename PointType>
35 class SparseModel : public Model 38 class SparseModel : public Model,
39 public TabularModel
36 { 40 {
37 public: 41 public:
38 SparseModel(size_t sampleRate, size_t resolution, 42 SparseModel(size_t sampleRate, size_t resolution,
39 bool notifyOnAdd = true); 43 bool notifyOnAdd = true);
40 virtual ~SparseModel() { } 44 virtual ~SparseModel() { }
256 SparseModel<PointType> *m_model; 260 SparseModel<PointType> *m_model;
257 PointType m_oldPoint; 261 PointType m_oldPoint;
258 PointType m_newPoint; 262 PointType m_newPoint;
259 }; 263 };
260 264
265 /**
266 * TabularModel methods.
267 */
268
269 virtual int getRowCount() const
270 {
271 return m_points.size();
272 }
273
274 virtual long getFrameForRow(int row) const
275 {
276 PointListIterator i = getPointListIteratorForRow(row);
277 if (i == m_points.end()) return 0;
278 return i->frame;
279 }
280
281 virtual int getRowForFrame(long frame) const
282 {
283 if (m_rows.empty()) rebuildRowVector();
284 std::vector<long>::iterator i =
285 std::lower_bound(m_rows.begin(), m_rows.end(), frame);
286 return std::distance(m_rows.begin(), i);
287 }
288
289 //!!! just for now
290 virtual int getColumnCount() const { return 1; }
291 virtual QString getHeading(int column) const { return tr("Unknown"); }
292 virtual QVariant getData(int row, int column, int role) const {
293 return QVariant();
294 }
295 virtual bool isColumnTimeValue(int column) const { return true; }
261 296
262
263 protected: 297 protected:
264 size_t m_sampleRate; 298 size_t m_sampleRate;
265 size_t m_resolution; 299 size_t m_resolution;
266 bool m_notifyOnAdd; 300 bool m_notifyOnAdd;
267 long m_sinceLastNotifyMin; 301 long m_sinceLastNotifyMin;
270 304
271 PointList m_points; 305 PointList m_points;
272 size_t m_pointCount; 306 size_t m_pointCount;
273 mutable QMutex m_mutex; 307 mutable QMutex m_mutex;
274 int m_completion; 308 int m_completion;
309
310 void getPointIterators(long frame,
311 PointListIterator &startItr,
312 PointListIterator &endItr) const;
313
314 // This is only used if the model is called on to act in
315 // TabularModel mode
316 mutable std::vector<long> m_rows; // map from row number to frame
317 void rebuildRowVector() const
318 {
319 m_rows.clear();
320 for (PointListIterator i = m_points.begin(); i != m_points.end(); ++i) {
321 m_rows.push_back(i->frame);
322 }
323 }
324
325 PointListIterator getPointListIteratorForRow(int row) const
326 {
327 if (m_rows.empty()) rebuildRowVector();
328 if (row < 0 || row + 1 > m_rows.size()) return m_points.end();
329
330 size_t frame = m_rows[row];
331 int indexAtFrame = 0;
332 int ri = row;
333 while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; }
334 int initialIndexAtFrame = indexAtFrame;
335
336 PointListIterator i0, i1;
337 getPointIterators(frame, i0, i1);
338 PointListIterator i = i0;
339
340 for (i = i0; i != i1; ++i) {
341 if (indexAtFrame > 0) { --indexAtFrame; continue; }
342 return i;
343 }
344
345 if (indexAtFrame > 0) {
346 std::cerr << "WARNING: SparseModel::getPointListIteratorForRow: No iterator available for row " << row << " (frame = " << frame << ", index at frame = " << initialIndexAtFrame << ", leftover index " << indexAtFrame << ")" << std::endl;
347 }
348 return i;
349 }
275 }; 350 };
276 351
277 352
278 template <typename PointType> 353 template <typename PointType>
279 SparseModel<PointType>::SparseModel(size_t sampleRate, 354 SparseModel<PointType>::SparseModel(size_t sampleRate,
368 443
369 template <typename PointType> 444 template <typename PointType>
370 typename SparseModel<PointType>::PointList 445 typename SparseModel<PointType>::PointList
371 SparseModel<PointType>::getPoints(long frame) const 446 SparseModel<PointType>::getPoints(long frame) const
372 { 447 {
448 PointListIterator startItr, endItr;
449 getPointIterators(frame, startItr, endItr);
450
451 PointList rv;
452
453 for (PointListIterator i = startItr; i != endItr; ++i) {
454 rv.insert(*i);
455 }
456
457 return rv;
458 }
459
460 template <typename PointType>
461 void
462 SparseModel<PointType>::getPointIterators(long frame,
463 PointListIterator &startItr,
464 PointListIterator &endItr) const
465 {
373 QMutexLocker locker(&m_mutex); 466 QMutexLocker locker(&m_mutex);
374 467
375 if (m_resolution == 0) return PointList(); 468 if (m_resolution == 0) {
469 startItr = m_points.end();
470 endItr = m_points.end();
471 return;
472 }
376 473
377 long start = (frame / m_resolution) * m_resolution; 474 long start = (frame / m_resolution) * m_resolution;
378 long end = start + m_resolution; 475 long end = start + m_resolution;
379 476
380 PointType startPoint(start), endPoint(end); 477 PointType startPoint(start), endPoint(end);
381 478
382 PointListIterator startItr = m_points.lower_bound(startPoint); 479 startItr = m_points.lower_bound(startPoint);
383 PointListIterator endItr = m_points.upper_bound(endPoint); 480 endItr = m_points.upper_bound(endPoint);
384
385 PointList rv;
386
387 for (PointListIterator i = startItr; i != endItr; ++i) {
388 rv.insert(*i);
389 }
390
391 return rv;
392 } 481 }
393 482
394 template <typename PointType> 483 template <typename PointType>
395 typename SparseModel<PointType>::PointList 484 typename SparseModel<PointType>::PointList
396 SparseModel<PointType>::getPreviousPoints(long originFrame) const 485 SparseModel<PointType>::getPreviousPoints(long originFrame) const
441 { 530 {
442 { 531 {
443 QMutexLocker locker(&m_mutex); 532 QMutexLocker locker(&m_mutex);
444 m_resolution = resolution; 533 m_resolution = resolution;
445 } 534 }
535 m_rows.clear();
446 emit modelChanged(); 536 emit modelChanged();
447 } 537 }
448 538
449 template <typename PointType> 539 template <typename PointType>
450 void 540 void
453 { 543 {
454 QMutexLocker locker(&m_mutex); 544 QMutexLocker locker(&m_mutex);
455 m_points.clear(); 545 m_points.clear();
456 m_pointCount = 0; 546 m_pointCount = 0;
457 } 547 }
548 m_rows.clear();
458 emit modelChanged(); 549 emit modelChanged();
459 } 550 }
460 551
461 template <typename PointType> 552 template <typename PointType>
462 void 553 void
474 // be queued from one thread to another), which is why we need the 565 // be queued from one thread to another), which is why we need the
475 // notifyOnAdd as an option rather than a necessity (the 566 // notifyOnAdd as an option rather than a necessity (the
476 // alternative is to notify on setCompletion). 567 // alternative is to notify on setCompletion).
477 568
478 if (m_notifyOnAdd) { 569 if (m_notifyOnAdd) {
570 m_rows.clear(); //!!! inefficient
479 emit modelChanged(point.frame, point.frame + m_resolution); 571 emit modelChanged(point.frame, point.frame + m_resolution);
480 } else { 572 } else {
481 if (m_sinceLastNotifyMin == -1 || 573 if (m_sinceLastNotifyMin == -1 ||
482 point.frame < m_sinceLastNotifyMin) { 574 point.frame < m_sinceLastNotifyMin) {
483 m_sinceLastNotifyMin = point.frame; 575 m_sinceLastNotifyMin = point.frame;
508 ++i; 600 ++i;
509 } 601 }
510 } 602 }
511 // std::cout << "SparseOneDimensionalModel: emit modelChanged(" 603 // std::cout << "SparseOneDimensionalModel: emit modelChanged("
512 // << point.frame << ")" << std::endl; 604 // << point.frame << ")" << std::endl;
605 m_rows.clear(); //!!! inefficient
513 emit modelChanged(point.frame, point.frame + m_resolution); 606 emit modelChanged(point.frame, point.frame + m_resolution);
514 } 607 }
515 608
516 template <typename PointType> 609 template <typename PointType>
517 void 610 void
527 if (!m_notifyOnAdd) { 620 if (!m_notifyOnAdd) {
528 emit completionChanged(); 621 emit completionChanged();
529 } 622 }
530 623
531 m_notifyOnAdd = true; // henceforth 624 m_notifyOnAdd = true; // henceforth
625 m_rows.clear(); //!!! inefficient
532 emit modelChanged(); 626 emit modelChanged();
533 627
534 } else if (!m_notifyOnAdd) { 628 } else if (!m_notifyOnAdd) {
535 629
536 if (update && 630 if (update &&
537 m_sinceLastNotifyMin >= 0 && 631 m_sinceLastNotifyMin >= 0 &&
538 m_sinceLastNotifyMax >= 0) { 632 m_sinceLastNotifyMax >= 0) {
633 m_rows.clear(); //!!! inefficient
539 emit modelChanged(m_sinceLastNotifyMin, m_sinceLastNotifyMax); 634 emit modelChanged(m_sinceLastNotifyMin, m_sinceLastNotifyMax);
540 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; 635 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
541 } else { 636 } else {
542 emit completionChanged(); 637 emit completionChanged();
543 } 638 }