annotate view/View.h @ 561:aced8ec09bc8

* Complete the overhaul of CSV file import; now you can pick the purpose for each column in the file, and SV should do the rest. The most significant practical improvement here is that we can now handle files in which time and duration do not necessarily appear in known columns.
author Chris Cannam
date Mon, 19 Jul 2010 17:08:56 +0000
parents 3f698e237585
children 4c484636d5ec
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@510 144 virtual void scroll(bool right, bool lots, bool doEmit = true);
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@516 178 virtual void setViewManager(ViewManager *m, long initialFrame);
Chris@127 179 virtual ViewManager *getViewManager() const { return m_manager; }
Chris@127 180
Chris@127 181 virtual void setFollowGlobalPan(bool f);
Chris@127 182 virtual bool getFollowGlobalPan() const { return m_followPan; }
Chris@127 183
Chris@127 184 virtual void setFollowGlobalZoom(bool f);
Chris@127 185 virtual bool getFollowGlobalZoom() const { return m_followZoom; }
Chris@127 186
Chris@224 187 virtual bool hasLightBackground() const;
Chris@287 188 virtual QColor getForeground() const;
Chris@287 189 virtual QColor getBackground() const;
Chris@127 190
Chris@127 191 enum TextStyle {
Chris@127 192 BoxedText,
Chris@127 193 OutlinedText
Chris@127 194 };
Chris@127 195
Chris@127 196 virtual void drawVisibleText(QPainter &p, int x, int y,
Chris@267 197 QString text, TextStyle style) const;
Chris@267 198
Chris@270 199 virtual void drawMeasurementRect(QPainter &p, const Layer *,
Chris@270 200 QRect rect, bool focus) const;
Chris@127 201
Chris@127 202 virtual bool shouldIlluminateLocalFeatures(const Layer *, QPoint &) const {
Chris@127 203 return false;
Chris@127 204 }
Chris@127 205 virtual bool shouldIlluminateLocalSelection(QPoint &, bool &, bool &) const {
Chris@127 206 return false;
Chris@127 207 }
Chris@127 208
Chris@127 209 virtual void setPlaybackFollow(PlaybackFollowMode m);
Chris@127 210 virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
Chris@127 211
Chris@127 212 typedef PropertyContainer::PropertyName PropertyName;
Chris@127 213
Chris@127 214 // We implement the PropertyContainer API, although we don't
Chris@127 215 // actually subclass PropertyContainer. We have our own
Chris@127 216 // PropertyContainer that we can return on request that just
Chris@127 217 // delegates back to us.
Chris@127 218 virtual PropertyContainer::PropertyList getProperties() const;
Chris@127 219 virtual QString getPropertyLabel(const PropertyName &) const;
Chris@127 220 virtual PropertyContainer::PropertyType getPropertyType(const PropertyName &) const;
Chris@127 221 virtual int getPropertyRangeAndValue(const PropertyName &,
Chris@216 222 int *min, int *max, int *deflt) const;
Chris@127 223 virtual QString getPropertyValueLabel(const PropertyName &,
Chris@127 224 int value) const;
Chris@127 225 virtual void setProperty(const PropertyName &, int value);
Chris@127 226 virtual QString getPropertyContainerName() const {
Chris@127 227 return objectName();
Chris@127 228 }
Chris@127 229 virtual QString getPropertyContainerIconName() const = 0;
Chris@127 230
Chris@127 231 virtual size_t getPropertyContainerCount() const;
Chris@127 232
Chris@127 233 virtual const PropertyContainer *getPropertyContainer(size_t i) const;
Chris@127 234 virtual PropertyContainer *getPropertyContainer(size_t i);
Chris@127 235
Chris@229 236 // Render the contents on a wide canvas
Chris@229 237 virtual QImage *toNewImage(size_t f0, size_t f1);
Chris@226 238 virtual QImage *toNewImage();
Chris@229 239 virtual QSize getImageSize(size_t f0, size_t f1);
Chris@229 240 virtual QSize getImageSize();
Chris@226 241
Chris@127 242 virtual int getTextLabelHeight(const Layer *layer, QPainter &) const;
Chris@127 243
Chris@127 244 virtual bool getValueExtents(QString unit, float &min, float &max,
Chris@127 245 bool &log) const;
Chris@127 246
Chris@316 247 virtual void toXml(QTextStream &stream, QString indent = "",
Chris@316 248 QString extraAttributes = "") const;
Chris@127 249
Chris@222 250 // First frame actually in model, to right of scale, if present
Chris@222 251 virtual size_t getFirstVisibleFrame() const;
Chris@222 252 virtual size_t getLastVisibleFrame() const;
Chris@222 253
Chris@127 254 size_t getModelsStartFrame() const;
Chris@127 255 size_t getModelsEndFrame() const;
Chris@127 256
Chris@315 257 typedef std::set<Model *> ModelSet;
Chris@315 258 ModelSet getModels();
Chris@315 259
Chris@301 260 //!!!
Chris@320 261 Model *getAligningModel() const;
Chris@320 262 size_t alignFromReference(size_t) const;
Chris@320 263 size_t alignToReference(size_t) const;
Chris@301 264 int getAlignedPlaybackFrame() const;
Chris@301 265
Chris@127 266 signals:
Chris@127 267 void propertyContainerAdded(PropertyContainer *pc);
Chris@127 268 void propertyContainerRemoved(PropertyContainer *pc);
Chris@127 269 void propertyContainerPropertyChanged(PropertyContainer *pc);
Chris@197 270 void propertyContainerPropertyRangeChanged(PropertyContainer *pc);
Chris@127 271 void propertyContainerNameChanged(PropertyContainer *pc);
Chris@298 272 void propertyContainerSelected(PropertyContainer *pc);
Chris@127 273 void propertyChanged(PropertyContainer::PropertyName);
Chris@127 274
Chris@336 275 void layerModelChanged();
Chris@336 276
Chris@211 277 void centreFrameChanged(unsigned long frame,
Chris@211 278 bool globalScroll,
Chris@211 279 PlaybackFollowMode followMode);
Chris@211 280
Chris@222 281 void zoomLevelChanged(unsigned long, bool);
Chris@127 282
Chris@189 283 void contextHelpChanged(const QString &);
Chris@189 284
Chris@127 285 public slots:
Chris@127 286 virtual void modelChanged();
Chris@127 287 virtual void modelChanged(size_t startFrame, size_t endFrame);
Chris@127 288 virtual void modelCompletionChanged();
Chris@320 289 virtual void modelAlignmentCompletionChanged();
Chris@127 290 virtual void modelReplaced();
Chris@127 291 virtual void layerParametersChanged();
Chris@197 292 virtual void layerParameterRangesChanged();
Chris@268 293 virtual void layerMeasurementRectsChanged();
Chris@127 294 virtual void layerNameChanged();
Chris@127 295
Chris@211 296 virtual void globalCentreFrameChanged(unsigned long);
Chris@211 297 virtual void viewCentreFrameChanged(View *, unsigned long);
Chris@127 298 virtual void viewManagerPlaybackFrameChanged(unsigned long);
Chris@222 299 virtual void viewZoomLevelChanged(View *, unsigned long, bool);
Chris@127 300
Chris@127 301 virtual void propertyContainerSelected(View *, PropertyContainer *pc);
Chris@127 302
Chris@127 303 virtual void selectionChanged();
Chris@127 304 virtual void toolModeChanged();
Chris@133 305 virtual void overlayModeChanged();
Chris@133 306 virtual void zoomWheelsEnabledChanged();
Chris@127 307
Chris@555 308 virtual void progressCheckStalledTimerElapsed();
Chris@555 309
Chris@127 310 protected:
Chris@127 311 View(QWidget *, bool showProgress);
Chris@127 312 virtual void paintEvent(QPaintEvent *e);
Chris@127 313 virtual void drawSelections(QPainter &);
Chris@127 314 virtual bool shouldLabelSelections() const { return true; }
Chris@229 315 virtual bool render(QPainter &paint, int x0, size_t f0, size_t f1);
Chris@339 316 virtual void setPaintFont(QPainter &paint);
Chris@339 317
Chris@127 318 typedef std::vector<Layer *> LayerList;
Chris@127 319
Chris@127 320 int getModelsSampleRate() const;
Chris@127 321 bool areLayersScrollable() const;
Chris@127 322 LayerList getScrollableBackLayers(bool testChanged, bool &changed) const;
Chris@127 323 LayerList getNonScrollableFrontLayers(bool testChanged, bool &changed) const;
Chris@127 324 size_t getZoomConstraintBlockSize(size_t blockSize,
Chris@127 325 ZoomConstraint::RoundingDirection dir =
Chris@127 326 ZoomConstraint::RoundNearest) const;
Chris@127 327
Chris@183 328 // True if the top layer(s) use colours for meaningful things. If
Chris@183 329 // this is the case, selections will be shown using unfilled boxes
Chris@183 330 // rather than with a translucent fill.
Chris@183 331 bool areLayerColoursSignificant() const;
Chris@183 332
Chris@217 333 // True if the top layer has a time axis on the x coordinate (this
Chris@217 334 // is generally the case except for spectrum/slice layers). It
Chris@217 335 // will not be possible to make or display selections if this is
Chris@217 336 // false.
Chris@217 337 bool hasTopLayerTimeXAxis() const;
Chris@217 338
Chris@127 339 bool setCentreFrame(size_t f, bool doEmit);
Chris@127 340
Chris@511 341 void movePlayPointer(unsigned long f);
Chris@511 342
Chris@127 343 void checkProgress(void *object);
Chris@384 344 int getProgressBarWidth() const; // if visible
Chris@127 345
Chris@127 346 size_t m_centreFrame;
Chris@127 347 int m_zoomLevel;
Chris@127 348 bool m_followPan;
Chris@127 349 bool m_followZoom;
Chris@127 350 PlaybackFollowMode m_followPlay;
Chris@127 351 size_t m_playPointerFrame;
Chris@127 352 bool m_lightBackground;
Chris@127 353 bool m_showProgress;
Chris@127 354
Chris@127 355 QPixmap *m_cache;
Chris@127 356 size_t m_cacheCentreFrame;
Chris@127 357 int m_cacheZoomLevel;
Chris@127 358 bool m_selectionCached;
Chris@127 359
Chris@127 360 bool m_deleting;
Chris@127 361
Chris@127 362 LayerList m_layers; // I don't own these, but see dtor note above
Chris@127 363 bool m_haveSelectedLayer;
Chris@127 364
Chris@127 365 // caches for use in getScrollableBackLayers, getNonScrollableFrontLayers
Chris@127 366 mutable LayerList m_lastScrollableBackLayers;
Chris@127 367 mutable LayerList m_lastNonScrollableBackLayers;
Chris@127 368
Chris@127 369 class LayerProgressBar : public QProgressBar {
Chris@127 370 public:
Chris@127 371 LayerProgressBar(QWidget *parent);
Chris@127 372 virtual QString text() const { return m_text; }
Chris@127 373 virtual void setText(QString text) { m_text = text; }
Chris@127 374 protected:
Chris@127 375 QString m_text;
Chris@127 376 };
Chris@127 377
Chris@555 378 struct ProgressBarRec {
Chris@555 379 QProgressBar *bar;
Chris@555 380 int lastCheck;
Chris@555 381 QTimer *checkTimer;
Chris@555 382 };
Chris@555 383 typedef std::map<Layer *, ProgressBarRec> ProgressMap;
Chris@127 384 ProgressMap m_progressBars; // I own the ProgressBars
Chris@127 385
Chris@127 386 ViewManager *m_manager; // I don't own this
Chris@127 387 ViewPropertyContainer *m_propertyContainer; // I own this
Chris@127 388 };
Chris@127 389
Chris@127 390
Chris@127 391 // Use this for delegation, because we can't subclass from
Chris@127 392 // PropertyContainer (which is a QObject) ourselves because of
Chris@127 393 // ambiguity with QFrame parent
Chris@127 394
Chris@127 395 class ViewPropertyContainer : public PropertyContainer
Chris@127 396 {
Chris@127 397 Q_OBJECT
Chris@127 398
Chris@127 399 public:
Chris@127 400 ViewPropertyContainer(View *v);
Chris@127 401 PropertyList getProperties() const { return m_v->getProperties(); }
Chris@127 402 QString getPropertyLabel(const PropertyName &n) const {
Chris@127 403 return m_v->getPropertyLabel(n);
Chris@127 404 }
Chris@127 405 PropertyType getPropertyType(const PropertyName &n) const {
Chris@127 406 return m_v->getPropertyType(n);
Chris@127 407 }
Chris@216 408 int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max,
Chris@216 409 int *deflt) const {
Chris@216 410 return m_v->getPropertyRangeAndValue(n, min, max, deflt);
Chris@127 411 }
Chris@127 412 QString getPropertyValueLabel(const PropertyName &n, int value) const {
Chris@127 413 return m_v->getPropertyValueLabel(n, value);
Chris@127 414 }
Chris@127 415 QString getPropertyContainerName() const {
Chris@127 416 return m_v->getPropertyContainerName();
Chris@127 417 }
Chris@127 418 QString getPropertyContainerIconName() const {
Chris@127 419 return m_v->getPropertyContainerIconName();
Chris@127 420 }
Chris@127 421
Chris@127 422 public slots:
Chris@127 423 virtual void setProperty(const PropertyName &n, int value) {
Chris@127 424 m_v->setProperty(n, value);
Chris@127 425 }
Chris@127 426
Chris@127 427 protected:
Chris@127 428 View *m_v;
Chris@127 429 };
Chris@127 430
Chris@127 431 #endif
Chris@127 432