annotate layer/Layer.h @ 947:e53a87a5efb2

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