svcore  1.9
TextModel.h
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #ifndef _TEXT_MODEL_H_
00017 #define _TEXT_MODEL_H_
00018 
00019 #include "SparseModel.h"
00020 #include "base/XmlExportable.h"
00021 #include "base/RealTime.h"
00022 
00023 #include <QStringList>
00024 
00031 struct TextPoint : public XmlExportable
00032 {
00033 public:
00034     TextPoint(long _frame) : frame(_frame), height(0.0f) { }
00035     TextPoint(long _frame, float _height, QString _label) : 
00036         frame(_frame), height(_height), label(_label) { }
00037 
00038     int getDimensions() const { return 2; }
00039     
00040     long frame;
00041     float height;
00042     QString label;
00043 
00044     QString getLabel() const { return label; }
00045     
00046     void toXml(QTextStream &stream, QString indent = "",
00047                QString extraAttributes = "") const
00048     {
00049         stream << QString("%1<point frame=\"%2\" height=\"%3\" label=\"%4\" %5/>\n")
00050             .arg(indent).arg(frame).arg(height)
00051             .arg(encodeEntities(label)).arg(extraAttributes);
00052     }
00053 
00054     QString toDelimitedDataString(QString delimiter, int sampleRate) const
00055     {
00056         QStringList list;
00057         list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
00058         list << QString("%1").arg(height);
00059         if (label != "") list << label;
00060         return list.join(delimiter);
00061     }
00062 
00063     struct Comparator {
00064         bool operator()(const TextPoint &p1,
00065                         const TextPoint &p2) const {
00066             if (p1.frame != p2.frame) return p1.frame < p2.frame;
00067             if (p1.height != p2.height) return p1.height < p2.height;
00068             return p1.label < p2.label;
00069         }
00070     };
00071     
00072     struct OrderComparator {
00073         bool operator()(const TextPoint &p1,
00074                         const TextPoint &p2) const {
00075             return p1.frame < p2.frame;
00076         }
00077     };
00078 };
00079 
00080 
00081 // Make this a class rather than a typedef so it can be predeclared.
00082 
00083 class TextModel : public SparseModel<TextPoint>
00084 {
00085     Q_OBJECT
00086     
00087 public:
00088     TextModel(int sampleRate, int resolution, bool notifyOnAdd = true) :
00089         SparseModel<TextPoint>(sampleRate, resolution, notifyOnAdd)
00090     { }
00091 
00092     virtual void toXml(QTextStream &out,
00093                        QString indent = "",
00094                        QString extraAttributes = "") const
00095     {
00096         SparseModel<TextPoint>::toXml
00097             (out, 
00098              indent,
00099              QString("%1 subtype=\"text\"")
00100              .arg(extraAttributes));
00101     }
00102 
00103     QString getTypeName() const { return tr("Text"); }
00104 
00109     virtual int getColumnCount() const
00110     {
00111         return 4;
00112     }
00113 
00114     virtual QString getHeading(int column) const
00115     {
00116         switch (column) {
00117         case 0: return tr("Time");
00118         case 1: return tr("Frame");
00119         case 2: return tr("Height");
00120         case 3: return tr("Label");
00121         default: return tr("Unknown");
00122         }
00123     }
00124 
00125     virtual QVariant getData(int row, int column, int role) const
00126     {
00127         if (column < 2) {
00128             return SparseModel<TextPoint>::getData
00129                 (row, column, role);
00130         }
00131 
00132         PointListConstIterator i = getPointListIteratorForRow(row);
00133         if (i == m_points.end()) return QVariant();
00134 
00135         switch (column) {
00136         case 2: return i->height;
00137         case 3: return i->label;
00138         default: return QVariant();
00139         }
00140     }
00141 
00142     virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
00143     {
00144         if (column < 2) {
00145             return SparseModel<TextPoint>::getSetDataCommand
00146                 (row, column, value, role);
00147         }
00148 
00149         if (role != Qt::EditRole) return 0;
00150         PointListIterator i = getPointListIteratorForRow(row);
00151         if (i == m_points.end()) return 0;
00152         EditCommand *command = new EditCommand(this, tr("Edit Data"));
00153 
00154         Point point(*i);
00155         command->deletePoint(point);
00156 
00157         switch (column) {
00158         case 2: point.height = value.toDouble(); break;
00159         case 3: point.label = value.toString(); break;
00160         }
00161 
00162         command->addPoint(point);
00163         return command->finish();
00164     }
00165 
00166     virtual bool isColumnTimeValue(int column) const
00167     {
00168         return (column < 2); 
00169     }
00170 
00171     virtual SortType getSortType(int column) const
00172     {
00173         if (column == 3) return SortAlphabetical;
00174         return SortNumeric;
00175     }
00176 
00177 };
00178 
00179 
00180 #endif
00181 
00182 
00183