annotate view/View.h @ 640:c6d705bf1672

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:36:43 +0100
parents c3593bb2de6b
children 596414d20ef0
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@127 203 virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
Chris@127 204 return false;
Chris@127 205 }
Chris@127 206 virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
Chris@127 207 return false;
Chris@127 208 }
Chris@127 209
Chris@127 210 virtual void setPlaybackFollow(PlaybackFollowMode m);
Chris@127 211 virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
Chris@127 212
Chris@127 213 typedef PropertyContainer::PropertyName PropertyName;
Chris@127 214
Chris@127 215 // We implement the PropertyContainer API, although we don't
Chris@127 216 // actually subclass PropertyContainer. We have our own
Chris@127 217 // PropertyContainer that we can return on request that just
Chris@127 218 // delegates back to us.
Chris@127 219 virtual PropertyContainer::PropertyList getProperties() const;
Chris@127 220 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@127 221 virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
Chris@127 222 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 223 int *min, int *max, int *deflt) const;
Chris@127 224 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@127 225 int value) const;
Chris@127 226 virtual void setProperty(const PropertyName &, int value);
Chris@127 227 virtual QString getPropertyContainerName() const {
Chris@127 228 return objectName();
Chris@127 229 }
Chris@127 230 virtual QString getPropertyContainerIconName() const = 0;
Chris@127 231
Chris@127 232 virtual size_t getPropertyContainerCount() const;
Chris@127 233
Chris@127 234 virtual const PropertyContainer *getPropertyContainer(size_t i) const;
Chris@127 235 virtual PropertyContainer *getPropertyContainer(size_t i);
Chris@127 236
Chris@229 237 // Render the contents on a wide canvas
Chris@229 238 virtual QImage *toNewImage(size_t f0, size_t f1);
Chris@226 239 virtual QImage *toNewImage();
Chris@229 240 virtual QSize getImageSize(size_t f0, size_t f1);
Chris@229 241 virtual QSize getImageSize();
Chris@226 242
Chris@127 243 virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
Chris@127 244
Chris@127 245 virtual bool getValueExtents(QString unit, float &min, float &max,
Chris@127 246 bool &log) const;
Chris@127 247
Chris@316 248 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 249 QString extraAttributes = "") const;
Chris@127 250
Chris@222 251 // First frame actually in model, to right of scale, if present
Chris@222 252 virtual size_t getFirstVisibleFrame() const;
Chris@222 253 virtual size_t getLastVisibleFrame() const;
Chris@222 254
Chris@127 255 size_t getModelsStartFrame() const;
Chris@127 256 size_t getModelsEndFrame() const;
Chris@127 257
Chris@315 258 typedef std::set<Model *> ModelSet;
Chris@315 259 ModelSet getModels();
Chris@315 260
Chris@301 261 //!!!
Chris@320 262 Model *getAligningModel() const;
Chris@320 263 size_t alignFromReference(size_t) const;
Chris@320 264 size_t alignToReference(size_t) const;
Chris@301 265 int getAlignedPlaybackFrame() const;
Chris@301 266
Chris@127 267 signals:
Chris@127 268 void propertyContainerAdded(PropertyContainer *pc);
Chris@127 269 void propertyContainerRemoved(PropertyContainer *pc);
Chris@127 270 void propertyContainerPropertyChanged(PropertyContainer *pc);
Chris@197 271 void propertyContainerPropertyRangeChanged(PropertyContainer *pc);
Chris@127 272 void propertyContainerNameChanged(PropertyContainer *pc);
Chris@298 273 void propertyContainerSelected(PropertyContainer *pc);
Chris@127 274 void propertyChanged(PropertyContainer::PropertyName);
Chris@127 275
Chris@336 276 void layerModelChanged();
Chris@336 277
Chris@211 278 void centreFrameChanged(unsigned long frame,
Chris@211 279 bool globalScroll,
Chris@211 280 PlaybackFollowMode followMode);
Chris@211 281
Chris@222 282 void zoomLevelChanged(unsigned long, bool);
Chris@127 283
Chris@189 284 void contextHelpChanged(const QString &);
Chris@189 285
Chris@127 286 public slots:
Chris@127 287 virtual void modelChanged();
Chris@127 288 virtual void modelChanged(size_t startFrame, size_t endFrame);
Chris@127 289 virtual void modelCompletionChanged();
Chris@320 290 virtual void modelAlignmentCompletionChanged();
Chris@127 291 virtual void modelReplaced();
Chris@127 292 virtual void layerParametersChanged();
Chris@197 293 virtual void layerParameterRangesChanged();
Chris@268 294 virtual void layerMeasurementRectsChanged();
Chris@127 295 virtual void layerNameChanged();
Chris@127 296
Chris@211 297 virtual void globalCentreFrameChanged(unsigned long);
Chris@211 298 virtual void viewCentreFrameChanged(View *, unsigned long);
Chris@127 299 virtual void viewManagerPlaybackFrameChanged(unsigned long);
Chris@222 300 virtual void viewZoomLevelChanged(View *, unsigned long, bool);
Chris@127 301
Chris@127 302 virtual void propertyContainerSelected(View *, PropertyContainer *pc);
Chris@127 303
Chris@127 304 virtual void selectionChanged();
Chris@127 305 virtual void toolModeChanged();
Chris@133 306 virtual void overlayModeChanged();
Chris@133 307 virtual void zoomWheelsEnabledChanged();
Chris@127 308
Chris@555 309 virtual void progressCheckStalledTimerElapsed();
Chris@555 310
Chris@127 311 protected:
Chris@127 312 View(QWidget *, bool showProgress);
Chris@127 313 virtual void paintEvent(QPaintEvent *e);
Chris@127 314 virtual void drawSelections(QPainter &);
Chris@127 315 virtual bool shouldLabelSelections() const { return true; }
Chris@229 316 virtual bool render(QPainter &paint, int x0, size_t f0, size_t f1);
Chris@339 317 virtual void setPaintFont(QPainter &paint);
Chris@339 318
Chris@127 319 typedef std::vector<Layer *> LayerList;
Chris@127 320
Chris@127 321 int getModelsSampleRate() const;
Chris@127 322 bool areLayersScrollable() const;
Chris@127 323 LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
Chris@127 324 LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
Chris@127 325 size_t getZoomConstraintBlockSize(size_t blockSize,
Chris@127 326 ZoomConstraint::RoundingDirection dir =
Chris@127 327 ZoomConstraint::RoundNearest) const;
Chris@127 328
Chris@183 329 // True if the top layer(s) use colours for meaningful things. If
Chris@183 330 // this is the case, selections will be shown using unfilled boxes
Chris@183 331 // rather than with a translucent fill.
Chris@183 332 bool areLayerColoursSignificant() const;
Chris@183 333
Chris@217 334 // True if the top layer has a time axis on the x coordinate (this
Chris@217 335 // is generally the case except for spectrum/slice layers). It
Chris@217 336 // will not be possible to make or display selections if this is
Chris@217 337 // false.
Chris@217 338 bool hasTopLayerTimeXAxis() const;
Chris@217 339
Chris@127 340 bool setCentreFrame(size_t f, bool doEmit);
Chris@127 341
Chris@511 342 void movePlayPointer(unsigned long f);
Chris@511 343
Chris@127 344 void checkProgress(void *object);
Chris@384 345 int getProgressBarWidth() const; // if visible
Chris@127 346
Chris@127 347 size_t m_centreFrame;
Chris@127 348 int m_zoomLevel;
Chris@127 349 bool m_followPan;
Chris@127 350 bool m_followZoom;
Chris@127 351 PlaybackFollowMode m_followPlay;
Chris@127 352 size_t m_playPointerFrame;
Chris@127 353 bool m_lightBackground;
Chris@127 354 bool m_showProgress;
Chris@127 355
Chris@127 356 QPixmap *m_cache;
Chris@127 357 size_t m_cacheCentreFrame;
Chris@127 358 int m_cacheZoomLevel;
Chris@127 359 bool m_selectionCached;
Chris@127 360
Chris@127 361 bool m_deleting;
Chris@127 362
Chris@127 363 LayerList m_layers; // I don't own these, but see dtor note above
Chris@127 364 bool m_haveSelectedLayer;
Chris@127 365
Chris@583 366 QString m_lastError;
Chris@583 367
Chris@127 368 // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
Chris@127 369 mutable LayerList m_lastScrollableBackLayers;
Chris@127 370 mutable LayerList m_lastNonScrollableBackLayers;
Chris@127 371
Chris@127 372 class LayerProgressBar : public QProgressBar {
Chris@127 373 public:
Chris@127 374 LayerProgressBar(QWidget *parent);
Chris@127 375 virtual QString text() const { return m_text; }
Chris@127 376 virtual void setText(QString text) { m_text = text; }
Chris@127 377 protected:
Chris@127 378 QString m_text;
Chris@127 379 };
Chris@127 380
Chris@555 381 struct ProgressBarRec {
Chris@555 382 QProgressBar *bar;
Chris@555 383 int lastCheck;
Chris@555 384 QTimer *checkTimer;
Chris@555 385 };
Chris@555 386 typedef std::map<Layer *, ProgressBarRec> ProgressMap;
Chris@127 387 ProgressMap m_progressBars; // I own the ProgressBars
Chris@127 388
Chris@127 389 ViewManager *m_manager; // I don't own this
Chris@127 390 ViewPropertyContainer *m_propertyContainer; // I own this
Chris@127 391 };
Chris@127 392
Chris@127 393
Chris@127 394 // Use this for delegation, because we can't subclass from
Chris@127 395 // PropertyContainer (which is a QObject) ourselves because of
Chris@127 396 // ambiguity with QFrame parent
Chris@127 397
Chris@127 398 class ViewPropertyContainer : public PropertyContainer
Chris@127 399 {
Chris@127 400 Q_OBJECT
Chris@127 401
Chris@127 402 public:
Chris@127 403 ViewPropertyContainer(View *v);
Chris@127 404 PropertyList getProperties() const { return m_v->getProperties(); }
Chris@127 405 QString getPropertyLabel(const PropertyName &n) const {
Chris@127 406 return m_v->getPropertyLabel(n);
Chris@127 407 }
Chris@127 408 PropertyType getPropertyType(const PropertyName &n) const {
Chris@127 409 return m_v->getPropertyType(n);
Chris@127 410 }
Chris@216 411 int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max,
Chris@216 412 int *deflt) const {
Chris@216 413 return m_v->getPropertyRangeAndValue(n, min, max, deflt);
Chris@127 414 }
Chris@127 415 QString getPropertyValueLabel(const PropertyName &n, int value) const {
Chris@127 416 return m_v->getPropertyValueLabel(n, value);
Chris@127 417 }
Chris@127 418 QString getPropertyContainerName() const {
Chris@127 419 return m_v->getPropertyContainerName();
Chris@127 420 }
Chris@127 421 QString getPropertyContainerIconName() const {
Chris@127 422 return m_v->getPropertyContainerIconName();
Chris@127 423 }
Chris@127 424
Chris@127 425 public slots:
Chris@127 426 virtual void setProperty(const PropertyName &n, int value) {
Chris@127 427 m_v->setProperty(n, value);
Chris@127 428 }
Chris@127 429
Chris@127 430 protected:
Chris@127 431 View *m_v;
Chris@127 432 };
Chris@127 433
Chris@127 434 #endif
Chris@127 435