annotate base/View.h @ 76:af2725b5d6fe

* Implement harmonic cursor in spectrogram * Implement layer export. This doesn't quite do the right thing for the SV XML layer export yet -- it doesn't include layer display information, so when imported, it only creates an invisible model. Could also do with fixing CSV file import so as to work correctly for note and text layers.
author Chris Cannam
date Mon, 10 Apr 2006 17:22:59 +0000
parents 47fd14e29813
children c983dda79f72
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@52 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #ifndef _CANVAS_H_
Chris@0 17 #define _CANVAS_H_
Chris@0 18
Chris@0 19 #include <QFrame>
Chris@0 20 #include <QProgressBar>
Chris@0 21
Chris@0 22 #include "base/ZoomConstraint.h"
Chris@0 23 #include "base/PropertyContainer.h"
Chris@8 24 #include "base/ViewManager.h"
Chris@3 25 #include "base/XmlExportable.h"
Chris@0 26
Martin@54 27 // #define DEBUG_VIEW_WIDGET_PAINT 1
Martin@54 28
Chris@0 29 class Layer;
Chris@29 30 class ViewPropertyContainer;
Chris@0 31
Chris@0 32 #include <map>
Chris@0 33
Chris@0 34 /**
Chris@0 35 * View is the base class of widgets that display one or more
Chris@0 36 * overlaid views of data against a horizontal time scale.
Chris@0 37 *
Chris@0 38 * A View may have any number of attached Layers, each of which
Chris@0 39 * is expected to have one data Model (although multiple views may
Chris@0 40 * share the same model).
Chris@0 41 *
Chris@0 42 * A View may be panned in time and zoomed, although the
Chris@0 43 * mechanisms for doing so (as well as any other operations and
Chris@0 44 * properties available) depend on the subclass.
Chris@0 45 */
Chris@0 46
Chris@0 47 class View : public QFrame,
Chris@3 48 public XmlExportable
Chris@0 49 {
Chris@0 50 Q_OBJECT
Chris@0 51
Chris@0 52 public:
Chris@0 53 /**
Chris@45 54 * Deleting a View does not delete any of its layers. They should
Chris@45 55 * be managed elsewhere (e.g. by the Document).
Chris@0 56 */
Chris@0 57 virtual ~View();
Chris@0 58
Chris@0 59 /**
Chris@0 60 * Retrieve the first visible sample frame on the widget.
Chris@0 61 * This is a calculated value based on the centre-frame, widget
Chris@0 62 * width and zoom level. The result may be negative.
Chris@0 63 */
Chris@0 64 virtual long getStartFrame() const;
Chris@0 65
Chris@0 66 /**
Chris@0 67 * Set the widget pan based on the given first visible frame. The
Chris@0 68 * frame value may be negative.
Chris@0 69 */
Chris@0 70 virtual void setStartFrame(long);
Chris@0 71
Chris@0 72 /**
Chris@0 73 * Return the centre frame of the visible widget. This is an
Chris@0 74 * exact value that does not depend on the zoom block size. Other
Chris@0 75 * frame values (start, end) are calculated from this based on the
Chris@0 76 * zoom and other factors.
Chris@0 77 */
Chris@0 78 virtual size_t getCentreFrame() const { return m_centreFrame; }
Chris@0 79
Chris@0 80 /**
Chris@0 81 * Set the centre frame of the visible widget.
Chris@0 82 */
Chris@0 83 virtual void setCentreFrame(size_t f) { setCentreFrame(f, true); }
Chris@0 84
Chris@0 85 /**
Chris@0 86 * Retrieve the last visible sample frame on the widget.
Chris@0 87 * This is a calculated value based on the centre-frame, widget
Chris@0 88 * width and zoom level.
Chris@0 89 */
Chris@0 90 virtual size_t getEndFrame() const;
Chris@0 91
Chris@0 92 /**
Chris@15 93 * Return the pixel x-coordinate corresponding to a given sample
Chris@15 94 * frame (which may be negative).
Chris@15 95 */
Chris@15 96 int getXForFrame(long frame) const;
Chris@15 97
Chris@15 98 /**
Chris@15 99 * Return the closest frame to the given pixel x-coordinate.
Chris@15 100 */
Chris@15 101 long getFrameForX(int x) const;
Chris@15 102
Chris@15 103 /**
Chris@33 104 * Return the pixel y-coordinate corresponding to a given
Chris@33 105 * frequency, if the frequency range is as specified. This does
Chris@33 106 * not imply any policy about layer frequency ranges, but it might
Chris@33 107 * be useful for layers to match theirs up if desired.
Chris@33 108 *
Chris@33 109 * Not thread-safe in logarithmic mode. Call only from GUI thread.
Chris@33 110 */
Chris@33 111 float getYForFrequency(float frequency, float minFreq, float maxFreq,
Chris@33 112 bool logarithmic) const;
Chris@33 113
Chris@33 114 /**
Chris@33 115 * Return the closest frequency to the given pixel y-coordinate,
Chris@33 116 * if the frequency range is as specified.
Chris@33 117 *
Chris@33 118 * Not thread-safe in logarithmic mode. Call only from GUI thread.
Chris@33 119 */
Chris@33 120 float getFrequencyForY(int y, float minFreq, float maxFreq,
Chris@33 121 bool logarithmic) const;
Chris@33 122
Chris@33 123 /**
Chris@22 124 * Return the zoom level, i.e. the number of frames per pixel
Chris@0 125 */
Chris@22 126 int getZoomLevel() const;
Chris@0 127
Chris@0 128 /**
Chris@0 129 * Set the zoom level, i.e. the number of frames per pixel. The
Chris@0 130 * centre frame will be unchanged; the start and end frames will
Chris@0 131 * change.
Chris@0 132 */
Chris@0 133 virtual void setZoomLevel(size_t z);
Chris@0 134
Chris@0 135 /**
Chris@0 136 * Zoom in or out.
Chris@0 137 */
Chris@0 138 virtual void zoom(bool in);
Chris@0 139
Chris@12 140 /**
Chris@12 141 * Scroll left or right by a smallish or largish amount.
Chris@12 142 */
Chris@12 143 virtual void scroll(bool right, bool lots);
Chris@12 144
Chris@0 145 virtual void addLayer(Layer *v);
Chris@0 146 virtual void removeLayer(Layer *v); // does not delete the layer
Chris@0 147 virtual int getLayerCount() const { return m_layers.size(); }
Chris@0 148
Chris@0 149 /**
Chris@0 150 * Return a layer, counted in stacking order. That is, layer 0 is
Chris@0 151 * the bottom layer and layer "getLayerCount()-1" is the top one.
Chris@0 152 */
Chris@0 153 virtual Layer *getLayer(int n) { return m_layers[n]; }
Chris@0 154
Chris@8 155 /**
Chris@8 156 * Return the layer last selected by the user. This is normally
Chris@8 157 * the top layer, the same as getLayer(getLayerCount()-1).
Chris@8 158 * However, if the user has selected the pane itself more recently
Chris@8 159 * than any of the layers on it, this function will return 0. It
Chris@8 160 * will also return 0 if there are no layers.
Chris@8 161 */
Chris@8 162 virtual Layer *getSelectedLayer();
Chris@36 163 virtual const Layer *getSelectedLayer() const;
Chris@8 164
Chris@0 165 virtual void setViewManager(ViewManager *m);
Chris@65 166 virtual ViewManager *getViewManager() const { return m_manager; }
Chris@0 167
Chris@0 168 virtual void setFollowGlobalPan(bool f);
Chris@0 169 virtual bool getFollowGlobalPan() const { return m_followPan; }
Chris@0 170
Chris@0 171 virtual void setFollowGlobalZoom(bool f);
Chris@0 172 virtual bool getFollowGlobalZoom() const { return m_followZoom; }
Chris@0 173
Chris@0 174 virtual void setLightBackground(bool lb) { m_lightBackground = lb; }
Chris@0 175 virtual bool hasLightBackground() const { return m_lightBackground; }
Chris@0 176
Chris@45 177 enum TextStyle {
Chris@45 178 BoxedText,
Chris@45 179 OutlinedText
Chris@45 180 };
Chris@45 181
Chris@46 182 virtual void drawVisibleText(QPainter &p, int x, int y,
Chris@46 183 QString text, TextStyle style);
Chris@45 184
Chris@36 185 virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
Chris@0 186 return false;
Chris@0 187 }
Chris@36 188 virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
Chris@34 189 return false;
Chris@34 190 }
Chris@0 191
Chris@0 192 enum PlaybackFollowMode {
Chris@0 193 PlaybackScrollContinuous,
Chris@0 194 PlaybackScrollPage,
Chris@0 195 PlaybackIgnore
Chris@0 196 };
Chris@0 197 virtual void setPlaybackFollow(PlaybackFollowMode m);
Chris@0 198 virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
Chris@0 199
Chris@30 200 typedef PropertyContainer::PropertyName PropertyName;
Chris@30 201
Chris@29 202 // We implement the PropertyContainer API, although we don't
Chris@29 203 // actually subclass PropertyContainer. We have our own
Chris@29 204 // PropertyContainer that we can return on request that just
Chris@29 205 // delegates back to us.
Chris@29 206 virtual PropertyContainer::PropertyList getProperties() const;
Chris@30 207 virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
Chris@30 208 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@29 209 int *min, int *max) const;
Chris@30 210 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@0 211 int value) const;
Chris@30 212 virtual void setProperty(const PropertyName &, int value);
Chris@0 213 virtual QString getPropertyContainerName() const {
Chris@0 214 return objectName();
Chris@0 215 }
Chris@30 216 virtual QString getPropertyContainerIconName() const = 0;
Chris@0 217
Chris@29 218 virtual size_t getPropertyContainerCount() const;
Chris@29 219
Chris@29 220 virtual const PropertyContainer *getPropertyContainer(size_t i) const;
Chris@29 221 virtual PropertyContainer *getPropertyContainer(size_t i);
Chris@29 222
Chris@3 223 virtual QString toXmlString(QString indent = "",
Chris@3 224 QString extraAttributes = "") const;
Chris@3 225
Chris@74 226 size_t getModelsStartFrame() const;
Chris@74 227 size_t getModelsEndFrame() const;
Chris@74 228
Chris@0 229 signals:
Chris@0 230 void propertyContainerAdded(PropertyContainer *pc);
Chris@0 231 void propertyContainerRemoved(PropertyContainer *pc);
Chris@0 232 void propertyContainerPropertyChanged(PropertyContainer *pc);
Chris@0 233 void propertyContainerNameChanged(PropertyContainer *pc);
Chris@30 234 void propertyChanged(PropertyName);
Chris@0 235
Chris@0 236 void centreFrameChanged(void *, unsigned long, bool);
Chris@0 237 void zoomLevelChanged(void *, unsigned long, bool);
Chris@0 238
Chris@0 239 public slots:
Chris@0 240 virtual void modelChanged();
Chris@0 241 virtual void modelChanged(size_t startFrame, size_t endFrame);
Chris@0 242 virtual void modelCompletionChanged();
Chris@0 243 virtual void modelReplaced();
Chris@0 244 virtual void layerParametersChanged();
Chris@0 245 virtual void layerNameChanged();
Chris@0 246
Chris@0 247 virtual void viewManagerCentreFrameChanged(void *, unsigned long, bool);
Chris@0 248 virtual void viewManagerPlaybackFrameChanged(unsigned long);
Chris@0 249 virtual void viewManagerZoomLevelChanged(void *, unsigned long, bool);
Chris@0 250
Chris@44 251 virtual void propertyContainerSelected(View *, PropertyContainer *pc);
Chris@0 252
Chris@9 253 virtual void selectionChanged();
Chris@8 254 virtual void toolModeChanged();
Chris@8 255
Chris@0 256 protected:
Chris@0 257 View(QWidget *, bool showProgress);
Chris@0 258 virtual void paintEvent(QPaintEvent *e);
Chris@9 259 virtual void drawSelections(QPainter &);
Chris@10 260 virtual bool shouldLabelSelections() const { return true; }
Chris@0 261
Chris@0 262 typedef std::vector<Layer *> LayerList;
Chris@0 263
Chris@0 264 int getModelsSampleRate() const;
Chris@0 265 bool areLayersScrollable() const;
Chris@31 266 LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
Chris@31 267 LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
Chris@0 268 size_t getZoomConstraintBlockSize(size_t blockSize,
Chris@0 269 ZoomConstraint::RoundingDirection dir =
Chris@0 270 ZoomConstraint::RoundNearest) const;
Chris@0 271
Chris@10 272 bool setCentreFrame(size_t f, bool doEmit);
Chris@0 273
Chris@0 274 void checkProgress(void *object);
Chris@0 275
Chris@3 276 size_t m_centreFrame;
Chris@3 277 int m_zoomLevel;
Chris@3 278 bool m_followPan;
Chris@3 279 bool m_followZoom;
Chris@3 280 PlaybackFollowMode m_followPlay;
Chris@3 281 size_t m_playPointerFrame;
Chris@3 282 bool m_lightBackground;
Chris@3 283 bool m_showProgress;
Chris@0 284
Chris@3 285 QPixmap *m_cache;
Chris@3 286 size_t m_cacheCentreFrame;
Chris@3 287 int m_cacheZoomLevel;
Chris@9 288 bool m_selectionCached;
Chris@0 289
Chris@3 290 bool m_deleting;
Chris@0 291
Chris@3 292 LayerList m_layers; // I don't own these, but see dtor note above
Chris@8 293 bool m_haveSelectedLayer;
Chris@0 294
Chris@0 295 // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
Chris@0 296 mutable LayerList m_lastScrollableBackLayers;
Chris@0 297 mutable LayerList m_lastNonScrollableBackLayers;
Chris@0 298
Chris@0 299 class LayerProgressBar : public QProgressBar {
Chris@0 300 public:
Chris@16 301 LayerProgressBar(QWidget *parent);
Chris@0 302 virtual QString text() const { return m_text; }
Chris@0 303 virtual void setText(QString text) { m_text = text; }
Chris@0 304 protected:
Chris@0 305 QString m_text;
Chris@0 306 };
Chris@0 307
Chris@0 308 typedef std::map<Layer *, LayerProgressBar *> ProgressMap;
Chris@0 309 ProgressMap m_progressBars; // I own the ProgressBars
Chris@0 310
Chris@0 311 ViewManager *m_manager; // I don't own this
Chris@29 312 ViewPropertyContainer *m_propertyContainer; // I own this
Chris@29 313 };
Chris@29 314
Chris@29 315
Chris@29 316 // Use this for delegation, because we can't subclass from
Chris@29 317 // PropertyContainer (which is a QObject) ourselves because of
Chris@29 318 // ambiguity with QFrame parent
Chris@29 319
Chris@29 320 class ViewPropertyContainer : public PropertyContainer
Chris@29 321 {
Chris@29 322 Q_OBJECT
Chris@29 323
Chris@29 324 public:
Chris@29 325 ViewPropertyContainer(View *v);
Chris@29 326 PropertyList getProperties() const { return m_v->getProperties(); }
Chris@29 327 PropertyType getPropertyType(const PropertyName &n) const {
Chris@29 328 return m_v->getPropertyType(n);
Chris@29 329 }
Chris@29 330 int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max) const {
Chris@29 331 return m_v->getPropertyRangeAndValue(n, min, max);
Chris@29 332 }
Chris@29 333 QString getPropertyValueLabel(const PropertyName &n, int value) const {
Chris@29 334 return m_v->getPropertyValueLabel(n, value);
Chris@29 335 }
Chris@29 336 QString getPropertyContainerName() const {
Chris@29 337 return m_v->getPropertyContainerName();
Chris@29 338 }
Chris@29 339 QString getPropertyContainerIconName() const {
Chris@30 340 return m_v->getPropertyContainerIconName();
Chris@29 341 }
Chris@29 342
Chris@29 343 public slots:
Chris@29 344 virtual void setProperty(const PropertyName &n, int value) {
Chris@29 345 m_v->setProperty(n, value);
Chris@29 346 }
Chris@29 347
Chris@29 348 protected:
Chris@29 349 View *m_v;
Chris@0 350 };
Chris@0 351
Chris@0 352 #endif
Chris@0 353