svgui  1.9
Layer.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 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