annotate base/Layer.h @ 117:c30728d5625c sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents c983dda79f72
children 53dfcd7db419
rev   line source
Chris@0 1
Chris@49 2 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 3
Chris@0 4 /*
Chris@52 5 Sonic Visualiser
Chris@52 6 An audio file viewer and annotation editor.
Chris@52 7 Centre for Digital Music, Queen Mary, University of London.
Chris@52 8 This file copyright 2006 Chris Cannam.
Chris@0 9
Chris@52 10 This program is free software; you can redistribute it and/or
Chris@52 11 modify it under the terms of the GNU General Public License as
Chris@52 12 published by the Free Software Foundation; either version 2 of the
Chris@52 13 License, or (at your option) any later version. See the file
Chris@52 14 COPYING included with this distribution for more information.
Chris@0 15 */
Chris@0 16
Chris@26 17 #ifndef _LAYER_H_
Chris@26 18 #define _LAYER_H_
Chris@0 19
Chris@0 20 #include "PropertyContainer.h"
Chris@3 21 #include "XmlExportable.h"
Chris@35 22 #include "Selection.h"
Chris@0 23
Chris@0 24 #include <QObject>
Chris@0 25 #include <QRect>
Chris@6 26 #include <QXmlAttributes>
Chris@0 27
Chris@39 28 #include <map>
Chris@39 29
Chris@0 30 class ZoomConstraint;
Chris@0 31 class Model;
Chris@0 32 class QPainter;
Chris@0 33 class View;
Chris@12 34 class QMouseEvent;
Chris@74 35 class Clipboard;
Chris@0 36
Chris@0 37 /**
Chris@0 38 * The base class for visual representations of the data found in a
Chris@0 39 * Model. Layers are expected to be able to draw themselves onto a
Chris@0 40 * View, and may also be editable.
Chris@0 41 */
Chris@0 42
Chris@29 43 class Layer : public PropertyContainer,
Chris@3 44 public XmlExportable
Chris@0 45 {
Chris@0 46 Q_OBJECT
Chris@0 47
Chris@0 48 public:
Chris@36 49 Layer();
Chris@0 50 virtual ~Layer();
Chris@0 51
Chris@0 52 virtual const Model *getModel() const = 0;
Chris@41 53 virtual Model *getModel() {
Chris@41 54 return const_cast<Model *>(const_cast<const Layer *>(this)->getModel());
Chris@41 55 }
Chris@41 56
Chris@0 57 virtual const ZoomConstraint *getZoomConstraint() const { return 0; }
Chris@36 58 virtual void paint(View *, QPainter &, QRect) const = 0;
Chris@0 59
Chris@0 60 enum VerticalPosition {
Chris@0 61 PositionTop, PositionMiddle, PositionBottom
Chris@0 62 };
Chris@0 63 virtual VerticalPosition getPreferredTimeRulerPosition() const {
Chris@0 64 return PositionMiddle;
Chris@0 65 }
Chris@0 66 virtual VerticalPosition getPreferredFrameCountPosition() const {
Chris@0 67 return PositionBottom;
Chris@0 68 }
Chris@0 69
Chris@12 70 virtual QString getPropertyContainerIconName() const;
Chris@12 71
Chris@0 72 virtual QString getPropertyContainerName() const {
Chris@0 73 return objectName();
Chris@0 74 }
Chris@0 75
Chris@47 76 virtual QString getLayerPresentationName() const;
Chris@47 77
Chris@36 78 virtual int getVerticalScaleWidth(View *, QPainter &) const { return 0; }
Chris@36 79 virtual void paintVerticalScale(View *, QPainter &, QRect) const { }
Chris@0 80
Chris@76 81 virtual bool getCrosshairExtents(View *, QPainter &, QPoint cursorPos,
Chris@76 82 std::vector<QRect> &) const { return false; }
Chris@76 83 virtual void paintCrosshairs(View *, QPainter &, QPoint) const { }
Chris@76 84
Chris@36 85 virtual QString getFeatureDescription(View *, QPoint &) const {
Chris@20 86 return "";
Chris@0 87 }
Chris@0 88
Chris@23 89 enum SnapType {
Chris@23 90 SnapLeft,
Chris@23 91 SnapRight,
Chris@23 92 SnapNearest,
Chris@23 93 SnapNeighbouring
Chris@23 94 };
Chris@8 95
Chris@23 96 /**
Chris@23 97 * Adjust the given frame to snap to the nearest feature, if
Chris@23 98 * possible.
Chris@23 99 *
Chris@23 100 * If snap is SnapLeft or SnapRight, adjust the frame to match
Chris@23 101 * that of the nearest feature in the given direction regardless
Chris@23 102 * of how far away it is. If snap is SnapNearest, adjust the
Chris@23 103 * frame to that of the nearest feature in either direction. If
Chris@23 104 * snap is SnapNeighbouring, adjust the frame to that of the
Chris@23 105 * nearest feature if it is close, and leave it alone (returning
Chris@23 106 * false) otherwise. SnapNeighbouring should always choose the
Chris@23 107 * same feature that would be used in an editing operation through
Chris@23 108 * calls to editStart etc.
Chris@23 109 *
Chris@23 110 * Return true if a suitable feature was found and frame adjusted
Chris@23 111 * accordingly. Return false if no suitable feature was
Chris@23 112 * available. Also return the resolution of the model in this
Chris@23 113 * layer in sample frames.
Chris@23 114 */
Chris@36 115 virtual bool snapToFeatureFrame(View *v,
Chris@36 116 int &frame,
Chris@23 117 size_t &resolution,
Chris@23 118 SnapType snap) const {
Chris@8 119 resolution = 1;
Chris@23 120 return false;
Chris@8 121 }
Chris@8 122
Chris@12 123 // Draw and edit modes:
Chris@8 124 //
Chris@12 125 // Layer needs to get actual mouse events, I guess. Draw mode is
Chris@8 126 // probably the easier.
Chris@8 127
Chris@36 128 virtual void drawStart(View *, QMouseEvent *) { }
Chris@36 129 virtual void drawDrag(View *, QMouseEvent *) { }
Chris@36 130 virtual void drawEnd(View *, QMouseEvent *) { }
Chris@13 131
Chris@36 132 virtual void editStart(View *, QMouseEvent *) { }
Chris@36 133 virtual void editDrag(View *, QMouseEvent *) { }
Chris@36 134 virtual void editEnd(View *, QMouseEvent *) { }
Chris@12 135
Chris@36 136 virtual void editOpen(View *, QMouseEvent *) { } // on double-click
Chris@32 137
Chris@35 138 virtual void moveSelection(Selection s, size_t newStartFrame) { }
Chris@35 139 virtual void resizeSelection(Selection s, Selection newSize) { }
Chris@35 140 virtual void deleteSelection(Selection s) { }
Chris@35 141
Chris@74 142 virtual void copy(Selection s, Clipboard &to) { }
Chris@74 143 virtual void paste(const Clipboard &from, int frameOffset) { }
Chris@35 144
Chris@8 145 // Text mode:
Chris@8 146 //
Chris@8 147 // Label nearest feature. We need to get the feature coordinates
Chris@8 148 // and current label from the layer, and then the pane can pop up
Chris@8 149 // a little text entry dialog at the right location. Or we edit
Chris@8 150 // in place? Probably the dialog is easier.
Chris@8 151
Chris@0 152 /**
Chris@36 153 * This should return true if the layer can safely be scrolled
Chris@36 154 * automatically by a given view (simply copying the existing data
Chris@0 155 * and then refreshing the exposed area) without altering its
Chris@36 156 * meaning. For the view widget as a whole this is usually not
Chris@0 157 * possible because of invariant (non-scrolling) material
Chris@0 158 * displayed over the top, but the widget may be able to optimise
Chris@0 159 * scrolling better if it is known that individual views can be
Chris@0 160 * scrolled safely in this way.
Chris@0 161 */
Chris@36 162 virtual bool isLayerScrollable(const View *) const { return true; }
Chris@0 163
Chris@0 164 /**
Chris@10 165 * This should return true if the layer completely obscures any
Chris@10 166 * underlying layers. It's used to determine whether the view can
Chris@10 167 * safely draw any selection rectangles under the layer instead of
Chris@10 168 * over it, in the case where the layer is not scrollable and
Chris@10 169 * therefore needs to be redrawn each time (so that the selection
Chris@10 170 * rectangle can be cached).
Chris@10 171 */
Chris@10 172 virtual bool isLayerOpaque() const { return false; }
Chris@10 173
Chris@10 174 /**
Chris@18 175 * This should return true if the layer can be edited by the user.
Chris@18 176 * If this is the case, the appropriate edit tools may be made
Chris@18 177 * available by the application and the layer's drawStart/Drag/End
Chris@18 178 * and editStart/Drag/End methods should be implemented.
Chris@18 179 */
Chris@18 180 virtual bool isLayerEditable() const { return false; }
Chris@18 181
Chris@18 182 /**
Chris@0 183 * Return the proportion of background work complete in drawing
Chris@0 184 * this view, as a percentage -- in most cases this will be the
Chris@0 185 * value returned by pointer from a call to the underlying model's
Chris@0 186 * isReady(int *) call. The widget may choose to show a progress
Chris@0 187 * meter if it finds that this returns < 100 at any given moment.
Chris@0 188 */
Chris@0 189 virtual int getCompletion() const { return 100; }
Chris@0 190
Chris@0 191 virtual void setObjectName(const QString &name);
Chris@0 192
Chris@7 193 /**
Chris@7 194 * Convert the layer's data (though not those of the model it
Chris@7 195 * refers to) into an XML string for file output. This class
Chris@7 196 * implements the basic name/type/model-id output; subclasses will
Chris@7 197 * typically call this superclass implementation with extra
Chris@7 198 * attributes describing their particular properties.
Chris@7 199 */
Chris@3 200 virtual QString toXmlString(QString indent = "",
Chris@3 201 QString extraAttributes = "") const;
Chris@3 202
Chris@7 203 /**
Chris@7 204 * Set the particular properties of a layer (those specific to the
Chris@7 205 * subclass) from a set of XML attributes. This is the effective
Chris@7 206 * inverse of the toXmlString method.
Chris@7 207 */
Chris@6 208 virtual void setProperties(const QXmlAttributes &) = 0;
Chris@6 209
Chris@24 210 /**
Chris@39 211 * Indicate that a layer is not currently visible in the given
Chris@39 212 * view and is not expected to become visible in the near future
Chris@39 213 * (for example because the user has explicitly removed or hidden
Chris@39 214 * it). The layer may respond by (for example) freeing any cache
Chris@40 215 * memory it is using, until next time its paint method is called,
Chris@40 216 * when it should set itself un-dormant again.
Chris@24 217 */
Chris@39 218 virtual void setLayerDormant(const View *v, bool dormant) {
Chris@39 219 m_dormancy[v] = dormant;
Chris@39 220 }
Chris@24 221
Chris@29 222 /**
Chris@39 223 * Return whether the layer is dormant (i.e. hidden) in the given
Chris@39 224 * view.
Chris@29 225 */
Chris@39 226 virtual bool isLayerDormant(const View *v) const {
Chris@39 227 if (m_dormancy.find(v) == m_dormancy.end()) return false;
Chris@39 228 return m_dormancy.find(v)->second;
Chris@39 229 }
Chris@29 230
Chris@29 231 virtual PlayParameters *getPlayParameters();
Chris@29 232
Chris@78 233 virtual bool needsTextLabelHeight() const { return false; }
Chris@78 234
Chris@117 235 virtual bool getValueExtents(float &min, float &max,
Chris@117 236 bool &logarithmic, QString &unit) const = 0;
Chris@117 237
Chris@117 238 virtual bool getDisplayExtents(float &min, float &max) const {
Chris@117 239 return false;
Chris@117 240 }
Chris@78 241
Chris@29 242 public slots:
Chris@36 243 void showLayer(View *, bool show);
Chris@28 244
Chris@0 245 signals:
Chris@0 246 void modelChanged();
Chris@0 247 void modelCompletionChanged();
Chris@0 248 void modelChanged(size_t startFrame, size_t endFrame);
Chris@0 249 void modelReplaced();
Chris@0 250
Chris@0 251 void layerParametersChanged();
Chris@0 252 void layerNameChanged();
Chris@0 253
Chris@0 254 protected:
Chris@40 255 mutable std::map<const void *, bool> m_dormancy;
Chris@0 256 };
Chris@0 257
Chris@0 258 #endif
Chris@0 259