Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 74 additions & 84 deletions src/engraving/dom/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,15 +428,27 @@ ChordRest* Score::addClone(ChordRest* cr, const Fraction& tick, const TDuration&

//---------------------------------------------------------
// setRest
// create one or more rests to fill "l"
// sets rests and returns the first one
//---------------------------------------------------------

Rest* Score::setRest(const Fraction& _tick, track_idx_t track, const Fraction& _l, bool useDots, Tuplet* tuplet, bool useFullMeasureRest)
{
std::vector<Rest*> rests = setRests(_tick, track, _l, useDots, tuplet, useFullMeasureRest);
return rests.empty() ? nullptr : rests.front();
}

//---------------------------------------------------------
// setRests
// create one or more rests to fill "l"
//---------------------------------------------------------

std::vector<Rest*> Score::setRests(const Fraction& _tick, track_idx_t track, const Fraction& _l, bool useDots, Tuplet* tuplet,
bool useFullMeasureRest)
{
Fraction l = _l;
Fraction tick = _tick;
Measure* measure = tick2measure(tick);
Rest* r = 0;
std::vector<Rest*> rests;
Staff* staff = Score::staff(track / VOICES);

while (!l.isZero()) {
Expand Down Expand Up @@ -488,9 +500,7 @@ Rest* Score::setRest(const Fraction& _tick, track_idx_t track, const Fraction& _
&& (useFullMeasureRest)) {
Rest* rest = addRest(tick, track, TDuration(DurationType::V_MEASURE), tuplet);
tick += rest->actualTicks();
if (r == 0) {
r = rest;
}
rests.push_back(rest);
} else {
//
// compute list of durations which will fit l
Expand All @@ -504,15 +514,13 @@ Rest* Score::setRest(const Fraction& _tick, track_idx_t track, const Fraction& _
= toRhythmicDurationList(f, true, tick - measure->tick(), sigmap()->timesig(tick).nominal(), measure, useDots ? 1 : 0);
}
if (dList.empty()) {
return 0;
return rests;
}

Rest* rest = 0;
for (const TDuration& d : dList) {
rest = addRest(tick, track, d, tuplet);
if (r == 0) {
r = rest;
}
rests.push_back(rest);
tick += rest->actualTicks();
}
}
Expand All @@ -524,7 +532,7 @@ Rest* Score::setRest(const Fraction& _tick, track_idx_t track, const Fraction& _
}
tick = measure->tick();
}
return r;
return rests;
}

//---------------------------------------------------------
Expand Down Expand Up @@ -3278,9 +3286,9 @@ void Score::deleteAnnotationsFromRange(Segment* s1, Segment* s2, track_idx_t tra
/// deletion operation.
//---------------------------------------------------------

ChordRest* Score::deleteRange(Segment* s1, Segment* s2, track_idx_t track1, track_idx_t track2, const SelectionFilter& filter)
std::vector<ChordRest*> Score::deleteRange(Segment* s1, Segment* s2, track_idx_t track1, track_idx_t track2, const SelectionFilter& filter)
{
ChordRest* cr = nullptr;
std::vector<ChordRest*> crs;

if (s1) {
// delete content from measures underlying mmrests
Expand Down Expand Up @@ -3401,23 +3409,21 @@ ChordRest* Score::deleteRange(Segment* s1, Segment* s2, track_idx_t track1, trac
Fraction tick3 = m->tick();
Fraction ff = m->stretchedLen(staff);
Rest* r = setRest(tick3, track, ff, false, 0);
if (!cr) {
cr = r;
}
crs.push_back(r);
if (s2 && (m == s2->measure())) {
break;
}
}
} else {
Rest* r = setRest(tick, track, f, false, currentTuplet);
if (!cr) {
cr = r;
std::vector<Rest*> rests = setRests(tick, track, f, false, currentTuplet);
for (Rest* r : rests) {
crs.push_back(r);
}
}
}
}
}
return cr;
return crs;
}

