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 : #include "noteinputbarmodel.h"
23 :
24 : #include "rcommand/commandtypes.h"
25 : #include "types/translatablestring.h"
26 :
27 : #include "notation/inotationelements.h" // IWYU pragma: keep
28 : #include "notation/inotationinteraction.h"
29 : #include "notation/inotationnoteinput.h"
30 : #include "notation/inotationselection.h"
31 : #include "notation/inotationundostack.h"
32 :
33 : #include "notationcommands.h"
34 :
35 : using namespace mu;
36 : using namespace mu::notation;
37 : using namespace muse;
38 : using namespace muse::ui;
39 : using namespace muse::uicomponents;
40 :
41 : static const QString TOOLBAR_NAME("noteInput");
42 :
43 : const std::string NoteInputBarModel::CROSS_STAFF_BEAMING_SUBITEMS("cross-staff-beaming-subitems");
44 : const std::string NoteInputBarModel::TUPLET_SUBITEMS("tuplets-subitems");
45 :
46 0 : NoteInputBarModel::NoteInputBarModel(QObject* parent)
47 0 : : AbstractMenuModel(parent)
48 : {
49 0 : }
50 :
51 0 : QVariant NoteInputBarModel::data(const QModelIndex& index, int role) const
52 : {
53 0 : int row = index.row();
54 0 : if (!isIndexValid(row)) {
55 0 : return QVariant();
56 : }
57 :
58 0 : const MenuItem* item = items().at(row);
59 0 : switch (role) {
60 0 : case OrderRole: return row;
61 0 : case SectionRole: return item->section();
62 : }
63 :
64 0 : return AbstractMenuModel::data(index, role);
65 : }
66 :
67 0 : QHash<int, QByteArray> NoteInputBarModel::roleNames() const
68 : {
69 0 : QHash<int, QByteArray> roles = AbstractMenuModel::roleNames();
70 0 : roles[OrderRole] = "order";
71 0 : roles[SectionRole] = "section";
72 :
73 0 : return roles;
74 0 : }
75 :
76 0 : void NoteInputBarModel::classBegin()
77 : {
78 0 : init();
79 0 : }
80 :
81 0 : void NoteInputBarModel::init()
82 : {
83 0 : subscribeOnChanges();
84 :
85 0 : uiState()->toolConfigChanged(TOOLBAR_NAME).onNotify(this, [this]() {
86 0 : load();
87 0 : });
88 :
89 0 : commandsController()->isNoteInputAllowedChanged().onReceive(this, [this](bool) {
90 0 : emit isInputAllowedChanged();
91 0 : });
92 :
93 0 : load();
94 0 : }
95 :
96 0 : const muse::ui::ToolConfig& NoteInputBarModel::defaultNoteInputConfig()
97 : {
98 0 : static ToolConfig config;
99 0 : if (!config.isValid()) {
100 0 : config.items = {
101 : { TOGGLE_NOTE_INPUT_BY_NOTE_NAME_COMMAND, true },
102 : { TOGGLE_NOTE_INPUT_BY_DURATION_COMMAND, true },
103 : { TOGGLE_NOTE_INPUT_RHYTHM_COMMAND, false },
104 : { TOGGLE_NOTE_INPUT_REPITCH_COMMAND, false },
105 : { TOGGLE_NOTE_INPUT_REALTIME_AUTO_COMMAND, false },
106 : { TOGGLE_NOTE_INPUT_REALTIME_MANUAL_COMMAND, false },
107 : { TOGGLE_NOTE_INPUT_TIMEWISE_COMMAND, false },
108 : { ToolConfig::____________, true },
109 : { SET_DURATION_1024TH_COMMAND, false },
110 : { SET_DURATION_512TH_COMMAND, false },
111 : { SET_DURATION_256TH_COMMAND, false },
112 : { SET_DURATION_128TH_COMMAND, false },
113 : { SET_DURATION_64TH_COMMAND, true },
114 : { SET_DURATION_32ND_COMMAND, true },
115 : { SET_DURATION_16TH_COMMAND, true },
116 : { SET_DURATION_EIGHTH_COMMAND, true },
117 : { SET_DURATION_QUARTER_COMMAND, true },
118 : { SET_DURATION_HALF_COMMAND, true },
119 : { SET_DURATION_WHOLE_COMMAND, true },
120 : { SET_DURATION_BREVE_COMMAND, false },
121 : { SET_DURATION_LONGA_COMMAND, false },
122 : { ToolConfig::____________, true },
123 : { TOGGLE_DOT_COMMAND, true },
124 : { TOGGLE_DOT2_COMMAND, false },
125 : { TOGGLE_DOT3_COMMAND, false },
126 : { TOGGLE_DOT4_COMMAND, false },
127 : { TOGGLE_REST_COMMAND, true },
128 : { ToolConfig::____________, true },
129 : { TOGGLE_FLAT2_COMMAND, true },
130 : { TOGGLE_FLAT_COMMAND, true },
131 : { TOGGLE_NAT_COMMAND, true },
132 : { TOGGLE_SHARP_COMMAND, true },
133 : { TOGGLE_SHARP2_COMMAND, true },
134 : { ToolConfig::____________, true },
135 : { TOGGLE_TIE_COMMAND, true },
136 : { ADD_SLUR_COMMAND, true },
137 : { TOGGLE_LV_COMMAND, false },
138 : { ToolConfig::____________, true },
139 : { TOGGLE_MARCATO_COMMAND, true },
140 : { TOGGLE_SFORZATO_COMMAND, true },
141 : { TOGGLE_TENUTO_COMMAND, true },
142 : { TOGGLE_STACCATO_COMMAND, true },
143 : { ToolConfig::____________, true },
144 : { CROSS_STAFF_BEAMING_SUBITEMS, true }, // service
145 : { TUPLET_SUBITEMS, true }, // service
146 : { FlipCommand::id, true },
147 : { ToolConfig::____________, true },
148 : { USE_VOICE_1_COMMAND, true },
149 : { USE_VOICE_2_COMMAND, true },
150 : { USE_VOICE_3_COMMAND, false },
151 : { USE_VOICE_4_COMMAND, false }
152 0 : };
153 : }
154 0 : return config;
155 0 : }
156 :
157 0 : void NoteInputBarModel::load()
158 : {
159 0 : MenuItemList items;
160 :
161 0 : ToolConfig noteInputConfig = uiState()->toolConfig(TOOLBAR_NAME, NoteInputBarModel::defaultNoteInputConfig());
162 :
163 0 : int section = 0;
164 0 : for (const ToolConfig::Item& citem : noteInputConfig.items) {
165 0 : if (!citem.show) {
166 0 : continue;
167 : }
168 :
169 0 : if (citem.isSeparator()) {
170 0 : section++;
171 0 : continue;
172 : }
173 :
174 0 : if (citem.intent == CROSS_STAFF_BEAMING_SUBITEMS) {
175 0 : MenuItem* item = makeServiceItem(CROSS_STAFF_BEAMING_SUBITEMS, QString::number(section));
176 0 : item->setSubitems(makeCrossStaffBeamingItems());
177 0 : items << item;
178 0 : } else if (citem.intent == TUPLET_SUBITEMS) {
179 0 : MenuItem* item = makeServiceItem(TUPLET_SUBITEMS, QString::number(section));
180 0 : item->setSubitems(makeTupletItems());
181 0 : items << item;
182 : } else {
183 0 : MenuItem* item = makeCommandItem(rcommand::Command(citem.intent), QString::number(section));
184 0 : items << item;
185 : }
186 : }
187 :
188 0 : items << makeAddItem(QString::number(++section));
189 0 : setItems(items);
190 0 : }
191 :
192 0 : bool NoteInputBarModel::isInputAllowed() const
193 : {
194 0 : return commandsController()->isNoteInputAllowed();
195 : }
196 :
197 0 : NoteInputBarModel::ServiceItemInfo NoteInputBarModel::serviceItemInfo(const std::string& intent)
198 : {
199 0 : if (intent == CROSS_STAFF_BEAMING_SUBITEMS) {
200 0 : return { TranslatableString("action", "Cross-staff beaming"), IconCode::Code::CROSS_STAFF_BEAMING };
201 0 : } else if (intent == TUPLET_SUBITEMS) {
202 0 : return { TranslatableString("action", "Tuplet"), IconCode::Code::NOTE_TUPLET };
203 : }
204 0 : return { };
205 0 : }
206 :
207 0 : MenuItem* NoteInputBarModel::makeServiceItem(const std::string& intent, const QString& section)
208 : {
209 0 : const ServiceItemInfo info = serviceItemInfo(intent);
210 0 : MenuItem* item = new MenuItem(this);
211 0 : item->setTitle(info.title);
212 0 : item->setIcon(info.icon);
213 0 : item->setSection(section);
214 0 : return item;
215 0 : }
216 :
217 0 : MenuItem* NoteInputBarModel::makeCommandItem(const muse::rcommand::Command& command, const QString& section)
218 : {
219 0 : const rcommand::CommandInfo info = commandsRegister()->commandInfo(command);
220 0 : MenuItem* item = new MenuItem(info, this);
221 0 : item->setSection(section);
222 0 : return item;
223 0 : }
224 :
225 0 : MenuItem* NoteInputBarModel::makeAddItem(const QString& section)
226 : {
227 0 : MenuItem* item = new MenuItem(this);
228 0 : item->setTitle(TranslatableString("global", "Add"));
229 0 : item->setIcon(IconCode::Code::PLUS);
230 0 : item->setSection(section);
231 0 : item->setSubitems(makeAddItems());
232 0 : return item;
233 : }
234 :
235 0 : MenuItemList NoteInputBarModel::makeCrossStaffBeamingItems()
236 : {
237 : MenuItemList items {
238 0 : makeMenuItem(MOVE_UP_COMMAND),
239 0 : makeMenuItem(MOVE_DOWN_COMMAND)
240 0 : };
241 :
242 0 : return items;
243 : }
244 :
245 0 : MenuItemList NoteInputBarModel::makeTupletItems()
246 : {
247 : MenuItemList items {
248 0 : makeMenuItem(ADD_DUPLET_COMMAND),
249 0 : makeMenuItem(ADD_TRIPLET_COMMAND),
250 0 : makeMenuItem(ADD_QUADRUPLET_COMMAND),
251 0 : makeMenuItem(ADD_QUINTUPLET_COMMAND),
252 0 : makeMenuItem(ADD_SEXTUPLET_COMMAND),
253 0 : makeMenuItem(ADD_SEPTUPLET_COMMAND),
254 0 : makeMenuItem(ADD_OCTUPLET_COMMAND),
255 0 : makeMenuItem(ADD_NONUPLET_COMMAND),
256 0 : makeMenuItem(OPEN_TUPLET_CONFIGURE_COMMAND)
257 0 : };
258 :
259 0 : return items;
260 : }
261 :
262 0 : MenuItemList NoteInputBarModel::makeAddItems()
263 : {
264 : MenuItemList items {
265 0 : makeMenu(TranslatableString("notation", "Notes"), makeNotesItems()),
266 0 : makeMenu(TranslatableString("notation", "Intervals"), makeIntervalsItems()),
267 0 : makeMenu(TranslatableString("notation", "Measures"), makeMeasuresItems()),
268 0 : makeMenu(TranslatableString("notation", "Frames"), makeFramesItems()),
269 0 : makeMenu(TranslatableString("notation", "Text"), makeTextItems()),
270 0 : makeMenu(TranslatableString("notation", "Lines"), makeLinesItems()),
271 0 : makeMenu(TranslatableString("notation", "Chords and fretboard diagrams"), makeChordAndFretboardDiagramsItems()),
272 0 : };
273 :
274 0 : return items;
275 : }
276 :
277 0 : MenuItemList NoteInputBarModel::makeNotesItems()
278 : {
279 : MenuItemList items {
280 0 : makeMenuItem(ENTER_NOTE_C_COMMAND),
281 0 : makeMenuItem(ENTER_NOTE_D_COMMAND),
282 0 : makeMenuItem(ENTER_NOTE_E_COMMAND),
283 0 : makeMenuItem(ENTER_NOTE_F_COMMAND),
284 0 : makeMenuItem(ENTER_NOTE_G_COMMAND),
285 0 : makeMenuItem(ENTER_NOTE_A_COMMAND),
286 0 : makeMenuItem(ENTER_NOTE_B_COMMAND),
287 0 : makeSeparator(),
288 0 : makeMenuItem(ADD_NOTE_C_COMMAND),
289 0 : makeMenuItem(ADD_NOTE_D_COMMAND),
290 0 : makeMenuItem(ADD_NOTE_E_COMMAND),
291 0 : makeMenuItem(ADD_NOTE_F_COMMAND),
292 0 : makeMenuItem(ADD_NOTE_G_COMMAND),
293 0 : makeMenuItem(ADD_NOTE_A_COMMAND),
294 0 : makeMenuItem(ADD_NOTE_B_COMMAND)
295 0 : };
296 :
297 0 : return items;
298 : }
299 :
300 0 : MenuItemList NoteInputBarModel::makeIntervalsItems()
301 : {
302 : MenuItemList items {
303 0 : makeMenuItem(ADD_INTERVAL_PLUS_1_COMMAND),
304 0 : makeMenuItem(ADD_INTERVAL_PLUS_2_COMMAND),
305 0 : makeMenuItem(ADD_INTERVAL_PLUS_3_COMMAND),
306 0 : makeMenuItem(ADD_INTERVAL_PLUS_4_COMMAND),
307 0 : makeMenuItem(ADD_INTERVAL_PLUS_5_COMMAND),
308 0 : makeMenuItem(ADD_INTERVAL_PLUS_6_COMMAND),
309 0 : makeMenuItem(ADD_INTERVAL_PLUS_7_COMMAND),
310 0 : makeMenuItem(ADD_INTERVAL_PLUS_8_COMMAND),
311 0 : makeMenuItem(ADD_INTERVAL_PLUS_9_COMMAND),
312 0 : makeMenuItem(ADD_INTERVAL_PLUS_10_COMMAND),
313 0 : makeSeparator(),
314 0 : makeMenuItem(ADD_INTERVAL_MINUS_2_COMMAND),
315 0 : makeMenuItem(ADD_INTERVAL_MINUS_3_COMMAND),
316 0 : makeMenuItem(ADD_INTERVAL_MINUS_4_COMMAND),
317 0 : makeMenuItem(ADD_INTERVAL_MINUS_5_COMMAND),
318 0 : makeMenuItem(ADD_INTERVAL_MINUS_6_COMMAND),
319 0 : makeMenuItem(ADD_INTERVAL_MINUS_7_COMMAND),
320 0 : makeMenuItem(ADD_INTERVAL_MINUS_8_COMMAND),
321 0 : makeMenuItem(ADD_INTERVAL_MINUS_9_COMMAND),
322 0 : makeMenuItem(ADD_INTERVAL_MINUS_10_COMMAND)
323 0 : };
324 :
325 0 : return items;
326 : }
327 :
328 0 : MenuItemList NoteInputBarModel::makeMeasuresItems()
329 : {
330 : MenuItemList items {
331 0 : makeMenuItem(INSERT_MEASURES_COMMAND),
332 0 : makeMenuItem(APPEND_MEASURES_COMMAND),
333 0 : makeSeparator(),
334 0 : makeMenuItem(INSERT_MEASURES_COMMAND),
335 0 : makeMenuItem(INSERT_MEASURES_AFTER_SELECTION_COMMAND),
336 0 : makeSeparator(),
337 0 : makeMenuItem(INSERT_MEASURES_AT_START_OF_SCORE_COMMAND),
338 0 : makeMenuItem(APPEND_MEASURES_COMMAND)
339 0 : };
340 :
341 0 : return items;
342 : }
343 :
344 0 : MenuItemList NoteInputBarModel::makeFramesItems()
345 : {
346 : MenuItemList items {
347 0 : makeMenuItem(INSERT_HBOX_COMMAND),
348 0 : makeMenuItem(INSERT_VBOX_COMMAND),
349 0 : makeMenuItem(INSERT_TEXTFRAME_COMMAND),
350 0 : makeMenuItem(INSERT_FRETFRAME_COMMAND),
351 0 : makeSeparator(),
352 0 : makeMenu(TranslatableString("notation", "Insert at end of score"), {
353 0 : makeMenuItem(APPEND_HBOX_COMMAND),
354 0 : makeMenuItem(APPEND_VBOX_COMMAND),
355 0 : makeMenuItem(APPEND_TEXTFRAME_COMMAND),
356 0 : makeMenuItem(APPEND_FRETFRAME_COMMAND)
357 : })
358 0 : };
359 :
360 0 : return items;
361 : }
362 :
363 0 : MenuItemList NoteInputBarModel::makeTextItems()
364 : {
365 : MenuItemList items {
366 0 : makeMenuItem(ADD_TITLE_TEXT_COMMAND),
367 0 : makeMenuItem(ADD_SUBTITLE_TEXT_COMMAND),
368 0 : makeMenuItem(ADD_COMPOSER_TEXT_COMMAND),
369 0 : makeMenuItem(ADD_LYRICIST_TEXT_COMMAND),
370 0 : makeMenuItem(ADD_PART_TEXT_COMMAND),
371 0 : makeSeparator(),
372 0 : makeMenuItem(ADD_SYSTEM_TEXT_COMMAND),
373 0 : makeMenuItem(ADD_STAFF_TEXT_COMMAND),
374 0 : makeMenuItem(ADD_DYNAMIC_COMMAND),
375 0 : makeMenuItem(ADD_EXPRESSION_TEXT_COMMAND),
376 0 : makeMenuItem(ADD_REHEARSALMARK_TEXT_COMMAND),
377 0 : makeMenuItem(ADD_INSTRUMENT_CHANGE_TEXT_COMMAND),
378 0 : makeMenuItem(ADD_FINGERING_TEXT_COMMAND),
379 0 : makeSeparator(),
380 0 : makeMenuItem(ADD_STICKING_TEXT_COMMAND),
381 0 : makeMenuItem(ADD_CHORD_TEXT_COMMAND),
382 0 : makeMenuItem(ADD_ROMAN_NUMERAL_TEXT_COMMAND),
383 0 : makeMenuItem(ADD_NASHVILLE_NUMBER_TEXT_COMMAND),
384 0 : makeMenuItem(ADD_LYRICS_COMMAND),
385 0 : makeMenuItem(ADD_FIGURED_BASS_COMMAND),
386 0 : makeMenuItem(ADD_TEMPO_COMMAND)
387 0 : };
388 :
389 0 : return items;
390 : }
391 :
392 0 : MenuItemList NoteInputBarModel::makeLinesItems()
393 : {
394 : MenuItemList items {
395 0 : makeMenuItem(ADD_SLUR_COMMAND),
396 0 : makeMenuItem(ADD_HAIRPIN_COMMAND),
397 0 : makeMenuItem(ADD_HAIRPIN_REVERSE_COMMAND),
398 0 : makeMenuItem(ADD_OTTAVA_8VA_COMMAND),
399 0 : makeMenuItem(ADD_OTTAVA_8VB_COMMAND),
400 0 : makeMenuItem(ADD_NOTELINE_COMMAND)
401 0 : };
402 :
403 0 : return items;
404 : }
405 :
406 0 : MenuItemList NoteInputBarModel::makeChordAndFretboardDiagramsItems()
407 : {
408 : MenuItemList items {
409 0 : makeMenuItem(ADD_CHORD_TEXT_COMMAND),
410 0 : makeMenuItem(ADD_FRETBOARD_DIAGRAM_COMMAND),
411 0 : makeSeparator(),
412 0 : makeMenuItem(INSERT_FRETFRAME_COMMAND, TranslatableString("notation", "Fretboard diagram legend"))
413 0 : };
414 :
415 0 : return items;
416 : }
|