annotate view/View.h @ 183:5f86ae638b04

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