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 : #include <memory>
24 :
25 : #include "palettecompat.h"
26 :
27 : #include "engraving/dom/textline.h"
28 : #include "engraving/rw/compat/compatutils.h"
29 :
30 : #include "engraving/dom/actionicon.h"
31 : #include "engraving/dom/arpeggio.h"
32 : #include "engraving/dom/articulation.h"
33 : #include "engraving/dom/bracket.h"
34 : #include "engraving/dom/bracketitem.h"
35 : #include "engraving/dom/chordbracket.h"
36 : #include "engraving/dom/chordrest.h"
37 : #include "engraving/dom/engravingitem.h"
38 : #include "engraving/dom/expression.h"
39 : #include "engraving/dom/factory.h"
40 : #include "engraving/dom/fret.h"
41 : #include "engraving/dom/hammeronpulloff.h"
42 : #include "engraving/dom/harmony.h"
43 : #include "engraving/dom/hairpin.h"
44 : #include "engraving/dom/instrchange.h"
45 : #include "engraving/dom/ornament.h"
46 : #include "engraving/dom/measure.h"
47 : #include "engraving/dom/part.h"
48 : #include "engraving/dom/pedal.h"
49 : #include "engraving/dom/score.h"
50 : #include "engraving/dom/stafftext.h"
51 : #include "engraving/dom/stringtunings.h"
52 : #include "engraving/dom/capo.h"
53 : #include "engraving/dom/marker.h"
54 : #include "engraving/dom/tapping.h"
55 : #include "engraving/dom/whammybar.h"
56 : #include "engraving/editing/editstaffbrackets.h"
57 : #include "engraving/types/symid.h"
58 : #include "engraving/types/typesconv.h"
59 : #include "engraving/dom/layoutbreak.h"
60 :
61 : #include "palette.h"
62 : #include "palettecell.h"
63 :
64 : using namespace mu::palette;
65 : using namespace mu::engraving;
66 :
67 : static const qreal COMPAT_FRAME_MAG = 1.25;
68 :
69 : static const std::unordered_set<ActionIconType> BENDS_ACTION_TYPES = {
70 : ActionIconType::STANDARD_BEND,
71 : ActionIconType::PRE_BEND,
72 : ActionIconType::GRACE_NOTE_BEND,
73 : ActionIconType::SLIGHT_BEND,
74 : };
75 :
76 : static const std::unordered_set<ActionIconType> DIVES_ACTION_TYPES = {
77 : ActionIconType::DIVE,
78 : ActionIconType::PRE_DIVE,
79 : ActionIconType::DIP,
80 : ActionIconType::SCOOP,
81 : };
82 :
83 : static const std::unordered_set<ActionIconType> BOXES_ACTION_TYPES = {
84 : ActionIconType::VFRAME,
85 : ActionIconType::HFRAME,
86 : ActionIconType::TFRAME,
87 : ActionIconType::FFRAME
88 : };
89 :
90 : static const std::unordered_map<String, String> FRET_DIAGRAMS_MIGRATION_MAP = {
91 : { u"X[3-O][2-O]O[1-O]O", u"C" },
92 : { u"X-[5-O][5-O][4-O]-;B3[1-5]", u"Cm" },
93 : { u"X[3-O][2-O][3-O][1-O]O", u"C7" },
94 :
95 : { u"XXO[2-O][3-O][2-O]", u"D" },
96 : { u"XXO[2-O][3-O][1-O]", u"Dm" },
97 : { u"XXO[2-O][1-O][2-O]", u"D7" },
98 :
99 : { u"O[2-O][2-O][1-O]OO", u"E" },
100 : { u"O[2-O][2-O]OOO", u"Em" },
101 : { u"O[2-O]O[1-O]OO", u"E7" },
102 :
103 : { u"-[3-O][3-O][2-O]--;B1[0-5]", u"F" },
104 : { u"-[3-O][3-O]---;B1[0-5]", u"Fm" },
105 : { u"-[3-O]-[2-O]--;B1[0-5]", u"F7" },
106 :
107 : { u"[3-O][2-O]OOO[3-O]", u"G" },
108 : { u"-[5-O][5-O]---;B3[0-5]", u"Gm" },
109 : { u"[3-O][2-O]OOO[1-O]", u"G7" },
110 :
111 : { u"XO[2-O][2-O][2-O]O", u"A" },
112 : { u"XO[2-O][2-O][1-O]O", u"Am" },
113 : { u"XO[2-O]O[2-O]O", u"A7" },
114 :
115 : { u"X-[4-O][4-O][4-O]-;B2[1-5]", u"B" },
116 : { u"X-[4-O][4-O][3-O]-;B2[1-5]", u"Bm" },
117 : { u"X[2-O][1-O][2-O]O[2-O]", u"B7" }
118 : };
119 :
120 0 : void PaletteCompat::migrateOldPaletteCellIfNeeded(PaletteCell* cell, Score* paletteScore)
121 : {
122 0 : EngravingItem* item = cell->element.get();
123 :
124 0 : if (item->isArticulation()) {
125 0 : const std::set<SymId>& ornamentIds = compat::CompatUtils::ORNAMENT_IDS;
126 0 : bool isOldOrnament = ornamentIds.find(toArticulation(item)->symId()) != ornamentIds.end();
127 :
128 0 : if (!isOldOrnament) {
129 0 : return;
130 : }
131 :
132 0 : Articulation* oldOrnament = toArticulation(item);
133 0 : Ornament* newOrnament = Factory::createOrnament((ChordRest*)(paletteScore->dummy()));
134 0 : newOrnament->setSymId(oldOrnament->symId());
135 0 : cell->element.reset(newOrnament);
136 0 : return;
137 : }
138 :
139 0 : if (item->isStaffText() && toStaffText(item)->textStyleType() == TextStyleType::EXPRESSION) {
140 0 : StaffText* oldExpression = toStaffText(item);
141 0 : Expression* newExpression = Factory::createExpression(paletteScore->dummy());
142 0 : if (oldExpression->xmlText() == "Expression") {
143 0 : newExpression->setXmlText("expression");
144 : } else {
145 0 : newExpression->setXmlText(oldExpression->xmlText());
146 : }
147 0 : cell->element.reset(newExpression);
148 0 : return;
149 : }
150 :
151 0 : if (item->isPedal() && !toPedal(item)->segmentsEmpty()) {
152 0 : Pedal* newPedal = Factory::createPedal(paletteScore->dummy());
153 0 : Pedal* oldPedal = toPedal(item);
154 :
155 0 : newPedal->setLineVisible(oldPedal->lineVisible());
156 0 : newPedal->setBeginHookType(oldPedal->beginHookType());
157 0 : newPedal->setEndHookType(oldPedal->endHookType());
158 :
159 0 : newPedal->setBeginText(newPedal->propertyDefault(Pid::BEGIN_TEXT).value<String>());
160 0 : newPedal->setContinueText(newPedal->propertyDefault(Pid::CONTINUE_TEXT).value<String>());
161 0 : newPedal->setEndText(newPedal->propertyDefault(Pid::END_TEXT).value<String>());
162 :
163 0 : cell->element.reset(newPedal);
164 0 : return;
165 : }
166 :
167 0 : if (item->isMarker() && paletteScore->mscVersion() < 470) {
168 0 : Marker* marker = toMarker(item);
169 :
170 0 : if (marker->markerType() == MarkerType::TOCODASYM) {
171 0 : return;
172 : }
173 :
174 0 : Marker* newMarker = marker->clone();
175 :
176 0 : std::string label = newMarker->label().toStdString();
177 0 : MarkerType mt = TConv::fromXml(label, MarkerType::USER);
178 0 : newMarker->setMarkerType(mt);
179 :
180 0 : cell->element.reset(newMarker);
181 0 : return;
182 0 : }
183 :
184 0 : if (item->isFretDiagram()) {
185 0 : FretDiagram* oldFretDiagram = toFretDiagram(item);
186 0 : String oldFretDiagramPattern = oldFretDiagram->patternFromDiagram();
187 0 : std::vector<String> oldFretDiagramPatternHarmonies = oldFretDiagram->harmoniesFromPattern(oldFretDiagramPattern);
188 :
189 0 : String harmonyName = muse::value(FRET_DIAGRAMS_MIGRATION_MAP, oldFretDiagramPattern);
190 0 : if (harmonyName.empty() || muse::contains(oldFretDiagramPatternHarmonies, harmonyName)) {
191 0 : return;
192 : }
193 :
194 0 : FretDiagram* newFretDiagram = Factory::createFretDiagram(paletteScore->dummy());
195 :
196 0 : if (harmonyName.empty()) {
197 0 : newFretDiagram->clear();
198 : } else {
199 0 : newFretDiagram->setHarmony(harmonyName);
200 0 : newFretDiagram->updateDiagram(harmonyName);
201 : }
202 :
203 0 : cell->element.reset(newFretDiagram);
204 0 : return;
205 0 : }
206 :
207 0 : if (item->isActionIcon() && muse::contains(BOXES_ACTION_TYPES, toActionIcon(item)->actionType())) {
208 0 : cell->mag = COMPAT_FRAME_MAG;
209 : }
210 :
211 0 : if (item->isInstrumentChange()) {
212 0 : InstrumentChange* newInstrumentChange = Factory::createInstrumentChange(paletteScore->dummy());
213 0 : newInstrumentChange->setXmlText(QT_TRANSLATE_NOOP("palette", "Change instr."));
214 :
215 0 : cell->element.reset(newInstrumentChange);
216 0 : return;
217 : }
218 : }
219 :
220 0 : void PaletteCompat::addNewItemsIfNeeded(Palette& palette, Score* paletteScore)
221 : {
222 0 : if (palette.type() == Palette::Type::Guitar) {
223 0 : addNewGuitarItems(palette, paletteScore);
224 0 : return;
225 : }
226 :
227 0 : if (palette.type() == Palette::Type::Bracket) {
228 0 : addNewBracketItems(palette, paletteScore);
229 0 : return;
230 : }
231 :
232 0 : if (palette.type() == Palette::Type::Line) {
233 0 : addNewLineItems(palette, paletteScore);
234 0 : return;
235 : }
236 :
237 0 : if (palette.type() == Palette::Type::FretboardDiagram) {
238 0 : addNewFretboardDiagramItems(palette, paletteScore);
239 0 : return;
240 : }
241 :
242 0 : if (palette.type() == Palette::Type::Repeat) {
243 0 : addNewRepeatItems(palette, paletteScore);
244 0 : return;
245 : }
246 :
247 0 : if (palette.type() == Palette::Type::Layout) {
248 0 : addNewLayoutItems(palette, paletteScore);
249 0 : return;
250 : }
251 :
252 0 : if (palette.type() == Palette::Type::Keyboard) {
253 0 : addNewKeyboardItems(palette, paletteScore);
254 0 : return;
255 : }
256 : }
257 :
258 0 : void PaletteCompat::removeOldItemsIfNeeded(Palette& palette)
259 : {
260 0 : if (palette.type() == Palette::Type::Articulation
261 0 : || palette.type() == Palette::Type::Guitar
262 0 : || palette.type() == Palette::Type::Arpeggio
263 0 : || palette.type() == Palette::Type::Line) {
264 0 : removeOldItems(palette);
265 : }
266 0 : }
267 :
268 0 : void PaletteCompat::addNewGuitarItems(Palette& guitarPalette, Score* paletteScore)
269 : {
270 0 : bool containsCapo = false;
271 0 : bool containsStringTunings = false;
272 0 : bool containsGuitarBends = false;
273 0 : bool containsFFrame = false;
274 0 : bool containsTapping = false;
275 0 : bool containsHammerOnPullOff = false;
276 0 : bool containsGuitarDives = false;
277 0 : bool containsWhammyBar = false;
278 :
279 0 : for (const PaletteCellPtr& cell : guitarPalette.cells()) {
280 0 : const ElementPtr element = cell->element;
281 0 : if (!element) {
282 0 : continue;
283 : }
284 :
285 0 : if (element->isCapo()) {
286 0 : containsCapo = true;
287 0 : } else if (element->isStringTunings()) {
288 0 : containsStringTunings = true;
289 0 : } else if (element->isActionIcon()) {
290 0 : const ActionIcon* icon = toActionIcon(element.get());
291 0 : if (muse::contains(BENDS_ACTION_TYPES, icon->actionType())) {
292 0 : containsGuitarBends = true;
293 : }
294 0 : if (muse::contains(DIVES_ACTION_TYPES, icon->actionType())) {
295 0 : containsGuitarDives = true;
296 : }
297 0 : if (icon->actionType() == ActionIconType::FFRAME) {
298 0 : containsFFrame = true;
299 : }
300 0 : } else if (element->isTapping()) {
301 0 : containsTapping = true;
302 0 : } else if (element->isHammerOnPullOff()) {
303 0 : containsHammerOnPullOff = true;
304 0 : } else if (element->isWhammyBar()) {
305 0 : containsWhammyBar = true;
306 : }
307 0 : }
308 :
309 0 : if (!containsWhammyBar) {
310 0 : auto whammyBar = Factory::makeWhammyBar(paletteScore->dummy());
311 0 : int defaultPosition = std::min(3, guitarPalette.cellsCount());
312 0 : guitarPalette.insertElement(defaultPosition, whammyBar, QT_TRANSLATE_NOOP("palette", "Whammy bar"),
313 0 : 0.8)->setElementTranslated(true);
314 0 : }
315 :
316 0 : if (!containsGuitarDives) {
317 0 : int defaultPosition = std::min(6, guitarPalette.cellsCount());
318 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::SCOOP, 1.5);
319 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::DIP, 1.4);
320 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::PRE_DIVE, 1.5);
321 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::DIVE, 1.5);
322 : }
323 :
324 0 : if (!containsGuitarBends) {
325 0 : int defaultPosition = std::min(10, guitarPalette.cellsCount());
326 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::SLIGHT_BEND, 1.5);
327 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::GRACE_NOTE_BEND, 1.4);
328 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::PRE_BEND, 1.5);
329 0 : guitarPalette.insertActionIcon(defaultPosition, ActionIconType::STANDARD_BEND, 1.5);
330 : }
331 :
332 0 : if (!containsTapping) {
333 0 : int defaultPosition = std::min(30, guitarPalette.cellsCount());
334 0 : auto lhTapping = Factory::makeTapping(paletteScore->dummy());
335 0 : lhTapping->setHand(TappingHand::LEFT);
336 0 : guitarPalette.insertElement(defaultPosition, lhTapping, QT_TRANSLATE_NOOP("palette", "Left-hand tapping"), 1.0);
337 :
338 0 : auto rhTapping = Factory::makeTapping(paletteScore->dummy());
339 0 : rhTapping->setHand(TappingHand::RIGHT);
340 0 : guitarPalette.insertElement(defaultPosition + 1, rhTapping, QT_TRANSLATE_NOOP("palette", "Right-hand tapping"), 1.0);
341 0 : }
342 :
343 0 : if (!containsHammerOnPullOff) {
344 0 : int defaultPosition = std::min(32, guitarPalette.cellsCount());
345 0 : auto hopo = Factory::makeHammerOnPullOff(paletteScore->dummy());
346 0 : guitarPalette.insertElement(defaultPosition, hopo, QT_TRANSLATE_NOOP("palette", "Hammer-on / pull-off"), 0.8);
347 0 : }
348 :
349 0 : if (!containsCapo) {
350 0 : auto capo = Factory::makeCapo(paletteScore->dummy());
351 0 : capo->setXmlText(String::fromAscii(QT_TRANSLATE_NOOP("palette", "Capo")));
352 0 : int defaultPosition = std::min(40, guitarPalette.cellsCount());
353 0 : guitarPalette.insertElement(defaultPosition, capo, QT_TRANSLATE_NOOP("palette", "Capo"), 0.9)->setElementTranslated(true);
354 0 : }
355 :
356 0 : if (!containsStringTunings) {
357 0 : auto stringTunings = Factory::makeStringTunings(paletteScore->dummy());
358 0 : stringTunings->setXmlText(u"<sym>guitarString6</sym> - D");
359 0 : stringTunings->initTextStyleType(TextStyleType::STRING_TUNINGS);
360 0 : int defaultPosition = std::min(41, guitarPalette.cellsCount());
361 0 : guitarPalette.insertElement(defaultPosition, stringTunings, QT_TRANSLATE_NOOP("palette", "String tunings"),
362 0 : 0.9)->setElementTranslated(true);
363 0 : }
364 :
365 0 : if (!containsFFrame) {
366 0 : guitarPalette.appendActionIcon(ActionIconType::FFRAME, COMPAT_FRAME_MAG);
367 : }
368 0 : }
369 :
370 0 : void PaletteCompat::addNewBracketItems(Palette& bracketsPalette, Score* paletteScore)
371 : {
372 0 : bool containsGroupBracket = false;
373 0 : staff_idx_t bracketStaffIdx = muse::nidx;
374 :
375 0 : for (const PaletteCellPtr& cell : bracketsPalette.cells()) {
376 0 : const ElementPtr element = cell->element;
377 0 : if (!element || !element->isBracket()) {
378 0 : continue;
379 : }
380 :
381 0 : BracketItem* bracketItem = toBracket(element.get())->bracketItem();
382 0 : if (bracketStaffIdx == muse::nidx) {
383 0 : bracketStaffIdx = bracketItem->startStaffIdx();
384 : }
385 :
386 0 : if (bracketItem->bracketType() == BracketType::GROUP) {
387 0 : containsGroupBracket = true;
388 : }
389 0 : }
390 :
391 0 : if (containsGroupBracket) {
392 0 : return;
393 : }
394 :
395 0 : if (bracketStaffIdx == muse::nidx) {
396 0 : Part* bracketItemOwnerPart = new Part(paletteScore);
397 0 : Staff* bracketItemOwner = Factory::createStaff(bracketItemOwnerPart);
398 0 : paletteScore->appendStaff(bracketItemOwner);
399 0 : bracketStaffIdx = bracketItemOwner->idx();
400 : }
401 :
402 0 : size_t groupBracketIdx = paletteScore->brackets(bracketStaffIdx).size();
403 0 : EditStaffBrackets::setBracketType(paletteScore, bracketStaffIdx, groupBracketIdx, BracketType::GROUP);
404 0 : BracketItem* groupBracketItem = paletteScore->brackets(bracketStaffIdx)[groupBracketIdx];
405 :
406 0 : auto groupBracket = Factory::makeBracket(paletteScore->dummy());
407 0 : groupBracket->setBracketItem(groupBracketItem);
408 0 : bracketsPalette.appendElement(groupBracket, QT_TRANSLATE_NOOP("palette", "Group bracket"));
409 0 : }
410 :
411 0 : void PaletteCompat::addNewLineItems(Palette& linesPalette, Score* paletteScore)
412 : {
413 0 : bool containsNoteAnchoredLine = false;
414 0 : bool containsLeftArrowHead = false;
415 0 : bool containsRightArrowHead = false;
416 0 : bool containsChordBrackets = false;
417 0 : for (const PaletteCellPtr& cell : linesPalette.cells()) {
418 0 : const ElementPtr element = cell->element;
419 0 : if (!element) {
420 0 : continue;
421 : }
422 :
423 0 : if (element->isActionIcon() && toActionIcon(element.get())->actionType() == ActionIconType::NOTE_ANCHORED_LINE) {
424 0 : containsNoteAnchoredLine = true;
425 : }
426 :
427 0 : if (element->isTextLineBase() && toTextLineBase(element.get())->endHookType() == HookType::ARROW) {
428 0 : containsRightArrowHead = true;
429 : }
430 :
431 0 : if (element->isTextLineBase() && toTextLineBase(element.get())->beginHookType() == HookType::ARROW) {
432 0 : containsLeftArrowHead = true;
433 : }
434 :
435 0 : if (element->isChordBracket()) {
436 0 : containsChordBrackets = true;
437 : }
438 0 : }
439 :
440 0 : if (!containsRightArrowHead) {
441 0 : int defaultPosition = std::min(20, linesPalette.cellsCount());
442 0 : auto rightArrowLine = Factory::makeTextLine(paletteScore->dummy());
443 0 : rightArrowLine->setDiagonal(true);
444 0 : rightArrowLine->setEndHookType(HookType::ARROW);
445 0 : linesPalette.insertElement(defaultPosition, rightArrowLine, QT_TRANSLATE_NOOP("palette", "Line (right arrowhead)"));
446 0 : }
447 :
448 0 : if (!containsLeftArrowHead) {
449 0 : int defaultPosition = std::min(21, linesPalette.cellsCount());
450 0 : auto leftArrowLine = Factory::makeTextLine(paletteScore->dummy());
451 0 : leftArrowLine->setDiagonal(true);
452 0 : leftArrowLine->setBeginHookType(HookType::ARROW);
453 0 : linesPalette.insertElement(defaultPosition, leftArrowLine, QT_TRANSLATE_NOOP("palette", "Line (left arrowhead)"));
454 0 : }
455 :
456 0 : if (!containsNoteAnchoredLine) {
457 0 : int defaultPosition = std::min(22, linesPalette.cellsCount());
458 0 : linesPalette.insertActionIcon(defaultPosition, ActionIconType::NOTE_ANCHORED_LINE, 2);
459 : }
460 :
461 0 : if (!containsChordBrackets) {
462 0 : int defaultPosition = std::min(27, linesPalette.cellsCount());
463 0 : addChordBrackets(linesPalette, paletteScore, defaultPosition);
464 : }
465 0 : }
466 :
467 0 : void PaletteCompat::addNewFretboardDiagramItems(Palette& fretboardDiagramPalette, engraving::Score* paletteScore)
468 : {
469 0 : bool containsBlankItem = false;
470 0 : for (const PaletteCellPtr& cell : fretboardDiagramPalette.cells()) {
471 0 : const ElementPtr element = cell->element;
472 0 : if (!element || !element->isFretDiagram()) {
473 0 : continue;
474 : }
475 :
476 0 : FretDiagram* fretDiagram = toFretDiagram(element.get());
477 0 : if (!fretDiagram->harmony() || fretDiagram->harmony()->harmonyName().empty()) {
478 0 : containsBlankItem = true;
479 0 : break;
480 : }
481 0 : }
482 :
483 0 : if (!containsBlankItem) {
484 0 : auto fret = Factory::makeFretDiagram(paletteScore->dummy());
485 0 : fret->clear();
486 0 : fretboardDiagramPalette.insertElement(0, fret, muse::TranslatableString("palette", "Blank"));
487 0 : }
488 0 : }
489 :
490 0 : void PaletteCompat::addNewRepeatItems(Palette& repeatPalette, engraving::Score* paletteScore)
491 : {
492 0 : bool containsToCodaSym = false;
493 0 : for (const PaletteCellPtr& cell : repeatPalette.cells()) {
494 0 : const ElementPtr element = cell->element;
495 0 : if (!element) {
496 0 : continue;
497 : }
498 :
499 0 : if (element->isMarker() && toMarker(element.get())->markerType() == MarkerType::TOCODASYM) {
500 0 : containsToCodaSym = true;
501 : }
502 0 : }
503 :
504 0 : if (!containsToCodaSym) {
505 0 : auto marker = Factory::makeMarker(paletteScore->dummy());
506 0 : marker->setMarkerType(MarkerType::TOCODASYM);
507 0 : marker->styleChanged();
508 0 : repeatPalette.insertElement(5, marker, TConv::userName(MarkerType::TOCODASYM));
509 0 : }
510 0 : }
511 :
512 0 : void PaletteCompat::addNewLayoutItems(Palette& layoutPalette, engraving::Score* paletteScore)
513 : {
514 0 : bool containsFFrame = false;
515 0 : bool containsLock = false;
516 0 : bool containsNoBreak = false;
517 0 : for (const PaletteCellPtr& cell : layoutPalette.cells()) {
518 0 : const ElementPtr element = cell->element;
519 0 : if (!element) {
520 0 : continue;
521 : }
522 :
523 0 : if (element->isActionIcon() && toActionIcon(element.get())->actionType() == ActionIconType::FFRAME) {
524 0 : containsFFrame = true;
525 : }
526 0 : if (element->isActionIcon() && toActionIcon(element.get())->actionType() == ActionIconType::PAGE_LOCK) {
527 0 : containsLock = true;
528 : }
529 0 : if (element->isLayoutBreak() && toLayoutBreak(element.get())->layoutBreakType() == LayoutBreakType::NOBREAK) {
530 0 : containsNoBreak = true;
531 : }
532 0 : }
533 :
534 0 : if (!containsFFrame) {
535 0 : int defaultPosition = std::min(10, layoutPalette.cellsCount());
536 0 : layoutPalette.insertActionIcon(defaultPosition, ActionIconType::FFRAME, COMPAT_FRAME_MAG);
537 : }
538 :
539 0 : if (!containsNoBreak) {
540 0 : int defaultPosition = std::min(3, layoutPalette.cellsCount());
541 0 : auto lb = Factory::makeLayoutBreak(paletteScore->dummy());
542 0 : lb->setLayoutBreakType(LayoutBreakType::NOBREAK);
543 0 : layoutPalette.insertElement(defaultPosition, lb, TConv::userName(LayoutBreakType::NOBREAK));
544 0 : }
545 :
546 0 : if (!containsLock) {
547 0 : int defaultPosition = std::min(5, layoutPalette.cellsCount());
548 0 : layoutPalette.insertActionIcon(defaultPosition, ActionIconType::PAGE_LOCK);
549 : }
550 0 : }
551 :
552 0 : void PaletteCompat::addNewKeyboardItems(Palette& keyPalette, engraving::Score* paletteScore)
553 : {
554 0 : bool containsChordBrackets = false;
555 0 : for (const PaletteCellPtr& cell : keyPalette.cells()) {
556 0 : if (cell->element && cell->element->isChordBracket()) {
557 0 : containsChordBrackets = true;
558 : }
559 : }
560 :
561 0 : if (!containsChordBrackets) {
562 0 : addChordBrackets(keyPalette, paletteScore);
563 : }
564 0 : }
565 :
566 0 : void PaletteCompat::addChordBrackets(Palette& palette, engraving::Score* paletteScore, size_t position)
567 : {
568 : std::array<QString, 3> names = { QT_TRANSLATE_NOOP("palette", "Chord bracket"),
569 : QT_TRANSLATE_NOOP("palette", "Chord bracket (play with left hand)"),
570 0 : QT_TRANSLATE_NOOP("palette", "Chord bracket (play with right hand)") };
571 0 : for (int i = 0; i < 3; ++i) {
572 0 : DirectionV hookPos = DirectionV(i);
573 0 : auto c = Factory::makeChordBracket(paletteScore->dummy());
574 0 : c->setProperty(Pid::BRACKET_HOOK_POS, hookPos);
575 0 : if (position != muse::nidx) {
576 0 : palette.insertElement(position + i, c, names[i]);
577 : } else {
578 0 : palette.appendElement(c, names[i]);
579 : }
580 0 : }
581 0 : }
582 :
583 0 : void PaletteCompat::removeOldItems(Palette& palette)
584 : {
585 0 : std::vector<PaletteCellPtr> cellsToRemove;
586 :
587 0 : for (const PaletteCellPtr& cell : palette.cells()) {
588 0 : const ElementPtr element = cell->element;
589 0 : if (!element) {
590 0 : continue;
591 : }
592 :
593 0 : if (element->isBend()) {
594 0 : cellsToRemove.emplace_back(cell);
595 : }
596 :
597 0 : if (element->isTremoloBar()) {
598 0 : cellsToRemove.emplace_back(cell);
599 : }
600 :
601 0 : if (element->isArticulation() && toArticulation(element.get())->isLaissezVib()) {
602 0 : cellsToRemove.emplace_back(cell);
603 : }
604 :
605 0 : if (element->isArpeggio() && toArpeggio(element.get())->arpeggioType() == ArpeggioType::BRACKET) {
606 0 : cellsToRemove.emplace_back(cell);
607 : }
608 :
609 0 : if (element->isHairpin() && toHairpin(element.get())->beginText() == u"<sym>dynamicMezzo</sym><sym>dynamicForte</sym>") {
610 0 : cellsToRemove.emplace_back(cell);
611 : }
612 0 : if (element->isCapo()) {
613 0 : cellsToRemove.emplace_back(cell);
614 : }
615 0 : if (element->isStringTunings()) {
616 0 : cellsToRemove.emplace_back(cell);
617 : }
618 0 : }
619 :
620 0 : palette.removeCells(cellsToRemove);
621 0 : }
|