Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <vector>
26 :
27 : #include <QGraphicsView>
28 : #include <QSplitter>
29 :
30 : #include "async/asyncable.h"
31 :
32 : #include "modularity/ioc.h"
33 : #include "ui/iuiconfiguration.h"
34 : #include "notation/inotation.h"
35 : #include "playback/iplaybackcontroller.h"
36 : #include "rcommand/icommanddispatcher.h"
37 :
38 : namespace mu::engraving {
39 : class Measure;
40 : class Page;
41 : class Part;
42 : class Score;
43 : class Staff;
44 : enum class SelState : char;
45 : }
46 :
47 : namespace mu::notation {
48 : class Timeline;
49 :
50 : class TRowLabels : public QGraphicsView
51 : {
52 : Q_OBJECT
53 :
54 : friend class TimelineAdapter;
55 :
56 : public:
57 : enum class MouseOverValue {
58 : NONE,
59 : MOVE_UP_ARROW,
60 : MOVE_DOWN_ARROW,
61 : MOVE_UP_DOWN_ARROW,
62 : COLLAPSE_UP_ARROW,
63 : COLLAPSE_DOWN_ARROW,
64 : OPEN_EYE,
65 : CLOSED_EYE
66 : };
67 :
68 : private:
69 : QSplitter* _splitter { nullptr };
70 : Timeline* _timeline { nullptr };
71 :
72 : QPoint _oldLoc;
73 :
74 : bool _dragging = false;
75 :
76 : std::vector<std::pair<QGraphicsItem*, int> > _metaLabels;
77 : std::map<MouseOverValue, QPixmap*> _mouseoverMap;
78 : std::tuple<QGraphicsPixmapItem*, MouseOverValue, unsigned> _oldItemInfo;
79 :
80 : void resizeEvent(QResizeEvent*) override;
81 : void mousePressEvent(QMouseEvent* event) override;
82 : void mouseMoveEvent(QMouseEvent* event) override;
83 : void mouseReleaseEvent(QMouseEvent* event) override;
84 : void contextMenuEvent(QContextMenuEvent*) override;
85 : void leaveEvent(QEvent*) override;
86 :
87 : private slots:
88 : void restrictScroll(int value);
89 :
90 : public slots:
91 : void mouseOver(QPointF scenePt);
92 :
93 : signals:
94 : void moved(QPointF p);
95 : void swapMeta(unsigned r, bool up);
96 : void requestContextMenu(QContextMenuEvent*);
97 :
98 : public:
99 : TRowLabels(QSplitter* splitter, Timeline* time);
100 :
101 : bool handleEvent(QEvent* event);
102 :
103 : void updateLabels(std::vector<std::pair<QString, bool> > labels, int height);
104 : QString cursorIsOn();
105 : };
106 :
107 : struct TimelineTheme {
108 : QColor backgroundColor, labelsColor1, labelsColor2, labelsColor3, gridColor1, gridColor2;
109 : QColor measureMetaColor, selectionColor, nonVisiblePenColor, nonVisibleBrushColor, colorBoxColor;
110 : QColor metaValuePenColor, metaValueBrushColor;
111 : };
112 :
113 : class Timeline : public QGraphicsView, public muse::Contextable, public muse::async::Asyncable
114 : {
115 : Q_OBJECT
116 :
117 : muse::GlobalInject<muse::ui::IUiConfiguration> uiConfiguration;
118 : muse::ContextInject<muse::rcommand::ICommandDispatcher> commandDispatcher = { this };
119 : muse::ContextInject<playback::IPlaybackController> playbackController = { this };
120 :
121 : public:
122 : enum class ItemType {
123 : TYPE_UNKNOWN = 0,
124 : TYPE_MEASURE,
125 : TYPE_META,
126 : };
127 0 : Q_ENUM(ItemType)
128 :
129 : Timeline(QSplitter* splitter, const muse::modularity::ContextPtr& iocCtx);
130 :
131 : bool handleEvent(QEvent* event);
132 :
133 0 : void updateGridView() { updateGrid(-1, -1); }
134 : void updateGridFromCmdState();
135 : void setNotation(INotationPtr notation);
136 :
137 : TRowLabels* labelsColumn() const;
138 :
139 : private:
140 : friend class TRowLabels;
141 :
142 : enum class ViewState {
143 : NORMAL,
144 : LASSO,
145 : DRAG
146 : };
147 :
148 : ViewState state = ViewState::NORMAL;
149 :
150 : static constexpr int keyItemType = 15;
151 :
152 : int _gridWidth = 20;
153 : int _gridHeight = 20;
154 : int _maxZoom = 50;
155 : int _minZoom = 5;
156 : int _spacing = 5;
157 :
158 : TimelineTheme _lightTheme, _darkTheme;
159 :
160 : std::tuple<int, qreal, engraving::EngravingItem*, engraving::EngravingItem*, bool> _repeatInfo;
161 : std::tuple<QGraphicsItem*, int, QColor> _oldHoverInfo;
162 :
163 : std::map<engraving::BarLineType, QPixmap*> _barlines;
164 : bool _isBarline { false };
165 :
166 : QSplitter* _splitter { nullptr };
167 : TRowLabels* _rowNames { nullptr };
168 :
169 : INotationPtr m_notation;
170 :
171 : int gridRows = 0;
172 : int gridCols = 0;
173 :
174 : QGraphicsPathItem* nonVisiblePathItem = nullptr;
175 : QGraphicsPathItem* visiblePathItem = nullptr;
176 : QGraphicsPathItem* selectionItem = nullptr;
177 :
178 : QGraphicsRectItem* _selectionBox { nullptr };
179 : std::vector<std::pair<QGraphicsItem*, int> > _metaRows;
180 :
181 : QPainterPath _selectionPath;
182 : QRectF _oldSelectionRect;
183 : bool _mousePressed { false };
184 : QPoint _oldLoc;
185 :
186 : bool _collapsedMeta { false };
187 :
188 : std::vector<std::tuple<QString, void (Timeline::*)(engraving::Segment*, int*, int), bool> > _metas;
189 : void tempoMeta(engraving::Segment* seg, int* stagger, int pos);
190 : void timeMeta(engraving::Segment* seg, int* stagger, int pos);
191 : void measureMeta(engraving::Segment*, int*, int pos);
192 : void rehearsalMeta(engraving::Segment* seg, int* stagger, int pos);
193 : void keyMeta(engraving::Segment* seg, int* stagger, int pos);
194 : void barlineMeta(engraving::Segment* seg, int* stagger, int pos);
195 : void jumpMarkerMeta(engraving::Segment* seg, int* stagger, int pos);
196 :
197 : bool addMetaValue(int x, int pos, QString metaText, int row, engraving::ElementType elementType, engraving::EngravingItem* element,
198 0 : engraving::Segment* seg, engraving::Measure* measure, QString tooltip = "");
199 : void setMetaData(QGraphicsItem* gi, int staff, engraving::ElementType et, engraving::Measure* m, bool full_measure,
200 : engraving::EngravingItem* e, QGraphicsItem* pairItem = nullptr, engraving::Segment* seg = nullptr);
201 : unsigned getMetaRow(QString targetText);
202 :
203 : int _globalMeasureNumber { 0 };
204 : int _globalZValue { 0 };
205 :
206 : // True if meta value was last clicked
207 : bool _metaValue = false;
208 :
209 : void mousePressEvent(QMouseEvent* event) override;
210 : void mouseMoveEvent(QMouseEvent* event) override;
211 : void mouseReleaseEvent(QMouseEvent*) override;
212 : void wheelEvent(QWheelEvent* event) override;
213 : void leaveEvent(QEvent*) override;
214 : void showEvent(QShowEvent*) override;
215 : void changeEvent(QEvent*) override;
216 :
217 : unsigned correctMetaRow(unsigned row);
218 : engraving::staff_idx_t correctStave(engraving::staff_idx_t stave);
219 :
220 : QList<engraving::Part*> getParts();
221 :
222 0 : QRectF getMeasureRect(int measureIndex, int row, int numMetas)
223 : {
224 0 : return QRectF(measureIndex * _gridWidth, _gridHeight * (row + numMetas) + 3, _gridWidth, _gridHeight);
225 : }
226 :
227 : void clearScene();
228 :
229 : void updateGrid(int startMeasure = -1, int endMeasure = -1);
230 :
231 : INotationInteractionPtr interaction() const;
232 : engraving::Score* score() const;
233 :
234 : private slots:
235 : void handleScroll(int value);
236 :
237 : void changeSelection(engraving::SelState);
238 : void mouseOver(QPointF pos);
239 : void swapMeta(unsigned row, bool switchUp);
240 : void requestInstrumentDialog();
241 : void toggleMetaRow();
242 : void updateTimelineTheme();
243 :
244 : void contextMenuEvent(QContextMenuEvent* event) override;
245 :
246 : signals:
247 : void moved(QPointF);
248 :
249 : private:
250 : int correctPart(engraving::staff_idx_t stave);
251 :
252 : void updateView();
253 : void drawSelection();
254 : void drawGrid(int globalRows, int globalCols, int startMeasure = 0, int endMeasure = -1);
255 :
256 : int nstaves() const;
257 :
258 : int getWidth() const;
259 : int getHeight() const;
260 : const TimelineTheme& activeTheme() const;
261 :
262 0 : void updateGridFull() { updateGrid(0, -1); }
263 :
264 : QColor colorBox(QGraphicsRectItem* item);
265 :
266 : std::vector<std::pair<QString, bool> > getLabels();
267 :
268 : unsigned nmetas() const;
269 :
270 0 : bool collapsed() const { return _collapsedMeta; }
271 0 : void setCollapsed(bool st) { _collapsedMeta = st; }
272 :
273 : engraving::Staff* numToStaff(int staff);
274 : void toggleShow(int staff);
275 : QString cursorIsOn(const QPoint& cursorPos);
276 :
277 : void seekSelection();
278 : };
279 : }
|