Skip to content

Commit f2eec69

Browse files
authored
Merge pull request #24385 from Jojo-Schmitz/Improvement-DoubleHalfListSelection
Improvements for double/half durations on range and list selection
2 parents 285c3d4 + 1a0109e commit f2eec69

File tree

2 files changed

+64
-36
lines changed

2 files changed

+64
-36
lines changed

src/engraving/editing/cmd.cpp

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939
#include "../dom/barline.h"
4040
#include "../dom/box.h"
4141
#include "../dom/chord.h"
42+
#include "../dom/chordrest.h"
4243
#include "../dom/clef.h"
4344
#include "../dom/drumset.h"
45+
#include "../dom/durationtype.h"
4446
#include "../dom/dynamic.h"
4547
#include "../dom/factory.h"
4648
#include "../dom/glissando.h"
@@ -3303,45 +3305,71 @@ void Score::cmdMirrorNoteHead()
33033305

33043306
void Score::cmdIncDecDuration(int nSteps, bool stepDotted)
33053307
{
3306-
EngravingItem* el = selection().element();
3307-
if (el == 0) {
3308-
return;
3309-
}
3310-
if (el->isNote()) {
3311-
el = el->parentItem();
3312-
}
3313-
if (!el->isChordRest()) {
3314-
return;
3315-
}
3316-
3317-
ChordRest* cr = toChordRest(el);
3308+
if (m_selection.isRange()) {
3309+
if (!m_selection.canCopy()) {
3310+
return;
3311+
}
3312+
ChordRest* firstCR = m_selection.firstChordRest();
3313+
if (firstCR->isGrace()) {
3314+
firstCR = toChordRest(firstCR->parent());
3315+
}
3316+
TDuration initialDuration = firstCR->ticks();
3317+
TDuration d = initialDuration.shiftRetainDots(nSteps, stepDotted);
3318+
if (!d.isValid()) {
3319+
return;
3320+
}
3321+
Fraction scale = d.ticks() / initialDuration.ticks();
3322+
for (ChordRest* cr : getSelectedChordRests()) {
3323+
Fraction newTicks = cr->ticks() * scale;
3324+
if (newTicks < Fraction(1, 1024)
3325+
|| (stepDotted && cr->durationType().dots() != firstCR->durationType().dots()
3326+
&& !cr->isGrace())) {
3327+
return;
3328+
}
3329+
}
3330+
const muse::ByteArray mimeData(m_selection.mimeData());
3331+
XmlReader e(mimeData);
3332+
deleteRange(m_selection.startSegment(), m_selection.endSegment(), staff2track(m_selection.staffStart()),
3333+
staff2track(m_selection.staffEnd()), selectionFilter(), m_selection.rangeContainsMultiNoteChords());
3334+
pasteStaff(e, m_selection.startSegment(), m_selection.staffStart(), scale);
3335+
} else if (m_selection.isList()) {
3336+
const std::set<ChordRest*> crs = getSelectedChordRests();
3337+
for (ChordRest* cr : crs) {
3338+
// if measure rest is selected as input, then the correct initialDuration will be the
3339+
// duration of the measure's time signature, else is just the ChordRest's duration
3340+
TDuration initialDuration = cr->durationType();
3341+
if (initialDuration == DurationType::V_MEASURE) {
3342+
initialDuration = TDuration(cr->measure()->timesig(), true);
3343+
3344+
if (initialDuration.fraction() < cr->measure()->timesig() && nSteps > 0) {
3345+
// Duration already shortened by truncation; shorten one step less
3346+
--nSteps;
3347+
}
3348+
}
33183349

3319-
// if measure rest is selected as input, then the correct initialDuration will be the
3320-
// duration of the measure's time signature, else is just the ChordRest's duration
3321-
TDuration initialDuration = cr->durationType();
3322-
if (initialDuration == DurationType::V_MEASURE) {
3323-
initialDuration = TDuration(cr->measure()->timesig(), true);
3350+
TDuration newDuration { stepDotted ? initialDuration.shiftRetainDots(nSteps, stepDotted) : initialDuration.shift(nSteps) };
3351+
if (!newDuration.isValid()) {
3352+
continue;
3353+
}
33243354

3325-
if (initialDuration.fraction() < cr->measure()->timesig() && nSteps > 0) {
3326-
// Duration already shortened by truncation; shorten one step less
3327-
--nSteps;
3355+
if (cr->isGrace()) {
3356+
undoChangeChordRestLen(cr, newDuration);
3357+
} else {
3358+
changeCRlen(cr, newDuration);
3359+
}
3360+
}
3361+
// 2nd loop needed to reselect what was selected before 1st loop
3362+
// as `changeCRlen()` changes the selection to `SelectType::SINGLE`
3363+
for (ChordRest* cr : crs) {
3364+
EngravingItem* e = cr;
3365+
if (cr->isChord()) {
3366+
e = toChord(cr)->upNote();
3367+
}
3368+
if (canReselectItem(e)) {
3369+
select(e, SelectType::ADD);
3370+
}
33283371
}
33293372
}
3330-
3331-
TDuration d = (nSteps != 0) ? initialDuration.shiftRetainDots(nSteps, stepDotted) : initialDuration;
3332-
if (!d.isValid()) {
3333-
return;
3334-
}
3335-
if (cr->isChord() && (toChord(cr)->noteType() != NoteType::NORMAL)) {
3336-
//
3337-
// handle appoggiatura and acciaccatura
3338-
//
3339-
undoChangeChordRestLen(cr, d);
3340-
} else {
3341-
changeCRlen(cr, d);
3342-
}
3343-
m_is.setDuration(d);
3344-
nextInputPos(cr, false);
33453373
}
33463374

33473375
//---------------------------------------------------------

src/engraving/editing/edit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6195,7 +6195,7 @@ static Chord* findLinkedChord(Chord* c, Staff* nstaff)
61956195
Segment* s = c->segment();
61966196
Measure* nm = nstaff->score()->tick2measure(s->tick());
61976197
Segment* ns = nm->findSegment(s->segmentType(), s->tick());
6198-
EngravingItem* ne = ns->element(dtrack);
6198+
EngravingItem* ne = ns ? ns->element(dtrack) : nullptr;
61996199
if (!ne || !ne->isChord()) {
62006200
return nullptr;
62016201
}

0 commit comments

Comments
 (0)