1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2009-2011 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __PIANOVIEW_H__
14 #define __PIANOVIEW_H__
15 
16 #include "libmscore/pos.h"
17 #include "pianorolledittool.h"
18 
19 namespace Ms {
20 
21 class Score;
22 class Staff;
23 class Chord;
24 class ChordRest;
25 class Segment;
26 class Note;
27 class NoteEvent;
28 class PianoView;
29 class NoteTweakerDialog;
30 
31 enum class NoteSelectType {
32       REPLACE = 0,
33       XOR,
34       ADD,
35       SUBTRACT,
36       FIRST
37       };
38 
39 enum class DragStyle {
40     NONE = 0,
41     CANCELLED,
42     SELECTION_RECT,
43     NOTES
44       };
45 
46 struct BarPattern {
47       QString name;
48       char isWhiteKey[12];  //Set to 1 for white keys, 0 for black
49       };
50 
51 //---------------------------------------------------------
52 //   PianoItem
53 //---------------------------------------------------------
54 
55 class PianoItem {
56       Note* _note;
57       PianoView* _pianoView;
58 
59       void paintNoteBlock(QPainter* painter, NoteEvent* evt);
60       QRect boundingRectTicks(NoteEvent* evt);
61       QRect boundingRectPixels(NoteEvent* evt);
62       bool intersectsBlock(int startTick, int endTick, int highPitch, int lowPitch, NoteEvent* evt);
63 
64    public:
65       const static int NOTE_BLOCK_CORNER_RADIUS = 3;
66 
67       PianoItem(Note*, PianoView*);
~PianoItem()68       ~PianoItem() {}
note()69       Note* note() { return _note; }
70       void paint(QPainter* painter);
71       bool intersects(int startTick, int endTick, int highPitch, int lowPitch);
72 
73       QRect boundingRect();
74 
75       NoteEvent* getTweakNoteEvent();
76       };
77 
78 //---------------------------------------------------------
79 //   PianoView
80 //---------------------------------------------------------
81 
82 class PianoView : public QGraphicsView {
83       Q_OBJECT
84 
85 public:
86       static const BarPattern barPatterns[];
87 
88 private:
89       Staff* _staff;
90       Chord* _chord;
91 
92       Pos trackingPos;  //Track mouse position
93       Pos* _locator;
94       int _ticks;
95       TType _timeType;
96       int _noteHeight;
97       qreal _xZoom;
98       int _tuplet;  //Tuplet divisions
99       int _subdiv;  //Beat subdivisions
100       int _barPattern;
101 
102       bool _playEventsView;
103       bool _mouseDown;
104       bool _dragStarted;
105       QString _dragNoteCache;
106       QPointF _mouseDownPos;
107       QPointF _lastMousePos;
108       QPointF _popupMenuPos;
109       DragStyle _dragStyle;
110       int _dragStartPitch;
111       bool _inProgressUndoEvent;
112 
113       //The length of the note we are using for editng purposes, expressed as a fraction of the measure.
114       // Note length will be (2^_editNoteLength) of a measure
115       int _editNoteLength = 0;
116       int _editNoteDots = 0;
117       int _editNoteVoice = 0;
118       PianoRollEditTool _editNoteTool = PianoRollEditTool::SELECT;
119 
120       QList<PianoItem*> _noteList;
121       quint8 _pitchHighlight[128];
122 
123       virtual void drawBackground(QPainter* painter, const QRectF& rect);
124 
125       void addChord(Chord* _chord, int voice);
126       QVector<Note*> getSegmentNotes(Segment* seg, int track);
127       void updateBoundingSize();
128       void clearNoteData();
129       void selectNotes(int startTick, int endTick, int lowPitch, int highPitch, NoteSelectType selType);
130       void showPopupMenu(const QPoint& pos);
131       bool cutChordRest(ChordRest* targetCr, int track, Fraction cutTick, ChordRest*& cr0, ChordRest*& cr1);
132       QVector<Note*> addNote(Fraction startTick, Fraction duration, int pitch, int track);
133       void handleSelectionClick();
134       void insertNote(int modifiers);
135       Fraction roundToStartBeat(int tick) const;
136       Fraction noteEditLength() const;
137       void changeChordLength(const QPointF& pos);
138       void eraseNote(const QPointF& pos);
139       void appendNoteToChord(const QPointF& pos);
140       void cutChord(const QPointF& pos);
141       void toggleTie(const QPointF& pos);
142       void toggleTie(Note*);
143       void dragSelectionNoteGroup();
144       void finishNoteGroupDrag();
toolCanDragNotes()145       bool toolCanDragNotes() const {
146             return _editNoteTool == PianoRollEditTool::SELECT || _editNoteTool == PianoRollEditTool::INSERT_NOTE ||
147                   _editNoteTool == PianoRollEditTool::APPEND_NOTE || _editNoteTool == PianoRollEditTool::CUT_CHORD ||
148                   _editNoteTool == PianoRollEditTool::TIE;
149             }
150 
151       QAction* getAction(const char* id);
152 
153    protected:
154       virtual void wheelEvent(QWheelEvent* event);
155       virtual void keyReleaseEvent(QKeyEvent* event);
156       virtual void mousePressEvent(QMouseEvent* event);
157       virtual void mouseReleaseEvent(QMouseEvent* event);
158       virtual void mouseMoveEvent(QMouseEvent* event);
159       virtual void leaveEvent(QEvent*);
160       virtual void contextMenuEvent(QContextMenuEvent *event);
161 
162    signals:
163       void xZoomChanged(qreal);
164       void tupletChanged(int);
165       void subdivChanged(int);
166       void barPatternChanged(int);
167       void noteHeightChanged(int);
168       void pitchChanged(int);
169       void trackingPosChanged(const Pos&);
170       void selectionChanged();
171       void showNoteTweakerRequest();
172 
173    public slots:
174       void moveLocator(int);
175       void updateNotes();
176       void setXZoom(int);
177       void setTuplet(int);
178       void setSubdiv(int);
179       void setBarPattern(int);
180       void togglePitchHighlight(int pitch);
181       void showNoteTweaker();
182       void setNotesToVoice(int voice);
183 
184       QString serializeSelectedNotes();
185       void pasteNotes(const QString& copiedNotes, Fraction pasteStartTick, int pitchOffset, bool xIsOffset = false);
186       void drawDraggedNotes(QPainter* painter);
187       void drawDraggedNote(QPainter* painter, Fraction startTick, Fraction frac, int pitch, int track, QColor color);
188 
189       void cutNotes();
190       void copyNotes();
191       void pasteNotesAtCursor();
192 
193    public:
194       PianoView();
195       ~PianoView();
staff()196       Staff* staff() { return _staff; }
197       void setStaff(Staff*, Pos* locator);
198       void ensureVisible(int tick);
noteHeight()199       int noteHeight() { return _noteHeight; }
xZoom()200       qreal xZoom() { return _xZoom; }
tuplet()201       int tuplet() { return _tuplet; }
subdiv()202       int subdiv() { return _subdiv; }
barPattern()203       int barPattern() { return _barPattern; }
editTool()204       PianoRollEditTool editTool() const { return _editNoteTool; }
items()205       QList<QGraphicsItem*> items() { return scene()->selectedItems(); }
editNoteDots()206       int editNoteDots() const { return _editNoteDots; }
207 
setEditNoteLength(int len)208       void setEditNoteLength(int len) { _editNoteLength = len; }
setEditNoteVoice(int voice)209       void setEditNoteVoice(int voice) { _editNoteVoice = voice; }
setEditNoteDots(int dot)210       void setEditNoteDots(int dot) { _editNoteDots = dot; }
setEditNoteTool(PianoRollEditTool tool)211       void setEditNoteTool(PianoRollEditTool tool) { _editNoteTool = tool; }
212 
213       int pixelXToTick(int pixX);
214       int tickToPixelX(int tick);
pixelYToPitch(int pixY)215       int pixelYToPitch(int pixY) { return (int)floor(128 - pixY / (qreal)_noteHeight); }
pitchToPixelY(int pitch)216       int pitchToPixelY(int pitch) { return (128 - pitch) * _noteHeight; }
217 
218       PianoItem* pickNote(int tick, int pitch);
219 
220       QList<PianoItem*> getSelectedItems();
221       QList<PianoItem*> getItems();
222 
223       void zoomView(int step, bool horizontal, int centerX, int centerY);
224 
playEventsView()225       bool playEventsView() { return _playEventsView; }
226       };
227 
228 
229 } // namespace Ms
230 #endif
231 
232