svcore
1.9
|
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