//---------------------------------------------------------
Expand All @@ -3426,24 +3432,12 @@ ChordRest* Score::deleteRange(Segment* s1, Segment* s2, track_idx_t track1, trac

void Score::cmdDeleteSelection()
{
ChordRest* crSelectedAfterDeletion = 0; // select something after deleting notes
std::vector<ChordRest*> crsSelectedAfterDeletion; // select something after deleting notes

if (selection().isRange()) {
Segment* s1 = selection().startSegment();
Segment* s2 = selection().endSegment();
const Fraction stick1 = selection().tickStart();
const Fraction stick2 = selection().tickEnd();
crSelectedAfterDeletion = deleteRange(s1, s2, staff2track(selection().staffStart()),
staff2track(selection().staffEnd()), selectionFilter());
s1 = tick2segment(stick1);
s2 = tick2segment(stick2, true);
if (s1 == 0 || s2 == 0) {
deselectAll();
} else {
m_selection.setStartSegment(s1);
m_selection.setEndSegment(s2);
m_selection.updateSelectedElements();
}
crsSelectedAfterDeletion = deleteRange(selection().startSegment(), selection().endSegment(),
staff2track(selection().staffStart()), staff2track(selection().staffEnd()),
selectionFilter());
} else {
// deleteItem modifies selection().elements() list,
// so we need a local copy:
Expand All @@ -3468,41 +3462,37 @@ void Score::cmdDeleteSelection()
// or of spanner or parent if that is more valid
Fraction tick = { -1, 1 };
track_idx_t track = mu::nidx;
if (!crSelectedAfterDeletion) {
if (e->isNote()) {
tick = toNote(e)->chord()->tick();
} else if (e->isRest() || e->isMMRest()) {
tick = toRest(e)->tick();
} else if (e->isMeasureRepeat()) { // may be attached in different measure than it appears
tick = toMeasureRepeat(e)->firstMeasureOfGroup()->first()->tick();
} else if (e->isSpannerSegment()) {
tick = toSpannerSegment(e)->spanner()->tick();
} else if (e->isBreath()) {
// we want the tick of the ChordRest that precedes the breath mark (in the same track)
for (Segment* s = toBreath(e)->segment()->prev(); s; s = s->prev()) {
if (s->isChordRestType() && s->element(e->track())) {
tick = s->tick();
break;
}
if (e->isNote()) {
tick = toNote(e)->chord()->tick();
} else if (e->isRest() || e->isMMRest()) {
tick = toRest(e)->tick();
} else if (e->isMeasureRepeat()) { // may be attached in different measure than it appears
tick = toMeasureRepeat(e)->firstMeasureOfGroup()->first()->tick();
} else if (e->isSpannerSegment()) {
tick = toSpannerSegment(e)->spanner()->tick();
} else if (e->isBreath()) {
// we want the tick of the ChordRest that precedes the breath mark (in the same track)
for (Segment* s = toBreath(e)->segment()->prev(); s; s = s->prev()) {
if (s->isChordRestType() && s->element(e->track())) {
tick = s->tick();
break;
}
} else if (e->isBarLine() && toBarLine(e)->barLineType() != BarLineType::START_REPEAT) {
// we want the tick of the ChordRest that precedes the barline (in the same track)
for (Segment* s = toBarLine(e)->segment()->prev(); s; s = s->prev()) {
if (s->isChordRestType() && s->element(e->track())) {
tick = s->tick();
break;
}
}
} else if (e->isBarLine() && toBarLine(e)->barLineType() != BarLineType::START_REPEAT) {
// we want the tick of the ChordRest that precedes the barline (in the same track)
for (Segment* s = toBarLine(e)->segment()->prev(); s; s = s->prev()) {
if (s->isChordRestType() && s->element(e->track())) {
tick = s->tick();
break;
}
} else if (e->explicitParent()
&& (e->explicitParent()->isSegment() || e->explicitParent()->isChord() || e->explicitParent()->isNote()
|| e->explicitParent()->isRest())) {
tick = e->parentItem()->tick();
}
//else tick < 0
track = e->track();
} else if (e->explicitParent()
&& (e->explicitParent()->isSegment() || e->explicitParent()->isChord() || e->explicitParent()->isNote()
|| e->explicitParent()->isRest())) {
tick = e->parentItem()->tick();
}

bool needFindCR = !crSelectedAfterDeletion && tick >= Fraction(0, 1) && track != mu::nidx;
//else tick < 0
track = e->track();

// We should not allow deleting the very first keySig of the piece, because it is
// logically incorrect and leads to a state of undefined key/transposition.
Expand All @@ -3511,18 +3501,14 @@ void Score::cmdDeleteSelection()
if (e->isKeySig()) {
if (e->tick() == Fraction(0, 1) || toKeySig(e)->forInstrumentChange()) {
MScore::setError(MsError::CANNOT_REMOVE_KEY_SIG);
if (needFindCR) {
crSelectedAfterDeletion = findCR(tick, track);
}
crsSelectedAfterDeletion.push_back(findCR(tick, track));
continue;
}
}

// Don't allow deleting the trill cue note
if (e->isNote() && toNote(e)->isTrillCueNote()) {
if (needFindCR) {
crSelectedAfterDeletion = findCR(tick, track);
}
crsSelectedAfterDeletion.push_back(findCR(tick, track));
continue;
}

Expand All @@ -3547,10 +3533,7 @@ void Score::cmdDeleteSelection()
}
deleteItem(e);
}

if (needFindCR) {
crSelectedAfterDeletion = findCR(tick, track);
}
crsSelectedAfterDeletion.push_back(findCR(tick, track));

// add these linked elements to list of already-deleted elements
for (EngravingObject* se : links) {
Expand All @@ -3562,18 +3545,25 @@ void Score::cmdDeleteSelection()
deselectAll();
// make new selection if appropriate
if (noteEntryMode()) {
if (crSelectedAfterDeletion) {
m_is.setSegment(crSelectedAfterDeletion->segment());
if (!crsSelectedAfterDeletion.empty()) {
m_is.setSegment(crsSelectedAfterDeletion[0]->segment());
} else {
crSelectedAfterDeletion = m_is.cr();
crsSelectedAfterDeletion.push_back(m_is.cr());
}
}
if (crSelectedAfterDeletion) {
if (crSelectedAfterDeletion->isChord()) {
select(toChord(crSelectedAfterDeletion)->upNote(), SelectType::SINGLE);
} else {
select(crSelectedAfterDeletion, SelectType::SINGLE);
if (!crsSelectedAfterDeletion.empty()) {
std::vector<EngravingItem*> elementsToSelect;
for (ChordRest* cr : crsSelectedAfterDeletion) {
if (cr) {
if (cr->isChord()) {
elementsToSelect.push_back(dynamic_cast<EngravingItem*>(toChord(cr)->upNote()));
}
if (cr->isRest()) {
elementsToSelect.push_back(dynamic_cast<EngravingItem*>(cr));
}
}
}
select(elementsToSelect, SelectType::ADD, 0);
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/engraving/dom/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3166,6 +3166,7 @@ void Score::padToggle(Pad p, const EditData& ed)
}

std::vector<ChordRest*> crs;
std::list<EngravingItem*> elementsToSelect;

if (selection().isSingle()) {
EngravingItem* e = selection().element();
Expand Down Expand Up @@ -3200,6 +3201,12 @@ void Score::padToggle(Pad p, const EditData& ed)
m_is.setAccidentalType(AccidentalType::NONE);
} else {
const auto elements = selection().uniqueElements();
for (EngravingItem* e : elements) {
if (selection().isList() || e->isRest() || e->isNote()) {
elementsToSelect.push_back(e);
deselect(e);
}
}
bool canAdjustLength = true;
for (EngravingItem* e : elements) {
ChordRest* cr = InputState::chordRest(e);
Expand Down Expand Up @@ -3238,6 +3245,17 @@ void Score::padToggle(Pad p, const EditData& ed)
changeCRlen(cr, m_is.duration());
}
}

if (!elementsToSelect.empty()) {
std::vector<EngravingItem*> selectList;
for (EngravingItem* e : elementsToSelect) {
if (e && !e->selected()) {
selectList.push_back(e);
}
}
select(selectList, SelectType::ADD, 0);
selection().updateSelectedElements();
}
}

static void onFocusedItemChanged(EngravingItem* item)
Expand Down
7 changes: 5 additions & 2 deletions src/engraving/dom/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,9 @@ class Score : public EngravingObject
Tuplet* addTuplet(ChordRest* destinationChordRest, Fraction ratio, TupletNumberType numberType, TupletBracketType bracketType);

ChordRest* addClone(ChordRest* cr, const Fraction& tick, const TDuration& d);
Rest* setRest(const Fraction& tick, track_idx_t track, const Fraction&, bool useDots, Tuplet* tuplet, bool useFullMeasureRest = true);
Rest* setRest(const Fraction& tick, track_idx_t track, const Fraction&, bool useDots, Tuplet* tuplet, bool useFullMeasureRest = true);
std::vector<Rest*> setRests(const Fraction& tick, track_idx_t track, const Fraction&, bool useDots, Tuplet* tuplet,
bool useFullMeasureRest = true);

void upDown(bool up, UpDownMode);
void upDownDelta(int pitchDelta);
Expand Down Expand Up @@ -1010,7 +1012,8 @@ class Score : public EngravingObject
const SelectionFilter& filter);
void deleteAnnotationsFromRange(Segment* segStart, Segment* segEnd, track_idx_t trackStart, track_idx_t trackEnd,
const SelectionFilter& filter);
ChordRest* deleteRange(Segment* segStart, Segment* segEnd, track_idx_t trackStart, track_idx_t trackEnd, const SelectionFilter& filter);
std::vector<ChordRest*> deleteRange(Segment* segStart, Segment* segEnd, track_idx_t trackStart, track_idx_t trackEnd,
const SelectionFilter& filter);

void update(bool resetCmdState, bool layoutAllParts = false);

Expand Down