svgui
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 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 _LAYER_H_ 00017 #define _LAYER_H_ 00018 00019 #include "base/PropertyContainer.h" 00020 #include "base/XmlExportable.h" 00021 #include "base/Selection.h" 00022 00023 #include "widgets/CommandHistory.h" 00024 00025 #include "system/System.h" 00026 00027 #include <QObject> 00028 #include <QRect> 00029 #include <QXmlAttributes> 00030 #include <QMutex> 00031 #include <QPixmap> 00032 00033 #include <map> 00034 #include <set> 00035 00036 #include <iostream> 00037 00038 class ZoomConstraint; 00039 class Model; 00040 class QPainter; 00041 class View; 00042 class QMouseEvent; 00043 class Clipboard; 00044 class RangeMapper; 00045 00052 class Layer : public PropertyContainer, 00053 public XmlExportable 00054 { 00055 Q_OBJECT 00056 00057 public: 00058 Layer(); 00059 virtual ~Layer(); 00060 00061 virtual const Model *getModel() const = 0; 00062 Model *getModel() { 00063 return const_cast<Model *>(const_cast<const Layer *>(this)->getModel()); 00064 } 00065 00071 virtual const ZoomConstraint *getZoomConstraint() const { return 0; } 00072 00081 virtual bool supportsOtherZoomLevels() const { return true; } 00082 00091 virtual void paint(View *, QPainter &, QRect) const = 0; 00092 00104 virtual void setSynchronousPainting(bool /* synchronous */) { } 00105 00106 enum VerticalPosition { 00107 PositionTop, PositionMiddle, PositionBottom 00108 }; 00109 virtual VerticalPosition getPreferredTimeRulerPosition() const { 00110 return PositionMiddle; 00111 } 00112 virtual VerticalPosition getPreferredFrameCountPosition() const { 00113 return PositionBottom; 00114 } 00115 virtual bool hasLightBackground() const { 00116 return true; 00117 } 00118 00119 virtual QString getPropertyContainerIconName() const; 00120 00121 virtual QString getPropertyContainerName() const { 00122 if (m_presentationName != "") return m_presentationName; 00123 else return objectName(); 00124 } 00125 00126 virtual void setPresentationName(QString name); 00127 00128 virtual QString getLayerPresentationName() const; 00129 virtual QPixmap getLayerPresentationPixmap(QSize) const { return QPixmap(); } 00130 00131 virtual int getVerticalScaleWidth(View *, bool detailed, 00132 QPainter &) const = 0; 00133 00134 virtual void paintVerticalScale(View *, bool /* detailed */, 00135 QPainter &, QRect) const { } 00136 00137 virtual bool getCrosshairExtents(View *, QPainter &, QPoint /* cursorPos */, 00138 std::vector<QRect> &) const { 00139 return false; 00140 } 00141 virtual void paintCrosshairs(View *, QPainter &, QPoint) const { } 00142 00143 virtual void paintMeasurementRects(View *, QPainter &, 00144 bool showFocus, QPoint focusPoint) const; 00145 00146 virtual bool nearestMeasurementRectChanged(View *, QPoint prev, 00147 QPoint now) const; 00148 00149 virtual QString getFeatureDescription(View *, QPoint &) const { 00150 return ""; 00151 } 00152 00153 virtual QString getLabelPreceding(int /* frame */) const { 00154 return ""; 00155 } 00156 00157 enum SnapType { 00158 SnapLeft, 00159 SnapRight, 00160 SnapNearest, 00161 SnapNeighbouring 00162 }; 00163 00183 virtual bool snapToFeatureFrame(View * /* v */, 00184 int & /* frame */, 00185 int &resolution, 00186 SnapType /* snap */) const { 00187 resolution = 1; 00188 return false; 00189 } 00190 00207 virtual bool snapToSimilarFeature(View * /* v */, 00208 int & /* source frame */, 00209 int &resolution, 00210 SnapType /* snap */) const { 00211 resolution = 1; 00212 return false; 00213 } 00214 00215 // Draw, erase, and edit modes: 00216 // 00217 // Layer needs to get actual mouse events, I guess. Draw mode is 00218 // probably the easier. 00219 00220 virtual void drawStart(View *, QMouseEvent *) { } 00221 virtual void drawDrag(View *, QMouseEvent *) { } 00222 virtual void drawEnd(View *, QMouseEvent *) { } 00223 00224 virtual void eraseStart(View *, QMouseEvent *) { } 00225 virtual void eraseDrag(View *, QMouseEvent *) { } 00226 virtual void eraseEnd(View *, QMouseEvent *) { } 00227 00228 virtual void editStart(View *, QMouseEvent *) { } 00229 virtual void editDrag(View *, QMouseEvent *) { } 00230 virtual void editEnd(View *, QMouseEvent *) { } 00231 00232 virtual void splitStart(View *, QMouseEvent *) { } 00233 virtual void splitEnd(View *, QMouseEvent *) { } 00234 virtual void addNote(View *, QMouseEvent *) { }; 00235 00236 // Measurement rectangle (or equivalent). Unlike draw and edit, 00237 // the base Layer class can provide working implementations of 00238 // these for most situations. 00239 // 00240 virtual void measureStart(View *, QMouseEvent *); 00241 virtual void measureDrag(View *, QMouseEvent *); 00242 virtual void measureEnd(View *, QMouseEvent *); 00243 virtual void measureDoubleClick(View *, QMouseEvent *); 00244 00245 virtual bool haveCurrentMeasureRect() const { 00246 return m_haveCurrentMeasureRect; 00247 } 00248 virtual void deleteCurrentMeasureRect(); // using a command 00249 00255 virtual bool editOpen(View *, QMouseEvent *) { return false; } 00256 00257 virtual void moveSelection(Selection, int /* newStartFrame */) { } 00258 virtual void resizeSelection(Selection, Selection /* newSize */) { } 00259 virtual void deleteSelection(Selection) { } 00260 00261 virtual void copy(View *, Selection, Clipboard & /* to */) { } 00262 00270 virtual bool paste(View *, 00271 const Clipboard & /* from */, 00272 int /* frameOffset */, 00273 bool /* interactive */) { return false; } 00274 00275 // Text mode: 00276 // 00277 // Label nearest feature. We need to get the feature coordinates 00278 // and current label from the layer, and then the pane can pop up 00279 // a little text entry dialog at the right location. Or we edit 00280 // in place? Probably the dialog is easier. 00281 00292 virtual bool isLayerScrollable(const View *) const { return true; } 00293 00302 virtual bool isLayerOpaque() const { return false; } 00303 00304 enum ColourSignificance { 00305 ColourAbsent, 00306 ColourIrrelevant, 00307 ColourDistinguishes, 00308 ColourAndBackgroundSignificant, 00309 ColourHasMeaningfulValue 00310 }; 00311 00330 virtual ColourSignificance getLayerColourSignificance() const = 0; 00331 00338 virtual bool isLayerEditable() const { return false; } 00339 00347 virtual int getCompletion(View *) const { return 100; } 00348 00354 virtual QString getError(View *) const { return ""; } 00355 00356 virtual void setObjectName(const QString &name); 00357 00365 virtual void toXml(QTextStream &stream, QString indent = "", 00366 QString extraAttributes = "") const; 00367 00373 virtual void setProperties(const QXmlAttributes &) = 0; 00374 00381 virtual void toBriefXml(QTextStream &stream, 00382 QString indent = "", 00383 QString extraAttributes = "") const; 00384 00390 virtual void addMeasurementRect(const QXmlAttributes &); 00391 00403 virtual void setLayerDormant(const View *v, bool dormant); 00404 00409 virtual bool isLayerDormant(const View *v) const; 00410 00411 virtual PlayParameters *getPlayParameters(); 00412 00413 virtual bool needsTextLabelHeight() const { return false; } 00414 00415 virtual bool hasTimeXAxis() const { return true; } 00416 00426 virtual bool getValueExtents(float &min, float &max, 00427 bool &logarithmic, QString &unit) const = 0; 00428 00437 virtual bool getDisplayExtents(float & /* min */, 00438 float & /* max */) const { 00439 return false; 00440 } 00441 00449 virtual bool setDisplayExtents(float /* min */, 00450 float /* max */) { 00451 return false; 00452 } 00453 00460 virtual bool getXScaleValue(const View *v, int x, 00461 float &value, QString &unit) const; 00462 00467 virtual bool getYScaleValue(const View *, int /* y */, 00468 float &/* value */, QString &/* unit */) const { 00469 return false; 00470 } 00471 00478 virtual bool getYScaleDifference(const View *v, int y0, int y1, 00479 float &diff, QString &unit) const; 00480 00495 virtual int getVerticalZoomSteps(int & /* defaultStep */) const { return 0; } 00496 00503 virtual int getCurrentVerticalZoomStep() const { return 0; } 00504 00511 virtual void setVerticalZoomStep(int) { } 00512 00519 virtual RangeMapper *getNewVerticalZoomRangeMapper() const { return 0; } 00520 00521 public slots: 00522 void showLayer(View *, bool show); 00523 00524 signals: 00525 void modelChanged(); 00526 void modelCompletionChanged(); 00527 void modelAlignmentCompletionChanged(); 00528 void modelChangedWithin(int startFrame, int endFrame); 00529 void modelReplaced(); 00530 00531 void layerParametersChanged(); 00532 void layerParameterRangesChanged(); 00533 void layerMeasurementRectsChanged(); 00534 void layerNameChanged(); 00535 00536 void verticalZoomChanged(); 00537 00538 protected: 00539 void connectSignals(const Model *); 00540 00541 virtual int alignToReference(View *v, int frame) const; 00542 virtual int alignFromReference(View *v, int frame) const; 00543 bool clipboardHasDifferentAlignment(View *v, const Clipboard &clip) const; 00544 00545 struct MeasureRect { 00546 00547 mutable QRect pixrect; 00548 bool haveFrames; 00549 int startFrame; // only valid if haveFrames 00550 int endFrame; // ditto 00551 double startY; 00552 double endY; 00553 00554 bool operator<(const MeasureRect &mr) const; 00555 void toXml(QTextStream &stream, QString indent) const; 00556 }; 00557 00558 class AddMeasurementRectCommand : public Command 00559 { 00560 public: 00561 AddMeasurementRectCommand(Layer *layer, MeasureRect rect) : 00562 m_layer(layer), m_rect(rect) { } 00563 00564 virtual QString getName() const; 00565 virtual void execute(); 00566 virtual void unexecute(); 00567 00568 private: 00569 Layer *m_layer; 00570 MeasureRect m_rect; 00571 }; 00572 00573 class DeleteMeasurementRectCommand : public Command 00574 { 00575 public: 00576 DeleteMeasurementRectCommand(Layer *layer, MeasureRect rect) : 00577 m_layer(layer), m_rect(rect) { } 00578 00579 virtual QString getName() const; 00580 virtual void execute(); 00581 virtual void unexecute(); 00582 00583 private: 00584 Layer *m_layer; 00585 MeasureRect m_rect; 00586 }; 00587 00588 void addMeasureRectToSet(const MeasureRect &r) { 00589 m_measureRects.insert(r); 00590 emit layerMeasurementRectsChanged(); 00591 } 00592 00593 void deleteMeasureRectFromSet(const MeasureRect &r) { 00594 m_measureRects.erase(r); 00595 emit layerMeasurementRectsChanged(); 00596 } 00597 00598 typedef std::set<MeasureRect> MeasureRectSet; 00599 MeasureRectSet m_measureRects; 00600 MeasureRect m_draggingRect; 00601 bool m_haveDraggingRect; 00602 mutable bool m_haveCurrentMeasureRect; 00603 mutable QPoint m_currentMeasureRectPoint; 00604 00605 // Note that pixrects are only correct for a single view. 00606 // So we should update them at the start of the paint procedure 00607 // (painting is single threaded) and only use them after that. 00608 void updateMeasurePixrects(View *v) const; 00609 00610 virtual void updateMeasureRectYCoords(View *v, const MeasureRect &r) const; 00611 virtual void setMeasureRectYCoord(View *v, MeasureRect &r, bool start, int y) const; 00612 virtual void setMeasureRectFromPixrect(View *v, MeasureRect &r, QRect pixrect) const; 00613 00614 // This assumes updateMeasurementPixrects has been called 00615 MeasureRectSet::const_iterator findFocusedMeasureRect(QPoint) const; 00616 00617 void paintMeasurementRect(View *v, QPainter &paint, 00618 const MeasureRect &r, bool focus) const; 00619 00620 QString m_presentationName; 00621 00622 private: 00623 mutable QMutex m_dormancyMutex; 00624 mutable std::map<const void *, bool> m_dormancy; 00625 }; 00626 00627 #endif 00628