Mercurial > hg > svcore
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 } |