Chris@441: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@441: Chris@441: /* Chris@441: Sonic Visualiser Chris@441: An audio file viewer and annotation editor. Chris@441: Centre for Digital Music, Queen Mary, University of London. Chris@441: This file copyright 2006 Chris Cannam. Chris@441: Chris@441: This program is free software; you can redistribute it and/or Chris@441: modify it under the terms of the GNU General Public License as Chris@441: published by the Free Software Foundation; either version 2 of the Chris@441: License, or (at your option) any later version. See the file Chris@441: COPYING included with this distribution for more information. Chris@441: */ Chris@441: Chris@441: #ifndef _REGION_MODEL_H_ Chris@441: #define _REGION_MODEL_H_ Chris@441: Chris@441: #include "IntervalModel.h" Chris@441: #include "base/RealTime.h" Chris@441: Chris@441: /** Chris@441: * RegionModel -- a concrete IntervalModel for intervals associated Chris@441: * with a value, which we call regions for no very compelling reason. Chris@441: */ Chris@441: Chris@441: /** Chris@441: * Region "point" type. A region is something that has an onset time, Chris@441: * a single value, and a duration. Like other points, it can also Chris@441: * have a label. Chris@441: * Chris@441: * This is called RegionRec instead of Region to avoid name collisions Chris@441: * with the X11 Region struct. Bah. Chris@441: */ Chris@441: Chris@441: struct RegionRec Chris@441: { Chris@441: public: Chris@441: RegionRec(long _frame) : frame(_frame), value(0.0f), duration(0) { } Chris@441: RegionRec(long _frame, float _value, size_t _duration, QString _label) : Chris@441: frame(_frame), value(_value), duration(_duration), label(_label) { } Chris@441: Chris@441: int getDimensions() const { return 3; } Chris@441: Chris@441: long frame; Chris@441: float value; Chris@441: size_t duration; Chris@441: QString label; Chris@441: Chris@441: QString getLabel() const { return label; } Chris@441: Chris@441: void toXml(QTextStream &stream, Chris@441: QString indent = "", Chris@441: QString extraAttributes = "") const Chris@441: { Chris@441: stream << Chris@441: QString("%1\n") Chris@441: .arg(indent).arg(frame).arg(value).arg(duration).arg(label).arg(extraAttributes); Chris@441: } Chris@441: Chris@441: QString toDelimitedDataString(QString delimiter, size_t sampleRate) const Chris@441: { Chris@441: QStringList list; Chris@441: list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str(); Chris@441: list << QString("%1").arg(value); Chris@441: list << RealTime::frame2RealTime(duration, sampleRate).toString().c_str(); Chris@441: if (label != "") list << label; Chris@441: return list.join(delimiter); Chris@441: } Chris@441: Chris@441: struct Comparator { Chris@441: bool operator()(const RegionRec &p1, Chris@441: const RegionRec &p2) const { Chris@441: if (p1.frame != p2.frame) return p1.frame < p2.frame; Chris@441: if (p1.value != p2.value) return p1.value < p2.value; Chris@441: if (p1.duration != p2.duration) return p1.duration < p2.duration; Chris@441: return p1.label < p2.label; Chris@441: } Chris@441: }; Chris@441: Chris@441: struct OrderComparator { Chris@441: bool operator()(const RegionRec &p1, Chris@441: const RegionRec &p2) const { Chris@441: return p1.frame < p2.frame; Chris@441: } Chris@441: }; Chris@441: }; Chris@441: Chris@441: Chris@441: class RegionModel : public IntervalModel Chris@441: { Chris@441: Q_OBJECT Chris@441: Chris@441: public: Chris@441: RegionModel(size_t sampleRate, size_t resolution, Chris@441: bool notifyOnAdd = true) : Chris@441: IntervalModel(sampleRate, resolution, notifyOnAdd), Chris@442: m_valueQuantization(0), Chris@442: m_haveDistinctValues(false) Chris@441: { Chris@441: } Chris@441: Chris@441: RegionModel(size_t sampleRate, size_t resolution, Chris@459: float valueMinimum, float valueMaximum, Chris@459: bool notifyOnAdd = true) : Chris@441: IntervalModel(sampleRate, resolution, Chris@441: valueMinimum, valueMaximum, Chris@441: notifyOnAdd), Chris@442: m_valueQuantization(0), Chris@442: m_haveDistinctValues(false) Chris@441: { Chris@441: } Chris@441: Chris@441: virtual ~RegionModel() Chris@441: { Chris@441: } Chris@441: Chris@441: float getValueQuantization() const { return m_valueQuantization; } Chris@441: void setValueQuantization(float q) { m_valueQuantization = q; } Chris@441: Chris@442: bool haveDistinctValues() const { return m_haveDistinctValues; } Chris@442: Chris@441: QString getTypeName() const { return tr("Region"); } Chris@441: Chris@441: virtual void toXml(QTextStream &out, Chris@441: QString indent = "", Chris@441: QString extraAttributes = "") const Chris@441: { Chris@441: std::cerr << "RegionModel::toXml: extraAttributes = \"" Chris@441: << extraAttributes.toStdString() << std::endl; Chris@441: Chris@441: IntervalModel::toXml Chris@441: (out, Chris@441: indent, Chris@452: QString("%1 subtype=\"region\" valueQuantization=\"%2\"") Chris@441: .arg(extraAttributes).arg(m_valueQuantization)); Chris@441: } Chris@441: Chris@441: /** Chris@441: * TabularModel methods. Chris@441: */ Chris@441: Chris@441: virtual int getColumnCount() const Chris@441: { Chris@441: return 6; Chris@441: } Chris@441: Chris@441: virtual QString getHeading(int column) const Chris@441: { Chris@441: switch (column) { Chris@441: case 0: return tr("Time"); Chris@441: case 1: return tr("Frame"); Chris@441: case 2: return tr("Value"); Chris@441: case 3: return tr("Duration"); Chris@441: case 4: return tr("Label"); Chris@441: default: return tr("Unknown"); Chris@441: } Chris@441: } Chris@441: Chris@441: virtual QVariant getData(int row, int column, int role) const Chris@441: { Chris@441: if (column < 4) { Chris@441: return IntervalModel::getData(row, column, role); Chris@441: } Chris@441: Chris@608: PointListConstIterator i = getPointListIteratorForRow(row); Chris@441: if (i == m_points.end()) return QVariant(); Chris@441: Chris@441: switch (column) { Chris@441: case 4: return i->label; Chris@441: default: return QVariant(); Chris@441: } Chris@441: } Chris@441: Chris@441: virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role) Chris@441: { Chris@441: if (column < 4) { Chris@441: return IntervalModel::getSetDataCommand Chris@441: (row, column, value, role); Chris@441: } Chris@441: Chris@441: if (role != Qt::EditRole) return false; Chris@441: PointListIterator i = getPointListIteratorForRow(row); Chris@441: if (i == m_points.end()) return false; Chris@441: EditCommand *command = new EditCommand(this, tr("Edit Data")); Chris@441: Chris@441: Point point(*i); Chris@441: command->deletePoint(point); Chris@441: Chris@441: switch (column) { Chris@441: case 4: point.label = value.toString(); break; Chris@441: } Chris@441: Chris@441: command->addPoint(point); Chris@441: return command->finish(); Chris@441: } Chris@441: Chris@441: virtual SortType getSortType(int column) const Chris@441: { Chris@441: if (column == 5) return SortAlphabetical; Chris@441: return SortNumeric; Chris@441: } Chris@441: Chris@442: virtual void addPoint(const Point &point) Chris@442: { Chris@442: if (point.value != 0.f) m_haveDistinctValues = true; Chris@442: IntervalModel::addPoint(point); Chris@442: } Chris@442: Chris@441: protected: Chris@441: float m_valueQuantization; Chris@442: bool m_haveDistinctValues; Chris@441: }; Chris@441: Chris@441: #endif