annotate view/View.h @ 317:e251c3599ea8

* Make RemoteFile far more pervasive, and use it for local files as well so that we can handle both transparently. Make it shallow copy with reference counting, so it can be used by value without having to worry about the cache file lifetime. Use RemoteFile for MainWindow file-open functions, etc
author Chris Cannam
date Thu, 18 Oct 2007 15:31:20 +0000
parents c0b9eec70639
children 984c1975f1ff
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@127 7 This file copyright 2006 Chris Cannam.
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@226 16 #ifndef _VIEW_H_
Chris@226 17 #define _VIEW_H_
Chris@127 18
Chris@127 19 #include <QFrame>
Chris@127 20 #include <QProgressBar>
Chris@127 21
Chris@127 22 #include "base/ZoomConstraint.h"
Chris@127 23 #include "base/PropertyContainer.h"
Chris@128 24 #include "ViewManager.h"
Chris@127 25 #include "base/XmlExportable.h"
Chris@127 26
Chris@127 27 // #define DEBUG_VIEW_WIDGET_PAINT 1
Chris@127 28
Chris@127 29 class Layer;
Chris@127 30 class ViewPropertyContainer;
Chris@127 31
Chris@127 32 #include <map>
Chris@315 33 #include <set>
Chris@127 34
Chris@127 35 /**
Chris@127 36 * View is the base class of widgets that display one or more
Chris@127 37 * overlaid views of data against a horizontal time scale.
Chris@127 38 *
Chris@127 39 * A View may have any number of attached Layers, each of which
Chris@127 40 * is expected to have one data Model (although multiple views may
Chris@127 41 * share the same model).
Chris@127 42 *
Chris@127 43 * A View may be panned in time and zoomed, although the
Chris@127 44 * mechanisms for doing so (as well as any other operations and
Chris@127 45 * properties available) depend on the subclass.
Chris@127 46 */
Chris@127 47
Chris@127 48 class View : public QFrame,
Chris@127 49 public XmlExportable
Chris@127 50 {
Chris@127 51 Q_OBJECT
Chris@127 52
Chris@127 53 public:
Chris@127 54 /**
Chris@127 55 * Deleting a View does not delete any of its layers. They should
Chris@127 56 * be managed elsewhere (e.g. by the Document).
Chris@127 57 */
Chris@127 58 virtual ~View();
Chris@127 59
Chris@127 60 /**
Chris@127 61 * Retrieve the first visible sample frame on the widget.
Chris@127 62 * This is a calculated value based on the centre-frame, widget
Chris@127 63 * width and zoom level. The result may be negative.
Chris@127 64 */
Chris@313 65 long getStartFrame() const;
Chris@127 66
Chris@127 67 /**
Chris@127 68 * Set the widget pan based on the given first visible frame. The
Chris@127 69 * frame value may be negative.
Chris@127 70 */
Chris@313 71 void setStartFrame(long);
Chris@127 72
Chris@127 73 /**
Chris@127 74 * Return the centre frame of the visible widget. This is an
Chris@127 75 * exact value that does not depend on the zoom block size. Other
Chris@127 76 * frame values (start, end) are calculated from this based on the
Chris@127 77 * zoom and other factors.
Chris@127 78 */
Chris@313 79 size_t getCentreFrame() const { return m_centreFrame; }
Chris@127 80
Chris@127 81 /**
Chris@127 82 * Set the centre frame of the visible widget.
Chris@127 83 */
Chris@313 84 void setCentreFrame(size_t f) { setCentreFrame(f, true); }
Chris@127 85
Chris@127 86 /**
Chris@127 87 * Retrieve the last visible sample frame on the widget.
Chris@127 88 * This is a calculated value based on the centre-frame, widget
Chris@127 89 * width and zoom level.
Chris@127 90 */
Chris@313 91 size_t getEndFrame() const;
Chris@127 92
Chris@127 93 /**
Chris@127 94 * Return the pixel x-coordinate corresponding to a given sample
Chris@127 95 * frame (which may be negative).
Chris@127 96 */
Chris@127 97 int getXForFrame(long frame) const;
Chris@127 98
Chris@127 99 /**
Chris@127 100 * Return the closest frame to the given pixel x-coordinate.
Chris@127 101 */
Chris@127 102 long getFrameForX(int x) const;
Chris@127 103
Chris@127 104 /**
Chris@127 105 * Return the pixel y-coordinate corresponding to a given
Chris@127 106 * frequency, if the frequency range is as specified. This does
Chris@127 107 * not imply any policy about layer frequency ranges, but it might
Chris@127 108 * be useful for layers to match theirs up if desired.
Chris@127 109 *
Chris@127 110 * Not thread-safe in logarithmic mode. Call only from GUI thread.
Chris@127 111 */
Chris@127 112 float getYForFrequency(float frequency, float minFreq, float maxFreq,
Chris@127 113 bool logarithmic) const;
Chris@127 114
Chris@127 115 /**
Chris@127 116 * Return the closest frequency to the given pixel y-coordinate,
Chris@127 117 * if the frequency range is as specified.
Chris@127 118 *
Chris@127 119 * Not thread-safe in logarithmic mode. Call only from GUI thread.
Chris@127 120 */
Chris@127 121 float getFrequencyForY(int y, float minFreq, float maxFreq,
Chris@127 122 bool logarithmic) const;
Chris@127 123
Chris@127 124 /**
Chris@127 125 * Return the zoom level, i.e. the number of frames per pixel
Chris@127 126 */
Chris@127 127 int getZoomLevel() const;
Chris@127 128
Chris@127 129 /**
Chris@127 130 * Set the zoom level, i.e. the number of frames per pixel. The
Chris@127 131 * centre frame will be unchanged; the start and end frames will
Chris@127 132 * change.
Chris@127 133 */
Chris@127 134 virtual void setZoomLevel(size_t z);
Chris@127 135
Chris@127 136 /**
Chris@127 137 * Zoom in or out.
Chris@127 138 */
Chris@127 139 virtual void zoom(bool in);
Chris@127 140
Chris@127 141 /**
Chris@127 142 * Scroll left or right by a smallish or largish amount.
Chris@127 143 */
Chris@127 144 virtual void scroll(bool right, bool lots);
Chris@127 145
Chris@127 146 virtual void addLayer(Layer *v);
Chris@127 147 virtual void removeLayer(Layer *v); // does not delete the layer
Chris@127 148 virtual int getLayerCount() const { return m_layers.size(); }
Chris@127 149
Chris@127 150 /**
Chris@127 151 * Return a layer, counted in stacking order. That is, layer 0 is
Chris@127 152 * the bottom layer and layer "getLayerCount()-1" is the top one.
Chris@127 153 */
Chris@277 154 virtual Layer *getLayer(int n) {
Chris@285 155 if (n < int(m_layers.size())) return m_layers[n]; else return 0;
Chris@277 156 }
Chris@127 157
Chris@127 158 /**
Chris@268 159 * Return the top layer. This is the same as
Chris@268 160 * getLayer(getLayerCount()-1) if there is at least one layer, and
Chris@268 161 * 0 otherwise.
Chris@268 162 */
Chris@268 163 virtual Layer *getTopLayer() {
Chris@268 164 return m_layers.empty() ? 0 : m_layers[m_layers.size()-1];
Chris@268 165 }
Chris@268 166
Chris@268 167 /**
Chris@127 168 * Return the layer last selected by the user. This is normally
Chris@127 169 * the top layer, the same as getLayer(getLayerCount()-1).
Chris@127 170 * However, if the user has selected the pane itself more recently
Chris@127 171 * than any of the layers on it, this function will return 0. It
Chris@127 172 * will also return 0 if there are no layers.
Chris@127 173 */
Chris@127 174 virtual Layer *getSelectedLayer();
Chris@127 175 virtual const Layer *getSelectedLayer() const;
Chris@127 176
Chris@127 177 virtual void setViewManager(ViewManager *m);
Chris@127 178 virtual ViewManager *getViewManager() const { return m_manager; }
Chris@127 179
Chris@127 180 virtual void setFollowGlobalPan(bool f);
Chris@127 181 virtual bool getFollowGlobalPan() const { return m_followPan; }
Chris@127 182
Chris@127 183 virtual void setFollowGlobalZoom(bool f);
Chris@127 184 virtual bool getFollowGlobalZoom() const { return m_followZoom; }
Chris@127 185
Chris@224 186 virtual bool hasLightBackground() const;
Chris@287 187 virtual QColor getForeground() const;
Chris@287 188 virtual QColor getBackground() const;
Chris@127 189
Chris@127 190 enum TextStyle {
Chris@127 191 BoxedText,
Chris@127 192 OutlinedText
Chris@127 193 };
Chris@127 194
Chris@127 195 virtual void drawVisibleText(QPainter &p, int x, int y,
Chris@267 196 QString text, TextStyle style) const;
Chris@267 197
Chris@270 198 virtual void drawMeasurementRect(QPainter &p, const Layer *,
Chris@270 199 QRect rect, bool focus) const;
Chris@127 200
Chris@127 201 virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
Chris@127 202 return false;
Chris@127 203 }
Chris@127 204 virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
Chris@127 205 return false;
Chris@127 206 }
Chris@127 207
Chris@127 208 virtual void setPlaybackFollow(PlaybackFollowMode m);
Chris@127 209 virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
Chris@127 210
Chris@127 211 typedef PropertyContainer::PropertyName PropertyName;
Chris@127 212
Chris@127 213 // We implement the PropertyContainer API, although we don't
Chris@127 214 // actually subclass PropertyContainer. We have our own
Chris@127 215 // PropertyContainer that we can return on request that just
Chris@127 216 // delegates back to us.
Chris@127 217 virtual PropertyContainer::PropertyList getProperties() const;
Chris@127 218 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@127 219 virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
Chris@127 220 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 221 int *min, int *max, int *deflt) const;
Chris@127 222 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@127 223 int value) const;
Chris@127 224 virtual void setProperty(const PropertyName &, int value);
Chris@127 225 virtual QString getPropertyContainerName() const {
Chris@127 226 return objectName();
Chris@127 227 }
Chris@127 228 virtual QString getPropertyContainerIconName() const = 0;
Chris@127 229
Chris@127 230 virtual size_t getPropertyContainerCount() const;
Chris@127 231
Chris@127 232 virtual const PropertyContainer *getPropertyContainer(size_t i) const;
Chris@127 233 virtual PropertyContainer *getPropertyContainer(size_t i);
Chris@127 234
Chris@229 235 // Render the contents on a wide canvas
Chris@229 236 virtual QImage *toNewImage(size_t f0, size_t f1);
Chris@226 237 virtual QImage *toNewImage();
Chris@229 238 virtual QSize getImageSize(size_t f0, size_t f1);
Chris@229 239 virtual QSize getImageSize();
Chris@226 240
Chris@127 241 virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
Chris@127 242
Chris@127 243 virtual bool getValueExtents(QString unit, float &min, float &max,
Chris@127 244 bool &log) const;
Chris@127 245
Chris@316 246 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 247 QString extraAttributes = "") const;
Chris@127 248
Chris@222 249 // First frame actually in model, to right of scale, if present
Chris@222 250 virtual size_t getFirstVisibleFrame() const;
Chris@222 251 virtual size_t getLastVisibleFrame() const;
Chris@222 252
Chris@127 253 size_t getModelsStartFrame() const;
Chris@127 254 size_t getModelsEndFrame() const;
Chris@127 255
Chris@315 256 typedef std::set<Model *> ModelSet;
Chris@315 257 ModelSet getModels();
Chris@315 258
Chris@301 259 //!!!
Chris@301 260 int getAlignedPlaybackFrame() const;
Chris@301 261
Chris@127 262 signals:
Chris@127 263 void propertyContainerAdded(PropertyContainer *pc);
Chris@127 264 void propertyContainerRemoved(PropertyContainer *pc);
Chris@127 265 void propertyContainerPropertyChanged(PropertyContainer *pc);
Chris@197 266 void propertyContainerPropertyRangeChanged(PropertyContainer *pc);
Chris@127 267 void propertyContainerNameChanged(PropertyContainer *pc);
Chris@298 268 void propertyContainerSelected(PropertyContainer *pc);
Chris@127 269 void propertyChanged(PropertyContainer::PropertyName);
Chris@127 270
Chris@211 271 void centreFrameChanged(unsigned long frame,
Chris@211 272 bool globalScroll,
Chris@211 273 PlaybackFollowMode followMode);
Chris@211 274
Chris@222 275 void zoomLevelChanged(unsigned long, bool);
Chris@127 276
Chris@189 277 void contextHelpChanged(const QString &);
Chris@189 278
Chris@127 279 public slots:
Chris@127 280 virtual void modelChanged();
Chris@127 281 virtual void modelChanged(size_t startFrame, size_t endFrame);
Chris@127 282 virtual void modelCompletionChanged();
Chris@127 283 virtual void modelReplaced();
Chris@127 284 virtual void layerParametersChanged();
Chris@197 285 virtual void layerParameterRangesChanged();
Chris@268 286 virtual void layerMeasurementRectsChanged();
Chris@127 287 virtual void layerNameChanged();
Chris@127 288
Chris@211 289 virtual void globalCentreFrameChanged(unsigned long);
Chris@211 290 virtual void viewCentreFrameChanged(View *, unsigned long);
Chris@127 291 virtual void viewManagerPlaybackFrameChanged(unsigned long);
Chris@222 292 virtual void viewZoomLevelChanged(View *, unsigned long, bool);
Chris@127 293
Chris@127 294 virtual void propertyContainerSelected(View *, PropertyContainer *pc);
Chris@127 295
Chris@127 296 virtual void selectionChanged();
Chris@127 297 virtual void toolModeChanged();
Chris@133 298 virtual void overlayModeChanged();
Chris@133 299 virtual void zoomWheelsEnabledChanged();
Chris@127 300
Chris@127 301 protected:
Chris@127 302 View(QWidget *, bool showProgress);
Chris@127 303 virtual void paintEvent(QPaintEvent *e);
Chris@127 304 virtual void drawSelections(QPainter &);
Chris@127 305 virtual bool shouldLabelSelections() const { return true; }
Chris@229 306 virtual bool render(QPainter &paint, int x0, size_t f0, size_t f1);
Chris@127 307
Chris@127 308 typedef std::vector<Layer *> LayerList;
Chris@127 309
Chris@127 310 int getModelsSampleRate() const;
Chris@127 311 bool areLayersScrollable() const;
Chris@127 312 LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
Chris@127 313 LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
Chris@127 314 size_t getZoomConstraintBlockSize(size_t blockSize,
Chris@127 315 ZoomConstraint::RoundingDirection dir =
Chris@127 316 ZoomConstraint::RoundNearest) const;
Chris@127 317
Chris@183 318 // True if the top layer(s) use colours for meaningful things. If
Chris@183 319 // this is the case, selections will be shown using unfilled boxes
Chris@183 320 // rather than with a translucent fill.
Chris@183 321 bool areLayerColoursSignificant() const;
Chris@183 322
Chris@217 323 // True if the top layer has a time axis on the x coordinate (this
Chris@217 324 // is generally the case except for spectrum/slice layers). It
Chris@217 325 // will not be possible to make or display selections if this is
Chris@217 326 // false.
Chris@217 327 bool hasTopLayerTimeXAxis() const;
Chris@217 328
Chris@127 329 bool setCentreFrame(size_t f, bool doEmit);
Chris@127 330
Chris@127 331 void checkProgress(void *object);
Chris@127 332
Chris@127 333 size_t m_centreFrame;
Chris@127 334 int m_zoomLevel;
Chris@127 335 bool m_followPan;
Chris@127 336 bool m_followZoom;
Chris@127 337 PlaybackFollowMode m_followPlay;
Chris@127 338 size_t m_playPointerFrame;
Chris@127 339 bool m_lightBackground;
Chris@127 340 bool m_showProgress;
Chris@127 341
Chris@127 342 QPixmap *m_cache;
Chris@127 343 size_t m_cacheCentreFrame;
Chris@127 344 int m_cacheZoomLevel;
Chris@127 345 bool m_selectionCached;
Chris@127 346
Chris@127 347 bool m_deleting;
Chris@127 348
Chris@127 349 LayerList m_layers; // I don't own these, but see dtor note above
Chris@127 350 bool m_haveSelectedLayer;
Chris@127 351
Chris@127 352 // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
Chris@127 353 mutable LayerList m_lastScrollableBackLayers;
Chris@127 354 mutable LayerList m_lastNonScrollableBackLayers;
Chris@127 355
Chris@127 356 class LayerProgressBar : public QProgressBar {
Chris@127 357 public:
Chris@127 358 LayerProgressBar(QWidget *parent);
Chris@127 359 virtual QString text() const { return m_text; }
Chris@127 360 virtual void setText(QString text) { m_text = text; }
Chris@127 361 protected:
Chris@127 362 QString m_text;
Chris@127 363 };
Chris@127 364
Chris@127 365 typedef std::map<Layer *, LayerProgressBar *> ProgressMap;
Chris@127 366 ProgressMap m_progressBars; // I own the ProgressBars
Chris@127 367
Chris@127 368 ViewManager *m_manager; // I don't own this
Chris@127 369 ViewPropertyContainer *m_propertyContainer; // I own this
Chris@127 370 };
Chris@127 371
Chris@127 372
Chris@127 373 // Use this for delegation, because we can't subclass from
Chris@127 374 // PropertyContainer (which is a QObject) ourselves because of
Chris@127 375 // ambiguity with QFrame parent
Chris@127 376
Chris@127 377 class ViewPropertyContainer : public PropertyContainer
Chris@127 378 {
Chris@127 379 Q_OBJECT
Chris@127 380
Chris@127 381 public:
Chris@127 382 ViewPropertyContainer(View *v);
Chris@127 383 PropertyList getProperties() const { return m_v->getProperties(); }
Chris@127 384 QString getPropertyLabel(const PropertyName &n) const {
Chris@127 385 return m_v->getPropertyLabel(n);
Chris@127 386 }
Chris@127 387 PropertyType getPropertyType(const PropertyName &n) const {
Chris@127 388 return m_v->getPropertyType(n);
Chris@127 389 }
Chris@216 390 int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max,
Chris@216 391 int *deflt) const {
Chris@216 392 return m_v->getPropertyRangeAndValue(n, min, max, deflt);
Chris@127 393 }
Chris@127 394 QString getPropertyValueLabel(const PropertyName &n, int value) const {
Chris@127 395 return m_v->getPropertyValueLabel(n, value);
Chris@127 396 }
Chris@127 397 QString getPropertyContainerName() const {
Chris@127 398 return m_v->getPropertyContainerName();
Chris@127 399 }
Chris@127 400 QString getPropertyContainerIconName() const {
Chris@127 401 return m_v->getPropertyContainerIconName();
Chris@127 402 }
Chris@127 403
Chris@127 404 public slots:
Chris@127 405 virtual void setProperty(const PropertyName &n, int value) {
Chris@127 406 m_v->setProperty(n, value);
Chris@127 407 }
Chris@127 408
Chris@127 409 protected:
Chris@127 410 View *m_v;
Chris@127 411 };
Chris@127 412
Chris@127 413 #endif
Chris@127 414