annotate view/ViewManager.h @ 1551:e79731086b0f

Fixes to NoteLayer, particularly to calculation of vertical scale when model unit is not Hz. To avoid inconsistency we now behave as if the unit is always Hz from the point of view of the external API and display, converting at the point where we obtain values from the events themselves. Also various fixes to editing.
author Chris Cannam
date Thu, 21 Nov 2019 14:02:57 +0000
parents 9bf8aa2916e9
children
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@1270 16 #ifndef SV_VIEW_MANAGER_H
Chris@1270 17 #define SV_VIEW_MANAGER_H
Chris@127 18
Chris@127 19 #include <QObject>
Chris@127 20 #include <QTimer>
Chris@292 21 #include <QPalette>
Chris@127 22
Chris@127 23 #include <map>
Chris@127 24
Chris@376 25 #include "base/ViewManagerBase.h"
Chris@128 26 #include "base/Selection.h"
Chris@128 27 #include "base/Command.h"
Chris@128 28 #include "base/Clipboard.h"
Chris@902 29 #include "base/BaseTypes.h"
Chris@1327 30 #include "base/ZoomLevel.h"
Chris@127 31
Chris@1479 32 #include "data/model/Model.h"
Chris@1479 33
Chris@127 34 class AudioPlaySource;
Chris@1210 35 class AudioRecordTarget;
Chris@127 36 class Model;
Chris@127 37
Chris@211 38 enum PlaybackFollowMode {
Chris@815 39
Chris@815 40 /**
Chris@815 41 * View scrolls continuously during playback, keeping the playback
Chris@815 42 * position at the centre.
Chris@815 43 */
Chris@211 44 PlaybackScrollContinuous,
Chris@815 45
Chris@815 46 /**
Chris@815 47 * View follows playback page-by-page, but dragging the view
Chris@815 48 * relocates playback to the centre frame. This is the classic
Chris@815 49 * Sonic Visualiser behaviour.
Chris@815 50 */
Chris@815 51 PlaybackScrollPageWithCentre,
Chris@815 52
Chris@815 53 /**
Chris@815 54 * View follows playback page-by-page, and the play head is moved
Chris@815 55 * (by the user) separately from dragging the view. This is
Chris@815 56 * roughly the behaviour of a typical DAW or audio editor.
Chris@815 57 */
Chris@211 58 PlaybackScrollPage,
Chris@815 59
Chris@815 60 /**
Chris@815 61 * View is detached from playback. It doesn't follow playback, and
Chris@815 62 * dragging the view does not affect the play head.
Chris@815 63 */
Chris@211 64 PlaybackIgnore
Chris@211 65 };
Chris@211 66
Chris@211 67 class View;
Chris@211 68
Chris@127 69 /**
Chris@127 70 * The ViewManager manages properties that may need to be synchronised
Chris@127 71 * between separate Views. For example, it handles signals associated
Chris@127 72 * with changes to the global pan and zoom, and it handles selections.
Chris@127 73 *
Chris@127 74 * Views should be implemented in such a way as to work
Chris@127 75 * correctly whether they are supplied with a ViewManager or not.
Chris@127 76 */
Chris@127 77
Chris@376 78 class ViewManager : public ViewManagerBase
Chris@127 79 {
Chris@127 80 Q_OBJECT
Chris@127 81
Chris@127 82 public:
Chris@127 83 ViewManager();
Chris@127 84 virtual ~ViewManager();
Chris@127 85
Chris@1406 86 void setAudioPlaySource(AudioPlaySource *source) override;
Chris@1406 87 void setAudioRecordTarget(AudioRecordTarget *target) override;
Chris@127 88
Chris@127 89 bool isPlaying() const;
Chris@1210 90 bool isRecording() const;
Chris@127 91
Chris@902 92 sv_frame_t getGlobalCentreFrame() const; // the set method is a slot
Chris@1327 93 ZoomLevel getGlobalZoom() const;
Chris@127 94
Chris@902 95 sv_frame_t getPlaybackFrame() const; // the set method is a slot
Chris@127 96
Chris@301 97 // Only meaningful in solo mode, and used for optional alignment feature
Chris@1479 98 ModelId getPlaybackModel() const;
Chris@1479 99 void setPlaybackModel(ModelId);
Chris@301 100
Chris@1406 101 sv_frame_t alignPlaybackFrameToReference(sv_frame_t) const override;
Chris@1406 102 sv_frame_t alignReferenceToPlaybackFrame(sv_frame_t) const override;
Chris@333 103
Chris@127 104 bool haveInProgressSelection() const;
Chris@127 105 const Selection &getInProgressSelection(bool &exclusive) const;
Chris@127 106 void setInProgressSelection(const Selection &selection, bool exclusive);
Chris@127 107 void clearInProgressSelection();
Chris@127 108
Chris@1406 109 const MultiSelection &getSelection() const override;
Chris@127 110
Chris@1406 111 const MultiSelection::SelectionList &getSelections() const override;
Chris@127 112 void setSelection(const Selection &selection);
Chris@127 113 void addSelection(const Selection &selection);
Chris@127 114 void removeSelection(const Selection &selection);
Chris@127 115 void clearSelections();
Chris@1406 116 sv_frame_t constrainFrameToSelection(sv_frame_t frame) const override;
Chris@127 117
Chris@127 118 /**
Chris@762 119 * Adding a selection normally emits the selectionChangedByUser
Chris@762 120 * signal. Call this to add a selection without emitting that signal.
Chris@762 121 * This is used in session file load, for example.
Chris@762 122 */
Chris@762 123 void addSelectionQuietly(const Selection &selection);
Chris@762 124
Chris@762 125 /**
Chris@127 126 * Return the selection that contains a given frame.
Chris@127 127 * If defaultToFollowing is true, and if the frame is not in a
Chris@127 128 * selected area, return the next selection after the given frame.
Chris@127 129 * Return the empty selection if no appropriate selection is found.
Chris@127 130 */
Chris@1406 131 Selection getContainingSelection(sv_frame_t frame, bool defaultToFollowing) const override;
Chris@127 132
Chris@127 133 Clipboard &getClipboard() { return m_clipboard; }
Chris@127 134
Chris@127 135 enum ToolMode {
Chris@1266 136 NavigateMode,
Chris@1266 137 SelectMode,
Chris@711 138 EditMode,
Chris@1266 139 DrawMode,
Chris@1266 140 EraseMode,
Chris@1266 141 MeasureMode,
Chris@1266 142 NoteEditMode //GF: Tonioni: this tool mode will be context sensitive.
Chris@127 143 };
Chris@127 144 ToolMode getToolMode() const { return m_toolMode; }
Chris@127 145 void setToolMode(ToolMode mode);
Chris@127 146
Chris@711 147 /// Override the tool mode for a specific view
Chris@711 148 void setToolModeFor(const View *v, ToolMode mode);
Chris@711 149 /// Return override mode if it exists for this view or global mode otherwise
Chris@711 150 ToolMode getToolModeFor(const View *v) const;
Chris@711 151 /// Clear all current view-specific overrides
Chris@711 152 void clearToolModeOverrides();
Chris@711 153
Chris@1406 154 bool getPlayLoopMode() const override { return m_playLoopMode; }
Chris@127 155 void setPlayLoopMode(bool on);
Chris@127 156
Chris@1406 157 bool getPlaySelectionMode() const override { return m_playSelectionMode; }
Chris@127 158 void setPlaySelectionMode(bool on);
Chris@127 159
Chris@1406 160 bool getPlaySoloMode() const override { return m_playSoloMode; }
Chris@301 161 void setPlaySoloMode(bool on);
Chris@301 162
Chris@1406 163 bool getAlignMode() const override { return m_alignMode; }
Chris@314 164 void setAlignMode(bool on);
Chris@314 165
Chris@326 166 void setIlluminateLocalFeatures(bool i) { m_illuminateLocalFeatures = i; }
Chris@326 167 void setShowWorkTitle(bool show) { m_showWorkTitle = show; }
matthiasm@822 168 void setShowDuration(bool show) { m_showDuration = show; }
Chris@326 169
Chris@224 170 /**
Chris@224 171 * The sample rate that is used for playback. This is usually the
Chris@224 172 * rate of the main model, but not always. Models whose rates
Chris@224 173 * differ from this will play back at the wrong speed -- there is
Chris@224 174 * no per-model resampler.
Chris@224 175 */
Chris@902 176 sv_samplerate_t getPlaybackSampleRate() const;
Chris@224 177
Chris@224 178 /**
Chris@224 179 * The sample rate of the audio output device. If the playback
Chris@224 180 * sample rate differs from this, everything will be resampled at
Chris@1181 181 * the output stage (but not before).
Chris@224 182 */
Chris@1181 183 sv_samplerate_t getDeviceSampleRate() const;
Chris@224 184
Chris@224 185 /**
Chris@224 186 * The sample rate of the current main model. This may in theory
Chris@224 187 * differ from the playback sample rate, in which case even the
Chris@224 188 * main model will play at the wrong speed.
Chris@224 189 */
Chris@902 190 sv_samplerate_t getMainModelSampleRate() const { return m_mainModelSampleRate; }
Chris@224 191
Chris@902 192 void setMainModelSampleRate(sv_samplerate_t sr) { m_mainModelSampleRate = sr; }
Chris@127 193
Chris@894 194 /**
Chris@894 195 * Take a "design pixel" size and scale it for the actual
Chris@894 196 * display. This is relevant to hi-dpi systems that do not do
Chris@894 197 * pixel doubling (i.e. Windows and Linux rather than OS/X).
Chris@894 198 */
Chris@1270 199 static int scalePixelSize(int pixels);
Chris@894 200
Chris@127 201 enum OverlayMode {
Chris@127 202 NoOverlays,
Chris@741 203 GlobalOverlays,
Chris@741 204 StandardOverlays,
Chris@127 205 AllOverlays
Chris@127 206 };
Chris@127 207 void setOverlayMode(OverlayMode mode);
Chris@127 208 OverlayMode getOverlayMode() const { return m_overlayMode; }
Chris@127 209
Chris@607 210 void setShowCentreLine(bool show);
Chris@607 211 bool shouldShowCentreLine() const { return m_showCentreLine; }
Chris@607 212
Chris@607 213 bool shouldShowDuration() const {
matthiasm@822 214 return m_overlayMode != NoOverlays && m_showDuration;
Chris@189 215 }
Chris@189 216 bool shouldShowFrameCount() const {
Chris@607 217 return m_showCentreLine && shouldShowDuration();
Chris@607 218 }
Chris@607 219 bool shouldShowVerticalScale() const {
Chris@189 220 return m_overlayMode != NoOverlays;
Chris@189 221 }
Chris@607 222 bool shouldShowVerticalColourScale() const {
Chris@607 223 return m_overlayMode == AllOverlays;
Chris@189 224 }
Chris@1281 225 bool shouldShowHorizontalValueScale() const { // for layers where x != time
Chris@1281 226 return m_overlayMode != NoOverlays;
Chris@1281 227 }
Chris@189 228 bool shouldShowSelectionExtents() const {
Chris@741 229 return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays;
Chris@189 230 }
Chris@189 231 bool shouldShowLayerNames() const {
Chris@189 232 return m_overlayMode == AllOverlays;
Chris@189 233 }
Chris@195 234 bool shouldShowScaleGuides() const {
Chris@195 235 return m_overlayMode != NoOverlays;
Chris@195 236 }
Chris@326 237 bool shouldShowWorkTitle() const {
Chris@326 238 return m_showWorkTitle;
Chris@326 239 }
Chris@326 240 bool shouldIlluminateLocalFeatures() const {
Chris@326 241 return m_illuminateLocalFeatures;
Chris@326 242 }
Chris@741 243 bool shouldShowFeatureLabels() const {
Chris@741 244 return m_overlayMode != NoOverlays && m_overlayMode != GlobalOverlays;
Chris@741 245 }
Chris@189 246
Chris@133 247 void setZoomWheelsEnabled(bool enable);
Chris@133 248 bool getZoomWheelsEnabled() const { return m_zoomWheelsEnabled; }
Chris@133 249
Chris@1468 250 /**
Chris@1468 251 * Enable or disable opportunistic editing. This allows certain
Chris@1468 252 * edits while not in edit modes - e.g. double-click on an item
Chris@1468 253 * while in navigate mode to open an edit dialog. It is enabled by
Chris@1468 254 * default, but it may be undesirable if the application is
Chris@1468 255 * intended to be "read-only".
Chris@1468 256 *
Chris@1468 257 * This setting makes no difference to behaviour when actually in
Chris@1468 258 * editing modes.
Chris@1468 259 *
Chris@1468 260 * Unlike some other options, this is considered to be
Chris@1468 261 * application-build-specific and is not restored from settings.
Chris@1468 262 */
Chris@1468 263 void setOpportunisticEditingEnabled(bool enable);
Chris@1468 264 bool getOpportunisticEditingEnabled() const {
Chris@1468 265 return m_opportunisticEditingEnabled;
Chris@1468 266 }
Chris@1468 267
Chris@292 268 void setGlobalDarkBackground(bool dark);
Chris@292 269 bool getGlobalDarkBackground() const;
Chris@292 270
Chris@127 271 signals:
Chris@211 272 /** Emitted when user causes the global centre frame to change. */
Chris@902 273 void globalCentreFrameChanged(sv_frame_t frame);
Chris@127 274
Chris@211 275 /** Emitted when user scrolls a view, but doesn't affect global centre. */
Chris@902 276 void viewCentreFrameChanged(View *v, sv_frame_t frame);
Chris@211 277
Chris@211 278 /** Emitted when a view zooms. */
Chris@1327 279 void viewZoomLevelChanged(View *v, ZoomLevel zoom, bool locked);
Chris@133 280
Chris@127 281 /** Emitted when the playback frame changes. */
Chris@902 282 void playbackFrameChanged(sv_frame_t frame);
Chris@127 283
Chris@1210 284 /** Emitted when the output or record levels change. Values in range 0.0 -> 1.0. */
Chris@1210 285 void monitoringLevelsChanged(float left, float right);
Chris@127 286
Chris@731 287 /** Emitted whenever the selection has changed. */
Chris@127 288 void selectionChanged();
Chris@127 289
Chris@731 290 /** Emitted when the selection has been changed through an
Chris@731 291 * explicit selection-editing action. *Not* emitted when the
Chris@731 292 * selection has been changed through undo or redo. */
Chris@731 293 void selectionChangedByUser();
Chris@731 294
Chris@127 295 /** Emitted when the in-progress (rubberbanding) selection has changed. */
Chris@127 296 void inProgressSelectionChanged();
Chris@127 297
Chris@127 298 /** Emitted when the tool mode has been changed. */
Chris@127 299 void toolModeChanged();
Chris@127 300
Chris@127 301 /** Emitted when the play loop mode has been changed. */
Chris@127 302 void playLoopModeChanged();
Chris@177 303 void playLoopModeChanged(bool);
Chris@127 304
Chris@127 305 /** Emitted when the play selection mode has been changed. */
Chris@127 306 void playSelectionModeChanged();
Chris@177 307 void playSelectionModeChanged(bool);
Chris@127 308
Chris@301 309 /** Emitted when the play solo mode has been changed. */
Chris@301 310 void playSoloModeChanged();
Chris@301 311 void playSoloModeChanged(bool);
Chris@301 312
Chris@314 313 /** Emitted when the alignment mode has been changed. */
Chris@314 314 void alignModeChanged();
Chris@314 315 void alignModeChanged(bool);
Chris@314 316
Chris@127 317 /** Emitted when the overlay mode has been changed. */
Chris@127 318 void overlayModeChanged();
Chris@127 319
Chris@607 320 /** Emitted when the centre line visibility has been changed. */
Chris@607 321 void showCentreLineChanged();
Chris@607 322
Chris@133 323 /** Emitted when the zoom wheels have been toggled. */
Chris@133 324 void zoomWheelsEnabledChanged();
Chris@133 325
Chris@1468 326 /** Emitted when editing-enabled has been toggled. */
Chris@1468 327 void opportunisticEditingEnabledChanged();
Chris@1468 328
Chris@502 329 /** Emitted when any loggable activity has occurred. */
Chris@502 330 void activity(QString);
Chris@502 331
Chris@211 332 public slots:
Chris@902 333 void viewCentreFrameChanged(sv_frame_t, bool, PlaybackFollowMode);
Chris@1327 334 void viewZoomLevelChanged(ZoomLevel, bool);
Chris@902 335 void setGlobalCentreFrame(sv_frame_t);
Chris@902 336 void setPlaybackFrame(sv_frame_t);
Chris@689 337 void playStatusChanged(bool playing);
Chris@1210 338 void recordStatusChanged(bool recording);
Chris@211 339
Chris@127 340 protected slots:
Chris@127 341 void checkPlayStatus();
Chris@902 342 void seek(sv_frame_t);
Chris@806 343 //!!! void considerZoomChange(void *, int, bool);
Chris@127 344
Chris@127 345 protected:
Chris@127 346 AudioPlaySource *m_playSource;
Chris@1210 347 AudioRecordTarget *m_recordTarget;
Chris@1210 348
Chris@902 349 sv_frame_t m_globalCentreFrame;
Chris@1327 350 ZoomLevel m_globalZoom;
Chris@902 351 mutable sv_frame_t m_playbackFrame;
Chris@1479 352 ModelId m_playbackModel;
Chris@902 353 sv_samplerate_t m_mainModelSampleRate;
Chris@127 354
Chris@127 355 float m_lastLeft;
Chris@127 356 float m_lastRight;
Chris@127 357
Chris@127 358 MultiSelection m_selections;
Chris@127 359 Selection m_inProgressSelection;
Chris@127 360 bool m_inProgressExclusive;
Chris@127 361
Chris@127 362 Clipboard m_clipboard;
Chris@127 363
Chris@127 364 ToolMode m_toolMode;
Chris@711 365 std::map<const View *, ToolMode> m_toolModeOverrides;
Chris@127 366
Chris@127 367 bool m_playLoopMode;
Chris@127 368 bool m_playSelectionMode;
Chris@301 369 bool m_playSoloMode;
Chris@314 370 bool m_alignMode;
Chris@127 371
Chris@762 372 void setSelections(const MultiSelection &ms, bool quietly = false);
Chris@127 373 void signalSelectionChange();
Chris@127 374
Chris@127 375 class SetSelectionCommand : public Command
Chris@127 376 {
Chris@127 377 public:
Chris@1266 378 SetSelectionCommand(ViewManager *vm, const MultiSelection &ms);
Chris@1266 379 virtual ~SetSelectionCommand();
Chris@1406 380 void execute() override;
Chris@1406 381 void unexecute() override;
Chris@1406 382 QString getName() const override;
Chris@127 383
Chris@127 384 protected:
Chris@1266 385 ViewManager *m_vm;
Chris@1266 386 MultiSelection m_oldSelection;
Chris@1266 387 MultiSelection m_newSelection;
Chris@127 388 };
Chris@127 389
Chris@127 390 OverlayMode m_overlayMode;
Chris@133 391 bool m_zoomWheelsEnabled;
Chris@1468 392 bool m_opportunisticEditingEnabled;
Chris@607 393 bool m_showCentreLine;
Chris@326 394 bool m_illuminateLocalFeatures;
Chris@326 395 bool m_showWorkTitle;
matthiasm@822 396 bool m_showDuration;
Chris@292 397
Chris@292 398 QPalette m_lightPalette;
Chris@292 399 QPalette m_darkPalette;
Chris@127 400 };
Chris@127 401
Chris@127 402 #endif
Chris@127 403