annotate view/View.h @ 473:4f4f943bfdfc

* Merge from one-fftdataserver-per-fftmodel branch. This bit of reworking (which is not described very accurately by the title of the branch) turns the MatrixFile object into something that either reads or writes, but not both, and separates the FFT file cache reader and writer implementations separately. This allows the FFT data server to have a single thread owning writers and one reader per "customer" thread, and for all locking to be vastly simplified and concentrated in the data server alone (because none of the classes it makes use of is used in more than one thread at a time). The result is faster and more trustworthy code.
author Chris Cannam
date Tue, 27 Jan 2009 13:25:10 +0000
parents c0818f064e66
children 683c46d7500b
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@127 144 virtual void scroll(bool right, bool lots);
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@127 178 virtual ViewManager *getViewManager() const { return m_manager; }
Chris@127 179
Chris@127 180 virtual void setFollowGlobalPan(bool f);
Chris@127 181 virtual bool getFollowGlobalPan() const { return m_followPan; }
Chris@127 182
Chris@127 183 virtual void setFollowGlobalZoom(bool f);
Chris@127 184 virtual bool getFollowGlobalZoom() const { return m_followZoom; }
Chris@127 185
Chris@224 186 virtual bool hasLightBackground() const;
Chris@287 187 virtual QColor getForeground() const;
Chris@287 188 virtual QColor getBackground() const;
Chris@127 189
Chris@127 190 enum TextStyle {
Chris@127 191 BoxedText,
Chris@127 192 OutlinedText
Chris@127 193 };
Chris@127 194
Chris@127 195 virtual void drawVisibleText(QPainter &p, int x, int y,
Chris@267 196 QString text, TextStyle style) const;
Chris@267 197
Chris@270 198 virtual void drawMeasurementRect(QPainter &p, const Layer *,
Chris@270 199 QRect rect, bool focus) const;
Chris@127 200
Chris@127 201 virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
Chris@127 202 return false;
Chris@127 203 }
Chris@127 204 virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
Chris@127 205 return false;
Chris@127 206 }
Chris@127 207
Chris@127 208 virtual void setPlaybackFollow(PlaybackFollowMode m);
Chris@127 209 virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
Chris@127 210
Chris@127 211 typedef PropertyContainer::PropertyName PropertyName;
Chris@127 212
Chris@127 213 // We implement the PropertyContainer API, although we don't
Chris@127 214 // actually subclass PropertyContainer. We have our own
Chris@127 215 // PropertyContainer that we can return on request that just
Chris@127 216 // delegates back to us.
Chris@127 217 virtual PropertyContainer::PropertyList getProperties() const;
Chris@127 218 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@127 219 virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
Chris@127 220 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 221 int *min, int *max, int *deflt) const;
Chris@127 222 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@127 223 int value) const;
Chris@127 224 virtual void setProperty(const PropertyName &, int value);
Chris@127 225 virtual QString getPropertyContainerName() const {
Chris@127 226 return objectName();
Chris@127 227 }
Chris@127 228 virtual QString getPropertyContainerIconName() const = 0;
Chris@127 229
Chris@127 230 virtual size_t getPropertyContainerCount() const;
Chris@127 231
Chris@127 232 virtual const PropertyContainer *getPropertyContainer(size_t i) const;
Chris@127 233 virtual PropertyContainer *getPropertyContainer(size_t i);
Chris@127 234
Chris@229 235 // Render the contents on a wide canvas
Chris@229 236 virtual QImage *toNewImage(size_t f0, size_t f1);
Chris@226 237 virtual QImage *toNewImage();
Chris@229 238 virtual QSize getImageSize(size_t f0, size_t f1);
Chris@229 239 virtual QSize getImageSize();
Chris@226 240
Chris@127 241 virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
Chris@127 242
Chris@127 243 virtual bool getValueExtents(QString unit, float &min, float &max,
Chris@127 244 bool &log) const;
Chris@127 245
Chris@316 246 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 247 QString extraAttributes = "") const;
Chris@127 248
Chris@222 249 // First frame actually in model, to right of scale, if present
Chris@222 250 virtual size_t getFirstVisibleFrame() const;
Chris@222 251 virtual size_t getLastVisibleFrame() const;
Chris@222 252
Chris@127 253 size_t getModelsStartFrame() const;
Chris@127 254 size_t getModelsEndFrame() const;
Chris@127 255
Chris@315 256 typedef std::set<Model *> ModelSet;
Chris@315 257 ModelSet getModels();
Chris@315 258
Chris@301 259 //!!!
Chris@320 260 Model *getAligningModel() const;
Chris@320 261 size_t alignFromReference(size_t) const;
Chris@320 262 size_t alignToReference(size_t) const;
Chris@301 263 int getAlignedPlaybackFrame() const;
Chris@301 264
Chris@127 265 signals:
Chris@127 266 void propertyContainerAdded(PropertyContainer *pc);
Chris@127 267 void propertyContainerRemoved(PropertyContainer *pc);
Chris@127 268 void propertyContainerPropertyChanged(PropertyContainer *pc);
Chris@197 269 void propertyContainerPropertyRangeChanged(PropertyContainer *pc);
Chris@127 270 void propertyContainerNameChanged(PropertyContainer *pc);
Chris@298 271 void propertyContainerSelected(PropertyContainer *pc);
Chris@127 272 void propertyChanged(PropertyContainer::PropertyName);
Chris@127 273
Chris@336 274 void layerModelChanged();
Chris@336 275
Chris@211 276 void centreFrameChanged(unsigned long frame,
Chris@211 277 bool globalScroll,
Chris@211 278 PlaybackFollowMode followMode);
Chris@211 279
Chris@222 280 void zoomLevelChanged(unsigned long, bool);
Chris@127 281
Chris@189 282 void contextHelpChanged(const QString &);
Chris@189 283
Chris@127 284 public slots:
Chris@127 285 virtual void modelChanged();
Chris@127 286 virtual void modelChanged(size_t startFrame, size_t endFrame);
Chris@127 287 virtual void modelCompletionChanged();
Chris@320 288 virtual void modelAlignmentCompletionChanged();
Chris@127 289 virtual void modelReplaced();
Chris@127 290 virtual void layerParametersChanged();
Chris@197 291 virtual void layerParameterRangesChanged();
Chris@268 292 virtual void layerMeasurementRectsChanged();
Chris@127 293 virtual void layerNameChanged();
Chris@127 294
Chris@211 295 virtual void globalCentreFrameChanged(unsigned long);
Chris@211 296 virtual void viewCentreFrameChanged(View *, unsigned long);
Chris@127 297 virtual void viewManagerPlaybackFrameChanged(unsigned long);
Chris@222 298 virtual void viewZoomLevelChanged(View *, unsigned long, bool);
Chris@127 299
Chris@127 300 virtual void propertyContainerSelected(View *, PropertyContainer *pc);
Chris@127 301
Chris@127 302 virtual void selectionChanged();
Chris@127 303 virtual void toolModeChanged();
Chris@133 304 virtual void overlayModeChanged();
Chris@133 305 virtual void zoomWheelsEnabledChanged();
Chris@127 306
Chris@127 307 protected:
Chris@127 308 View(QWidget *, bool showProgress);
Chris@127 309 virtual void paintEvent(QPaintEvent *e);
Chris@127 310 virtual void drawSelections(QPainter &);
Chris@127 311 virtual bool shouldLabelSelections() const { return true; }
Chris@229 312 virtual bool render(QPainter &paint, int x0, size_t f0, size_t f1);
Chris@339 313 virtual void setPaintFont(QPainter &paint);
Chris@339 314
Chris@127 315 typedef std::vector<Layer *> LayerList;
Chris@127 316
Chris@127 317 int getModelsSampleRate() const;
Chris@127 318 bool areLayersScrollable() const;
Chris@127 319 LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
Chris@127 320 LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
Chris@127 321 size_t getZoomConstraintBlockSize(size_t blockSize,
Chris@127 322 ZoomConstraint::RoundingDirection dir =
Chris@127 323 ZoomConstraint::RoundNearest) const;
Chris@127 324
Chris@183 325 // True if the top layer(s) use colours for meaningful things. If
Chris@183 326 // this is the case, selections will be shown using unfilled boxes
Chris@183 327 // rather than with a translucent fill.
Chris@183 328 bool areLayerColoursSignificant() const;
Chris@183 329
Chris@217 330 // True if the top layer has a time axis on the x coordinate (this
Chris@217 331 // is generally the case except for spectrum/slice layers). It
Chris@217 332 // will not be possible to make or display selections if this is
Chris@217 333 // false.
Chris@217 334 bool hasTopLayerTimeXAxis() const;
Chris@217 335
Chris@127 336 bool setCentreFrame(size_t f, bool doEmit);
Chris@127 337
Chris@127 338 void checkProgress(void *object);
Chris@384 339 int getProgressBarWidth() const; // if visible
Chris@127 340
Chris@127 341 size_t m_centreFrame;
Chris@127 342 int m_zoomLevel;
Chris@127 343 bool m_followPan;
Chris@127 344 bool m_followZoom;
Chris@127 345 PlaybackFollowMode m_followPlay;
Chris@127 346 size_t m_playPointerFrame;
Chris@127 347 bool m_lightBackground;
Chris@127 348 bool m_showProgress;
Chris@127 349
Chris@127 350 QPixmap *m_cache;
Chris@127 351 size_t m_cacheCentreFrame;
Chris@127 352 int m_cacheZoomLevel;
Chris@127 353 bool m_selectionCached;
Chris@127 354
Chris@127 355 bool m_deleting;
Chris@127 356
Chris@127 357 LayerList m_layers; // I don't own these, but see dtor note above
Chris@127 358 bool m_haveSelectedLayer;
Chris@127 359
Chris@127 360 // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
Chris@127 361 mutable LayerList m_lastScrollableBackLayers;
Chris@127 362 mutable LayerList m_lastNonScrollableBackLayers;
Chris@127 363
Chris@127 364 class LayerProgressBar : public QProgressBar {
Chris@127 365 public:
Chris@127 366 LayerProgressBar(QWidget *parent);
Chris@127 367 virtual QString text() const { return m_text; }
Chris@127 368 virtual void setText(QString text) { m_text = text; }
Chris@127 369 protected:
Chris@127 370 QString m_text;
Chris@127 371 };
Chris@127 372
Chris@385 373 // typedef std::map<Layer *, LayerProgressBar *> ProgressMap;
Chris@385 374 typedef std::map<Layer *, QProgressBar *> ProgressMap;
Chris@127 375 ProgressMap m_progressBars; // I own the ProgressBars
Chris@127 376
Chris@127 377 ViewManager *m_manager; // I don't own this
Chris@127 378 ViewPropertyContainer *m_propertyContainer; // I own this
Chris@127 379 };
Chris@127 380
Chris@127 381
Chris@127 382 // Use this for delegation, because we can't subclass from
Chris@127 383 // PropertyContainer (which is a QObject) ourselves because of
Chris@127 384 // ambiguity with QFrame parent
Chris@127 385
Chris@127 386 class ViewPropertyContainer : public PropertyContainer
Chris@127 387 {
Chris@127 388 Q_OBJECT
Chris@127 389
Chris@127 390 public:
Chris@127 391 ViewPropertyContainer(View *v);
Chris@127 392 PropertyList getProperties() const { return m_v->getProperties(); }
Chris@127 393 QString getPropertyLabel(const PropertyName &n) const {
Chris@127 394 return m_v->getPropertyLabel(n);
Chris@127 395 }
Chris@127 396 PropertyType getPropertyType(const PropertyName &n) const {
Chris@127 397 return m_v->getPropertyType(n);
Chris@127 398 }
Chris@216 399 int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max,
Chris@216 400 int *deflt) const {
Chris@216 401 return m_v->getPropertyRangeAndValue(n, min, max, deflt);
Chris@127 402 }
Chris@127 403 QString getPropertyValueLabel(const PropertyName &n, int value) const {
Chris@127 404 return m_v->getPropertyValueLabel(n, value);
Chris@127 405 }
Chris@127 406 QString getPropertyContainerName() const {
Chris@127 407 return m_v->getPropertyContainerName();
Chris@127 408 }
Chris@127 409 QString getPropertyContainerIconName() const {
Chris@127 410 return m_v->getPropertyContainerIconName();
Chris@127 411 }
Chris@127 412
Chris@127 413 public slots:
Chris@127 414 virtual void setProperty(const PropertyName &n, int value) {
Chris@127 415 m_v->setProperty(n, value);
Chris@127 416 }
Chris@127 417
Chris@127 418 protected:
Chris@127 419 View *m_v;
Chris@127 420 };
Chris@127 421
Chris@127 422 #endif
Chris@127 423