Skip to content

Commit e60691c

Browse files
Merge pull request #30340 from mathesoncalum/23492-partial_copy_errors
Fix #23492: Add error message when attempting to copy partial tuplet/tremolo
2 parents 5cf0eed + 051935a commit e60691c

File tree

5 files changed

+57
-32
lines changed

5 files changed

+57
-32
lines changed

src/engraving/dom/mscore.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ std::string MScore::errorToString(MsError err)
104104
case MsError::CANNOT_REMOVE_TIME_TUPLET: return "CANNOT_REMOVE_TIME_TUPLET";
105105
case MsError::CANNOT_REMOVE_TIME_MEASURE_REPEAT: return "CANNOT_REMOVE_TIME_MEASURE_REPEAT";
106106
case MsError::NO_DEST: return "NO_DEST";
107+
case MsError::SOURCE_PARTIAL_TUPLET: return "SOURCE_PARTIAL_TUPLET";
107108
case MsError::DEST_TUPLET: return "DEST_TUPLET";
108109
case MsError::TUPLET_CROSSES_BAR: return "TUPLET_CROSSES_BAR";
109110
case MsError::DEST_LOCAL_TIME_SIGNATURE: return "DEST_LOCAL_TIME_SIGNATURE";
111+
case MsError::SOURCE_PARTIAL_TREMOLO: return "SOURCE_PARTIAL_TREMOLO";
110112
case MsError::DEST_TREMOLO: return "DEST_TREMOLO";
111113
case MsError::NO_MIME: return "NO_MIME";
112114
case MsError::DEST_NO_CR: return "DEST_NO_CR";

src/engraving/dom/mscore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,11 @@ enum class MsError : unsigned char {
151151
CANNOT_REMOVE_TIME_TUPLET,
152152
CANNOT_REMOVE_TIME_MEASURE_REPEAT,
153153
NO_DEST,
154+
SOURCE_PARTIAL_TUPLET,
154155
DEST_TUPLET,
155156
TUPLET_CROSSES_BAR,
156157
DEST_LOCAL_TIME_SIGNATURE,
158+
SOURCE_PARTIAL_TREMOLO,
157159
DEST_TREMOLO,
158160
NO_MIME,
159161
DEST_NO_CR,

src/engraving/dom/select.cpp

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,74 +1375,80 @@ std::vector<Note*> Selection::noteList(track_idx_t selTrack) const
13751375
}
13761376

13771377
//---------------------------------------------------------
1378-
// checkStart
1379-
// return false if element is NOT a tuplet or is start of a tuplet/tremolo
1380-
// return true if element is part of a tuplet/tremolo, but not the start
1378+
// checkStartForPartialCopy
1379+
// return no error if element is NOT a tuplet or is start of a tuplet/tremolo
1380+
// return error if element is part of a tuplet/tremolo, but not the start
13811381
//---------------------------------------------------------
13821382

