# HG changeset patch # User Chris Cannam # Date 1218124760 0 # Node ID 7226ebac8bd357fc93a4ec3211af9ad8a211496b # Parent cff476cfce772d06f660ef73ce9642b1285518e7 * Add IntervalModel as base class for NoteModel (and other, further models, hopefully) diff -r cff476cfce77 -r 7226ebac8bd3 data/data.pro --- a/data/data.pro Thu Jul 10 12:50:56 2008 +0000 +++ b/data/data.pro Thu Aug 07 15:59:20 2008 +0000 @@ -50,6 +50,7 @@ model/EditableDenseThreeDimensionalModel.h \ model/FFTModel.h \ model/ImageModel.h \ + model/IntervalModel.h \ model/Labeller.h \ model/Model.h \ model/ModelDataTableModel.h \ @@ -100,7 +101,6 @@ model/FFTModel.cpp \ model/Model.cpp \ model/ModelDataTableModel.cpp \ - model/NoteModel.cpp \ model/PowerOfSqrtTwoZoomConstraint.cpp \ model/PowerOfTwoZoomConstraint.cpp \ model/RangeSummarisableTimeValueModel.cpp \ diff -r cff476cfce77 -r 7226ebac8bd3 data/model/IntervalModel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/model/IntervalModel.h Thu Aug 07 15:59:20 2008 +0000 @@ -0,0 +1,188 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2006-2008 Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _INTERVAL_MODEL_H_ +#define _INTERVAL_MODEL_H_ + +#include "SparseValueModel.h" +#include "base/RealTime.h" + +/** + * Model containing sparse data (points with some properties) of which + * the properties include a duration and an arbitrary float value. + * The other properties depend on the point type. + */ + +template +class IntervalModel : public SparseValueModel +{ +public: + IntervalModel(size_t sampleRate, size_t resolution, + bool notifyOnAdd = true) : + SparseValueModel(sampleRate, resolution, notifyOnAdd) + { } + + IntervalModel(size_t sampleRate, size_t resolution, + float valueMinimum, float valueMaximum, + bool notifyOnAdd = true) : + SparseValueModel(sampleRate, resolution, + valueMinimum, valueMaximum, + notifyOnAdd) + { } + + /** + * PointTypes have a duration, so this returns all points that span any + * of the given range (as well as the usual additional few before + * and after). Consequently this can be very slow (optimised data + * structures still to be done!). + */ + virtual typename SparseValueModel::PointList getPoints(long start, long end) const; + + /** + * PointTypes have a duration, so this returns all points that span the + * given frame. Consequently this can be very slow (optimised + * data structures still to be done!). + */ + virtual typename SparseValueModel::PointList getPoints(long frame) const; + + /** + * TabularModel methods. + */ + + virtual QVariant getData(int row, int column, int role) const + { + if (column < 2) { + return SparseValueModel::getData + (row, column, role); + } + + typename SparseModel::PointList::const_iterator i + = SparseModel::getPointListIteratorForRow(row); + if (i == SparseModel::m_points.end()) return QVariant(); + + switch (column) { + case 2: + if (role == Qt::EditRole || role == TabularModel::SortRole) return i->value; + else return QString("%1 %2").arg(i->value).arg + (IntervalModel::getScaleUnits()); + case 3: return int(i->duration); //!!! could be better presented + default: return QVariant(); + } + } + + virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role) + { + if (column < 2) { + return SparseValueModel::getSetDataCommand + (row, column, value, role); + } + + if (role != Qt::EditRole) return false; + // gah. This is such garbage. Thank you, C++! I love you too + typename SparseModel::PointList::const_iterator i + = SparseModel::getPointListIteratorForRow(row); + if (i == SparseModel::m_points.end()) return false; + typename IntervalModel::EditCommand *command + = new typename IntervalModel::EditCommand + (this, IntervalModel::tr("Edit Data")); + + PointType point(*i); + command->deletePoint(point); + + switch (column) { + case 0: case 1: point.frame = value.toInt(); break; + case 2: point.value = value.toDouble(); break; + case 3: point.duration = value.toInt(); break; + } + + command->addPoint(point); + return command->finish(); + } + + virtual bool isColumnTimeValue(int column) const + { + return (column < 2 || column == 3); + } +}; + +template +typename SparseValueModel::PointList +IntervalModel::getPoints(long start, long end) const +{ + typedef IntervalModel I; + + if (start > end) return typename I::PointList(); + + QMutex &mutex(I::m_mutex); + QMutexLocker locker(&mutex); + + PointType endPoint(end); + + typename I::PointListIterator endItr = I::m_points.upper_bound(endPoint); + + if (endItr != I::m_points.end()) ++endItr; + if (endItr != I::m_points.end()) ++endItr; + + typename I::PointList rv; + + for (typename I::PointListIterator i = endItr; i != I::m_points.begin(); ) { + --i; + if (i->frame < start) { + if (i->frame + long(i->duration) >= start) { + rv.insert(*i); + } + } else if (i->frame <= end) { + rv.insert(*i); + } + } + + return rv; +} + +template +typename SparseValueModel::PointList +IntervalModel::getPoints(long frame) const +{ + typedef IntervalModel I; + + QMutex &mutex(I::m_mutex); + QMutexLocker locker(&mutex); + + if (I::m_resolution == 0) return typename I::PointList(); + + long start = (frame / I::m_resolution) * I::m_resolution; + long end = start + I::m_resolution; + + PointType endPoint(end); + + typename I::PointListIterator endItr = I::m_points.upper_bound(endPoint); + + typename I::PointList rv; + + for (typename I::PointListIterator i = endItr; i != I::m_points.begin(); ) { + --i; + if (i->frame < start) { + if (i->frame + long(i->duration) >= start) { + rv.insert(*i); + } + } else if (i->frame <= end) { + rv.insert(*i); + } + } + + return rv; +} + +#endif diff -r cff476cfce77 -r 7226ebac8bd3 data/model/ModelDataTableModel.cpp --- a/data/model/ModelDataTableModel.cpp Thu Jul 10 12:50:56 2008 +0000 +++ b/data/model/ModelDataTableModel.cpp Thu Aug 07 15:59:20 2008 +0000 @@ -160,8 +160,8 @@ void ModelDataTableModel::sort(int column, Qt::SortOrder sortOrder) { - std::cerr << "ModelDataTableModel::sort(" << column << ", " << sortOrder - << ")" << std::endl; +// std::cerr << "ModelDataTableModel::sort(" << column << ", " << sortOrder +// << ")" << std::endl; int prevCurrent = getCurrentRow(); if (m_sortColumn != column) { clearSort(); @@ -170,7 +170,7 @@ m_sortOrdering = sortOrder; int current = getCurrentRow(); if (current != prevCurrent) { - std::cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << std::endl; +// std::cerr << "Current row changed from " << prevCurrent << " to " << current << " for underlying row " << m_currentRow << std::endl; emit currentChanged(createIndex(current, 0, 0)); } emit layoutChanged(); diff -r cff476cfce77 -r 7226ebac8bd3 data/model/NoteModel.cpp --- a/data/model/NoteModel.cpp Thu Jul 10 12:50:56 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Sonic Visualiser - An audio file viewer and annotation editor. - Centre for Digital Music, Queen Mary, University of London. - This file copyright 2006 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "NoteModel.h" - -NoteModel::PointList -NoteModel::getPoints(long start, long end) const -{ - if (start > end) return PointList(); - QMutexLocker locker(&m_mutex); - - Note endPoint(end); - - PointListIterator endItr = m_points.upper_bound(endPoint); - - if (endItr != m_points.end()) ++endItr; - if (endItr != m_points.end()) ++endItr; - - PointList rv; - - for (PointListIterator i = endItr; i != m_points.begin(); ) { - --i; - if (i->frame < start) { - if (i->frame + long(i->duration) >= start) { - rv.insert(*i); - } - } else if (i->frame <= end) { - rv.insert(*i); - } - } - - return rv; -} - -NoteModel::PointList -NoteModel::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; - - Note endPoint(end); - - PointListIterator endItr = m_points.upper_bound(endPoint); - - PointList rv; - - for (PointListIterator i = endItr; i != m_points.begin(); ) { - --i; - if (i->frame < start) { - if (i->frame + long(i->duration) >= start) { - rv.insert(*i); - } - } else if (i->frame <= end) { - rv.insert(*i); - } - } - - return rv; -} diff -r cff476cfce77 -r 7226ebac8bd3 data/model/NoteModel.h --- a/data/model/NoteModel.h Thu Jul 10 12:50:56 2008 +0000 +++ b/data/model/NoteModel.h Thu Aug 07 15:59:20 2008 +0000 @@ -16,7 +16,7 @@ #ifndef _NOTE_MODEL_H_ #define _NOTE_MODEL_H_ -#include "SparseValueModel.h" +#include "IntervalModel.h" #include "base/RealTime.h" #include "base/PlayParameterRepository.h" @@ -86,15 +86,14 @@ }; -class NoteModel : public SparseValueModel +class NoteModel : public IntervalModel { Q_OBJECT public: NoteModel(size_t sampleRate, size_t resolution, bool notifyOnAdd = true) : - SparseValueModel(sampleRate, resolution, - notifyOnAdd), + IntervalModel(sampleRate, resolution, notifyOnAdd), m_valueQuantization(0) { PlayParameterRepository::getInstance()->addPlayable(this); @@ -103,9 +102,9 @@ NoteModel(size_t sampleRate, size_t resolution, float valueMinimum, float valueMaximum, bool notifyOnAdd = true) : - SparseValueModel(sampleRate, resolution, - valueMinimum, valueMaximum, - notifyOnAdd), + IntervalModel(sampleRate, resolution, + valueMinimum, valueMaximum, + notifyOnAdd), m_valueQuantization(0) { PlayParameterRepository::getInstance()->addPlayable(this); @@ -119,21 +118,6 @@ float getValueQuantization() const { return m_valueQuantization; } void setValueQuantization(float q) { m_valueQuantization = q; } - /** - * Notes have a duration, so this returns all points that span any - * of the given range (as well as the usual additional few before - * and after). Consequently this can be very slow (optimised data - * structures still to be done!). - */ - virtual PointList getPoints(long start, long end) const; - - /** - * Notes have a duration, so this returns all points that span the - * given frame. Consequently this can be very slow (optimised - * data structures still to be done!). - */ - virtual PointList getPoints(long frame) const; - QString getTypeName() const { return tr("Note"); } virtual bool canPlay() const { return true; } @@ -155,7 +139,7 @@ std::cerr << "NoteModel::toXml: extraAttributes = \"" << extraAttributes.toStdString() << std::endl; - SparseValueModel::toXml + IntervalModel::toXml (out, indent, QString("%1 valueQuantization=\"%2\"") @@ -186,19 +170,14 @@ virtual QVariant getData(int row, int column, int role) const { - if (column < 2) { - return SparseValueModel::getData - (row, column, role); + if (column < 4) { + return IntervalModel::getData(row, column, role); } PointListIterator i = getPointListIteratorForRow(row); if (i == m_points.end()) return QVariant(); switch (column) { - case 2: - if (role == Qt::EditRole || role == SortRole) return i->value; - else return QString("%1 %2").arg(i->value).arg(getScaleUnits()); - case 3: return int(i->duration); case 4: return i->level; case 5: return i->label; default: return QVariant(); @@ -207,8 +186,8 @@ virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role) { - if (column < 2) { - return SparseValueModel::getSetDataCommand + if (column < 4) { + return IntervalModel::getSetDataCommand (row, column, value, role); } @@ -221,9 +200,6 @@ command->deletePoint(point); switch (column) { - case 0: case 1: point.frame = value.toInt(); break; - case 2: point.value = value.toDouble(); break; - case 3: point.duration = value.toInt(); break; case 4: point.level = value.toDouble(); break; case 5: point.label = value.toString(); break; } @@ -232,11 +208,6 @@ return command->finish(); } - virtual bool isColumnTimeValue(int column) const - { - return (column < 2); - } - virtual SortType getSortType(int column) const { if (column == 5) return SortAlphabetical;