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