annotate layer/Layer.h @ 1403:10e768adaee5

Retain consistent min freq (rather than min bin no) when changing fft parameters in spectrum; scale ffts by window size rather than fft size in case of oversampling, to avoid fading out because of scale factor including zero padding
author Chris Cannam
date Thu, 15 Nov 2018 15:08:08 +0000
parents c39f2d439d59
children a18e78b9c78b
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@182 7 This file copyright 2006 Chris Cannam and QMUL.
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 _LAYER_H_
Chris@127 17 #define _LAYER_H_
Chris@127 18
Chris@128 19 #include "base/PropertyContainer.h"
Chris@128 20 #include "base/XmlExportable.h"
Chris@128 21 #include "base/Selection.h"
Chris@127 22
Chris@376 23 #include "widgets/CommandHistory.h"
Chris@376 24
Chris@523 25 #include "system/System.h"
Chris@523 26
Chris@127 27 #include <QObject>
Chris@127 28 #include <QRect>
Chris@127 29 #include <QXmlAttributes>
Chris@131 30 #include <QMutex>
Chris@299 31 #include <QPixmap>
Chris@127 32
Chris@127 33 #include <map>
Chris@268 34 #include <set>
Chris@127 35
Chris@552 36 #include <iostream>
Chris@552 37
Chris@127 38 class ZoomConstraint;
Chris@127 39 class Model;
Chris@127 40 class QPainter;
Chris@127 41 class View;
Chris@916 42 class LayerGeometryProvider;
Chris@127 43 class QMouseEvent;
Chris@127 44 class Clipboard;
Chris@187 45 class RangeMapper;
Chris@127 46
Chris@127 47 /**
Chris@127 48 * The base class for visual representations of the data found in a
Chris@127 49 * Model. Layers are expected to be able to draw themselves onto a
Chris@127 50 * View, and may also be editable.
Chris@127 51 */
Chris@127 52
Chris@127 53 class Layer : public PropertyContainer,
Chris@1266 54 public XmlExportable
Chris@127 55 {
Chris@127 56 Q_OBJECT
Chris@127 57
Chris@127 58 public:
Chris@127 59 Layer();
Chris@127 60 virtual ~Layer();
Chris@127 61
Chris@127 62 virtual const Model *getModel() const = 0;
Chris@502 63 Model *getModel() {
Chris@1266 64 return const_cast<Model *>(const_cast<const Layer *>(this)->getModel());
Chris@127 65 }
Chris@947 66
Chris@137 67 /**
Chris@137 68 * Return a zoom constraint object defining the supported zoom
Chris@137 69 * levels for this layer. If this returns zero, the layer will
Chris@137 70 * support any integer zoom level.
Chris@137 71 */
Chris@127 72 virtual const ZoomConstraint *getZoomConstraint() const { return 0; }
Chris@137 73
Chris@137 74 /**
Chris@137 75 * Return true if this layer can handle zoom levels other than
Chris@137 76 * those supported by its zoom constraint (presumably less
Chris@137 77 * efficiently or accurately than the officially supported zoom
Chris@137 78 * levels). If true, the layer will unenthusistically accept any
Chris@137 79 * integer zoom level from 1 to the maximum returned by its zoom
Chris@137 80 * constraint.
Chris@137 81 */
Chris@137 82 virtual bool supportsOtherZoomLevels() const { return true; }
Chris@137 83
Chris@389 84 /**
Chris@389 85 * Paint the given rectangle of this layer onto the given view
Chris@389 86 * using the given painter, superimposing it on top of any
Chris@916 87 * existing material in that view. The LayerGeometryProvider (an
Chris@916 88 * interface implemented by View) is provided here because it is
Chris@916 89 * possible for one layer to exist in more than one view, so the
Chris@916 90 * dimensions of the view may vary from one paint call to another
Chris@916 91 * (without any view having been resized).
Chris@389 92 */
Chris@916 93 virtual void paint(LayerGeometryProvider *, QPainter &, QRect) const = 0;
Chris@127 94
Chris@389 95 /**
Chris@389 96 * Enable or disable synchronous painting. If synchronous
Chris@389 97 * painting is enabled, a call to paint() must complete painting
Chris@389 98 * the entire rectangle before it returns. If synchronous
Chris@389 99 * painting is disabled (which should be the default), the paint()
Chris@389 100 * call may defer painting some regions if data is not yet
Chris@389 101 * available, by calling back on its view to schedule another
Chris@389 102 * update. Synchronous painting is necessary when rendering to an
Chris@389 103 * image. Simple layer types will always paint synchronously, and
Chris@389 104 * so may ignore this.
Chris@389 105 */
Chris@389 106 virtual void setSynchronousPainting(bool /* synchronous */) { }
Chris@389 107
Chris@127 108 enum VerticalPosition {
Chris@1266 109 PositionTop, PositionMiddle, PositionBottom
Chris@127 110 };
Chris@127 111 virtual VerticalPosition getPreferredTimeRulerPosition() const {
Chris@1266 112 return PositionMiddle;
Chris@127 113 }
Chris@127 114 virtual VerticalPosition getPreferredFrameCountPosition() const {
Chris@1266 115 return PositionBottom;
Chris@127 116 }
Chris@224 117 virtual bool hasLightBackground() const {
Chris@224 118 return true;
Chris@224 119 }
Chris@127 120
Chris@127 121 virtual QString getPropertyContainerIconName() const;
Chris@127 122
Chris@127 123 virtual QString getPropertyContainerName() const {
Chris@363 124 if (m_presentationName != "") return m_presentationName;
Chris@1266 125 else return objectName();
Chris@127 126 }
Chris@127 127
Chris@363 128 virtual void setPresentationName(QString name);
Chris@363 129
Chris@127 130 virtual QString getLayerPresentationName() const;
Chris@299 131 virtual QPixmap getLayerPresentationPixmap(QSize) const { return QPixmap(); }
Chris@127 132
Chris@916 133 virtual int getVerticalScaleWidth(LayerGeometryProvider *, bool detailed,
Chris@607 134 QPainter &) const = 0;
Chris@607 135
Chris@916 136 virtual void paintVerticalScale(LayerGeometryProvider *, bool /* detailed */,
Chris@607 137 QPainter &, QRect) const { }
Chris@127 138
Chris@1390 139 virtual int getHorizontalScaleHeight(LayerGeometryProvider *, QPainter &) const { return 0; }
Chris@1390 140
Chris@916 141 virtual bool getCrosshairExtents(LayerGeometryProvider *, QPainter &, QPoint /* cursorPos */,
Chris@127 142 std::vector<QRect> &) const {
Chris@127 143 return false;
Chris@127 144 }
Chris@916 145 virtual void paintCrosshairs(LayerGeometryProvider *, QPainter &, QPoint) const { }
Chris@127 146
Chris@916 147 virtual void paintMeasurementRects(LayerGeometryProvider *, QPainter &,
Chris@272 148 bool showFocus, QPoint focusPoint) const;
Chris@272 149
Chris@916 150 virtual bool nearestMeasurementRectChanged(LayerGeometryProvider *, QPoint prev,
Chris@272 151 QPoint now) const;
Chris@267 152
Chris@916 153 virtual QString getFeatureDescription(LayerGeometryProvider *, QPoint &) const {
Chris@1266 154 return "";
Chris@127 155 }
Chris@127 156
Chris@909 157 virtual QString getLabelPreceding(sv_frame_t /* frame */) const {
Chris@552 158 return "";
Chris@552 159 }
Chris@552 160
Chris@127 161 enum SnapType {
Chris@1266 162 SnapLeft,
Chris@1266 163 SnapRight,
Chris@1266 164 SnapNearest,
Chris@1266 165 SnapNeighbouring
Chris@127 166 };
Chris@127 167
Chris@127 168 /**
Chris@127 169 * Adjust the given frame to snap to the nearest feature, if
Chris@127 170 * possible.
Chris@127 171 *
Chris@127 172 * If snap is SnapLeft or SnapRight, adjust the frame to match
Chris@127 173 * that of the nearest feature in the given direction regardless
Chris@127 174 * of how far away it is. If snap is SnapNearest, adjust the
Chris@127 175 * frame to that of the nearest feature in either direction. If
Chris@127 176 * snap is SnapNeighbouring, adjust the frame to that of the
Chris@127 177 * nearest feature if it is close, and leave it alone (returning
Chris@127 178 * false) otherwise. SnapNeighbouring should always choose the
Chris@127 179 * same feature that would be used in an editing operation through
Chris@127 180 * calls to editStart etc.
Chris@127 181 *
Chris@127 182 * Return true if a suitable feature was found and frame adjusted
Chris@180 183 * accordingly. Return false if no suitable feature was available
Chris@517 184 * (and leave frame unmodified). If returning true, also return
Chris@517 185 * the resolution of the model in this layer in sample frames.
Chris@127 186 */
Chris@916 187 virtual bool snapToFeatureFrame(LayerGeometryProvider * /* v */,
Chris@1266 188 sv_frame_t & /* frame */,
Chris@1266 189 int &resolution,
Chris@1266 190 SnapType /* snap */) const {
Chris@1266 191 resolution = 1;
Chris@1266 192 return false;
Chris@127 193 }
Chris@127 194
Chris@517 195 /**
Chris@517 196 * Adjust the given frame to snap to the next feature that has
Chris@517 197 * "effectively" the same value as the feature prior to the given
Chris@517 198 * frame, if possible.
Chris@517 199 *
Chris@517 200 * The snap type must be SnapLeft (snap to the time of the next
Chris@517 201 * feature prior to the one preceding the given frame that has a
Chris@517 202 * similar value to it) or SnapRight (snap to the time of the next
Chris@517 203 * feature following the given frame that has a similar value to
Chris@517 204 * the feature preceding it). Other values are not permitted.
Chris@517 205 *
Chris@517 206 * Return true if a suitable feature was found and frame adjusted
Chris@517 207 * accordingly. Return false if no suitable feature was available
Chris@517 208 * (and leave frame unmodified). If returning true, also return
Chris@517 209 * the resolution of the model in this layer in sample frames.
Chris@517 210 */
Chris@916 211 virtual bool snapToSimilarFeature(LayerGeometryProvider * /* v */,
Chris@904 212 sv_frame_t & /* source frame */,
Chris@805 213 int &resolution,
Chris@517 214 SnapType /* snap */) const {
Chris@1266 215 resolution = 1;
Chris@1266 216 return false;
Chris@517 217 }
Chris@517 218
Chris@335 219 // Draw, erase, and edit modes:
Chris@127 220 //
Chris@127 221 // Layer needs to get actual mouse events, I guess. Draw mode is
Chris@127 222 // probably the easier.
Chris@127 223
Chris@916 224 virtual void drawStart(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 225 virtual void drawDrag(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 226 virtual void drawEnd(LayerGeometryProvider *, QMouseEvent *) { }
Chris@127 227
Chris@916 228 virtual void eraseStart(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 229 virtual void eraseDrag(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 230 virtual void eraseEnd(LayerGeometryProvider *, QMouseEvent *) { }
Chris@335 231
Chris@916 232 virtual void editStart(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 233 virtual void editDrag(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 234 virtual void editEnd(LayerGeometryProvider *, QMouseEvent *) { }
Chris@127 235
Chris@916 236 virtual void splitStart(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 237 virtual void splitEnd(LayerGeometryProvider *, QMouseEvent *) { }
Chris@916 238 virtual void addNote(LayerGeometryProvider *, QMouseEvent *) { };
gyorgyf@635 239
Chris@267 240 // Measurement rectangle (or equivalent). Unlike draw and edit,
Chris@267 241 // the base Layer class can provide working implementations of
Chris@267 242 // these for most situations.
Chris@267 243 //
Chris@916 244 virtual void measureStart(LayerGeometryProvider *, QMouseEvent *);
Chris@916 245 virtual void measureDrag(LayerGeometryProvider *, QMouseEvent *);
Chris@916 246 virtual void measureEnd(LayerGeometryProvider *, QMouseEvent *);
Chris@916 247 virtual void measureDoubleClick(LayerGeometryProvider *, QMouseEvent *);
Chris@267 248
Chris@283 249 virtual bool haveCurrentMeasureRect() const {
Chris@283 250 return m_haveCurrentMeasureRect;
Chris@283 251 }
Chris@283 252 virtual void deleteCurrentMeasureRect(); // using a command
Chris@283 253
Chris@255 254 /**
Chris@255 255 * Open an editor on the item under the mouse (e.g. on
Chris@255 256 * double-click). If there is no item or editing is not
Chris@255 257 * supported, return false.
Chris@255 258 */
Chris@916 259 virtual bool editOpen(LayerGeometryProvider *, QMouseEvent *) { return false; }
Chris@127 260
Chris@905 261 virtual void moveSelection(Selection, sv_frame_t /* newStartFrame */) { }
Chris@127 262 virtual void resizeSelection(Selection, Selection /* newSize */) { }
Chris@127 263 virtual void deleteSelection(Selection) { }
Chris@127 264
Chris@916 265 virtual void copy(LayerGeometryProvider *, Selection, Clipboard & /* to */) { }
Chris@127 266
Chris@127 267 /**
Chris@127 268 * Paste from the given clipboard onto the layer at the given
Chris@127 269 * frame offset. If interactive is true, the layer may ask the
Chris@127 270 * user about paste options through a dialog if desired, and may
Chris@127 271 * return false if the user cancelled the paste operation. This
Chris@127 272 * function should return true if a paste actually occurred.
Chris@127 273 */
Chris@916 274 virtual bool paste(LayerGeometryProvider *,
Chris@359 275 const Clipboard & /* from */,
Chris@904 276 sv_frame_t /* frameOffset */,
Chris@127 277 bool /* interactive */) { return false; }
Chris@127 278
Chris@127 279 // Text mode:
Chris@127 280 //
Chris@127 281 // Label nearest feature. We need to get the feature coordinates
Chris@127 282 // and current label from the layer, and then the pane can pop up
Chris@127 283 // a little text entry dialog at the right location. Or we edit
Chris@127 284 // in place? Probably the dialog is easier.
Chris@127 285
Chris@127 286 /**
Chris@127 287 * This should return true if the layer can safely be scrolled
Chris@127 288 * automatically by a given view (simply copying the existing data
Chris@127 289 * and then refreshing the exposed area) without altering its
Chris@127 290 * meaning. For the view widget as a whole this is usually not
Chris@127 291 * possible because of invariant (non-scrolling) material
Chris@127 292 * displayed over the top, but the widget may be able to optimise
Chris@127 293 * scrolling better if it is known that individual views can be
Chris@127 294 * scrolled safely in this way.
Chris@127 295 */
Chris@916 296 virtual bool isLayerScrollable(const LayerGeometryProvider *) const { return true; }
Chris@127 297
Chris@127 298 /**
Chris@127 299 * This should return true if the layer completely obscures any
Chris@127 300 * underlying layers. It's used to determine whether the view can
Chris@127 301 * safely draw any selection rectangles under the layer instead of
Chris@127 302 * over it, in the case where the layer is not scrollable and
Chris@127 303 * therefore needs to be redrawn each time (so that the selection
Chris@127 304 * rectangle can be cached).
Chris@127 305 */
Chris@127 306 virtual bool isLayerOpaque() const { return false; }
Chris@127 307
Chris@287 308 enum ColourSignificance {
Chris@287 309 ColourAbsent,
Chris@287 310 ColourIrrelevant,
Chris@287 311 ColourDistinguishes,
Chris@287 312 ColourAndBackgroundSignificant,
Chris@287 313 ColourHasMeaningfulValue
Chris@287 314 };
Chris@287 315
Chris@127 316 /**
Chris@287 317 * This should return the degree of meaning associated with colour
Chris@287 318 * in this layer.
Chris@287 319 *
Chris@287 320 * If ColourAbsent, the layer does not use colour. If
Chris@287 321 * ColourIrrelevant, the layer is coloured and the colour may be
Chris@287 322 * set by the user, but it doesn't really matter what the colour
Chris@287 323 * is (for example, in a time ruler layer). If
Chris@287 324 * ColourDistinguishes, then the colour is used to distinguish
Chris@287 325 * this layer from other similar layers (e.g. for data layers).
Chris@287 326 * If ColourAndBackgroundSignificant, then the layer should be
Chris@287 327 * given greater weight than ColourDistinguishes layers when
Chris@287 328 * choosing a background colour (e.g. for waveforms). If
Chris@287 329 * ColourHasMeaningfulValue, colours are actually meaningful --
Chris@287 330 * the view will then show selections using unfilled rectangles
Chris@287 331 * instead of translucent filled rectangles, so as not to disturb
Chris@287 332 * the colours underneath.
Chris@183 333 */
Chris@287 334 virtual ColourSignificance getLayerColourSignificance() const = 0;
Chris@183 335
Chris@183 336 /**
Chris@127 337 * This should return true if the layer can be edited by the user.
Chris@127 338 * If this is the case, the appropriate edit tools may be made
Chris@127 339 * available by the application and the layer's drawStart/Drag/End
Chris@127 340 * and editStart/Drag/End methods should be implemented.
Chris@127 341 */
Chris@127 342 virtual bool isLayerEditable() const { return false; }
Chris@127 343
Chris@127 344 /**
Chris@127 345 * Return the proportion of background work complete in drawing
Chris@127 346 * this view, as a percentage -- in most cases this will be the
Chris@127 347 * value returned by pointer from a call to the underlying model's
Chris@226 348 * isReady(int *) call. The view may choose to show a progress
Chris@127 349 * meter if it finds that this returns < 100 at any given moment.
Chris@127 350 */
Chris@916 351 virtual int getCompletion(LayerGeometryProvider *) const { return 100; }
Chris@127 352
Chris@583 353 /**
Chris@583 354 * Return an error string if any errors have occurred while
Chris@583 355 * loading or processing data for the given view. Return the
Chris@583 356 * empty string if no error has occurred.
Chris@583 357 */
Chris@916 358 virtual QString getError(LayerGeometryProvider *) const { return ""; }
Chris@583 359
Chris@127 360 virtual void setObjectName(const QString &name);
Chris@127 361
Chris@127 362 /**
Chris@127 363 * Convert the layer's data (though not those of the model it
Chris@316 364 * refers to) into XML for file output. This class implements the
Chris@316 365 * basic name/type/model-id output; subclasses will typically call
Chris@316 366 * this superclass implementation with extra attributes describing
Chris@316 367 * their particular properties.
Chris@127 368 */
Chris@316 369 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 370 QString extraAttributes = "") const;
Chris@127 371
Chris@127 372 /**
Chris@127 373 * Set the particular properties of a layer (those specific to the
Chris@127 374 * subclass) from a set of XML attributes. This is the effective
Chris@316 375 * inverse of the toXml method.
Chris@127 376 */
Chris@127 377 virtual void setProperties(const QXmlAttributes &) = 0;
Chris@127 378
Chris@127 379 /**
Chris@316 380 * Produce XML containing the layer's ID and type. This is used
Chris@316 381 * to refer to the layer in the display section of the SV session
Chris@316 382 * file, for a layer that has already been described in the data
Chris@316 383 * section.
Chris@269 384 */
Chris@316 385 virtual void toBriefXml(QTextStream &stream,
Chris@316 386 QString indent = "",
Chris@316 387 QString extraAttributes = "") const;
Chris@269 388
Chris@269 389 /**
Chris@269 390 * Add a measurement rectangle from the given XML attributes
Chris@269 391 * (presumably taken from a measurement element).
Chris@269 392 * Does not use a command.
Chris@269 393 */
Chris@269 394 virtual void addMeasurementRect(const QXmlAttributes &);
Chris@269 395
Chris@269 396 /**
Chris@127 397 * Indicate that a layer is not currently visible in the given
Chris@127 398 * view and is not expected to become visible in the near future
Chris@127 399 * (for example because the user has explicitly removed or hidden
Chris@127 400 * it). The layer may respond by (for example) freeing any cache
Chris@127 401 * memory it is using, until next time its paint method is called,
Chris@127 402 * when it should set itself un-dormant again.
Chris@131 403 *
Chris@131 404 * A layer class that overrides this function must also call this
Chris@131 405 * class's implementation.
Chris@127 406 */
Chris@916 407 virtual void setLayerDormant(const LayerGeometryProvider *v, bool dormant);
Chris@127 408
Chris@127 409 /**
Chris@127 410 * Return whether the layer is dormant (i.e. hidden) in the given
Chris@127 411 * view.
Chris@127 412 */
Chris@916 413 virtual bool isLayerDormant(const LayerGeometryProvider *v) const;
Chris@127 414
Chris@127 415 virtual PlayParameters *getPlayParameters();
Chris@127 416
Chris@1391 417 /**
Chris@1391 418 * True if this layer will need to place text labels when it is
Chris@1391 419 * painted. The view will take into account how many layers are
Chris@1391 420 * requesting this, and will provide a distinct y-coord to each
Chris@1391 421 * layer on request via View::getTextLabelHeight().
Chris@1391 422 */
Chris@127 423 virtual bool needsTextLabelHeight() const { return false; }
Chris@127 424
Chris@1389 425 /**
Chris@1389 426 * Return true if the X axis on the layer is time proportional to
Chris@1389 427 * audio frames, false otherwise. Almost all layer types return
Chris@1389 428 * true here: the exceptions are spectrum and slice layers.
Chris@1389 429 */
Chris@217 430 virtual bool hasTimeXAxis() const { return true; }
Chris@217 431
Chris@127 432 /**
Chris@1389 433 * Update the X and Y axis scales, where appropriate, to focus on
Chris@1389 434 * the given rectangular region. This should *only* be overridden
Chris@1389 435 * by layers whose hasTimeXAxis() returns false - the pane handles
Chris@1389 436 * zooming appropriately in every "normal" case.
Chris@1389 437 */
Chris@1389 438 virtual void zoomToRegion(const LayerGeometryProvider *, QRect) {
Chris@1389 439 return;
Chris@1389 440 }
Chris@1389 441
Chris@1389 442 /**
Chris@127 443 * Return the minimum and maximum values for the y axis of the
Chris@127 444 * model in this layer, as well as whether the layer is configured
Chris@127 445 * to use a logarithmic y axis display. Also return the unit for
Chris@127 446 * these values if known.
Chris@127 447 *
Chris@127 448 * This function returns the "normal" extents for the layer, not
Chris@127 449 * necessarily the extents actually in use in the display.
Chris@127 450 */
Chris@904 451 virtual bool getValueExtents(double &min, double &max,
Chris@127 452 bool &logarithmic, QString &unit) const = 0;
Chris@127 453
Chris@127 454 /**
Chris@127 455 * Return the minimum and maximum values within the displayed
Chris@127 456 * range for the y axis, if only a subset of the whole range of
Chris@127 457 * the model (returned by getValueExtents) is being displayed.
Chris@127 458 * Return false if the layer is not imposing a particular display
Chris@127 459 * extent (using the normal layer extents or deferring to whatever
Chris@127 460 * is in use for the same units elsewhere in the view).
Chris@127 461 */
Chris@904 462 virtual bool getDisplayExtents(double & /* min */,
Chris@904 463 double & /* max */) const {
Chris@127 464 return false;
Chris@127 465 }
Chris@127 466
Chris@127 467 /**
Chris@127 468 * Set the displayed minimum and maximum values for the y axis to
Chris@127 469 * the given range, if supported. Return false if not supported
Chris@127 470 * on this layer (and set nothing). In most cases, layers that
Chris@127 471 * return false for getDisplayExtents should also return false for
Chris@127 472 * this function.
Chris@127 473 */
Chris@904 474 virtual bool setDisplayExtents(double /* min */,
Chris@904 475 double /* max */) {
Chris@127 476 return false;
Chris@127 477 }
Chris@127 478
Chris@133 479 /**
Chris@260 480 * Return the value and unit at the given x coordinate in the
Chris@260 481 * given view. This is for descriptive purposes using the
Chris@260 482 * measurement tool. The default implementation works correctly
Chris@260 483 * if the layer hasTimeXAxis().
Chris@260 484 */
Chris@916 485 virtual bool getXScaleValue(const LayerGeometryProvider *v, int x,
Chris@904 486 double &value, QString &unit) const;
Chris@260 487
Chris@260 488 /**
Chris@260 489 * Return the value and unit at the given y coordinate in the
Chris@260 490 * given view.
Chris@260 491 */
Chris@916 492 virtual bool getYScaleValue(const LayerGeometryProvider *, int /* y */,
Chris@904 493 double &/* value */, QString &/* unit */) const {
Chris@260 494 return false;
Chris@260 495 }
Chris@260 496
Chris@260 497 /**
Chris@274 498 * Return the difference between the values at the given y
Chris@274 499 * coordinates in the given view, and the unit of the difference.
Chris@274 500 * The default implementation just calls getYScaleValue twice and
Chris@274 501 * returns the difference, with the same unit.
Chris@274 502 */
Chris@916 503 virtual bool getYScaleDifference(const LayerGeometryProvider *v, int y0, int y1,
Chris@904 504 double &diff, QString &unit) const;
Chris@274 505
Chris@274 506 /**
Chris@133 507 * Get the number of vertical zoom steps available for this layer.
Chris@133 508 * If vertical zooming is not available, return 0. The meaning of
Chris@133 509 * "zooming" is entirely up to the layer -- changing the zoom
Chris@133 510 * level may cause the layer to reset its display extents or
Chris@180 511 * change another property such as display gain. However, layers
Chris@180 512 * are advised for consistency to treat smaller zoom steps as
Chris@180 513 * "more distant" or "zoomed out" and larger ones as "closer" or
Chris@180 514 * "zoomed in".
Chris@180 515 *
Chris@133 516 * Layers that provide this facility should also emit the
Chris@133 517 * verticalZoomChanged signal if their vertical zoom changes
Chris@133 518 * due to factors other than setVerticalZoomStep being called.
Chris@133 519 */
Chris@248 520 virtual int getVerticalZoomSteps(int & /* defaultStep */) const { return 0; }
Chris@133 521
Chris@133 522 /**
Chris@133 523 * Get the current vertical zoom step. A layer may support finer
Chris@133 524 * control over ranges etc than is available through the integer
Chris@133 525 * zoom step mechanism; if this one does, it should just return
Chris@133 526 * the nearest of the available zoom steps to the current settings.
Chris@133 527 */
Chris@133 528 virtual int getCurrentVerticalZoomStep() const { return 0; }
Chris@133 529
Chris@133 530 /**
Chris@133 531 * Set the vertical zoom step. The meaning of "zooming" is
Chris@133 532 * entirely up to the layer -- changing the zoom level may cause
Chris@133 533 * the layer to reset its display extents or change another
Chris@133 534 * property such as display gain.
Chris@133 535 */
Chris@133 536 virtual void setVerticalZoomStep(int) { }
Chris@133 537
Chris@187 538 /**
Chris@187 539 * Create and return a range mapper for vertical zoom step values.
Chris@187 540 * See the RangeMapper documentation for more details. The
Chris@187 541 * returned value is allocated on the heap and will be deleted by
Chris@187 542 * the caller.
Chris@187 543 */
Chris@187 544 virtual RangeMapper *getNewVerticalZoomRangeMapper() const { return 0; }
Chris@187 545
Chris@947 546 /**
Chris@947 547 * Return true if this layer type can function without a model
Chris@947 548 * being set. If false (the default), the layer will not be loaded
Chris@947 549 * from a session if its model cannot be found.
Chris@947 550 */
Chris@947 551 virtual bool canExistWithoutModel() const { return false; }
Chris@947 552
Chris@127 553 public slots:
Chris@916 554 void showLayer(LayerGeometryProvider *, bool show);
Chris@127 555
Chris@127 556 signals:
Chris@127 557 void modelChanged();
Chris@127 558 void modelCompletionChanged();
Chris@320 559 void modelAlignmentCompletionChanged();
Chris@906 560 void modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame);
Chris@127 561 void modelReplaced();
Chris@127 562
Chris@127 563 void layerParametersChanged();
Chris@197 564 void layerParameterRangesChanged();
Chris@268 565 void layerMeasurementRectsChanged();
Chris@127 566 void layerNameChanged();
Chris@127 567
Chris@133 568 void verticalZoomChanged();
Chris@133 569
Chris@267 570 protected:
Chris@320 571 void connectSignals(const Model *);
Chris@320 572
Chris@916 573 virtual sv_frame_t alignToReference(LayerGeometryProvider *v, sv_frame_t frame) const;
Chris@916 574 virtual sv_frame_t alignFromReference(LayerGeometryProvider *v, sv_frame_t frame) const;
Chris@916 575 bool clipboardHasDifferentAlignment(LayerGeometryProvider *v, const Clipboard &clip) const;
Chris@359 576
Chris@267 577 struct MeasureRect {
Chris@268 578
Chris@267 579 mutable QRect pixrect;
Chris@268 580 bool haveFrames;
Chris@905 581 sv_frame_t startFrame; // only valid if haveFrames
Chris@905 582 sv_frame_t endFrame; // ditto
Chris@273 583 double startY;
Chris@273 584 double endY;
Chris@268 585
Chris@268 586 bool operator<(const MeasureRect &mr) const;
Chris@316 587 void toXml(QTextStream &stream, QString indent) const;
Chris@267 588 };
Chris@267 589
Chris@268 590 class AddMeasurementRectCommand : public Command
Chris@268 591 {
Chris@268 592 public:
Chris@268 593 AddMeasurementRectCommand(Layer *layer, MeasureRect rect) :
Chris@268 594 m_layer(layer), m_rect(rect) { }
Chris@268 595
Chris@268 596 virtual QString getName() const;
Chris@268 597 virtual void execute();
Chris@268 598 virtual void unexecute();
Chris@268 599
Chris@268 600 private:
Chris@268 601 Layer *m_layer;
Chris@268 602 MeasureRect m_rect;
Chris@268 603 };
Chris@268 604
Chris@283 605 class DeleteMeasurementRectCommand : public Command
Chris@283 606 {
Chris@283 607 public:
Chris@283 608 DeleteMeasurementRectCommand(Layer *layer, MeasureRect rect) :
Chris@283 609 m_layer(layer), m_rect(rect) { }
Chris@283 610
Chris@283 611 virtual QString getName() const;
Chris@283 612 virtual void execute();
Chris@283 613 virtual void unexecute();
Chris@283 614
Chris@283 615 private:
Chris@283 616 Layer *m_layer;
Chris@283 617 MeasureRect m_rect;
Chris@283 618 };
Chris@283 619
Chris@269 620 void addMeasureRectToSet(const MeasureRect &r) {
Chris@268 621 m_measureRects.insert(r);
Chris@268 622 emit layerMeasurementRectsChanged();
Chris@268 623 }
Chris@268 624
Chris@269 625 void deleteMeasureRectFromSet(const MeasureRect &r) {
Chris@268 626 m_measureRects.erase(r);
Chris@268 627 emit layerMeasurementRectsChanged();
Chris@268 628 }
Chris@268 629
Chris@268 630 typedef std::set<MeasureRect> MeasureRectSet;
Chris@268 631 MeasureRectSet m_measureRects;
Chris@267 632 MeasureRect m_draggingRect;
Chris@267 633 bool m_haveDraggingRect;
Chris@283 634 mutable bool m_haveCurrentMeasureRect;
Chris@283 635 mutable QPoint m_currentMeasureRectPoint;
Chris@272 636
Chris@272 637 // Note that pixrects are only correct for a single view.
Chris@272 638 // So we should update them at the start of the paint procedure
Chris@272 639 // (painting is single threaded) and only use them after that.
Chris@916 640 void updateMeasurePixrects(LayerGeometryProvider *v) const;
Chris@273 641
Chris@916 642 virtual void updateMeasureRectYCoords(LayerGeometryProvider *v, const MeasureRect &r) const;
Chris@916 643 virtual void setMeasureRectYCoord(LayerGeometryProvider *v, MeasureRect &r, bool start, int y) const;
Chris@916 644 virtual void setMeasureRectFromPixrect(LayerGeometryProvider *v, MeasureRect &r, QRect pixrect) const;
Chris@272 645
Chris@272 646 // This assumes updateMeasurementPixrects has been called
Chris@272 647 MeasureRectSet::const_iterator findFocusedMeasureRect(QPoint) const;
Chris@267 648
Chris@916 649 void paintMeasurementRect(LayerGeometryProvider *v, QPainter &paint,
Chris@270 650 const MeasureRect &r, bool focus) const;
Chris@268 651
Chris@1315 652 bool valueExtentsMatchMine(LayerGeometryProvider *v) const;
Chris@1315 653
Chris@363 654 QString m_presentationName;
Chris@363 655
Chris@131 656 private:
Chris@131 657 mutable QMutex m_dormancyMutex;
Chris@127 658 mutable std::map<const void *, bool> m_dormancy;
Chris@127 659 };
Chris@127 660
Chris@127 661 #endif
Chris@127 662