annotate layer/Layer.h @ 349:369a197737c7

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