annotate layer/FlexiNoteLayer.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 e6362cf5ff1d
children
rev   line source
Chris@58 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@30 2
Chris@30 3 /*
Chris@59 4 Sonic Visualiser
Chris@59 5 An audio file viewer and annotation editor.
Chris@59 6 Centre for Digital Music, Queen Mary, University of London.
Chris@59 7 This file copyright 2006 Chris Cannam.
Chris@30 8
Chris@59 9 This program is free software; you can redistribute it and/or
Chris@59 10 modify it under the terms of the GNU General Public License as
Chris@59 11 published by the Free Software Foundation; either version 2 of the
Chris@59 12 License, or (at your option) any later version. See the file
Chris@59 13 COPYING included with this distribution for more information.
Chris@30 14 */
Chris@30 15
Chris@1407 16 #ifndef SV_FLEXINOTE_LAYER_H
Chris@1407 17 #define SV_FLEXINOTE_LAYER_H
Chris@30 18
Chris@287 19 #include "SingleColourLayer.h"
Chris@701 20 #include "VerticalScaleLayer.h"
Chris@701 21
Chris@1426 22 #include "data/model/NoteModel.h"
Chris@30 23
Chris@30 24 #include <QObject>
Chris@30 25 #include <QColor>
Chris@30 26
Chris@30 27 class View;
Chris@30 28 class QPainter;
Chris@745 29 class SparseTimeValueModel;
Chris@702 30
Chris@702 31 class FlexiNoteLayer : public SingleColourLayer,
Chris@702 32 public VerticalScaleLayer
Chris@30 33 {
Chris@30 34 Q_OBJECT
Chris@30 35
Chris@30 36 public:
matthiasm@620 37 FlexiNoteLayer();
Chris@30 38
Chris@1406 39 void paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const override;
Chris@30 40
Chris@1406 41 int getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &) const override;
Chris@1406 42 void paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect rect) const override;
Chris@692 43
Chris@1406 44 QString getFeatureDescription(LayerGeometryProvider *v, QPoint &) const override;
Chris@30 45
Chris@1406 46 bool snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
Chris@1547 47 int &resolution,
Chris@1547 48 SnapType snap, int ycoord) const override;
Chris@30 49
Chris@1406 50 void drawStart(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 51 void drawDrag(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 52 void drawEnd(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@30 53
Chris@1406 54 void eraseStart(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 55 void eraseDrag(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 56 void eraseEnd(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@335 57
Chris@1406 58 void editStart(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 59 void editDrag(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 60 void editEnd(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@30 61
Chris@1406 62 void splitStart(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@1406 63 void splitEnd(LayerGeometryProvider *v, QMouseEvent *) override;
matthiasm@660 64
Chris@1406 65 void addNote(LayerGeometryProvider *v, QMouseEvent *e) override;
gyorgyf@635 66
Chris@916 67 virtual void mouseMoveEvent(LayerGeometryProvider *v, QMouseEvent *);
gyorgyf@646 68
Chris@1406 69 bool editOpen(LayerGeometryProvider *v, QMouseEvent *) override;
Chris@70 70
Chris@1406 71 void moveSelection(Selection s, sv_frame_t newStartFrame) override;
Chris@1406 72 void resizeSelection(Selection s, Selection newSize) override;
Chris@1406 73 void deleteSelection(Selection s) override;
matthiasm@784 74 virtual void deleteSelectionInclusive(Selection s);
Chris@76 75
Chris@1406 76 void copy(LayerGeometryProvider *v, Selection s, Clipboard &to) override;
Chris@1406 77 bool paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset,
Chris@1406 78 bool interactive) override;
Chris@43 79
Chris@916 80 void splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame);
Chris@916 81 void snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s);
Chris@916 82 void mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive);
Chris@746 83
Chris@1469 84 ModelId getModel() const override { return m_model; }
Chris@1469 85 void setModel(ModelId model); // a NoteModel please
Chris@30 86
Chris@1406 87 PropertyList getProperties() const override;
Chris@1406 88 QString getPropertyLabel(const PropertyName &) const override;
Chris@1406 89 PropertyType getPropertyType(const PropertyName &) const override;
Chris@1406 90 QString getPropertyGroupName(const PropertyName &) const override;
Chris@1406 91 int getPropertyRangeAndValue(const PropertyName &,
Chris@1406 92 int *min, int *max, int *deflt) const override;
Chris@1406 93 QString getPropertyValueLabel(const PropertyName &,
Chris@1406 94 int value) const override;
Chris@1406 95 void setProperty(const PropertyName &, int value) override;
Chris@30 96
Chris@30 97 enum VerticalScale {
Chris@101 98 AutoAlignScale,
Chris@101 99 LinearScale,
Chris@101 100 LogScale,
Chris@101 101 MIDIRangeScale
Chris@30 102 };
gyorgyf@649 103
gyorgyf@649 104 //GF: Tonioni: context sensitive note edit actions (denoted clockwise from top).
gyorgyf@649 105 enum EditMode {
matthiasm@651 106 DragNote,
matthiasm@651 107 RightBoundary,
matthiasm@651 108 SplitNote,
matthiasm@651 109 LeftBoundary
gyorgyf@649 110 };
gyorgyf@658 111
gyorgyf@658 112 void setIntelligentActions(bool on) { m_intelligentActions=on; }
Chris@30 113
Chris@30 114 void setVerticalScale(VerticalScale scale);
Chris@30 115 VerticalScale getVerticalScale() const { return m_verticalScale; }
Chris@30 116
Chris@1406 117 bool isLayerScrollable(const LayerGeometryProvider *v) const override;
Chris@30 118
Chris@1406 119 bool isLayerEditable() const override { return true; }
Chris@30 120
Chris@1469 121 int getCompletion(LayerGeometryProvider *) const override;
Chris@30 122
Chris@1406 123 bool getValueExtents(double &min, double &max,
Chris@1469 124 bool &log, QString &unit) const override;
Chris@101 125
Chris@1406 126 bool getDisplayExtents(double &min, double &max) const override;
Chris@1406 127 bool setDisplayExtents(double min, double max) override;
Chris@439 128
Chris@1406 129 int getVerticalZoomSteps(int &defaultStep) const override;
Chris@1406 130 int getCurrentVerticalZoomStep() const override;
Chris@1406 131 void setVerticalZoomStep(int) override;
Chris@1406 132 RangeMapper *getNewVerticalZoomRangeMapper() const override;
Chris@79 133
Chris@507 134 /**
Chris@507 135 * Add a note-on. Used when recording MIDI "live". The note will
Chris@507 136 * not be finally added to the layer until the corresponding
Chris@507 137 * note-off.
Chris@507 138 */
Chris@904 139 void addNoteOn(sv_frame_t frame, int pitch, int velocity);
Chris@507 140
Chris@507 141 /**
Chris@507 142 * Add a note-off. This will cause a note to appear, if and only
Chris@507 143 * if there is a matching pending note-on.
Chris@507 144 */
Chris@904 145 void addNoteOff(sv_frame_t frame, int pitch);
Chris@507 146
Chris@507 147 /**
Chris@507 148 * Abandon all pending note-on events.
Chris@507 149 */
Chris@507 150 void abandonNoteOns();
Chris@507 151
Chris@1406 152 void toXml(QTextStream &stream, QString indent = "",
Chris@1406 153 QString extraAttributes = "") const override;
Chris@30 154
Chris@1406 155 void setProperties(const QXmlAttributes &attributes) override;
matthiasm@651 156
Chris@916 157 void setVerticalRangeToNoteRange(LayerGeometryProvider *v);
Chris@30 158
Chris@701 159 /// VerticalScaleLayer methods
Chris@1406 160 int getYForValue(LayerGeometryProvider *v, double value) const override;
Chris@1406 161 double getValueForY(LayerGeometryProvider *v, int y) const override;
Chris@1406 162 QString getScaleUnits() const override;
Chris@701 163
Chris@875 164 signals:
Chris@922 165 void reAnalyseRegion(sv_frame_t, sv_frame_t, float, float);
Chris@876 166 void materialiseReAnalysis();
Chris@875 167
Chris@30 168 protected:
Chris@916 169 void getScaleExtents(LayerGeometryProvider *, double &min, double &max, bool &log) const;
Chris@101 170 bool shouldConvertMIDIToHz() const;
Chris@30 171
Chris@1406 172 int getDefaultColourHint(bool dark, bool &impose) override;
Chris@287 173
Chris@1426 174 EventVector getLocalPoints(LayerGeometryProvider *v, int) const;
Chris@30 175
Chris@1426 176 bool getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &) const;
Chris@1426 177 bool getNoteToEdit(LayerGeometryProvider *v, int x, int y, Event &) const;
Chris@1426 178 void getRelativeMousePosition(LayerGeometryProvider *v, Event &note, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const;
Chris@1469 179 ModelId getAssociatedPitchModel(LayerGeometryProvider *v) const;
Chris@1426 180 bool updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event &note) const;
Chris@916 181 void splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e);
Chris@550 182
Chris@1469 183 ModelId m_model;
Chris@30 184 bool m_editing;
gyorgyf@658 185 bool m_intelligentActions;
Chris@551 186 int m_dragPointX;
Chris@551 187 int m_dragPointY;
Chris@551 188 int m_dragStartX;
Chris@551 189 int m_dragStartY;
Chris@1426 190 Event m_originalPoint;
Chris@1426 191 Event m_editingPoint;
Chris@904 192 sv_frame_t m_greatestLeftNeighbourFrame;
Chris@904 193 sv_frame_t m_smallestRightNeighbourFrame;
Chris@1470 194 ChangeEventsCommand *m_editingCommand;
Chris@30 195 VerticalScale m_verticalScale;
gyorgyf@649 196 EditMode m_editMode;
Chris@376 197
Chris@1426 198 typedef std::set<Event> NoteSet;
Chris@1426 199 NoteSet m_pendingNoteOns;
Chris@507 200
Chris@904 201 mutable double m_scaleMinimum;
Chris@904 202 mutable double m_scaleMaximum;
Chris@439 203
Chris@439 204 bool shouldAutoAlign() const;
Chris@439 205
Chris@1470 206 void finish(ChangeEventsCommand *command) {
Chris@376 207 Command *c = command->finish();
Chris@376 208 if (c) CommandHistory::getInstance()->addCommand(c, false);
Chris@376 209 }
Chris@30 210 };
Chris@30 211
Chris@30 212 #endif
Chris@30 213