1383-
static bool checkStart(EngravingItem* e)
1383+
static MsError checkStartForPartialCopy(EngravingItem* e)
13841384
{
13851385
if (!e || !e->isChordRest()) {
1386-
return false;
1386+
return MsError::MS_NO_ERROR;
13871387
}
1388-
ChordRest* cr = toChordRest(e);
1389-
bool rv = false;
1388+
1389+
const ChordRest* cr = toChordRest(e);
13901390
if (cr->tuplet()) {
13911391
// check that complete tuplet is selected, all the way up to top level
13921392
Tuplet* tuplet = cr->tuplet();
13931393
while (tuplet) {
13941394
if (tuplet->elements().front() != e) {
1395-
return true;
1395+
return MsError::SOURCE_PARTIAL_TUPLET;
13961396
}
13971397
e = tuplet;
13981398
tuplet = tuplet->tuplet();
13991399
}
1400-
} else if (cr->isChord()) {
1401-
rv = false;
1402-
Chord* chord = toChord(cr);
1403-
if (chord->tremoloTwoChord()) {
1404-
rv = chord->tremoloTwoChord()->chord2() == chord;
1400+
}
1401+
1402+
if (cr->isChord()) {
1403+
const Chord* chord = toChord(cr);
1404+
const TremoloTwoChord* ttc = chord ? chord->tremoloTwoChord() : nullptr;
1405+
if (ttc && ttc->chord2() == chord) {
1406+
return MsError::SOURCE_PARTIAL_TREMOLO;
14051407
}
14061408
}
1407-
return rv;
1409+
1410+
return MsError::MS_NO_ERROR;
14081411
}
14091412

14101413
//---------------------------------------------------------
1411-
// checkEnd
1412-
// return false if element is NOT a tuplet or is end of a tuplet
1413-
// return true if element is part of a tuplet, but not the end
1414+
// checkEndForPartialCopy
1415+
// return no error if element is NOT a tuplet or is end of a tuplet/tremolo
1416+
// return error if element is part of a tuplet/tremolo, but not the end
14141417
//---------------------------------------------------------
14151418

1416-
static bool checkEnd(EngravingItem* e, const Fraction& endTick)
1419+
static MsError checkEndForPartialCopy(EngravingItem* e, const Fraction& endTick)
14171420
{
14181421
if (!e || !e->isChordRest()) {
1419-
return false;
1422+
return MsError::MS_NO_ERROR;
14201423
}
1421-
ChordRest* cr = toChordRest(e);
1422-
bool rv = false;
1424+
1425+
const ChordRest* cr = toChordRest(e);
14231426
if (cr->tuplet()) {
14241427
// check that complete tuplet is selected, all the way up to top level
14251428
Tuplet* tuplet = cr->tuplet();
14261429
while (tuplet) {
14271430
if (tuplet->elements().back() != e) {
1428-
return true;
1431+
return MsError::SOURCE_PARTIAL_TUPLET;
14291432
}
14301433
e = tuplet;
14311434
tuplet = tuplet->tuplet();
14321435
}
14331436
// also check that the selection extends to the end of the top-level tuplet
14341437
tuplet = toTuplet(e);
14351438
if (tuplet->endTick() > endTick) {
1436-
return true;
1439+
return MsError::SOURCE_PARTIAL_TUPLET;
14371440
}
1438-
} else if (cr->isChord()) {
1439-
rv = false;
1440-
Chord* chord = toChord(cr);
1441-
if (chord->tremoloTwoChord()) {
1442-
rv = chord->tremoloTwoChord()->chord1() == chord;
1441+
}
1442+
1443+
if (cr->isChord()) {
1444+
const Chord* chord = toChord(cr);
1445+
const TremoloTwoChord* ttc = chord ? chord->tremoloTwoChord() : nullptr;
1446+
if (ttc && ttc->chord1() == chord) {
1447+
return MsError::SOURCE_PARTIAL_TREMOLO;
14431448
}
14441449
}
1445-
return rv;
1450+
1451+
return MsError::MS_NO_ERROR;
14461452
}
14471453

14481454
//---------------------------------------------------------
@@ -1469,8 +1475,12 @@ bool Selection::canCopy() const
14691475

14701476
// check first cr in track within selection
14711477
ChordRest* check = m_startSegment->nextChordRest(track);
1472-
if (check && check->tick() < endTick && checkStart(check)) {
1473-
return false;
1478+
if (check && check->tick() < endTick) {
1479+
const MsError err = checkStartForPartialCopy(check);
1480+
if (err != MsError::MS_NO_ERROR) {
1481+
MScore::setError(err);
1482+
return false;
1483+
}
14741484
}
14751485

14761486
if (!m_endSegment) {
@@ -1486,7 +1496,9 @@ bool Selection::canCopy() const
14861496
endSegmentSelection = endSegmentSelection->nextCR(track);
14871497
}
14881498

1489-
if (checkEnd(endSegmentSelection->element(track), endTick)) {
1499+
const MsError err = checkEndForPartialCopy(endSegmentSelection->element(track), endTick);
1500+
if (err != MsError::MS_NO_ERROR) {
1501+
MScore::setError(err);
14901502
return false;
14911503
}
14921504
}

src/notation/internal/mscoreerrorscontroller.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ void MScoreErrorsController::checkAndShowMScoreError()
116116
case MsError::NO_DEST:
117117
title = muse::trc("notation", "No destination to paste");
118118
break;
119+
case MsError::SOURCE_PARTIAL_TUPLET:
120+
title = muse::trc("notation", "This selection cannot be copied");
121+
message = muse::trc("notation", "Please select all notes that are part of this tuplet and try again.");
122+
break;
119123
case MsError::DEST_TUPLET:
120124
title = muse::trc("notation", "Cannot paste into tuplet");
121125
break;
@@ -125,6 +129,10 @@ void MScoreErrorsController::checkAndShowMScoreError()
125129
case MsError::DEST_LOCAL_TIME_SIGNATURE:
126130
title = muse::trc("notation", "Cannot paste in local time signature");
127131
break;
132+
case MsError::SOURCE_PARTIAL_TREMOLO:
133+
title = muse::trc("notation", "This selection cannot be copied");
134+
message = muse::trc("notation", "Please select all notes that are part of this tremolo and try again.");
135+
break;
128136
case MsError::DEST_TREMOLO:
129137
title = muse::trc("notation", "Cannot paste in tremolo");
130138
break;

src/notation/internal/notationinteraction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5076,6 +5076,7 @@ void NotationInteraction::addBoxes(BoxType boxType, int count, int beforeBoxInde
50765076
void NotationInteraction::copySelection()
50775077
{
50785078
if (!selection()->canCopy()) {
5079+
MScoreErrorsController(iocContext()).checkAndShowMScoreError();
50795080
return;
50805081
}
50815082

0 commit comments

Comments
 (0)