Skip to content

Commit

Permalink
Merge pull request #601 from mgavioli/Fix_clef_change_and_courtesy_clef
Browse files Browse the repository at this point in the history
Fix clef change and courtesy clef display.
  • Loading branch information
mgavioli committed Dec 28, 2013
2 parents ca722c6 + 3d932d4 commit b83bb62
Show file tree
Hide file tree
Showing 12 changed files with 1,297 additions and 85 deletions.
49 changes: 45 additions & 4 deletions libmscore/clef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,13 @@ void Clef::layout()
int lines = 5; // assume a resonable default
qreal lineDist = 1.0;

StaffType* staffType;
if (staff() && staff()->staffType()) {
Staff* stf = staff();
StaffType* staffType = nullptr;
if (stf && stf->staffType()) {
staffType = staff()->staffType();
if (!staffType->genClef()) { // if no clef, set empty bbox and do nothing
qDeleteAll(elements);
elements.clear();
setbbox(QRectF());
return;
}
Expand All @@ -163,8 +166,46 @@ void Clef::layout()
if (ClefInfo::staffGroup(clefType()) != TAB_STAFF_GROUP)
setClefType( ClefType(score()->styleI(ST_tabClef)) );
}
// all staff types: init values from staff type
lines = staffType->lines();

//
// all staff types
//
// courtesy clef
//
bool showClef = true;
Segment* clefSeg = static_cast<Segment*>(parent());
if (clefSeg) {
int tick = clefSeg->tick();
// only if there is a clef change
if (stf->clef(tick) != stf->clef(tick-1)) {
// locate clef at the begining of next measure, if any
Clef* clefNext = nullptr;
Segment* clefSegNext = nullptr;
Measure* meas = static_cast<Measure*>(clefSeg->parent());
Measure* measNext = meas->nextMeasure();
if (measNext) {
clefSegNext = measNext->findSegment(Segment::SegClef, tick);
if (clefSegNext)
clefNext = static_cast<Clef*>(clefSegNext->element(track()));
}
// show this clef if: it is not a courtesy clef (no next clef or not at the end of the measure)
showClef = !clefNext || (clefSeg->tick() != meas->tick() + meas->ticks())
// if courtesy clef: show if score has courtesy clefs on
|| ( score()->styleB(ST_genCourtesyClef)
// AND measure is not at the end of a repeat or of a section
&& !( (meas->repeatFlags() & RepeatEnd) || meas->sectionBreak() )
// AND this clef has courtesy clef turned on
&& showCourtesy() );
if (!showClef) { // if no clef, set empty bbox and do nothing
qDeleteAll(elements);
elements.clear();
setbbox(QRectF());
return;
}
}
}

lines = staffType->lines(); // init values from staff type
lineDist = staffType->lineDistance().val();
}

Expand Down
61 changes: 1 addition & 60 deletions libmscore/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1959,67 +1959,8 @@ QList<System*> Score::layoutSystemRow(qreal rowWidth, bool isFirstSystem, bool u
}
}

// courtesy clefs
// no courtesy clef if this measure is the end of a repeat
// courtesy clefs: show/hide of courtesy clefs moved to Clef::layout()

bool showCourtesyClef = styleB(ST_genCourtesyClef) && nm && !(m->repeatFlags() & RepeatEnd);
for (int staffIdx = 0; staffIdx < _staves.size(); ++staffIdx) {
Staff* staff = _staves[staffIdx];
ClefType clefType = staff->clef(tick);
if (clefType == staff->clef(tick-1))
continue;

bool show = showCourtesyClef;
Clef* clef;
if (showCourtesyClef) {
// locate a clef in next measure and, if found,
// check if it has court. sig turned off
s = nm->findSegment(Segment::SegClef, tick);
if (s) {
clef = static_cast<Clef*>(s->element(staffIdx*VOICES));
if (clef && !clef->showCourtesy()) {
show = false;
continue; // this key change has court. sig turned off
}
}
}
s = m->findSegment(Segment::SegClef, tick);
if (s)
clef = static_cast<Clef*>(s->element(staffIdx * VOICES));
else
clef = 0;
Clef* nextClef = 0;
Segment* ns = nm->findSegment(Segment::SegClef, tick);
if (ns)
nextClef = static_cast<Clef*>(ns->element(staffIdx * VOICES));
if (clef && !nextClef) {
//
// move original clef to next measure
//
nextClef = clef->clone();
ns = nm->undoGetSegment(Segment::SegClef, tick);
nextClef->setParent(ns);
undoAddElement(nextClef);
}
if (clef && !show) {
undoRemoveElement(clef);
clef = 0;
}
else if (!clef && show) {
s = m->undoGetSegment(Segment::SegClef, tick);
int track = staffIdx * VOICES;
clef = new Clef(this);
clef->setClefType(clefType);
clef->setTrack(track);
clef->setSmall(true);
clef->setParent(s);
undoAddElement(clef);
}
if (clef)
clef->setGenerated(true);
if (nextClef)
nextClef->setGenerated(false);
}
}

//
Expand Down
41 changes: 21 additions & 20 deletions libmscore/undo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,41 +512,42 @@ void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType st)
continue;
}

// move clef to last segment of prev measure?
// TODO: section break?
Segment* segment = measure->findSegment(seg->segmentType(), tick);
Segment* destSeg = measure->findSegment(Segment::SegClef, tick);

