annotate layer/Layer.h @ 583:4c484636d5ec

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