fix #139316 Regression: inability to change a clef inside a system leads to crash

This commit is contained in:
Werner Schweer 2016-10-30 16:27:55 +01:00
parent 292a8d9cd1
commit 9f12f2aa7c
5 changed files with 34 additions and 76 deletions

View file

@ -2633,46 +2633,7 @@ void Score::cmdInsertClef(ClefType type)
void Score::cmdInsertClef(Clef* clef, ChordRest* cr)
{
Clef* gclef = 0;
for (ScoreElement* e : cr->linkList()) {
ChordRest* cr = static_cast<ChordRest*>(e); // toChordRest() does not work as e is ScoreElement
Score* score = cr->score();
//
// create a clef segment before cr if needed
//
Segment* s = cr->segment();
int rtick = s->rtick();
Measure* m = s->measure();
Segment* cs;
if (rtick == 0) {
cs = m->findFirst(Segment::Type::HeaderClef, 0);
if (!cs)
cs = m->undoGetSegmentR(Segment::Type::HeaderClef, 0);
else {
if (cs->next() == s)
;
else {
for (int staffIdx = 0; staffIdx < nstaves(); ++staffIdx) {
Element* e = cs->element(staffIdx * VOICES);
if (e)
e->setGenerated(false);
}
cs = m->undoGetSegmentR(Segment::Type::Clef, 0);
}
}
}
else
cs = m->undoGetSegmentR(Segment::Type::Clef, 0);
Clef* c = toClef(gclef ? gclef->linkedClone() : clef->clone());
gclef = c;
c->setScore(score);
c->setTrack(cr->staffIdx() * VOICES);
c->setParent(cs);
score->undo(new AddElement(c));
}
undoChangeClef(cr->staff(), cr->segment(), clef->clefType());
delete clef;
}

View file

@ -93,9 +93,9 @@ void updateNoteLines(Segment* segment, int track)
if (staff->isDrumStaff() || staff->isTabStaff())
return;
for (Segment* s = segment->next1(); s; s = s->next1()) {
if (s->segmentType() == Segment::Type::Clef && s->element(track) && !s->element(track)->generated())
if ((s->segmentType() & (Segment::Type::Clef | Segment::Type::HeaderClef)) && s->element(track) && !s->element(track)->generated())
break;
if (s->segmentType() != Segment::Type::ChordRest)
if (!s->isChordRestType())
continue;
for (int t = track; t < track + VOICES; ++t) {
Element* e = s->element(t);
@ -505,18 +505,29 @@ void Score::undoChangeKeySig(Staff* ostaff, int tick, KeySigEvent key)
// create a clef before segment seg
//---------------------------------------------------------
void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType st)
void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType ct)
{
// bool firstSeg = seg->measure()->first() == seg;
bool firstSeg = seg->isHeaderClefType();
Segment::Type st;
if (seg->isHeaderClefType())
st = Segment::Type::HeaderClef;
else if (seg->isClefType())
st = Segment::Type::Clef;
else if (seg->rtick() == 0)
st = Segment::Type::HeaderClef;
else
st = Segment::Type::Clef;
bool moveClef = (st == Segment::Type::HeaderClef) && seg->measure()->prevMeasure();
// printf("change clef seg %s rtick %d move %d\n", seg->subTypeName(), seg->rtick(), moveClef);
Clef* gclef = 0;
int tick = seg->tick();
int rtick = seg->rtick();
for (Staff* staff : ostaff->staffList()) {
if (staff->staffType()->group() != ClefInfo::staffGroup(st))
if (staff->staffType()->group() != ClefInfo::staffGroup(ct))
continue;
Score* score = staff->score();
int tick = seg->tick();
Measure* measure = score->tick2measure(tick);
if (!measure) {
@ -524,19 +535,16 @@ void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType st)
continue;
}
Segment* destSeg = measure->findSegment(seg->segmentType(), tick);
// move measure-initial clef to last segment of prev measure
if (firstSeg && measure->prevMeasure() ) { // if at start of measure and there is a previous measure
Segment* destSeg;
int rt;
if (moveClef) { // if at start of measure and there is a previous measure
measure = measure->prevMeasure();
destSeg = measure->findSegmentR(Segment::Type::Clef, measure->ticks());
rt = measure->ticks();
}
else
rt = rtick;
destSeg = measure->undoGetSegmentR(st, rt);
if (!destSeg) {
destSeg = new Segment(measure, Segment::Type::HeaderClef, measure->ticks());
score->undoAddElement(destSeg);
}
int staffIdx = staff->idx();
int track = staffIdx * VOICES;
Clef* clef = toClef(destSeg->element(track));
@ -549,18 +557,18 @@ void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType st)
Instrument* i = staff->part()->instrument(tick);
ClefType cp, tp;
if (i->transpose().isZero()) {
cp = st;
tp = st;
cp = ct;
tp = ct;
}
else {
bool concertPitch = clef->concertPitch();
if (concertPitch) {
cp = st;
cp = ct;
tp = clef->transposingClef();
}
else {
cp = clef->concertClef();
tp = st;
tp = ct;
}
}
clef->setGenerated(false);
@ -586,11 +594,12 @@ void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType st)
gclef = clef;
}
clef->setTrack(track);
clef->setClefType(st);
clef->setClefType(ct);
clef->setParent(destSeg);
score->undo(new AddElement(clef));
clef->layout();
}
clef->setSmall(true);
}
}

View file

@ -312,15 +312,6 @@ void Palette::mousePressEvent(QMouseEvent* ev)
emit displayMore(_name);
}
//---------------------------------------------------------
// mouseReleaseEvent
//---------------------------------------------------------
void Palette::mouseReleaseEvent(QMouseEvent*)
{
printf("mouse release\n");
}
//---------------------------------------------------------
// mouseMoveEvent
//---------------------------------------------------------
@ -992,7 +983,7 @@ QPixmap Palette::pixmap(int paletteIdx) const
int w = r.width() * cellMag;
int h = r.height() * cellMag;
printf("h %f * %f = %d, %f\n", r.height(), cellMag, h, r.y());
// printf("h %f * %f = %d, %f\n", r.height(), cellMag, h, r.y());
QPixmap pm(w, h);
pm.fill(Qt::transparent);

View file

@ -129,7 +129,6 @@ class Palette : public QWidget {
virtual void paintEvent(QPaintEvent*) override;
virtual void mousePressEvent(QMouseEvent*) override;
virtual void mouseReleaseEvent(QMouseEvent*) override;
virtual void mouseDoubleClickEvent(QMouseEvent*) override;
virtual void mouseMoveEvent(QMouseEvent*) override;
virtual void leaveEvent(QEvent*) override;

View file

@ -4793,9 +4793,7 @@ void ScoreView::cmdChangeEnharmonic(bool up)
void ScoreView::cloneElement(Element* e)
{
if (!e->isMovable() && e->type() != Element::Type::SPACER && e->type() != Element::Type::VBOX)
return;
if(e->type() == Element::Type::NOTE || e->type() == Element::Type::REST || e->type() == Element::Type::MEASURE)
if (e->isMeasure() || e->isNote() || e->isVBox() || e->isSpacer())
return;
QDrag* drag = new QDrag(this);
QMimeData* mimeData = new QMimeData;