annotate view/View.h @ 789:9fd1bdf214dd tonioni

Play pointer: when user drags pane during playback such that the pointer is no longer visible, accept that and stop trying to track it until pointer naturally comes back within visible area
author Chris Cannam
date Thu, 12 Jun 2014 12:48:11 +0100
parents 56ba2b03508e
children edada332c374
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@226 16 #ifndef _VIEW_H_
Chris@226 17 #define _VIEW_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@315 33 #include <set>
Chris@127 34
Chris@127 35 /**
Chris@127 36 * View is the base class of widgets that display one or more
Chris@127 37 * overlaid views of data against a horizontal time scale.
Chris@127 38 *
Chris@127 39 * A View may have any number of attached Layers, each of which
Chris@127 40 * is expected to have one data Model (although multiple views may
Chris@127 41 * share the same model).
Chris@127 42 *
Chris@127 43 * A View may be panned in time and zoomed, although the
Chris@127 44 * mechanisms for doing so (as well as any other operations and
Chris@127 45 * properties available) depend on the subclass.
Chris@127 46 */
Chris@127 47
Chris@127 48 class View : public QFrame,
Chris@127 49 public XmlExportable
Chris@127 50 {
Chris@127 51 Q_OBJECT
Chris@127 52
Chris@127 53 public:
Chris@127 54 /**
Chris@127 55 * Deleting a View does not delete any of its layers. They should
Chris@127 56 * be managed elsewhere (e.g. by the Document).
Chris@127 57 */
Chris@127 58 virtual ~View();
Chris@127 59
Chris@127 60 /**
Chris@127 61 * Retrieve the first visible sample frame on the widget.
Chris@127 62 * This is a calculated value based on the centre-frame, widget
Chris@127 63 * width and zoom level. The result may be negative.
Chris@127 64 */
Chris@313 65 long getStartFrame() const;
Chris@127 66
Chris@127 67 /**
Chris@127 68 * Set the widget pan based on the given first visible frame. The
Chris@127 69 * frame value may be negative.
Chris@127 70 */
Chris@313 71 void setStartFrame(long);
Chris@127 72
Chris@127 73 /**
Chris@127 74 * Return the centre frame of the visible widget. This is an
Chris@127 75 * exact value that does not depend on the zoom block size. Other
Chris@127 76 * frame values (start, end) are calculated from this based on the
Chris@127 77 * zoom and other factors.
Chris@127 78 */
Chris@313 79 size_t getCentreFrame() const { return m_centreFrame; }
Chris@127 80
Chris@127 81 /**
Chris@127 82 * Set the centre frame of the visible widget.
Chris@127 83 */
Chris@313 84 void setCentreFrame(size_t f) { setCentreFrame(f, true); }
Chris@127 85
Chris@127 86 /**
Chris@127 87 * Retrieve the last visible sample frame on the widget.
Chris@127 88 * This is a calculated value based on the centre-frame, widget
Chris@127 89 * width and zoom level.
Chris@127 90 */
Chris@313 91 size_t getEndFrame() const;
Chris@127 92
Chris@127 93 /**
Chris@127 94 * Return the pixel x-coordinate corresponding to a given sample
Chris@127 95 * frame (which may be negative).
Chris@127 96 */
Chris@127 97 int getXForFrame(long frame) const;
Chris@127 98
Chris@127 99 /**
Chris@127 100 * Return the closest frame to the given pixel x-coordinate.
Chris@127 101 */
Chris@127 102 long getFrameForX(int x) const;
Chris@127 103
Chris@127 104 /**
Chris@127 105 * Return the pixel y-coordinate corresponding to a given
Chris@127 106 * frequency, if the frequency range is as specified. This does
Chris@127 107 * not imply any policy about layer frequency ranges, but it might
Chris@127 108 * be useful for layers to match theirs up if desired.
Chris@127 109 *
Chris@127 110 * Not thread-safe in logarithmic mode. Call only from GUI thread.
Chris@127 111 */
Chris@127 112 float getYForFrequency(float frequency, float minFreq, float maxFreq,
Chris@127 113 bool logarithmic) const;
Chris@127 114
Chris@127 115 /**
Chris@127 116 * Return the closest frequency to the given pixel y-coordinate,
Chris@127 117 * if the frequency range is as specified.
Chris@127 118 *
Chris@127 119 * Not thread-safe in logarithmic mode. Call only from GUI thread.
Chris@127 120 */
Chris@127 121 float getFrequencyForY(int y, float minFreq, float maxFreq,
Chris@127 122 bool logarithmic) const;
Chris@127 123
Chris@127 124 /**
Chris@127 125 * Return the zoom level, i.e. the number of frames per pixel
Chris@127 126 */
Chris@127 127 int getZoomLevel() const;
Chris@127 128
Chris@127 129 /**
Chris@127 130 * Set the zoom level, i.e. the number of frames per pixel. The
Chris@127 131 * centre frame will be unchanged; the start and end frames will
Chris@127 132 * change.
Chris@127 133 */
Chris@127 134 virtual void setZoomLevel(size_t z);
Chris@127 135
Chris@127 136 /**
Chris@127 137 * Zoom in or out.
Chris@127 138 */
Chris@127 139 virtual void zoom(bool in);
Chris@127 140
Chris@127 141 /**
Chris@127 142 * Scroll left or right by a smallish or largish amount.
Chris@127 143 */
Chris@510 144 virtual void scroll(bool right, bool lots, bool doEmit = true);
Chris@127 145
Chris@127 146 virtual void addLayer(Layer *v);
Chris@127 147 virtual void removeLayer(Layer *v); // does not delete the layer
Chris@127 148 virtual int getLayerCount() const { return m_layers.size(); }
Chris@127 149
Chris@127 150 /**
Chris@127 151 * Return a layer, counted in stacking order. That is, layer 0 is
Chris@127 152 * the bottom layer and layer "getLayerCount()-1" is the top one.
Chris@127 153 */
Chris@277 154 virtual Layer *getLayer(int n) {
Chris@285 155 if (n < int(m_layers.size())) return m_layers[n]; else return 0;
Chris@277 156 }
Chris@127 157
Chris@127 158 /**
Chris@268 159 * Return the top layer. This is the same as
Chris@268 160 * getLayer(getLayerCount()-1) if there is at least one layer, and
Chris@268 161 * 0 otherwise.
Chris@268 162 */
Chris@268 163 virtual Layer *getTopLayer() {
Chris@268 164 return m_layers.empty() ? 0 : m_layers[m_layers.size()-1];
Chris@268 165 }
Chris@268 166
Chris@268 167 /**
Chris@127 168 * Return the layer last selected by the user. This is normally
Chris@127 169 * the top layer, the same as getLayer(getLayerCount()-1).
Chris@127 170 * However, if the user has selected the pane itself more recently
Chris@127 171 * than any of the layers on it, this function will return 0. It
Chris@127 172 * will also return 0 if there are no layers.
Chris@127 173 */
Chris@127 174 virtual Layer *getSelectedLayer();
Chris@127 175 virtual const Layer *getSelectedLayer() const;
Chris@127 176
Chris@127 177 virtual void setViewManager(ViewManager *m);
Chris@516 178 virtual void setViewManager(ViewManager *m, long initialFrame);
Chris@127 179 virtual ViewManager *getViewManager() const { return m_manager; }
Chris@127 180
Chris@127 181 virtual void setFollowGlobalPan(bool f);
Chris@127 182 virtual bool getFollowGlobalPan() const { return m_followPan; }
Chris@127 183
Chris@127 184 virtual void setFollowGlobalZoom(bool f);
Chris@127 185 virtual bool getFollowGlobalZoom() const { return m_followZoom; }
Chris@127 186
Chris@224 187 virtual bool hasLightBackground() const;
Chris@287 188 virtual QColor getForeground() const;
Chris@287 189 virtual QColor getBackground() const;
Chris@127 190
Chris@127 191 enum TextStyle {
Chris@127 192 BoxedText,
Chris@630 193 OutlinedText,
Chris@630 194 OutlinedItalicText
Chris@127 195 };
Chris@127 196
Chris@127 197 virtual void drawVisibleText(QPainter &p, int x, int y,
Chris@267 198 QString text, TextStyle style) const;
Chris@267 199
Chris@270 200 virtual void drawMeasurementRect(QPainter &p, const Layer *,
Chris@270 201 QRect rect, bool focus) const;
Chris@127 202
Chris@741 203 virtual bool shouldShowFeatureLabels() const {
Chris@741 204 return m_manager && m_manager->shouldShowFeatureLabels();
Chris@741 205 }
Chris@127 206 virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
Chris@127 207 return false;
Chris@127 208 }
Chris@127 209 virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
Chris@127 210 return false;
Chris@127 211 }
Chris@127 212
Chris@127 213 virtual void setPlaybackFollow(PlaybackFollowMode m);
Chris@127 214 virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
Chris@127 215
Chris@127 216 typedef PropertyContainer::PropertyName PropertyName;
Chris@127 217
Chris@127 218 // We implement the PropertyContainer API, although we don't
Chris@127 219 // actually subclass PropertyContainer. We have our own
Chris@127 220 // PropertyContainer that we can return on request that just
Chris@127 221 // delegates back to us.
Chris@127 222 virtual PropertyContainer::PropertyList getProperties() const;
Chris@127 223 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@127 224 virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
Chris@127 225 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 226 int *min, int *max, int *deflt) const;
Chris@127 227 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@127 228 int value) const;
Chris@127 229 virtual void setProperty(const PropertyName &, int value);
Chris@127 230 virtual QString getPropertyContainerName() const {
Chris@127 231 return objectName();
Chris@127 232 }
Chris@127 233 virtual QString getPropertyContainerIconName() const = 0;
Chris@127 234
Chris@127 235 virtual size_t getPropertyContainerCount() const;
Chris@127 236
Chris@127 237 virtual const PropertyContainer *getPropertyContainer(size_t i) const;
Chris@127 238 virtual PropertyContainer *getPropertyContainer(size_t i);
Chris@127 239
Chris@229 240 // Render the contents on a wide canvas
Chris@229 241 virtual QImage *toNewImage(size_t f0, size_t f1);
Chris@226 242 virtual QImage *toNewImage();
Chris@229 243 virtual QSize getImageSize(size_t f0, size_t f1);
Chris@229 244 virtual QSize getImageSize();
Chris@226 245
Chris@127 246 virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
Chris@127 247
Chris@127 248 virtual bool getValueExtents(QString unit, float &min, float &max,
Chris@127 249 bool &log) const;
Chris@127 250
Chris@316 251 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 252 QString extraAttributes = "") const;
Chris@127 253
Chris@222 254 // First frame actually in model, to right of scale, if present
Chris@222 255 virtual size_t getFirstVisibleFrame() const;
Chris@222 256 virtual size_t getLastVisibleFrame() const;
Chris@222 257
Chris@127 258 size_t getModelsStartFrame() const;
Chris@127 259 size_t getModelsEndFrame() const;
Chris@127 260
Chris@315 261 typedef std::set<Model *> ModelSet;
Chris@315 262 ModelSet getModels();
Chris@315 263
Chris@301 264 //!!!
Chris@320 265 Model *getAligningModel() const;
Chris@320 266 size_t alignFromReference(size_t) const;
Chris@320 267 size_t alignToReference(size_t) const;
Chris@301 268 int getAlignedPlaybackFrame() const;
Chris@301 269
Chris@127 270 signals:
Chris@127 271 void propertyContainerAdded(PropertyContainer *pc);
Chris@127 272 void propertyContainerRemoved(PropertyContainer *pc);
Chris@127 273 void propertyContainerPropertyChanged(PropertyContainer *pc);
Chris@197 274 void propertyContainerPropertyRangeChanged(PropertyContainer *pc);
Chris@127 275 void propertyContainerNameChanged(PropertyContainer *pc);
Chris@298 276 void propertyContainerSelected(PropertyContainer *pc);
Chris@127 277 void propertyChanged(PropertyContainer::PropertyName);
Chris@127 278
Chris@336 279 void layerModelChanged();
Chris@336 280
Chris@211 281 void centreFrameChanged(unsigned long frame,
Chris@211 282 bool globalScroll,
Chris@211 283 PlaybackFollowMode followMode);
Chris@211 284
Chris@222 285 void zoomLevelChanged(unsigned long, bool);
Chris@127 286
Chris@189 287 void contextHelpChanged(const QString &);
Chris@189 288
Chris@127 289 public slots:
Chris@127 290 virtual void modelChanged();
Chris@127 291 virtual void modelChanged(size_t startFrame, size_t endFrame);
Chris@127 292 virtual void modelCompletionChanged();
Chris@320 293 virtual void modelAlignmentCompletionChanged();
Chris@127 294 virtual void modelReplaced();
Chris@127 295 virtual void layerParametersChanged();
Chris@197 296 virtual void layerParameterRangesChanged();
Chris@268 297 virtual void layerMeasurementRectsChanged();
Chris@127 298 virtual void layerNameChanged();
Chris@127 299
Chris@211 300 virtual void globalCentreFrameChanged(unsigned long);
Chris@211 301 virtual void viewCentreFrameChanged(View *, unsigned long);
Chris@127 302 virtual void viewManagerPlaybackFrameChanged(unsigned long);
Chris@222 303 virtual void viewZoomLevelChanged(View *, unsigned long, bool);
Chris@127 304
Chris@127 305 virtual void propertyContainerSelected(View *, PropertyContainer *pc);
Chris@127 306
Chris@127 307 virtual void selectionChanged();
Chris@127 308 virtual void toolModeChanged();
Chris@133 309 virtual void overlayModeChanged();
Chris@133 310 virtual void zoomWheelsEnabledChanged();
Chris@127 311
Chris@555 312 virtual void progressCheckStalledTimerElapsed();
Chris@555 313
Chris@127 314 protected:
Chris@127 315 View(QWidget *, bool showProgress);
Chris@127 316 virtual void paintEvent(QPaintEvent *e);
Chris@127 317 virtual void drawSelections(QPainter &);
Chris@127 318 virtual bool shouldLabelSelections() const { return true; }
Chris@229 319 virtual bool render(QPainter &paint, int x0, size_t f0, size_t f1);
Chris@339 320 virtual void setPaintFont(QPainter &paint);
Chris@339 321
Chris@127 322 typedef std::vector<Layer *> LayerList;
Chris@127 323
Chris@127 324 int getModelsSampleRate() const;
Chris@127 325 bool areLayersScrollable() const;
Chris@127 326 LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
Chris@127 327 LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
Chris@127 328 size_t getZoomConstraintBlockSize(size_t blockSize,
Chris@127 329 ZoomConstraint::RoundingDirection dir =
Chris@127 330 ZoomConstraint::RoundNearest) const;
Chris@127 331
Chris@183 332 // True if the top layer(s) use colours for meaningful things. If
Chris@183 333 // this is the case, selections will be shown using unfilled boxes
Chris@183 334 // rather than with a translucent fill.
Chris@183 335 bool areLayerColoursSignificant() const;
Chris@183 336
Chris@217 337 // True if the top layer has a time axis on the x coordinate (this
Chris@217 338 // is generally the case except for spectrum/slice layers). It
Chris@217 339 // will not be possible to make or display selections if this is
Chris@217 340 // false.
Chris@217 341 bool hasTopLayerTimeXAxis() const;
Chris@217 342
Chris@127 343 bool setCentreFrame(size_t f, bool doEmit);
Chris@127 344
Chris@511 345 void movePlayPointer(unsigned long f);
Chris@511 346
Chris@127 347 void checkProgress(void *object);
Chris@384 348 int getProgressBarWidth() const; // if visible
Chris@127 349
Chris@127 350 size_t m_centreFrame;
Chris@127 351 int m_zoomLevel;
Chris@127 352 bool m_followPan;
Chris@127 353 bool m_followZoom;
Chris@127 354 PlaybackFollowMode m_followPlay;
Chris@789 355 bool m_followPlayIsDetached;
Chris@127 356 size_t m_playPointerFrame;
Chris@127 357 bool m_lightBackground;
Chris@127 358 bool m_showProgress;
Chris@127 359
Chris@127 360 QPixmap *m_cache;
Chris@127 361 size_t m_cacheCentreFrame;
Chris@127 362 int m_cacheZoomLevel;
Chris@127 363 bool m_selectionCached;
Chris@127 364
Chris@127 365 bool m_deleting;
Chris@127 366
Chris@127 367 LayerList m_layers; // I don't own these, but see dtor note above
Chris@127 368 bool m_haveSelectedLayer;
Chris@127 369
Chris@583 370 QString m_lastError;
Chris@583 371
Chris@127 372 // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
Chris@127 373 mutable LayerList m_lastScrollableBackLayers;
Chris@127 374 mutable LayerList m_lastNonScrollableBackLayers;
Chris@127 375
Chris@127 376 class LayerProgressBar : public QProgressBar {
Chris@127 377 public:
Chris@127 378 LayerProgressBar(QWidget *parent);
Chris@127 379 virtual QString text() const { return m_text; }
Chris@127 380 virtual void setText(QString text) { m_text = text; }
Chris@127 381 protected:
Chris@127 382 QString m_text;
Chris@127 383 };
Chris@127 384
Chris@555 385 struct ProgressBarRec {
Chris@555 386 QProgressBar *bar;
Chris@555 387 int lastCheck;
Chris@555 388 QTimer *checkTimer;
Chris@555 389 };
Chris@555 390 typedef std::map<Layer *, ProgressBarRec> ProgressMap;
Chris@127 391 ProgressMap m_progressBars; // I own the ProgressBars
Chris@127 392
Chris@127 393 ViewManager *m_manager; // I don't own this
Chris@127 394 ViewPropertyContainer *m_propertyContainer; // I own this
Chris@127 395 };
Chris@127 396
Chris@127 397
Chris@127 398 // Use this for delegation, because we can't subclass from
Chris@127 399 // PropertyContainer (which is a QObject) ourselves because of
Chris@127 400 // ambiguity with QFrame parent
Chris@127 401
Chris@127 402 class ViewPropertyContainer : public PropertyContainer
Chris@127 403 {
Chris@127 404 Q_OBJECT
Chris@127 405
Chris@127 406 public:
Chris@127 407 ViewPropertyContainer(View *v);
Chris@728 408 virtual ~ViewPropertyContainer();
Chris@728 409
Chris@127 410 PropertyList getProperties() const { return m_v->getProperties(); }
Chris@127 411 QString getPropertyLabel(const PropertyName &n) const {
Chris@127 412 return m_v->getPropertyLabel(n);
Chris@127 413 }
Chris@127 414 PropertyType getPropertyType(const PropertyName &n) const {
Chris@127 415 return m_v->getPropertyType(n);
Chris@127 416 }
Chris@216 417 int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max,
Chris@216 418 int *deflt) const {
Chris@216 419 return m_v->getPropertyRangeAndValue(n, min, max, deflt);
Chris@127 420 }
Chris@127 421 QString getPropertyValueLabel(const PropertyName &n, int value) const {
Chris@127 422 return m_v->getPropertyValueLabel(n, value);
Chris@127 423 }
Chris@127 424 QString getPropertyContainerName() const {
Chris@127 425 return m_v->getPropertyContainerName();
Chris@127 426 }
Chris@127 427 QString getPropertyContainerIconName() const {
Chris@127 428 return m_v->getPropertyContainerIconName();
Chris@127 429 }
Chris@127 430
Chris@127 431 public slots:
Chris@127 432 virtual void setProperty(const PropertyName &n, int value) {
Chris@127 433 m_v->setProperty(n, value);
Chris@127 434 }
Chris@127 435
Chris@127 436 protected:
Chris@127 437 View *m_v;
Chris@127 438 };
Chris@127 439
Chris@127 440 #endif
Chris@127 441