if (firstSeg
&& measure->prevMeasure()
&& !(measure->prevMeasure()->repeatFlags() & RepeatEnd)
// move measure-initial clef to last segment of prev measure

if (firstSeg // if at start of measure
&& measure->prevMeasure() // and there is a previous measure
) {
measure = measure->prevMeasure();
segment = measure->findSegment(seg->segmentType(), tick);
if (!segment && (seg->segmentType() != Segment::SegClef))
segment = measure->findSegment(Segment::SegClef, tick);
destSeg = measure->findSegment(Segment::SegClef, tick);
}

if (segment) {
if (segment->segmentType() != Segment::SegClef) {
if (segment->prev() && segment->prev()->segmentType() == Segment::SegClef) {
segment = segment->prev();
if (destSeg) {
// if destSeg not a Clef seg...
if (destSeg->segmentType() != Segment::SegClef) {
// ...check prev seg is Clef seg: if yes, prev seg is our dest seg
if (destSeg->prev() && destSeg->prev()->segmentType() == Segment::SegClef) {
destSeg = destSeg->prev();
}
// if no Clef seg (current or previous), create a new Clef seg
else {
Segment* s = new Segment(measure, Segment::SegClef, seg->tick());
s->setNext(segment);
s->setPrev(segment->prev());
s->setNext(destSeg);
s->setPrev(destSeg->prev());
score->undoAddElement(s);
segment = s;
destSeg = s;
}
}
}
// if no dest seg, create a new Clef seg
else {
segment = new Segment(measure, Segment::SegClef, seg->tick());
score->undoAddElement(segment);
destSeg = new Segment(measure, Segment::SegClef, seg->tick());
score->undoAddElement(destSeg);
}
int staffIdx = staff->idx();
int track = staffIdx * VOICES;
Clef* clef = static_cast<Clef*>(segment->element(track));
Clef* clef = static_cast<Clef*>(destSeg->element(track));

if (clef) {
//
Expand Down Expand Up @@ -577,7 +578,7 @@ void Score::undoChangeClef(Staff* ostaff, Segment* seg, ClefType st)
clef = new Clef(score);
clef->setTrack(track);
clef->setClefType(st);
clef->setParent(segment);
clef->setParent(destSeg);
score->undo(new AddElement(clef));
}
}
Expand Down
42 changes: 42 additions & 0 deletions mscore/inspector/inspector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,48 @@ InspectorClef::InspectorClef(QWidget* parent)
mapSignals();
}

// InspectorClef::setElement

void InspectorClef::setElement()
{
otherClef = nullptr; // no 'other clef' yet
InspectorBase::setElement();

// try to locate the 'other clef' of a courtesy / main pair
Clef * clef = static_cast<Clef*>(inspector->element());
// if not in a clef-segment-measure hierachy, do nothing
if (!clef->parent() || clef->parent()->type() != Element::SEGMENT)
return;
Segment* segm = static_cast<Segment*>(clef->parent());
int segmTick = segm->tick();
if (!segm->parent() || segm->parent()->type() != Element::MEASURE)
return;

Measure* meas = static_cast<Measure*>(segm->parent());
Measure* otherMeas = nullptr;
Segment* otherSegm = nullptr;
if (segmTick == meas->tick()) // if clef segm is measure-initial
otherMeas = meas->prevMeasure(); // look for a previous measure
else if (segmTick == meas->tick()+meas->ticks()) // if clef segm is measure-final
otherMeas = meas->nextMeasure(); // look for a next measure
// look for a clef segment in the 'other' measure at the same tick of this clef segment
if (otherMeas)
otherSegm = otherMeas->findSegment(Segment::SegClef, segmTick);
// if any 'other' segment found, look for a clef in the same track as this
if (otherSegm)
otherClef = static_cast<Clef*>(otherSegm->element(clef->track()));
}

// InspectorClef::valueChanged

void InspectorClef::valueChanged(int idx)
{
// copy into 'other clef' the ShowCouretsy ser of this clef
if (idx == 6 && otherClef)
otherClef->setShowCourtesy(c.showCourtesy->isChecked());
InspectorBase::valueChanged(idx);
}

//---------------------------------------------------------
// InspectorTempoText
//---------------------------------------------------------
Expand Down
7 changes: 7 additions & 0 deletions mscore/inspector/inspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,22 @@ class InspectorRest : public InspectorBase {
// InspectorClef
//---------------------------------------------------------

class Clef;

class InspectorClef : public InspectorBase {
Q_OBJECT

UiInspectorElement e;
Ui::InspectorSegment s;
Ui::InspectorClef c;
Clef* otherClef; // the courtesy clef for a main clef or viceversa
// used to keep in sync ShowCourtesy setting of both clefs
protected slots:
virtual void valueChanged(int idx);

public:
InspectorClef(QWidget* parent);
virtual void setElement();
};

//---------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion mtest/libmscore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#=============================================================================

subdirs(
beam chordsymbol clef compat concertpitch copypaste copypastesymbollist dynamic element
beam chordsymbol clef clef_courtesy compat concertpitch copypaste copypastesymbollist dynamic element
hairpin join keysig layout link measure midi note plugins repeat split
splitstaff timesig transpose tuplet
)
Expand Down
16 changes: 16 additions & 0 deletions mtest/libmscore/clef_courtesy/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#=============================================================================
# MuseScore
# Music Composition & Notation
#
# Copyright (C) 2011 Werner Schweer
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation and appearing in
# the file LICENSE.GPL
#=============================================================================

set(TARGET tst_clef_courtesy)

include(${PROJECT_SOURCE_DIR}/mtest/cmake.inc)

Loading

0 comments on commit b83bb62

Please sign in to comment.