Mercurial > hg > svcore
diff 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 |
line wrap: on
line diff
--- a/data/model/SparseModel.h Wed Jun 11 12:54:18 2008 +0000 +++ b/data/model/SparseModel.h Wed Jun 11 16:13:25 2008 +0000 @@ -17,22 +17,26 @@ #define _SPARSE_MODEL_H_ #include "Model.h" +#include "TabularModel.h" #include "base/Command.h" #include <iostream> #include <set> +#include <vector> +#include <algorithm> + #include <QMutex> #include <QTextStream> - /** * Model containing sparse data (points with some properties). The * properties depend on the point type. */ template <typename PointType> -class SparseModel : public Model +class SparseModel : public Model, + public TabularModel { public: SparseModel(size_t sampleRate, size_t resolution, @@ -258,8 +262,38 @@ PointType m_newPoint; }; + /** + * TabularModel methods. + */ + + virtual int getRowCount() const + { + return m_points.size(); + } + + virtual long getFrameForRow(int row) const + { + PointListIterator i = getPointListIteratorForRow(row); + if (i == m_points.end()) return 0; + return i->frame; + } + + virtual int getRowForFrame(long frame) const + { + if (m_rows.empty()) rebuildRowVector(); + std::vector<long>::iterator i = + std::lower_bound(m_rows.begin(), m_rows.end(), frame); + return std::distance(m_rows.begin(), i); + } + + //!!! just for now + virtual int getColumnCount() const { return 1; } + virtual QString getHeading(int column) const { return tr("Unknown"); } + virtual QVariant getData(int row, int column, int role) const { + return QVariant(); + } + virtual bool isColumnTimeValue(int column) const { return true; } - protected: size_t m_sampleRate; size_t m_resolution; @@ -272,6 +306,47 @@ size_t m_pointCount; mutable QMutex m_mutex; int m_completion; + + void getPointIterators(long frame, + PointListIterator &startItr, + PointListIterator &endItr) const; + + // This is only used if the model is called on to act in + // TabularModel mode + mutable std::vector<long> m_rows; // map from row number to frame + void rebuildRowVector() const + { + m_rows.clear(); + for (PointListIterator i = m_points.begin(); i != m_points.end(); ++i) { + m_rows.push_back(i->frame); + } + } + + PointListIterator getPointListIteratorForRow(int row) const + { + if (m_rows.empty()) rebuildRowVector(); + if (row < 0 || row + 1 > m_rows.size()) return m_points.end(); + + size_t frame = m_rows[row]; + int indexAtFrame = 0; + int ri = row; + while (ri > 0 && m_rows[ri-1] == m_rows[row]) { --ri; ++indexAtFrame; } + int initialIndexAtFrame = indexAtFrame; + + PointListIterator i0, i1; + getPointIterators(frame, i0, i1); + PointListIterator i = i0; + + for (i = i0; i != i1; ++i) { + if (indexAtFrame > 0) { --indexAtFrame; continue; } + return i; + } + + if (indexAtFrame > 0) { + std::cerr << "WARNING: SparseModel::getPointListIteratorForRow: No iterator available for row " << row << " (frame = " << frame << ", index at frame = " << initialIndexAtFrame << ", leftover index " << indexAtFrame << ")" << std::endl; + } + return i; + } }; @@ -370,17 +445,8 @@ typename SparseModel<PointType>::PointList SparseModel<PointType>::getPoints(long frame) const { - QMutexLocker locker(&m_mutex); - - if (m_resolution == 0) return PointList(); - - long start = (frame / m_resolution) * m_resolution; - long end = start + m_resolution; - - PointType startPoint(start), endPoint(end); - - PointListIterator startItr = m_points.lower_bound(startPoint); - PointListIterator endItr = m_points.upper_bound(endPoint); + PointListIterator startItr, endItr; + getPointIterators(frame, startItr, endItr); PointList rv; @@ -392,6 +458,29 @@ } template <typename PointType> +void +SparseModel<PointType>::getPointIterators(long frame, + PointListIterator &startItr, + PointListIterator &endItr) const +{ + QMutexLocker locker(&m_mutex); + + if (m_resolution == 0) { + startItr = m_points.end(); + endItr = m_points.end(); + return; + } + + long start = (frame / m_resolution) * m_resolution; + long end = start + m_resolution; + + PointType startPoint(start), endPoint(end); + + startItr = m_points.lower_bound(startPoint); + endItr = m_points.upper_bound(endPoint); +} + +template <typename PointType> typename SparseModel<PointType>::PointList SparseModel<PointType>::getPreviousPoints(long originFrame) const { @@ -443,6 +532,7 @@ QMutexLocker locker(&m_mutex); m_resolution = resolution; } + m_rows.clear(); emit modelChanged(); } @@ -455,6 +545,7 @@ m_points.clear(); m_pointCount = 0; } + m_rows.clear(); emit modelChanged(); } @@ -476,6 +567,7 @@ // alternative is to notify on setCompletion). if (m_notifyOnAdd) { + m_rows.clear(); //!!! inefficient emit modelChanged(point.frame, point.frame + m_resolution); } else { if (m_sinceLastNotifyMin == -1 || @@ -510,6 +602,7 @@ } // std::cout << "SparseOneDimensionalModel: emit modelChanged(" // << point.frame << ")" << std::endl; + m_rows.clear(); //!!! inefficient emit modelChanged(point.frame, point.frame + m_resolution); } @@ -529,6 +622,7 @@ } m_notifyOnAdd = true; // henceforth + m_rows.clear(); //!!! inefficient emit modelChanged(); } else if (!m_notifyOnAdd) { @@ -536,6 +630,7 @@ if (update && m_sinceLastNotifyMin >= 0 && m_sinceLastNotifyMax >= 0) { + m_rows.clear(); //!!! inefficient emit modelChanged(m_sinceLastNotifyMin, m_sinceLastNotifyMax); m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1; } else {