Chris@147: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@147: 
Chris@147: /*
Chris@147:     Sonic Visualiser
Chris@147:     An audio file viewer and annotation editor.
Chris@147:     Centre for Digital Music, Queen Mary, University of London.
Chris@147:     This file copyright 2006 Chris Cannam.
Chris@147:     
Chris@147:     This program is free software; you can redistribute it and/or
Chris@147:     modify it under the terms of the GNU General Public License as
Chris@147:     published by the Free Software Foundation; either version 2 of the
Chris@147:     License, or (at your option) any later version.  See the file
Chris@147:     COPYING included with this distribution for more information.
Chris@147: */
Chris@147: 
Chris@147: #ifndef _SPARSE_VALUE_MODEL_H_
Chris@147: #define _SPARSE_VALUE_MODEL_H_
Chris@147: 
Chris@147: #include "SparseModel.h"
Chris@150: #include "base/UnitDatabase.h"
Chris@147: 
Chris@257: #include <cmath>
Chris@257: 
Chris@147: /**
Chris@147:  * Model containing sparse data (points with some properties) of which
Chris@147:  * one of the properties is an arbitrary float value.  The other
Chris@147:  * properties depend on the point type.
Chris@147:  */
Chris@147: 
Chris@147: template <typename PointType>
Chris@147: class SparseValueModel : public SparseModel<PointType>
Chris@147: {
Chris@147: public:
Chris@147:     SparseValueModel(size_t sampleRate, size_t resolution,
Chris@256: 		     bool notifyOnAdd = true) :
Chris@256: 	SparseModel<PointType>(sampleRate, resolution, notifyOnAdd),
Chris@256: 	m_valueMinimum(0.f),
Chris@256: 	m_valueMaximum(0.f),
Chris@256:         m_haveExtents(false)
Chris@256:     { }
Chris@256: 
Chris@256:     SparseValueModel(size_t sampleRate, size_t resolution,
Chris@147: 		     float valueMinimum, float valueMaximum,
Chris@147: 		     bool notifyOnAdd = true) :
Chris@147: 	SparseModel<PointType>(sampleRate, resolution, notifyOnAdd),
Chris@147: 	m_valueMinimum(valueMinimum),
Chris@256: 	m_valueMaximum(valueMaximum),
Chris@256:         m_haveExtents(true)
Chris@147:     { }
Chris@147: 
Chris@147:     using SparseModel<PointType>::m_points;
Chris@147:     using SparseModel<PointType>::modelChanged;
Chris@301:     using SparseModel<PointType>::getPoints;
Chris@345:     using SparseModel<PointType>::tr;
Chris@345: 
Chris@345:     QString getTypeName() const { return tr("Sparse Value"); }
Chris@147: 
Chris@147:     virtual float getValueMinimum() const { return m_valueMinimum; }
Chris@147:     virtual float getValueMaximum() const { return m_valueMaximum; }
Chris@147: 
Chris@147:     virtual QString getScaleUnits() const { return m_units; }
Chris@147:     virtual void setScaleUnits(QString units) {
Chris@147:         m_units = units;
Chris@147:         UnitDatabase::getInstance()->registerUnit(units);
Chris@147:     }
Chris@147: 
Chris@147:     virtual void addPoint(const PointType &point)
Chris@147:     {
Chris@147: 	bool allChange = false;
Chris@256: 
Chris@257:         if (!std::isnan(point.value) && !std::isinf(point.value)) {
Chris@256:             if (!m_haveExtents || point.value < m_valueMinimum) {
Chris@256:                 m_valueMinimum = point.value; allChange = true;
Chris@296: //                std::cerr << "addPoint: value min = " << m_valueMinimum << std::endl;
Chris@256:             }
Chris@256:             if (!m_haveExtents || point.value > m_valueMaximum) {
Chris@256:                 m_valueMaximum = point.value; allChange = true;
Chris@296: //                std::cerr << "addPoint: value max = " << m_valueMaximum << " (min = " << m_valueMinimum << ")" << std::endl;
Chris@256:             }
Chris@256:             m_haveExtents = true;
Chris@256:         }
Chris@147: 
Chris@147: 	SparseModel<PointType>::addPoint(point);
Chris@147: 	if (allChange) emit modelChanged();
Chris@147:     }
Chris@147: 
Chris@147:     virtual void deletePoint(const PointType &point)
Chris@147:     {
Chris@147: 	SparseModel<PointType>::deletePoint(point);
Chris@147: 
Chris@147: 	if (point.value == m_valueMinimum ||
Chris@147: 	    point.value == m_valueMaximum) {
Chris@147: 
Chris@147: 	    float formerMin = m_valueMinimum, formerMax = m_valueMaximum;
Chris@147: 
Chris@147: 	    for (typename SparseModel<PointType>::PointList::const_iterator i
Chris@147: 		     = m_points.begin();
Chris@147: 		 i != m_points.end(); ++i) {
Chris@147: 
Chris@147: 		if (i == m_points.begin() || i->value < m_valueMinimum) {
Chris@147: 		    m_valueMinimum = i->value;
Chris@296: //                    std::cerr << "deletePoint: value min = " << m_valueMinimum << std::endl;
Chris@147: 		} 
Chris@147: 		if (i == m_points.begin() || i->value > m_valueMaximum) {
Chris@147: 		    m_valueMaximum = i->value;
Chris@296: //                    std::cerr << "deletePoint: value max = " << m_valueMaximum << std::endl;
Chris@147: 		} 
Chris@147: 	    }
Chris@147: 
Chris@147: 	    if (formerMin != m_valueMinimum || formerMax != m_valueMaximum) {
Chris@147: 		emit modelChanged();
Chris@147: 	    }
Chris@147: 	}
Chris@147:     }
Chris@147: 
Chris@318:     virtual void toXml(QTextStream &stream,
Chris@318:                        QString indent = "",
Chris@314:                        QString extraAttributes = "") const
Chris@147:     {
Chris@318:         std::cerr << "SparseValueModel::toXml: extraAttributes = \"" 
Chris@318:                   << extraAttributes.toStdString() << std::endl;
Chris@318: 
Chris@314: 	SparseModel<PointType>::toXml
Chris@318: 	    (stream,
Chris@318:              indent,
Chris@147: 	     QString("%1 minimum=\"%2\" maximum=\"%3\" units=\"%4\"")
Chris@147: 	     .arg(extraAttributes).arg(m_valueMinimum).arg(m_valueMaximum)
Chris@147:              .arg(this->encodeEntities(m_units)));
Chris@147:     }
Chris@147: 
Chris@147: protected:
Chris@147:     float m_valueMinimum;
Chris@147:     float m_valueMaximum;
Chris@256:     bool m_haveExtents;
Chris@147:     QString m_units;
Chris@147: };
Chris@147: 
Chris@147: 
Chris@147: #endif
Chris@147: