svcore  1.9
ImageModel.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-2007 Chris Cannam and QMUL.
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 _IMAGE_MODEL_H_
00017 #define _IMAGE_MODEL_H_
00018 
00019 #include "SparseModel.h"
00020 #include "base/XmlExportable.h"
00021 #include "base/RealTime.h"
00022 
00023 #include <QStringList>
00024 
00031 struct ImagePoint : public XmlExportable
00032 {
00033 public:
00034     ImagePoint(long _frame) : frame(_frame) { }
00035     ImagePoint(long _frame, QString _image, QString _label) :
00036         frame(_frame), image(_image), label(_label) { }
00037 
00038     int getDimensions() const { return 1; }
00039     
00040     long frame;
00041     QString image;
00042     QString label;
00043 
00044     QString getLabel() const { return label; }
00045     
00046     void toXml(QTextStream &stream,
00047                QString indent = "",
00048                QString extraAttributes = "") const
00049     {
00050         stream <<
00051             QString("%1<point frame=\"%2\" image=\"%3\" label=\"%4\" %5/>\n")
00052             .arg(indent).arg(frame)
00053             .arg(encodeEntities(image))
00054             .arg(encodeEntities(label))
00055             .arg(extraAttributes);
00056     }
00057 
00058     QString toDelimitedDataString(QString delimiter, int sampleRate) const
00059     {
00060         QStringList list;
00061         list << RealTime::frame2RealTime(frame, sampleRate).toString().c_str();
00062         list << image;
00063         if (label != "") list << label;
00064         return list.join(delimiter);
00065     }
00066 
00067     struct Comparator {
00068         bool operator()(const ImagePoint &p1,
00069                         const ImagePoint &p2) const {
00070             if (p1.frame != p2.frame) return p1.frame < p2.frame;
00071             if (p1.label != p2.label) return p1.label < p2.label;
00072             return p1.image < p2.image;
00073         }
00074     };
00075     
00076     struct OrderComparator {
00077         bool operator()(const ImagePoint &p1,
00078                         const ImagePoint &p2) const {
00079             return p1.frame < p2.frame;
00080         }
00081     };
00082 };
00083 
00084 
00085 // Make this a class rather than a typedef so it can be predeclared.
00086 
00087 class ImageModel : public SparseModel<ImagePoint>
00088 {
00089     Q_OBJECT
00090 
00091 public:
00092     ImageModel(int sampleRate, int resolution, bool notifyOnAdd = true) :
00093         SparseModel<ImagePoint>(sampleRate, resolution, notifyOnAdd)
00094     { }
00095 
00096     QString getTypeName() const { return tr("Image"); }
00097 
00098     virtual void toXml(QTextStream &out,
00099                        QString indent = "",
00100                        QString extraAttributes = "") const
00101     {
00102         SparseModel<ImagePoint>::toXml
00103             (out, 
00104              indent,
00105              QString("%1 subtype=\"image\"")
00106              .arg(extraAttributes));
00107     }
00108 
00112     class ChangeImageCommand : public Command
00113     {
00114     public:
00115         ChangeImageCommand(ImageModel *model,
00116                            const ImagePoint &point,
00117                            QString newImage,
00118                            QString newLabel) :
00119             m_model(model), m_oldPoint(point), m_newPoint(point) {
00120             m_newPoint.image = newImage;
00121             m_newPoint.label = newLabel;
00122         }
00123 
00124         virtual QString getName() const { return tr("Edit Image"); }
00125 
00126         virtual void execute() { 
00127             m_model->deletePoint(m_oldPoint);
00128             m_model->addPoint(m_newPoint);
00129             std::swap(m_oldPoint, m_newPoint);
00130         }
00131 
00132         virtual void unexecute() { execute(); }
00133 
00134     private:
00135         ImageModel *m_model;
00136         ImagePoint m_oldPoint;
00137         ImagePoint m_newPoint;
00138     };
00139 
00144     virtual int getColumnCount() const
00145     {
00146         return 4;
00147     }
00148 
00149     virtual QString getHeading(int column) const
00150     {
00151         switch (column) {
00152         case 0: return tr("Time");
00153         case 1: return tr("Frame");
00154         case 2: return tr("Image");
00155         case 3: return tr("Label");
00156         default: return tr("Unknown");
00157         }
00158     }
00159 
00160     virtual QVariant getData(int row, int column, int role) const
00161     {
00162         if (column < 2) {
00163             return SparseModel<ImagePoint>::getData
00164                 (row, column, role);
00165         }
00166 
00167         PointListConstIterator i = getPointListIteratorForRow(row);
00168         if (i == m_points.end()) return QVariant();
00169 
00170         switch (column) {
00171         case 2: return i->image;
00172         case 3: return i->label;
00173         default: return QVariant();
00174         }
00175     }
00176 
00177     virtual Command *getSetDataCommand(int row, int column, const QVariant &value, int role)
00178     {
00179         if (column < 2) {
00180             return SparseModel<ImagePoint>::getSetDataCommand
00181                 (row, column, value, role);
00182         }
00183 
00184         if (role != Qt::EditRole) return 0;
00185         PointListIterator i = getPointListIteratorForRow(row);
00186         if (i == m_points.end()) return 0;
00187         EditCommand *command = new EditCommand(this, tr("Edit Data"));
00188 
00189         Point point(*i);
00190         command->deletePoint(point);
00191 
00192         switch (column) {
00193         case 2: point.image = value.toString(); break;
00194         case 3: point.label = value.toString(); break;
00195         }
00196 
00197         command->addPoint(point);
00198         return command->finish();
00199     }
00200 
00201     virtual bool isColumnTimeValue(int column) const
00202     {
00203         return (column < 2); 
00204     }
00205 
00206     virtual SortType getSortType(int column) const
00207     {
00208         if (column > 2) return SortAlphabetical;
00209         return SortNumeric;
00210     }
00211 };
00212 
00213 
00214 #endif
00215 
00216 
00217