2012-05-26 14:26:10 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
|
|
|
// Copyright (C) 2002-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 LICENCE.GPL
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/**
|
|
|
|
\file
|
|
|
|
Implementation of most part of class Measure.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "measure.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "note.h"
|
|
|
|
#include "rest.h"
|
|
|
|
#include "chord.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "score.h"
|
|
|
|
#include "clef.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "dynamic.h"
|
|
|
|
#include "slur.h"
|
2013-08-22 12:18:14 +02:00
|
|
|
#include "tie.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "sig.h"
|
|
|
|
#include "beam.h"
|
|
|
|
#include "tuplet.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "undo.h"
|
|
|
|
#include "hairpin.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "select.h"
|
|
|
|
#include "staff.h"
|
|
|
|
#include "part.h"
|
|
|
|
#include "style.h"
|
|
|
|
#include "bracket.h"
|
|
|
|
#include "ottava.h"
|
|
|
|
#include "trill.h"
|
|
|
|
#include "pedal.h"
|
|
|
|
#include "timesig.h"
|
|
|
|
#include "barline.h"
|
|
|
|
#include "layoutbreak.h"
|
|
|
|
#include "page.h"
|
|
|
|
#include "lyrics.h"
|
|
|
|
#include "volta.h"
|
|
|
|
#include "image.h"
|
|
|
|
#include "hook.h"
|
|
|
|
#include "beam.h"
|
|
|
|
#include "pitchspelling.h"
|
|
|
|
#include "keysig.h"
|
|
|
|
#include "breath.h"
|
|
|
|
#include "tremolo.h"
|
|
|
|
#include "drumset.h"
|
|
|
|
#include "repeat.h"
|
|
|
|
#include "box.h"
|
|
|
|
#include "harmony.h"
|
|
|
|
#include "tempotext.h"
|
|
|
|
#include "sym.h"
|
|
|
|
#include "stafftext.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "glissando.h"
|
|
|
|
#include "articulation.h"
|
|
|
|
#include "spacer.h"
|
|
|
|
#include "duration.h"
|
|
|
|
#include "fret.h"
|
|
|
|
#include "stafftype.h"
|
2013-12-05 21:37:28 +01:00
|
|
|
#include "stringdata.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "tiemap.h"
|
|
|
|
#include "tupletmap.h"
|
|
|
|
#include "accidental.h"
|
|
|
|
#include "layout.h"
|
|
|
|
#include "icon.h"
|
2013-11-25 12:17:12 +01:00
|
|
|
#include "ambitus.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// MStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
MStaff::MStaff()
|
|
|
|
{
|
2013-03-08 16:07:03 +01:00
|
|
|
_noText = 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
distanceUp = .0;
|
|
|
|
distanceDown = .0;
|
|
|
|
lines = 0;
|
|
|
|
hasVoices = false;
|
|
|
|
_vspacerUp = 0;
|
|
|
|
_vspacerDown = 0;
|
|
|
|
_visible = true;
|
|
|
|
_slashStyle = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
MStaff::~MStaff()
|
|
|
|
{
|
2013-03-08 16:07:03 +01:00
|
|
|
delete _noText;
|
2012-05-26 14:26:10 +02:00
|
|
|
delete lines;
|
|
|
|
delete _vspacerUp;
|
|
|
|
delete _vspacerDown;
|
|
|
|
}
|
|
|
|
|
2013-03-08 16:07:03 +01:00
|
|
|
MStaff::MStaff(const MStaff& m)
|
|
|
|
{
|
|
|
|
_noText = 0;
|
|
|
|
distanceUp = m.distanceUp;
|
|
|
|
distanceDown = m.distanceDown;
|
|
|
|
lines = m.lines;
|
|
|
|
hasVoices = m.hasVoices;
|
|
|
|
_vspacerUp = 0;
|
|
|
|
_vspacerDown = 0;
|
|
|
|
_visible = m._visible;
|
|
|
|
_slashStyle = m._slashStyle;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure::Measure(Score* s)
|
|
|
|
: MeasureBase(s),
|
|
|
|
_timesig(4,4), _len(4,4)
|
|
|
|
{
|
|
|
|
_repeatCount = 2;
|
2014-06-02 12:18:28 +02:00
|
|
|
_repeatFlags = Repeat::NONE;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
int n = _score->nstaves();
|
2013-01-03 16:56:56 +01:00
|
|
|
staves.reserve(n);
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < n; ++staffIdx) {
|
|
|
|
MStaff* s = new MStaff;
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
s->lines = new StaffLines(score());
|
|
|
|
s->lines->setTrack(staffIdx * VOICES);
|
|
|
|
s->lines->setParent(this);
|
|
|
|
s->lines->setVisible(!staff->invisible());
|
|
|
|
staves.push_back(s);
|
|
|
|
}
|
|
|
|
|
2012-07-31 09:48:37 +02:00
|
|
|
_minWidth1 = 0.0;
|
|
|
|
_minWidth2 = 0.0;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
_no = 0;
|
|
|
|
_noOffset = 0;
|
2013-03-08 12:55:12 +01:00
|
|
|
_noMode = MeasureNumberMode::AUTO;
|
2012-05-26 14:26:10 +02:00
|
|
|
_userStretch = 1.0; // ::style->measureSpacing;
|
|
|
|
_irregular = false;
|
|
|
|
_breakMultiMeasureRest = false;
|
|
|
|
_breakMMRest = false;
|
|
|
|
_endBarLineGenerated = true;
|
|
|
|
_endBarLineVisible = true;
|
2014-05-30 10:14:09 +02:00
|
|
|
_endBarLineType = BarLineType::NORMAL;
|
2013-09-19 15:08:54 +02:00
|
|
|
_mmRest = 0;
|
|
|
|
_mmRestCount = 0;
|
2014-05-22 10:10:58 +02:00
|
|
|
setFlag(ElementFlag::MOVABLE, true);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure::Measure(const Measure& m)
|
|
|
|
: MeasureBase(m)
|
|
|
|
{
|
|
|
|
_segments = m._segments.clone();
|
|
|
|
_timesig = m._timesig;
|
|
|
|
_len = m._len;
|
|
|
|
_repeatCount = m._repeatCount;
|
|
|
|
_repeatFlags = m._repeatFlags;
|
|
|
|
|
2013-05-29 10:31:26 +02:00
|
|
|
staves.reserve(m.staves.size());
|
2012-05-26 14:26:10 +02:00
|
|
|
foreach(MStaff* ms, m.staves)
|
|
|
|
staves.append(new MStaff(*ms));
|
|
|
|
|
2012-07-31 09:48:37 +02:00
|
|
|
_minWidth1 = m._minWidth1;
|
|
|
|
_minWidth2 = m._minWidth2;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
_no = m._no;
|
|
|
|
_noOffset = m._noOffset;
|
|
|
|
_userStretch = m._userStretch;
|
2012-07-31 09:48:37 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
_irregular = m._irregular;
|
|
|
|
_breakMultiMeasureRest = m._breakMultiMeasureRest;
|
|
|
|
_breakMMRest = m._breakMMRest;
|
|
|
|
_endBarLineGenerated = m._endBarLineGenerated;
|
|
|
|
_endBarLineVisible = m._endBarLineVisible;
|
|
|
|
_endBarLineType = m._endBarLineType;
|
2013-09-19 15:08:54 +02:00
|
|
|
_mmRest = m._mmRest;
|
|
|
|
_mmRestCount = m._mmRestCount;
|
2012-05-26 14:26:10 +02:00
|
|
|
_playbackCount = m._playbackCount;
|
|
|
|
_endBarLineColor = m._endBarLineColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setScore
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::setScore(Score* score)
|
|
|
|
{
|
|
|
|
MeasureBase::setScore(score);
|
|
|
|
for (Segment* s = first(); s; s = s->next())
|
|
|
|
s->setScore(score);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// MStaff::setScore
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void MStaff::setScore(Score* score)
|
|
|
|
{
|
|
|
|
if (lines)
|
|
|
|
lines->setScore(score);
|
|
|
|
if (_vspacerUp)
|
|
|
|
_vspacerUp->setScore(score);
|
|
|
|
if (_vspacerDown)
|
|
|
|
_vspacerDown->setScore(score);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure::~Measure()
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s;) {
|
|
|
|
Segment* ns = s->next();
|
|
|
|
delete s;
|
|
|
|
s = ns;
|
|
|
|
}
|
2013-01-03 16:56:56 +01:00
|
|
|
qDeleteAll(staves);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// dump
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
Debug only.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Measure::dump() const
|
|
|
|
{
|
|
|
|
qDebug("dump measure:");
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::remove(Segment* el)
|
|
|
|
{
|
|
|
|
#ifndef NDEBUG
|
2013-10-25 12:17:42 +02:00
|
|
|
if (score()->undoRedo()) {
|
2014-05-30 17:25:32 +02:00
|
|
|
qFatal("remove segment <%s> in undo/redo", el->subTypeName());
|
2013-10-25 12:17:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Q_ASSERT(!score()->undoRedo());
|
2014-06-24 18:36:02 +02:00
|
|
|
Q_ASSERT(el->type() == Element::Type::SEGMENT);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (el->prev()) {
|
|
|
|
Q_ASSERT(el->prev()->next() == el);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Q_ASSERT(el == _segments.first());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (el->next()) {
|
|
|
|
Q_ASSERT(el->next()->prev() == el);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Q_ASSERT(el == _segments.last());
|
|
|
|
}
|
|
|
|
#endif
|
2014-06-03 15:28:10 +02:00
|
|
|
#if 0
|
2012-05-26 14:26:10 +02:00
|
|
|
int tracks = staves.size() * VOICES;
|
|
|
|
for (int track = 0; track < tracks; track += VOICES) {
|
|
|
|
if (!el->element(track))
|
|
|
|
continue;
|
2014-06-25 11:46:10 +02:00
|
|
|
if (el->segmentType() == Segment::Type::KeySig)
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->staff(track/VOICES)->setUpdateKeymap(true);
|
|
|
|
}
|
2014-06-03 15:28:10 +02:00
|
|
|
#endif
|
2012-05-26 14:26:10 +02:00
|
|
|
_segments.remove(el);
|
2012-08-08 20:46:29 +02:00
|
|
|
setDirty();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// AcEl
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
struct AcEl {
|
|
|
|
Note* note;
|
|
|
|
qreal x;
|
|
|
|
};
|
|
|
|
|
2013-10-15 15:39:01 +02:00
|
|
|
#if 0
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// layoutChords0
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::layoutChords0(Segment* segment, int startTrack)
|
|
|
|
{
|
|
|
|
int staffIdx = startTrack/VOICES;
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
qreal staffMag = staff->mag();
|
|
|
|
|
|
|
|
int endTrack = startTrack + VOICES;
|
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(segment->element(track));
|
|
|
|
if (!cr)
|
|
|
|
continue;
|
2013-06-20 10:19:04 +02:00
|
|
|
layoutCR0(cr, staffMag);
|
|
|
|
}
|
|
|
|
}
|
2013-10-15 15:39:01 +02:00
|
|
|
#endif
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-06-20 10:19:04 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// layoutCR0
|
|
|
|
//---------------------------------------------------------
|
2013-01-02 14:33:23 +01:00
|
|
|
|
2013-06-20 10:19:04 +02:00
|
|
|
void Measure::layoutCR0(ChordRest* cr, qreal mm)
|
|
|
|
{
|
|
|
|
Drumset* drumset = 0;
|
|
|
|
if (cr->staff()->part()->instr()->useDrumset())
|
|
|
|
drumset = cr->staff()->part()->instr()->drumset();
|
|
|
|
|
|
|
|
qreal m = mm;
|
|
|
|
if (cr->small())
|
2014-05-26 15:31:36 +02:00
|
|
|
m *= score()->styleD(StyleIdx::smallNoteMag);
|
2013-06-20 10:19:04 +02:00
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
if (cr->type() == Element::Type::CHORD) {
|
2013-06-20 10:19:04 +02:00
|
|
|
Chord* chord = static_cast<Chord*>(cr);
|
|
|
|
for (Chord* c : chord->graceNotes())
|
|
|
|
layoutCR0(c, mm);
|
|
|
|
|
2014-05-27 10:35:28 +02:00
|
|
|
if (chord->noteType() != NoteType::NORMAL)
|
2014-05-26 15:31:36 +02:00
|
|
|
m *= score()->styleD(StyleIdx::graceNoteMag);
|
2013-06-20 10:19:04 +02:00
|
|
|
if (drumset) {
|
2014-03-26 11:02:23 +01:00
|
|
|
for (Note* note : chord->notes()) {
|
2013-06-20 10:19:04 +02:00
|
|
|
int pitch = note->pitch();
|
|
|
|
if (!drumset->isValid(pitch)) {
|
|
|
|
// qDebug("unmapped drum note %d", pitch);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
note->setHeadGroup(drumset->noteHead(pitch));
|
|
|
|
note->setLine(drumset->line(pitch));
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2012-08-01 18:00:27 +02:00
|
|
|
}
|
2013-06-20 10:19:04 +02:00
|
|
|
chord->computeUp();
|
|
|
|
chord->layoutStem1();
|
|
|
|
}
|
|
|
|
if (m != mag()) {
|
|
|
|
cr->setMag(m);
|
|
|
|
setDirty();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// findAccidental
|
2012-08-07 12:44:19 +02:00
|
|
|
/// return current accidental value at note position
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-08 20:46:29 +02:00
|
|
|
AccidentalVal Measure::findAccidental(Note* note) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
AccidentalState tversatz; // state of already set accidentals for this measure
|
2014-06-03 15:28:10 +02:00
|
|
|
tversatz.init(note->chord()->staff()->key(tick()));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type st = Segment::Type::ChordRest;
|
2012-05-26 14:26:10 +02:00
|
|
|
for (Segment* segment = first(st); segment; segment = segment->next(st)) {
|
|
|
|
int startTrack = note->staffIdx() * VOICES;
|
|
|
|
int endTrack = startTrack + VOICES;
|
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
Element* e = segment->element(track);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (!e || e->type() != Element::Type::CHORD)
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
Chord* chord = static_cast<Chord*>(e);
|
2013-09-02 12:13:46 +02:00
|
|
|
for (Chord* chord1 : chord->graceNotes()) {
|
|
|
|
for (Note* note1 : chord1->notes()) {
|
|
|
|
if (note1->tieBack())
|
|
|
|
continue;
|
|
|
|
//
|
|
|
|
// compute accidental
|
|
|
|
//
|
|
|
|
int tpc = note1->tpc();
|
|
|
|
int line = absStep(tpc, note1->pitch());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-09-02 12:13:46 +02:00
|
|
|
if (note == note1)
|
|
|
|
return tversatz.accidentalVal(line);
|
|
|
|
tversatz.setAccidentalVal(line, tpc2alter(tpc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (Note* note1 : chord->notes()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (note1->tieBack())
|
|
|
|
continue;
|
|
|
|
//
|
|
|
|
// compute accidental
|
|
|
|
//
|
2012-08-06 21:55:51 +02:00
|
|
|
int tpc = note1->tpc();
|
2012-08-07 16:05:37 +02:00
|
|
|
int line = absStep(tpc, note1->pitch());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
if (note == note1)
|
|
|
|
return tversatz.accidentalVal(line);
|
2012-08-06 21:55:51 +02:00
|
|
|
tversatz.setAccidentalVal(line, tpc2alter(tpc));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-02 12:13:46 +02:00
|
|
|
qDebug("Measure::findAccidental: note not found");
|
2014-05-27 11:41:07 +02:00
|
|
|
return AccidentalVal::NATURAL;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-08-07 12:44:19 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// findAccidental
|
|
|
|
/// Compute accidental state at segment/staffIdx for
|
|
|
|
/// relative staff line.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-08 20:46:29 +02:00
|
|
|
AccidentalVal Measure::findAccidental(Segment* s, int staffIdx, int line) const
|
2012-08-06 21:55:51 +02:00
|
|
|
{
|
|
|
|
AccidentalState tversatz; // state of already set accidentals for this measure
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2014-06-03 15:28:10 +02:00
|
|
|
tversatz.init(staff->key(tick()));
|
2012-08-06 21:55:51 +02:00
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type st = Segment::Type::ChordRest;
|
2014-06-01 20:24:29 +02:00
|
|
|
int startTrack = staffIdx * VOICES;
|
|
|
|
int endTrack = startTrack + VOICES;
|
2012-08-06 21:55:51 +02:00
|
|
|
for (Segment* segment = first(st); segment; segment = segment->next(st)) {
|
|
|
|
if (segment == s) {
|
2012-08-07 12:44:19 +02:00
|
|
|
ClefType clef = staff->clef(s->tick());
|
2012-08-07 16:05:37 +02:00
|
|
|
int l = relStep(line, clef);
|
2012-08-06 21:55:51 +02:00
|
|
|
return tversatz.accidentalVal(l);
|
|
|
|
}
|
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
Element* e = segment->element(track);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (!e || e->type() != Element::Type::CHORD)
|
2012-08-06 21:55:51 +02:00
|
|
|
continue;
|
|
|
|
Chord* chord = static_cast<Chord*>(e);
|
2013-09-02 12:13:46 +02:00
|
|
|
for (Chord* chord1 : chord->graceNotes()) {
|
|
|
|
for (Note* note : chord1->notes()) {
|
|
|
|
if (note->tieBack())
|
|
|
|
continue;
|
|
|
|
int tpc = note->tpc();
|
|
|
|
int l = absStep(tpc, note->pitch());
|
|
|
|
tversatz.setAccidentalVal(l, tpc2alter(tpc));
|
|
|
|
}
|
|
|
|
}
|
2012-08-06 21:55:51 +02:00
|
|
|
|
2013-09-02 12:13:46 +02:00
|
|
|
for (Note* note : chord->notes()) {
|
2012-08-06 21:55:51 +02:00
|
|
|
if (note->tieBack())
|
|
|
|
continue;
|
|
|
|
int tpc = note->tpc();
|
2012-08-07 16:05:37 +02:00
|
|
|
int l = absStep(tpc, note->pitch());
|
2012-08-06 21:55:51 +02:00
|
|
|
tversatz.setAccidentalVal(l, tpc2alter(tpc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
qDebug("segment not found");
|
2014-05-27 11:41:07 +02:00
|
|
|
return AccidentalVal::NATURAL;
|
2012-08-06 21:55:51 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Measure::layout
|
2012-10-16 17:11:35 +02:00
|
|
|
/// Layout measure; must fit into \a width.
|
|
|
|
///
|
|
|
|
/// Note: minWidth = width - stretch
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::layout(qreal width)
|
|
|
|
{
|
|
|
|
int nstaves = _score->nstaves();
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
|
|
|
staves[staffIdx]->distanceUp = 0.0;
|
|
|
|
staves[staffIdx]->distanceDown = 0.0;
|
|
|
|
StaffLines* sl = staves[staffIdx]->lines;
|
|
|
|
if (sl)
|
|
|
|
sl->setMag(score()->staff(staffIdx)->mag());
|
|
|
|
staves[staffIdx]->lines->layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
// height of boundingRect will be set in system->layout2()
|
|
|
|
// keep old value for relayout
|
|
|
|
|
2013-01-02 09:29:17 +01:00
|
|
|
bbox().setRect(0.0, 0.0, width, height());
|
2012-07-31 09:48:37 +02:00
|
|
|
layoutX(width);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// tick2pos
|
2013-06-19 16:25:29 +02:00
|
|
|
// return x position for tick relative to System
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Measure::tick2pos(int tck) const
|
|
|
|
{
|
2013-09-19 15:08:54 +02:00
|
|
|
if (isMMRest()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* s = first(Segment::Type::ChordRest);
|
2012-10-16 17:11:35 +02:00
|
|
|
qreal x1 = s->x();
|
|
|
|
qreal w = width() - x1;
|
2013-09-19 15:08:54 +02:00
|
|
|
return x1 + (tck * w) / (ticks() * mmRestCount());
|
2012-10-16 17:11:35 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
Segment* s;
|
|
|
|
qreal x1 = 0;
|
|
|
|
qreal x2 = 0;
|
|
|
|
int tick1 = tick();
|
|
|
|
int tick2 = tick1;
|
2014-06-25 11:46:10 +02:00
|
|
|
for (s = first(Segment::Type::ChordRest); s; s = s->next(Segment::Type::ChordRest)) {
|
2013-06-19 16:25:29 +02:00
|
|
|
x2 = s->x();
|
2012-05-26 14:26:10 +02:00
|
|
|
tick2 = s->tick();
|
2013-06-19 16:25:29 +02:00
|
|
|
if (tck == tick2)
|
|
|
|
return x2 + pos().x();
|
|
|
|
if (tck <= tick2)
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
x1 = x2;
|
|
|
|
tick1 = tick2;
|
|
|
|
}
|
|
|
|
if (s == 0) {
|
|
|
|
x2 = width();
|
2013-06-19 16:25:29 +02:00
|
|
|
tick2 = endTick();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-06-19 16:25:29 +02:00
|
|
|
qreal dx = x2 - x1;
|
|
|
|
int dt = tick2 - tick1;
|
|
|
|
x1 += (dt == 0) ? 0.0 : (dx * (tck - tick1) / dt);
|
|
|
|
return x1 + pos().x();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// layout2
|
|
|
|
// called after layout of all pages
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::layout2()
|
|
|
|
{
|
|
|
|
if (parent() == 0)
|
|
|
|
return;
|
|
|
|
|
2013-09-20 12:59:31 +02:00
|
|
|
Q_ASSERT(score()->nstaves() == staves.size());
|
|
|
|
|
|
|
|
int tracks = score()->nstaves() * VOICES;
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal _spatium = spatium();
|
2014-06-25 11:46:10 +02:00
|
|
|
static const Segment::Type st { Segment::Type::ChordRest };
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = 0; track < tracks; ++track) {
|
|
|
|
for (Segment* s = first(st); s; s = s->next(st)) {
|
2013-09-20 12:59:31 +02:00
|
|
|
ChordRest* cr = s->cr(track);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!cr)
|
|
|
|
continue;
|
2012-12-06 12:46:05 +01:00
|
|
|
int n = cr->lyricsList().size();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
Lyrics* lyrics = cr->lyricsList().at(i);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (lyrics)
|
|
|
|
system()->layoutLyrics(lyrics, s, track/VOICES);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (track % VOICES == 0) {
|
|
|
|
int staffIdx = track / VOICES;
|
|
|
|
qreal y = system()->staff(staffIdx)->y();
|
|
|
|
Spacer* sp = staves[staffIdx]->_vspacerDown;
|
|
|
|
if (sp) {
|
|
|
|
sp->layout();
|
|
|
|
int n = score()->staff(staffIdx)->lines() - 1;
|
|
|
|
sp->setPos(_spatium * .5, y + n * _spatium);
|
|
|
|
}
|
|
|
|
sp = staves[staffIdx]->_vspacerUp;
|
|
|
|
if (sp) {
|
|
|
|
sp->layout();
|
|
|
|
sp->setPos(_spatium * .5, y - sp->gap());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-20 12:59:31 +02:00
|
|
|
for (MStaff* ms : staves)
|
|
|
|
ms->lines->setWidth(width());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
MeasureBase::layout(); // layout LAYOUT_BREAK elements
|
|
|
|
|
|
|
|
//
|
|
|
|
// set measure number
|
|
|
|
//
|
|
|
|
bool smn = false;
|
2012-10-17 10:39:39 +02:00
|
|
|
|
2013-03-08 16:07:03 +01:00
|
|
|
// if (!_noText || _noText->generated()) {
|
2013-03-08 12:55:12 +01:00
|
|
|
if (_noMode == MeasureNumberMode::SHOW)
|
|
|
|
smn = true;
|
|
|
|
else if (_noMode == MeasureNumberMode::HIDE)
|
|
|
|
smn = false;
|
|
|
|
else {
|
2014-05-26 15:31:36 +02:00
|
|
|
if (score()->styleB(StyleIdx::showMeasureNumber)
|
2013-03-08 12:55:12 +01:00
|
|
|
&& !_irregular
|
2014-05-26 15:31:36 +02:00
|
|
|
&& (_no || score()->styleB(StyleIdx::showMeasureNumberOne))) {
|
|
|
|
if (score()->styleB(StyleIdx::measureNumberSystem))
|
2013-03-08 12:55:12 +01:00
|
|
|
smn = system()->firstMeasure() == this;
|
|
|
|
else {
|
2014-05-26 15:31:36 +02:00
|
|
|
smn = (_no == 0 && score()->styleB(StyleIdx::showMeasureNumberOne)) ||
|
|
|
|
( ((_no+1) % score()->style(StyleIdx::measureNumberInterval).toInt()) == 0 );
|
2013-03-08 12:55:12 +01:00
|
|
|
}
|
2012-10-17 10:39:39 +02:00
|
|
|
}
|
|
|
|
}
|
2013-03-08 16:07:03 +01:00
|
|
|
QString s;
|
|
|
|
if (smn)
|
|
|
|
s = QString("%1").arg(_no + 1);
|
2013-05-01 22:44:49 +02:00
|
|
|
int nn = 1;
|
2014-05-26 15:31:36 +02:00
|
|
|
if (!score()->styleB(StyleIdx::measureNumberAllStaffs)) {
|
2013-05-01 22:44:49 +02:00
|
|
|
//find first non invisible staff
|
2013-09-20 12:59:31 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < staves.size(); ++staffIdx) {
|
2013-05-01 22:44:49 +02:00
|
|
|
MStaff* ms = staves.at(staffIdx);
|
|
|
|
SysStaff* s = system()->staff(staffIdx);
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
if (ms->visible() && staff->show() && s->show()) {
|
2013-09-06 14:11:05 +02:00
|
|
|
nn = staffIdx;
|
2013-05-01 22:44:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-20 12:59:31 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < staves.size(); ++staffIdx) {
|
2013-03-08 16:07:03 +01:00
|
|
|
MStaff* ms = staves.at(staffIdx);
|
|
|
|
Text* t = ms->noText();
|
|
|
|
if (smn) {
|
2014-05-26 15:31:36 +02:00
|
|
|
if ((staffIdx == nn || score()->styleB(StyleIdx::measureNumberAllStaffs))) {
|
2014-05-22 22:51:26 +02:00
|
|
|
if (t == 0) {
|
|
|
|
t = new Text(score());
|
2014-05-22 10:10:58 +02:00
|
|
|
t->setFlag(ElementFlag::ON_STAFF, true);
|
|
|
|
// t->setFlag(ElementFlag::MOVABLE, false); ??
|
2014-05-22 22:51:26 +02:00
|
|
|
t->setTrack(staffIdx * VOICES);
|
|
|
|
t->setGenerated(true);
|
2014-05-30 10:13:29 +02:00
|
|
|
t->setTextStyleType(TextStyleType::MEASURE_NUMBER);
|
2014-05-22 22:51:26 +02:00
|
|
|
t->setParent(this);
|
|
|
|
score()->undoAddElement(t);
|
|
|
|
}
|
|
|
|
if(t) {
|
|
|
|
t->setText(s);
|
|
|
|
t->layout();
|
2014-05-26 15:31:36 +02:00
|
|
|
smn = score()->styleB(StyleIdx::measureNumberAllStaffs);
|
2014-05-22 22:51:26 +02:00
|
|
|
}
|
2013-09-06 14:11:05 +02:00
|
|
|
}
|
2013-03-08 16:07:03 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (t)
|
|
|
|
score()->undoRemoveElement(t);
|
2012-10-17 10:39:39 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-03-08 16:07:03 +01:00
|
|
|
// }
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// slur layout needs articulation layout first
|
|
|
|
//
|
|
|
|
for (Segment* s = first(st); s; s = s->next(st)) {
|
|
|
|
for (int track = 0; track < tracks; ++track) {
|
2012-10-23 20:22:49 +02:00
|
|
|
if (!score()->staff(track / VOICES)->show()) {
|
2013-03-14 16:36:24 +01:00
|
|
|
track += VOICES-1;
|
2012-10-23 20:22:49 +02:00
|
|
|
continue;
|
|
|
|
}
|
2014-07-02 09:55:50 +02:00
|
|
|
ChordRest* cr = static_cast<ChordRest*>(s->element(track));
|
|
|
|
if (!cr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (cr->type() == Element::Type::CHORD) {
|
|
|
|
Chord* c = static_cast<Chord*>(cr);
|
|
|
|
for (const Note* note : c->notes()) {
|
|
|
|
Tie* tie = note->tieFor();
|
|
|
|
if (tie)
|
|
|
|
tie->layout();
|
|
|
|
foreach (Spanner* sp, note->spannerFor())
|
|
|
|
sp->layout();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2014-07-02 09:55:50 +02:00
|
|
|
DurationElement* de = cr;
|
|
|
|
while (de->tuplet() && de->tuplet()->elements().front() == de) {
|
|
|
|
de->tuplet()->layout();
|
|
|
|
de = de->tuplet();
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// findChord
|
2013-06-24 13:46:21 +02:00
|
|
|
/// Search for chord at position \a tick in \a track
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-06-24 13:46:21 +02:00
|
|
|
Chord* Measure::findChord(int tick, int track)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (Segment* seg = last(); seg; seg = seg->prev()) {
|
|
|
|
if (seg->tick() < tick)
|
|
|
|
return 0;
|
|
|
|
if (seg->tick() == tick) {
|
|
|
|
Element* el = seg->element(track);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (el && el->type() == Element::Type::CHORD)
|
2012-12-06 12:46:05 +01:00
|
|
|
return static_cast<Chord*>(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// findChordRest
|
2013-06-24 13:46:21 +02:00
|
|
|
/// Search for chord or rest at position \a tick at \a staff in \a voice.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
ChordRest* Measure::findChordRest(int tick, int track)
|
|
|
|
{
|
|
|
|
for (Segment* seg = first(); seg; seg = seg->next()) {
|
|
|
|
if (seg->tick() > tick)
|
|
|
|
return 0;
|
|
|
|
if (seg->tick() == tick) {
|
|
|
|
Element* el = seg->element(track);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (el && (el->type() == Element::Type::CHORD || el->type() == Element::Type::REST)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
return (ChordRest*)el;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// tick2segment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-06-16 23:33:37 +02:00
|
|
|
Segment* Measure::tick2segment(int tick) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
|
|
|
if (s->tick() == tick) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::ChordRest)
|
2012-05-26 14:26:10 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
if (s->tick() > tick)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// findSegment
|
2013-05-29 10:31:26 +02:00
|
|
|
/// Search for a segment of type \a st at position \a t.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Measure::findSegment(Segment::Type st, int t)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Segment* s;
|
|
|
|
for (s = first(); s && s->tick() < t; s = s->next())
|
|
|
|
;
|
2013-06-25 19:52:00 +02:00
|
|
|
for (; s && s->tick() == t; s = s->next()) {
|
|
|
|
if (s->segmentType() == st)
|
2013-05-24 12:36:32 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoGetSegment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Measure::undoGetSegment(Segment::Type type, int tick)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Segment* s = findSegment(type, tick);
|
|
|
|
if (s == 0) {
|
|
|
|
s = new Segment(this, type, tick);
|
|
|
|
score()->undoAddElement(s);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// getSegment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Segment* Measure::getSegment(Element* e, int tick)
|
|
|
|
{
|
2013-06-25 19:52:00 +02:00
|
|
|
return getSegment(Segment::segmentType(e->type()), tick);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// getSegment
|
2012-09-10 16:10:25 +02:00
|
|
|
/// Get a segment of type \a st at tick position \a t.
|
|
|
|
/// If the segment does not exist, it is created.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Measure::getSegment(Segment::Type st, int tick)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-02-27 11:10:57 +01:00
|
|
|
Segment* s = findSegment(st, tick);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!s) {
|
2013-02-27 11:10:57 +01:00
|
|
|
s = new Segment(this, st, tick);
|
2012-05-26 14:26:10 +02:00
|
|
|
add(s);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// add
|
2012-07-31 09:48:37 +02:00
|
|
|
/// Add new Element \a el to Measure.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::add(Element* el)
|
|
|
|
{
|
2012-08-08 20:46:29 +02:00
|
|
|
setDirty();
|
2012-05-26 14:26:10 +02:00
|
|
|
el->setParent(this);
|
2014-06-24 18:36:02 +02:00
|
|
|
Element::Type type = el->type();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
// if (MScore::debugMode)
|
|
|
|
// qDebug("measure %p(%d): add %s %p", this, _no, el->name(), el);
|
|
|
|
|
|
|
|
switch (type) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TEXT:
|
2013-03-08 16:07:03 +01:00
|
|
|
staves[el->staffIdx()]->setNoText(static_cast<Text*>(el));
|
2012-10-17 10:39:39 +02:00
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TUPLET:
|
2012-05-26 14:26:10 +02:00
|
|
|
qDebug("Measure::add(Tuplet) ??");
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SPACER:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Spacer* sp = static_cast<Spacer*>(el);
|
2014-05-26 12:46:24 +02:00
|
|
|
if (sp->spacerType() == SpacerType::UP)
|
2012-05-26 14:26:10 +02:00
|
|
|
staves[el->staffIdx()]->_vspacerUp = sp;
|
2014-05-26 12:46:24 +02:00
|
|
|
else if (sp->spacerType() == SpacerType::DOWN)
|
2012-05-26 14:26:10 +02:00
|
|
|
staves[el->staffIdx()]->_vspacerDown = sp;
|
|
|
|
}
|
|
|
|
break;
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SEGMENT:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Segment* seg = static_cast<Segment*>(el);
|
2014-06-03 15:28:10 +02:00
|
|
|
#if 0
|
2014-06-25 11:46:10 +02:00
|
|
|
if (seg->segmentType() == Segment::Type::KeySig) {
|
2014-06-03 15:28:10 +02:00
|
|
|
int tracks = staves.size() * VOICES;
|
2012-10-02 13:52:23 +02:00
|
|
|
for (int track = 0; track < tracks; track += VOICES) {
|
|
|
|
if (!seg->element(track))
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->staff(track/VOICES)->setUpdateKeymap(true);
|
2012-10-02 13:52:23 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-03 15:28:10 +02:00
|
|
|
#endif
|
2013-06-05 09:53:38 +02:00
|
|
|
|
|
|
|
// insert segment at specific position
|
|
|
|
if (seg->next()) {
|
|
|
|
_segments.insert(seg, seg->next());
|
|
|
|
break;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
int t = seg->tick();
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type st = seg->segmentType();
|
2013-02-27 11:10:57 +01:00
|
|
|
Segment* s;
|
2013-06-12 14:23:57 +02:00
|
|
|
for (s = first(); s && s->tick() < t; s = s->next())
|
|
|
|
;
|
|
|
|
if (s) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (st == Segment::Type::ChordRest) {
|
2013-06-12 14:23:57 +02:00
|
|
|
while (s && s->segmentType() != st && s->tick() == t) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::EndBarLine)
|
2013-06-12 14:23:57 +02:00
|
|
|
break;
|
|
|
|
s = s->next();
|
2013-02-27 11:10:57 +01:00
|
|
|
}
|
2013-06-12 14:23:57 +02:00
|
|
|
}
|
|
|
|
else {
|
2013-12-31 12:33:30 +01:00
|
|
|
if (s && s->tick() == t) {
|
|
|
|
while (s && s->segmentType() <= st) {
|
|
|
|
if (s->next() && s->next()->tick() != t)
|
|
|
|
break;
|
|
|
|
s = s->next();
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-06-12 14:23:57 +02:00
|
|
|
//
|
|
|
|
// place breath _after_ chord
|
|
|
|
//
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s && st == Segment::Type::Breath)
|
2013-06-12 14:23:57 +02:00
|
|
|
s = s->next();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2013-02-27 11:10:57 +01:00
|
|
|
seg->setParent(this);
|
2013-12-31 12:33:30 +01:00
|
|
|
|
2013-02-27 11:10:57 +01:00
|
|
|
_segments.insert(seg, s);
|
2014-06-25 11:46:10 +02:00
|
|
|
if ((seg->segmentType() == Segment::Type::TimeSig) && seg->element(0)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
#if 0
|
|
|
|
Fraction nfraction(static_cast<TimeSig*>(seg->element(0))->getSig());
|
|
|
|
setTimesig2(nfraction);
|
|
|
|
for (Measure* m = nextMeasure(); m; m = m->nextMeasure()) {
|
|
|
|
if (m->first(SegTimeSig))
|
|
|
|
break;
|
|
|
|
m->setTimesig2(nfraction);
|
|
|
|
}
|
|
|
|
#endif
|
2014-05-30 10:16:38 +02:00
|
|
|
score()->addLayoutFlags(LayoutFlag::FIX_TICKS);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::JUMP:
|
2014-07-17 09:32:30 +02:00
|
|
|
_repeatFlags = _repeatFlags | Repeat::JUMP;
|
2013-03-25 16:27:20 +01:00
|
|
|
_el.push_back(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::HBOX:
|
2012-05-26 14:26:10 +02:00
|
|
|
if (el->staff())
|
|
|
|
el->setMag(el->staff()->mag()); // ?!
|
2013-03-25 16:27:20 +01:00
|
|
|
_el.push_back(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::MEASURE:
|
2013-10-30 14:21:08 +01:00
|
|
|
_mmRest = static_cast<Measure*>(el);
|
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
|
|
|
MeasureBase::add(el);
|
|
|
|
break;
|
|
|
|
}
|
2012-08-01 22:15:58 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
2012-08-08 20:46:29 +02:00
|
|
|
/// Remove Element \a el from Measure.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::remove(Element* el)
|
|
|
|
{
|
2012-08-08 20:46:29 +02:00
|
|
|
setDirty();
|
2012-05-26 14:26:10 +02:00
|
|
|
switch(el->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TEXT:
|
2013-03-08 16:07:03 +01:00
|
|
|
staves[el->staffIdx()]->setNoText(static_cast<Text*>(0));
|
2012-10-17 10:39:39 +02:00
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SPACER:
|
2014-05-26 12:46:24 +02:00
|
|
|
if (static_cast<Spacer*>(el)->spacerType() == SpacerType::DOWN)
|
2012-05-26 14:26:10 +02:00
|
|
|
staves[el->staffIdx()]->_vspacerDown = 0;
|
2014-05-26 12:46:24 +02:00
|
|
|
else if (static_cast<Spacer*>(el)->spacerType() == SpacerType::UP)
|
2012-05-26 14:26:10 +02:00
|
|
|
staves[el->staffIdx()]->_vspacerUp = 0;
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SEGMENT:
|
2012-05-26 14:26:10 +02:00
|
|
|
remove(static_cast<Segment*>(el));
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::JUMP:
|
2014-07-17 09:32:30 +02:00
|
|
|
resetRepeatFlag(Repeat::JUMP);
|
2012-05-26 14:26:10 +02:00
|
|
|
// fall through
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::HBOX:
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!_el.remove(el)) {
|
|
|
|
qDebug("Measure(%p)::remove(%s,%p) not found",
|
|
|
|
this, el->name(), el);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::CLEF:
|
|
|
|
case Element::Type::CHORD:
|
|
|
|
case Element::Type::REST:
|
|
|
|
case Element::Type::TIMESIG:
|
2012-05-26 14:26:10 +02:00
|
|
|
for (Segment* segment = first(); segment; segment = segment->next()) {
|
|
|
|
int staves = _score->nstaves();
|
|
|
|
int tracks = staves * VOICES;
|
|
|
|
for (int track = 0; track < tracks; ++track) {
|
|
|
|
Element* e = segment->element(track);
|
|
|
|
if (el == e) {
|
|
|
|
segment->setElement(track, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
qDebug("Measure::remove: %s %p not found", el->name(), el);
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::MEASURE:
|
2013-10-30 14:21:08 +01:00
|
|
|
_mmRest = 0;
|
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
|
|
|
MeasureBase::remove(el);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// change
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::change(Element* o, Element* n)
|
|
|
|
{
|
2014-06-24 18:36:02 +02:00
|
|
|
if (o->type() == Element::Type::TUPLET) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Tuplet* t = static_cast<Tuplet*>(n);
|
|
|
|
foreach(DurationElement* e, t->elements()) {
|
|
|
|
e->setTuplet(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
remove(o);
|
|
|
|
add(n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// moveTicks
|
|
|
|
// Also adjust endBarLine if measure len has changed. For this
|
|
|
|
// diff == 0 cannot be optimized away
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::moveTicks(int diff)
|
|
|
|
{
|
|
|
|
setTick(tick() + diff);
|
|
|
|
for (Segment* segment = first(); segment; segment = segment->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (segment->segmentType() & (Segment::Type::EndBarLine | Segment::Type::TimeSigAnnounce))
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->setTick(tick() + ticks());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::removeStaves(int sStaff, int eStaff)
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
|
|
|
for (int staff = eStaff-1; staff >= sStaff; --staff) {
|
|
|
|
s->removeStaff(staff);
|
|
|
|
}
|
|
|
|
}
|
2013-09-20 12:59:31 +02:00
|
|
|
foreach (Element* e, _el) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e->track() == -1)
|
|
|
|
continue;
|
|
|
|
int voice = e->voice();
|
|
|
|
int staffIdx = e->staffIdx();
|
|
|
|
if (staffIdx >= eStaff) {
|
|
|
|
staffIdx -= eStaff - sStaff;
|
|
|
|
e->setTrack(staffIdx * VOICES + voice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::insertStaves(int sStaff, int eStaff)
|
|
|
|
{
|
2013-09-20 12:59:31 +02:00
|
|
|
foreach (Element* e, _el) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e->track() == -1)
|
|
|
|
continue;
|
|
|
|
int staffIdx = e->staffIdx();
|
|
|
|
if (staffIdx >= sStaff) {
|
|
|
|
int voice = e->voice();
|
|
|
|
staffIdx += eStaff - sStaff;
|
|
|
|
e->setTrack(staffIdx * VOICES + voice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
|
|
|
for (int staff = sStaff; staff < eStaff; ++staff) {
|
|
|
|
s->insertStaff(staff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// cmdRemoveStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::cmdRemoveStaves(int sStaff, int eStaff)
|
|
|
|
{
|
|
|
|
int sTrack = sStaff * VOICES;
|
|
|
|
int eTrack = eStaff * VOICES;
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
|
|
|
for (int track = eTrack - 1; track >= sTrack; --track) {
|
|
|
|
Element* el = s->element(track);
|
2013-07-15 07:53:16 +02:00
|
|
|
if (el) {
|
2014-05-21 20:08:37 +02:00
|
|
|
el->undoUnlink();
|
|
|
|
_score->undo(new RemoveElement(el));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2014-05-21 20:08:37 +02:00
|
|
|
foreach (Element* e, s->annotations()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int staffIdx = e->staffIdx();
|
2014-05-23 09:50:53 +02:00
|
|
|
if ((staffIdx >= sStaff) && (staffIdx < eStaff) && !e->systemFlag()) {
|
2014-05-21 20:08:37 +02:00
|
|
|
e->undoUnlink();
|
|
|
|
_score->undo(new RemoveElement(e));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 20:08:37 +02:00
|
|
|
foreach (Element* e, _el) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e->track() == -1)
|
|
|
|
continue;
|
|
|
|
int staffIdx = e->staffIdx();
|
2014-05-21 20:08:37 +02:00
|
|
|
if (staffIdx >= sStaff && staffIdx < eStaff) {
|
|
|
|
e->undoUnlink();
|
|
|
|
_score->undo(new RemoveElement(e));
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_score->undo(new RemoveStaves(this, sStaff, eStaff));
|
|
|
|
|
|
|
|
for (int i = eStaff - 1; i >= sStaff; --i)
|
|
|
|
_score->undo(new RemoveMStaff(this, *(staves.begin()+i), i));
|
|
|
|
|
|
|
|
// barLine
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// cmdAddStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::cmdAddStaves(int sStaff, int eStaff, bool createRest)
|
|
|
|
{
|
|
|
|
_score->undo(new InsertStaves(this, sStaff, eStaff));
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* ts = findSegment(Segment::Type::TimeSig, tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
for (int i = sStaff; i < eStaff; ++i) {
|
|
|
|
Staff* staff = _score->staff(i);
|
|
|
|
MStaff* ms = new MStaff;
|
|
|
|
ms->lines = new StaffLines(score());
|
|
|
|
ms->lines->setTrack(i * VOICES);
|
|
|
|
// ms->lines->setLines(staff->lines());
|
|
|
|
ms->lines->setParent(this);
|
|
|
|
ms->lines->setVisible(!staff->invisible());
|
|
|
|
|
|
|
|
_score->undo(new InsertMStaff(this, ms, i));
|
|
|
|
|
|
|
|
if (createRest) {
|
2014-02-17 23:06:11 +01:00
|
|
|
if (_timesig != len()) {
|
|
|
|
score()->setRest(tick(), i * VOICES, len(), false, 0, false);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
score()->setRest(tick(), i * VOICES, len(), false, 0, true);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// replicate time signature
|
|
|
|
if (ts) {
|
|
|
|
TimeSig* ots = 0;
|
|
|
|
for (int track = 0; track < staves.size() * VOICES; ++track) {
|
|
|
|
if (ts->element(track)) {
|
|
|
|
ots = (TimeSig*)ts->element(track);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ots) {
|
|
|
|
TimeSig* timesig = new TimeSig(*ots);
|
|
|
|
timesig->setTrack(i * VOICES);
|
2013-03-05 20:23:59 +01:00
|
|
|
timesig->setSig(ots->sig(), ots->timeSigType());
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoAddElement(timesig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setTrack
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void MStaff::setTrack(int track)
|
|
|
|
{
|
|
|
|
if (lines)
|
|
|
|
lines->setTrack(track);
|
|
|
|
if (_vspacerUp)
|
|
|
|
_vspacerUp->setTrack(track);
|
|
|
|
if (_vspacerDown)
|
|
|
|
_vspacerDown->setTrack(track);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertMStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::insertMStaff(MStaff* staff, int idx)
|
|
|
|
{
|
|
|
|
staves.insert(idx, staff);
|
|
|
|
for (int staffIdx = 0; staffIdx < staves.size(); ++staffIdx)
|
|
|
|
staves[staffIdx]->setTrack(staffIdx * VOICES);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeMStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::removeMStaff(MStaff* /*staff*/, int idx)
|
|
|
|
{
|
|
|
|
staves.removeAt(idx);
|
|
|
|
for (int staffIdx = 0; staffIdx < staves.size(); ++staffIdx)
|
|
|
|
staves[staffIdx]->setTrack(staffIdx * VOICES);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::insertStaff(Staff* staff, int staffIdx)
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s; s = s->next())
|
|
|
|
s->insertStaff(staffIdx);
|
|
|
|
|
|
|
|
MStaff* ms = new MStaff;
|
|
|
|
ms->lines = new StaffLines(score());
|
|
|
|
ms->lines->setParent(this);
|
|
|
|
ms->lines->setTrack(staffIdx * VOICES);
|
|
|
|
// ms->distanceUp = 0.0;
|
2014-05-26 15:31:36 +02:00
|
|
|
// ms->distanceDown = 0.0; // TODO point(staffIdx == 0 ? score()->styleS(StyleIdx::minSystemDistance) : score()->styleS(StyleIdx::staffDistance));
|
2012-05-26 14:26:10 +02:00
|
|
|
ms->lines->setVisible(!staff->invisible());
|
|
|
|
insertMStaff(ms, staffIdx);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// staffabbox
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QRectF Measure::staffabbox(int staffIdx) const
|
|
|
|
{
|
|
|
|
System* s = system();
|
|
|
|
QRectF sb(s->staff(staffIdx)->bbox());
|
|
|
|
QRectF rrr(sb.translated(s->pagePos()));
|
|
|
|
QRectF rr(abbox());
|
|
|
|
QRectF r(rr.x(), rrr.y(), rr.width(), rrr.height());
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// acceptDrop
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
Return true if an Element of type \a type can be dropped on a Measure
|
|
|
|
*/
|
|
|
|
|
2014-06-19 15:27:44 +02:00
|
|
|
bool Measure::acceptDrop(MuseScoreView* viewer, const QPointF&, Element* e) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-06-19 15:27:44 +02:00
|
|
|
switch (e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::MEASURE_LIST:
|
|
|
|
case Element::Type::JUMP:
|
|
|
|
case Element::Type::MARKER:
|
|
|
|
case Element::Type::LAYOUT_BREAK:
|
|
|
|
case Element::Type::STAFF_LIST:
|
|
|
|
case Element::Type::BRACKET:
|
|
|
|
case Element::Type::REPEAT_MEASURE:
|
|
|
|
case Element::Type::MEASURE:
|
|
|
|
case Element::Type::SPACER:
|
|
|
|
case Element::Type::IMAGE:
|
|
|
|
case Element::Type::BAR_LINE:
|
|
|
|
case Element::Type::SYMBOL:
|
|
|
|
case Element::Type::CLEF:
|
|
|
|
case Element::Type::KEYSIG:
|
|
|
|
case Element::Type::TIMESIG:
|
2014-06-19 15:27:44 +02:00
|
|
|
viewer->setDropRectangle(canvasBoundingRect());
|
2012-05-26 14:26:10 +02:00
|
|
|
return true;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ICON:
|
2013-03-05 20:23:59 +01:00
|
|
|
switch(static_cast<Icon*>(e)->iconType()) {
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::VFRAME:
|
|
|
|
case IconType::HFRAME:
|
|
|
|
case IconType::TFRAME:
|
|
|
|
case IconType::FFRAME:
|
|
|
|
case IconType::MEASURE:
|
2014-06-19 15:27:44 +02:00
|
|
|
viewer->setDropRectangle(canvasBoundingRect());
|
2012-05-26 14:26:10 +02:00
|
|
|
return true;
|
2014-05-30 10:14:57 +02:00
|
|
|
default:
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// drop
|
|
|
|
/// Drop element.
|
|
|
|
/// Handle a dropped element at position \a pos of given
|
|
|
|
/// element \a type and \a subtype.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* Measure::drop(const DropData& data)
|
|
|
|
{
|
|
|
|
Element* e = data.element;
|
|
|
|
int staffIdx;
|
|
|
|
Segment* seg;
|
|
|
|
_score->pos2measure(data.pos, &staffIdx, 0, &seg, 0);
|
|
|
|
|
|
|
|
if (e->systemFlag())
|
|
|
|
staffIdx = 0;
|
2014-06-04 13:48:10 +02:00
|
|
|
#if 0 // yet(?) unused
|
2012-05-26 14:26:10 +02:00
|
|
|
QPointF mrp(data.pos - pagePos());
|
2014-06-04 13:48:10 +02:00
|
|
|
#endif
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
|
|
|
|
switch(e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::MEASURE_LIST:
|
2012-05-26 14:26:10 +02:00
|
|
|
qDebug("drop measureList or StaffList");
|
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::STAFF_LIST:
|
2012-05-26 14:26:10 +02:00
|
|
|
qDebug("drop staffList");
|
|
|
|
//TODO score()->pasteStaff(e, this, staffIdx);
|
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::MARKER:
|
|
|
|
case Element::Type::JUMP:
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setParent(seg);
|
|
|
|
e->setTrack(0);
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::DYNAMIC:
|
|
|
|
case Element::Type::FRET_DIAGRAM:
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setParent(seg);
|
|
|
|
e->setTrack(staffIdx * VOICES);
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::IMAGE:
|
|
|
|
case Element::Type::SYMBOL:
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setParent(seg);
|
|
|
|
e->setTrack(staffIdx * VOICES);
|
|
|
|
e->layout();
|
|
|
|
{
|
|
|
|
QPointF uo(data.pos - e->canvasPos() - data.dragOffset);
|
|
|
|
e->setUserOff(uo);
|
|
|
|
}
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::BRACKET:
|
2013-06-28 17:46:24 +02:00
|
|
|
{
|
|
|
|
Bracket* b = static_cast<Bracket*>(e);
|
|
|
|
int level = 0;
|
|
|
|
int firstStaff = 0;
|
|
|
|
foreach (Staff* s, score()->staves()) {
|
|
|
|
foreach (const BracketItem& bi, s->brackets()) {
|
|
|
|
int lastStaff = firstStaff + bi._bracketSpan - 1;
|
|
|
|
if (staffIdx >= firstStaff && staffIdx <= lastStaff)
|
|
|
|
++level;
|
|
|
|
}
|
2013-09-09 11:31:07 +02:00
|
|
|
firstStaff++;
|
2013-06-28 17:46:24 +02:00
|
|
|
}
|
|
|
|
score()->undoAddBracket(staff, level, b->bracketType(), 1);
|
|
|
|
delete b;
|
|
|
|
}
|
|
|
|
return 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::CLEF:
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoChangeClef(staff, first(), static_cast<Clef*>(e)->clefType());
|
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::KEYSIG:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
KeySig* ks = static_cast<KeySig*>(e);
|
|
|
|
KeySigEvent k = ks->keySigEvent();
|
|
|
|
//add custom key to score if not exist
|
|
|
|
if (k.custom()) {
|
|
|
|
int customIdx = score()->customKeySigIdx(ks);
|
|
|
|
if (customIdx == -1) {
|
|
|
|
customIdx = score()->addCustomKeySig(ks);
|
|
|
|
k.setCustomType(customIdx);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
delete ks;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
delete ks;
|
2014-06-03 15:28:10 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
if (data.modifiers & Qt::ControlModifier) {
|
2012-08-09 21:54:27 +02:00
|
|
|
// apply only to this stave
|
2014-06-20 17:07:22 +02:00
|
|
|
score()->undoChangeKeySig(staff, tick(), k.key());
|
2012-08-09 21:54:27 +02:00
|
|
|
}
|
|
|
|
else {
|
2012-05-26 14:26:10 +02:00
|
|
|
// apply to all staves:
|
|
|
|
foreach(Staff* s, score()->staves())
|
2014-06-20 17:07:22 +02:00
|
|
|
score()->undoChangeKeySig(s, tick(), k.key());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-08-10 10:14:17 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TIMESIG:
|
2012-06-28 09:28:13 +02:00
|
|
|
score()->cmdAddTimeSig(this, staffIdx, static_cast<TimeSig*>(e),
|
|
|
|
data.modifiers & Qt::ControlModifier);
|
2012-05-26 14:26:10 +02:00
|
|
|
return 0;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::LAYOUT_BREAK:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
LayoutBreak* lb = static_cast<LayoutBreak*>(e);
|
|
|
|
if (
|
2014-06-25 13:57:29 +02:00
|
|
|
(lb->layoutBreakType() == LayoutBreak::Type::PAGE && _pageBreak)
|
|
|
|
|| (lb->layoutBreakType() == LayoutBreak::Type::LINE && _lineBreak)
|
|
|
|
|| (lb->layoutBreakType() == LayoutBreak::Type::SECTION && _sectionBreak)
|
2012-05-26 14:26:10 +02:00
|
|
|
) {
|
|
|
|
//
|
|
|
|
// if break already set
|
|
|
|
//
|
|
|
|
delete lb;
|
|
|
|
break;
|
|
|
|
}
|
2014-06-25 13:57:29 +02:00
|
|
|
// make sure there is only LayoutBreak::Type::LINE or LayoutBreak::Type::PAGE
|
|
|
|
if ((lb->layoutBreakType() != LayoutBreak::Type::SECTION) && (_pageBreak || _lineBreak)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
foreach(Element* le, _el) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (le->type() == Element::Type::LAYOUT_BREAK
|
2014-06-25 13:57:29 +02:00
|
|
|
&& (static_cast<LayoutBreak*>(le)->layoutBreakType() == LayoutBreak::Type::LINE
|
|
|
|
|| static_cast<LayoutBreak*>(le)->layoutBreakType() == LayoutBreak::Type::PAGE)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoChangeElement(le, e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lb->setTrack(-1); // this are system elements
|
|
|
|
lb->setParent(this);
|
|
|
|
score()->undoAddElement(lb);
|
|
|
|
return lb;
|
|
|
|
}
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SPACER:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Spacer* spacer = static_cast<Spacer*>(e);
|
|
|
|
spacer->setTrack(staffIdx * VOICES);
|
|
|
|
spacer->setParent(this);
|
|
|
|
score()->undoAddElement(spacer);
|
|
|
|
return spacer;
|
|
|
|
}
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::BAR_LINE:
|
2012-11-09 17:31:50 +01:00
|
|
|
{
|
|
|
|
BarLine* bl = static_cast<BarLine*>(e);
|
|
|
|
// if dropped bar line refers to span rather than to subtype
|
|
|
|
if (bl->spanFrom() != 0 && bl->spanTo() != DEFAULT_BARLINE_TO) {
|
|
|
|
// get existing bar line for this staff, and drop the change to it
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* seg = undoGetSegment(Segment::Type::EndBarLine, tick() + ticks());
|
2012-11-09 17:31:50 +01:00
|
|
|
BarLine* cbl = static_cast<BarLine*>(seg->element(staffIdx * VOICES));
|
|
|
|
if (cbl)
|
|
|
|
cbl->drop(data);
|
|
|
|
}
|
|
|
|
// if dropped bar line refers to line subtype
|
|
|
|
else {
|
2013-03-05 20:23:59 +01:00
|
|
|
score()->undoChangeBarLine(this, bl->barLineType());
|
2012-11-09 17:31:50 +01:00
|
|
|
delete e;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2012-11-09 17:31:50 +01:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::REPEAT_MEASURE:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
delete e;
|
2013-09-26 20:07:58 +02:00
|
|
|
return cmdInsertRepeatMeasure(staffIdx);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ICON:
|
2013-03-05 20:23:59 +01:00
|
|
|
switch(static_cast<Icon*>(e)->iconType()) {
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::VFRAME:
|
2014-06-24 18:36:02 +02:00
|
|
|
score()->insertMeasure(Element::Type::VBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::HFRAME:
|
2014-06-24 18:36:02 +02:00
|
|
|
score()->insertMeasure(Element::Type::HBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::TFRAME:
|
2014-06-24 18:36:02 +02:00
|
|
|
score()->insertMeasure(Element::Type::TBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::FFRAME:
|
2014-06-24 18:36:02 +02:00
|
|
|
score()->insertMeasure(Element::Type::FBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::MEASURE:
|
2014-06-24 18:36:02 +02:00
|
|
|
score()->insertMeasure(Element::Type::MEASURE, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
default:
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
qDebug("Measure: cannot drop %s here", e->name());
|
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-26 20:07:58 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// cmdInsertRepeatMeasure
|
|
|
|
//---------------------------------------------------------
|
2014-05-20 17:26:26 +02:00
|
|
|
|
2013-09-26 20:07:58 +02:00
|
|
|
RepeatMeasure* Measure::cmdInsertRepeatMeasure(int staffIdx)
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// see also cmdDeleteSelection()
|
|
|
|
//
|
2014-05-27 10:34:08 +02:00
|
|
|
_score->select(0, SelectType::SINGLE, 0);
|
2013-09-26 20:07:58 +02:00
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() & Segment::Type::ChordRest) {
|
2013-09-26 20:07:58 +02:00
|
|
|
int strack = staffIdx * VOICES;
|
|
|
|
int etrack = strack + VOICES;
|
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* el = s->element(track);
|
|
|
|
if (el)
|
|
|
|
_score->undoRemoveElement(el);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// add repeat measure
|
|
|
|
//
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* seg = undoGetSegment(Segment::Type::ChordRest, tick());
|
2013-09-26 20:07:58 +02:00
|
|
|
RepeatMeasure* rm = new RepeatMeasure(_score);
|
|
|
|
rm->setTrack(staffIdx * VOICES);
|
|
|
|
rm->setParent(seg);
|
2014-05-29 14:04:14 +02:00
|
|
|
_score->undoAddCR(rm, this, tick());
|
2014-05-20 17:26:26 +02:00
|
|
|
foreach (Element* el, _el) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (el->type() == Element::Type::SLUR && el->staffIdx() == staffIdx)
|
2013-09-26 20:07:58 +02:00
|
|
|
_score->undoRemoveElement(el);
|
|
|
|
}
|
|
|
|
return rm;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// adjustToLen
|
|
|
|
// change actual measure len, adjust elements to
|
|
|
|
// new len
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::adjustToLen(Fraction nf)
|
|
|
|
{
|
2014-05-20 17:26:26 +02:00
|
|
|
int ol = len().ticks();
|
|
|
|
int nl = nf.ticks();
|
|
|
|
int diff = nl - ol;
|
2014-02-11 17:39:44 +01:00
|
|
|
|
|
|
|
int startTick = endTick();
|
|
|
|
if (diff < 0)
|
|
|
|
startTick += diff;
|
2013-10-21 13:11:04 +02:00
|
|
|
|
2014-05-20 17:26:26 +02:00
|
|
|
score()->undoInsertTime(startTick, diff);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-05-20 17:26:26 +02:00
|
|
|
for (Score* s : score()->scoreList()) {
|
|
|
|
Measure* m = s->tick2measure(tick());
|
|
|
|
s->undo(new ChangeMeasureLen(m, nf));
|
|
|
|
if (nl > ol) {
|
|
|
|
// move EndBarLine, TimeSigAnnounce, KeySigAnnounce
|
|
|
|
for (Segment* s = m->first(); s; s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() & (Segment::Type::EndBarLine|Segment::Type::TimeSigAnnounce|Segment::Type::KeySigAnnounce)) {
|
2014-05-20 17:26:26 +02:00
|
|
|
s->setTick(tick() + nl);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-22 16:18:35 +02:00
|
|
|
Score* s = score()->rootScore();
|
|
|
|
Measure* m = this;
|
|
|
|
QList<int> sl = s->uniqueStaves();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-05-22 16:18:35 +02:00
|
|
|
for (int staffIdx : sl) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int rests = 0;
|
|
|
|
int chords = 0;
|
|
|
|
Rest* rest = 0;
|
2014-05-20 17:26:26 +02:00
|
|
|
for (Segment* segment = m->first(); segment; segment = segment->next()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int strack = staffIdx * VOICES;
|
|
|
|
int etrack = strack + VOICES;
|
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* e = segment->element(track);
|
2013-10-21 13:11:04 +02:00
|
|
|
if (e) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() == Element::Type::REST) {
|
2013-10-21 13:11:04 +02:00
|
|
|
++rests;
|
|
|
|
rest = static_cast<Rest*>(e);
|
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (e->type() == Element::Type::CHORD)
|
2013-10-21 13:11:04 +02:00
|
|
|
++chords;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-28 23:30:57 +01:00
|
|
|
// if just a single rest
|
2013-10-21 13:11:04 +02:00
|
|
|
if (rests == 1 && chords == 0) {
|
2014-03-28 23:30:57 +01:00
|
|
|
// if measure value didn't change, stick to whole measure rest
|
2014-05-20 17:26:26 +02:00
|
|
|
if (_timesig == nf)
|
2014-05-21 15:43:19 +02:00
|
|
|
s->undo(new ChangeChordRestLen(rest, TDuration(TDuration::DurationType::V_MEASURE)));
|
2014-05-20 17:26:26 +02:00
|
|
|
else { // if measure value did change, represent with rests actual measure value
|
2014-03-28 23:30:57 +01:00
|
|
|
// convert the measure duration in a list of values (no dots for rests)
|
|
|
|
QList<TDuration> durList = toDurationList(nf, false, 0);
|
2014-05-20 17:26:26 +02:00
|
|
|
|
2014-03-28 23:30:57 +01:00
|
|
|
// set the existing rest to the first value of the duration list
|
2014-05-20 17:26:26 +02:00
|
|
|
s->undo(new ChangeChordRestLen(rest, durList[0]));
|
|
|
|
|
2014-03-28 23:30:57 +01:00
|
|
|
// add rests for any other duration list value
|
2014-03-29 14:03:41 +01:00
|
|
|
int tickOffset = tick() + durList[0].ticks();
|
2014-03-28 23:30:57 +01:00
|
|
|
for (int i = 1; i < durList.count(); i++) {
|
2014-05-20 17:26:26 +02:00
|
|
|
Rest* newRest = new Rest(s);
|
2014-03-28 23:30:57 +01:00
|
|
|
newRest->setDurationType(durList.at(i));
|
|
|
|
newRest->setDuration(durList.at(i).fraction());
|
|
|
|
newRest->setTrack(rest->track());
|
|
|
|
score()->undoAddCR(newRest, this, tickOffset);
|
|
|
|
tickOffset += durList.at(i).ticks();
|
|
|
|
}
|
|
|
|
}
|
2014-05-20 17:26:26 +02:00
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-02-17 23:06:11 +01:00
|
|
|
|
2013-10-21 13:11:04 +02:00
|
|
|
int strack = staffIdx * VOICES;
|
|
|
|
int etrack = strack + VOICES;
|
|
|
|
|
|
|
|
for (int trk = strack; trk < etrack; ++trk) {
|
|
|
|
int n = diff;
|
|
|
|
bool rFlag = false;
|
|
|
|
if (n < 0) {
|
2014-05-20 17:26:26 +02:00
|
|
|
for (Segment* segment = m->last(); segment;) {
|
2013-10-21 13:11:04 +02:00
|
|
|
Segment* pseg = segment->prev();
|
|
|
|
Element* e = segment->element(trk);
|
|
|
|
if (e && e->isChordRest()) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(e);
|
2014-05-21 15:43:19 +02:00
|
|
|
if (cr->durationType() == TDuration::DurationType::V_MEASURE) {
|
2014-02-17 23:06:11 +01:00
|
|
|
int actualTicks = cr->actualTicks();
|
|
|
|
n += actualTicks;
|
|
|
|
cr->setDurationType(TDuration(actualTicks));
|
|
|
|
}
|
2013-10-21 13:11:04 +02:00
|
|
|
else
|
|
|
|
n += cr->actualTicks();
|
2014-05-20 17:26:26 +02:00
|
|
|
s->undoRemoveElement(e);
|
2013-10-21 13:11:04 +02:00
|
|
|
if (n >= 0)
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-10-21 13:11:04 +02:00
|
|
|
segment = pseg;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-10-21 13:11:04 +02:00
|
|
|
rFlag = true;
|
|
|
|
}
|
|
|
|
int voice = trk % VOICES;
|
|
|
|
if ((n > 0) && (rFlag || voice == 0)) {
|
|
|
|
// add rest to measure
|
|
|
|
int rtick = tick() + nl - n;
|
|
|
|
int track = staffIdx * VOICES + voice;
|
2014-05-20 17:26:26 +02:00
|
|
|
s->setRest(rtick, track, Fraction::fromTicks(n), false, 0, false);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (diff < 0) {
|
|
|
|
//
|
|
|
|
// CHECK: do not remove all slurs
|
|
|
|
//
|
2014-05-20 17:26:26 +02:00
|
|
|
foreach(Element* e, *m->el()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() == Element::Type::SLUR)
|
2014-05-20 17:26:26 +02:00
|
|
|
s->undoRemoveElement(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::write(Xml& xml, int staff, bool writeSystemElements) const
|
|
|
|
{
|
|
|
|
int mno = _no + 1;
|
|
|
|
if (_len != _timesig) {
|
|
|
|
// this is an irregular measure
|
|
|
|
xml.stag(QString("Measure number=\"%1\" len=\"%2/%3\"").arg(mno).arg(_len.numerator()).arg(_len.denominator()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
xml.stag(QString("Measure number=\"%1\"").arg(mno));
|
2014-02-28 14:25:47 +01:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.curTick = tick();
|
|
|
|
|
2014-02-26 19:06:42 +01:00
|
|
|
if (_mmRestCount > 0)
|
|
|
|
xml.tag("multiMeasureRest", _mmRestCount);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (writeSystemElements) {
|
2014-05-23 12:10:15 +02:00
|
|
|
if (_repeatFlags & Repeat::START)
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.tagE("startRepeat");
|
2014-05-23 12:10:15 +02:00
|
|
|
if (_repeatFlags & Repeat::END)
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.tag("endRepeat", _repeatCount);
|
|
|
|
if (_irregular)
|
|
|
|
xml.tagE("irregular");
|
|
|
|
if (_breakMultiMeasureRest)
|
|
|
|
xml.tagE("breakMultiMeasureRest");
|
|
|
|
if (_userStretch != 1.0)
|
|
|
|
xml.tag("stretch", _userStretch);
|
|
|
|
if (_noOffset)
|
|
|
|
xml.tag("noOffset", _noOffset);
|
|
|
|
}
|
|
|
|
qreal _spatium = spatium();
|
|
|
|
MStaff* mstaff = staves[staff];
|
2013-03-08 16:07:03 +01:00
|
|
|
if (mstaff->noText() && !mstaff->noText()->generated()) {
|
|
|
|
xml.stag("MeasureNumber");
|
|
|
|
mstaff->noText()->writeProperties(xml);
|
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
if (mstaff->_vspacerUp)
|
|
|
|
xml.tag("vspacerUp", mstaff->_vspacerUp->gap() / _spatium);
|
|
|
|
if (mstaff->_vspacerDown)
|
|
|
|
xml.tag("vspacerDown", mstaff->_vspacerDown->gap() / _spatium);
|
|
|
|
if (!mstaff->_visible)
|
|
|
|
xml.tag("visible", mstaff->_visible);
|
|
|
|
if (mstaff->_slashStyle)
|
|
|
|
xml.tag("slashStyle", mstaff->_slashStyle);
|
|
|
|
|
|
|
|
int strack = staff * VOICES;
|
|
|
|
int etrack = strack + VOICES;
|
|
|
|
foreach (const Element* el, _el) {
|
2012-09-21 12:23:18 +02:00
|
|
|
if (!el->generated() && ((el->staffIdx() == staff) || (el->systemFlag() && writeSystemElements))) {
|
2012-05-26 14:26:10 +02:00
|
|
|
el->write(xml);
|
|
|
|
}
|
|
|
|
}
|
2013-09-19 15:08:54 +02:00
|
|
|
Q_ASSERT(first());
|
|
|
|
Q_ASSERT(last());
|
2013-10-13 13:06:32 +02:00
|
|
|
score()->writeSegments(xml, strack, etrack, first(), last()->next1(), writeSystemElements, false, false);
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
2014-02-26 19:06:42 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// ticks
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Measure::ticks() const
|
|
|
|
{
|
|
|
|
return _len.ticks();
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Measure::read
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
void Measure::read(XmlReader& e, int staffIdx)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Segment* segment = 0;
|
|
|
|
qreal _spatium = spatium();
|
|
|
|
|
2013-06-16 23:33:37 +02:00
|
|
|
QList<Chord*> graceNotes;
|
|
|
|
|
2013-09-05 19:02:43 +02:00
|
|
|
//sort tuplet elements. needed for nested tuplets #22537
|
|
|
|
if (score()->mscVersion() <= 114) {
|
2014-04-23 20:59:32 +02:00
|
|
|
for (Tuplet* t : e.tuplets()) {
|
2013-09-05 19:02:43 +02:00
|
|
|
t->sortElements();
|
|
|
|
}
|
|
|
|
}
|
2013-01-23 14:14:09 +01:00
|
|
|
e.tuplets().clear();
|
2013-06-10 21:13:04 +02:00
|
|
|
e.setTrack(staffIdx * VOICES);
|
2013-01-23 14:14:09 +01:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int n = staves.size(); n <= staffIdx; ++n) {
|
|
|
|
Staff* staff = score()->staff(n);
|
2012-09-14 10:09:06 +02:00
|
|
|
MStaff* s = new MStaff;
|
2012-05-26 14:26:10 +02:00
|
|
|
s->lines = new StaffLines(score());
|
|
|
|
s->lines->setParent(this);
|
|
|
|
s->lines->setTrack(n * VOICES);
|
|
|
|
s->lines->setVisible(!staff->invisible());
|
|
|
|
staves.append(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
// tick is obsolete
|
2013-01-11 18:10:18 +01:00
|
|
|
if (e.hasAttribute("tick"))
|
2014-07-21 14:16:16 +02:00
|
|
|
e.initTick(score()->fileDivision(e.intAttribute("tick")));
|
2013-06-24 19:01:31 +02:00
|
|
|
// setTick(e.tick());
|
2013-06-10 21:13:04 +02:00
|
|
|
// e.setTick(tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-06-04 18:29:14 +02:00
|
|
|
bool irregular;
|
2013-01-11 18:10:18 +01:00
|
|
|
if (e.hasAttribute("len")) {
|
|
|
|
QStringList sl = e.attribute("len").split('/');
|
2012-05-26 14:26:10 +02:00
|
|
|
if (sl.size() == 2)
|
|
|
|
_len = Fraction(sl[0].toInt(), sl[1].toInt());
|
|
|
|
else
|
2013-01-11 18:10:18 +01:00
|
|
|
qDebug("illegal measure size <%s>", qPrintable(e.attribute("len")));
|
2012-05-26 14:26:10 +02:00
|
|
|
irregular = true;
|
|
|
|
score()->sigmap()->add(tick(), SigEvent(_len, _timesig));
|
|
|
|
score()->sigmap()->add(tick() + ticks(), SigEvent(_timesig));
|
|
|
|
}
|
2013-06-04 18:29:14 +02:00
|
|
|
else
|
2012-10-25 14:50:17 +02:00
|
|
|
irregular = false;
|
2013-06-04 18:29:14 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2012-06-28 15:12:17 +02:00
|
|
|
Fraction timeStretch(staff->timeStretch(tick()));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
const QStringRef& tag(e.name());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
if (tag == "tick")
|
2014-07-21 14:16:16 +02:00
|
|
|
e.initTick(e.readInt());
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "BarLine") {
|
|
|
|
BarLine* barLine = new BarLine(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
barLine->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
barLine->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type st;
|
2014-01-07 11:42:17 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// SegStartRepeatBarLine: always at the beginning tick of a measure
|
|
|
|
// SegBarLine: in the middle of a measure, has no semantic
|
|
|
|
// SegEndBarLine: at the end tick of a measure
|
|
|
|
|
2014-02-26 19:06:42 +01:00
|
|
|
if (isMMRest()) {
|
|
|
|
// this is a multi measure rest
|
|
|
|
// always preceded by the first measure it replaces
|
|
|
|
Measure* m = e.lastMeasure();
|
|
|
|
Q_ASSERT(m); // debug
|
|
|
|
if (m) {
|
|
|
|
m->setMMRest(this);
|
|
|
|
setTick(m->tick());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((e.tick() != tick()) && (e.tick() != endTick())) {
|
2014-06-25 11:46:10 +02:00
|
|
|
st = Segment::Type::BarLine;
|
2014-02-26 19:06:42 +01:00
|
|
|
}
|
2014-05-30 10:14:09 +02:00
|
|
|
else if (barLine->barLineType() == BarLineType::START_REPEAT && e.tick() == tick())
|
2014-06-25 11:46:10 +02:00
|
|
|
st = Segment::Type::StartRepeatBarLine;
|
2012-05-26 14:26:10 +02:00
|
|
|
else {
|
2014-06-25 10:19:37 +02:00
|
|
|
if (!barLine->customSubtype())
|
|
|
|
setEndBarLineType(barLine->barLineType(), false, true);
|
|
|
|
if (!barLine->customSpan()) {
|
2012-10-14 13:46:04 +02:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
barLine->setSpan(staff->barLineSpan());
|
|
|
|
}
|
2014-06-25 11:46:10 +02:00
|
|
|
st = Segment::Type::EndBarLine;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-12-31 12:33:30 +01:00
|
|
|
segment = getSegment(st, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(barLine);
|
|
|
|
}
|
|
|
|
else if (tag == "Chord") {
|
2013-06-19 18:20:09 +02:00
|
|
|
|
2013-06-16 23:33:37 +02:00
|
|
|
Chord* chord = new Chord(score());
|
|
|
|
chord->setTrack(e.track());
|
|
|
|
chord->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2013-06-10 21:13:04 +02:00
|
|
|
|
2014-05-27 10:35:28 +02:00
|
|
|
if (chord->noteType() != NoteType::NORMAL)
|
2013-06-16 23:33:37 +02:00
|
|
|
graceNotes.push_back(chord);
|
2012-05-26 14:26:10 +02:00
|
|
|
else {
|
2013-06-16 23:33:37 +02:00
|
|
|
segment->add(chord);
|
2014-06-25 11:46:10 +02:00
|
|
|
Q_ASSERT(segment->segmentType() == Segment::Type::ChordRest);
|
2013-06-24 13:46:21 +02:00
|
|
|
|
2013-06-16 23:33:37 +02:00
|
|
|
for (int i = 0; i < graceNotes.size(); ++i) {
|
|
|
|
Chord* gc = graceNotes[i];
|
|
|
|
gc->setGraceIndex(i);
|
|
|
|
chord->add(gc);
|
|
|
|
}
|
|
|
|
graceNotes.clear();
|
|
|
|
|
2013-06-10 21:13:04 +02:00
|
|
|
Fraction ts(timeStretch * chord->globalDuration());
|
|
|
|
int crticks = ts.ticks();
|
|
|
|
|
2014-05-26 11:35:24 +02:00
|
|
|
if (chord->tremolo() && chord->tremolo()->tremoloType() < TremoloType::R8) {
|
2013-06-10 21:13:04 +02:00
|
|
|
//
|
|
|
|
// old style tremolo found
|
|
|
|
//
|
|
|
|
Tremolo* tremolo = chord->tremolo();
|
|
|
|
TremoloType st;
|
|
|
|
switch (tremolo->tremoloType()) {
|
|
|
|
default:
|
2014-05-26 11:35:24 +02:00
|
|
|
case TremoloType::OLD_R8: st = TremoloType::R8; break;
|
|
|
|
case TremoloType::OLD_R16: st = TremoloType::R16; break;
|
|
|
|
case TremoloType::OLD_R32: st = TremoloType::R32; break;
|
|
|
|
case TremoloType::OLD_C8: st = TremoloType::C8; break;
|
|
|
|
case TremoloType::OLD_C16: st = TremoloType::C16; break;
|
|
|
|
case TremoloType::OLD_C32: st = TremoloType::C32; break;
|
2013-06-10 21:13:04 +02:00
|
|
|
}
|
|
|
|
tremolo->setTremoloType(st);
|
|
|
|
if (tremolo->twoNotes()) {
|
|
|
|
int track = chord->track();
|
|
|
|
Segment* ss = 0;
|
2014-06-25 11:46:10 +02:00
|
|
|
for (Segment* ps = first(Segment::Type::ChordRest); ps; ps = ps->next(Segment::Type::ChordRest)) {
|
2013-06-10 21:13:04 +02:00
|
|
|
if (ps->tick() >= e.tick())
|
|
|
|
break;
|
|
|
|
if (ps->element(track))
|
|
|
|
ss = ps;
|
|
|
|
}
|
|
|
|
Chord* pch = 0; // previous chord
|
|
|
|
if (ss) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(ss->element(track));
|
2014-06-24 18:36:02 +02:00
|
|
|
if (cr && cr->type() == Element::Type::CHORD)
|
2013-06-10 21:13:04 +02:00
|
|
|
pch = static_cast<Chord*>(cr);
|
|
|
|
}
|
|
|
|
if (pch) {
|
|
|
|
tremolo->setParent(pch);
|
|
|
|
pch->setTremolo(tremolo);
|
|
|
|
chord->setTremolo(0);
|
2013-06-27 18:31:00 +02:00
|
|
|
// force duration to half
|
2013-06-27 10:03:36 +02:00
|
|
|
Fraction pts(timeStretch * pch->globalDuration());
|
|
|
|
int pcrticks = pts.ticks();
|
|
|
|
pch->setDuration(pcrticks / 2);
|
|
|
|
chord->setDuration(crticks / 2);
|
2013-06-10 21:13:04 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
qDebug("tremolo: first note not found");
|
|
|
|
}
|
|
|
|
crticks /= 2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tremolo->setParent(chord);
|
|
|
|
}
|
|
|
|
}
|
2014-07-21 14:16:16 +02:00
|
|
|
e.incTick(crticks);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tag == "Rest") {
|
|
|
|
Rest* rest = new Rest(score());
|
2014-05-21 15:43:19 +02:00
|
|
|
rest->setDurationType(TDuration::DurationType::V_MEASURE);
|
2012-05-26 14:26:10 +02:00
|
|
|
rest->setDuration(timesig()/timeStretch);
|
2013-01-21 20:21:41 +01:00
|
|
|
rest->setTrack(e.track());
|
2013-01-08 11:00:53 +01:00
|
|
|
rest->read(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-01-21 20:21:41 +01:00
|
|
|
segment = getSegment(rest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(rest);
|
|
|
|
if (!rest->duration().isValid()) // hack
|
|
|
|
rest->setDuration(timesig()/timeStretch);
|
|
|
|
Fraction ts(timeStretch * rest->globalDuration());
|
|
|
|
|
2014-07-21 14:16:16 +02:00
|
|
|
e.incTick(ts.ticks());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Breath") {
|
|
|
|
Breath* breath = new Breath(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
breath->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
breath->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::Breath, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(breath);
|
|
|
|
}
|
|
|
|
else if (tag == "endSpanner") {
|
|
|
|
int id = e.attribute("id").toInt();
|
2014-07-21 13:24:21 +02:00
|
|
|
Spanner* spanner = e.findSpanner(id);
|
2013-01-11 18:10:18 +01:00
|
|
|
if (spanner) {
|
2013-06-25 14:29:18 +02:00
|
|
|
spanner->setTick2(e.tick());
|
2013-10-13 11:36:08 +02:00
|
|
|
// if (spanner->track2() == -1)
|
2014-01-18 18:19:46 +01:00
|
|
|
// the absence of a track tag [?] means the
|
|
|
|
// track is the same as the beginning of the slur
|
2014-03-15 12:57:36 +01:00
|
|
|
if (spanner->track2() == -1)
|
2014-01-23 23:13:33 +01:00
|
|
|
spanner->setTrack2(spanner->track() ? spanner->track() : e.track());
|
2014-07-15 12:49:51 +02:00
|
|
|
if (spanner->type() == Element::Type::HAIRPIN) {
|
2013-01-11 18:10:18 +01:00
|
|
|
Hairpin* hp = static_cast<Hairpin*>(spanner);
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->updateHairpin(hp);
|
|
|
|
}
|
|
|
|
}
|
2013-10-13 13:06:32 +02:00
|
|
|
else {
|
|
|
|
// remember "endSpanner" values
|
|
|
|
SpannerValues sv;
|
|
|
|
sv.spannerId = id;
|
|
|
|
sv.track2 = e.track();
|
|
|
|
sv.tick2 = e.tick();
|
|
|
|
e.addSpannerValues(sv);
|
|
|
|
}
|
2013-01-11 18:10:18 +01:00
|
|
|
e.readNext();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-01-21 22:30:59 +01:00
|
|
|
else if (tag == "Slur") {
|
|
|
|
Slur *sl = new Slur(score());
|
|
|
|
sl->setTick(e.tick());
|
|
|
|
sl->read(e);
|
|
|
|
score()->addSpanner(sl);
|
|
|
|
//
|
|
|
|
// check if we already saw "endSpanner"
|
|
|
|
//
|
2014-07-21 13:24:21 +02:00
|
|
|
int id = e.spannerId(sl);
|
|
|
|
const SpannerValues* sv = e.spannerValues(id);
|
2014-01-21 22:30:59 +01:00
|
|
|
if (sv) {
|
|
|
|
sl->setTick2(sv->tick2);
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "HairPin"
|
|
|
|
|| tag == "Pedal"
|
|
|
|
|| tag == "Ottava"
|
|
|
|
|| tag == "Trill"
|
|
|
|
|| tag == "TextLine"
|
|
|
|
|| tag == "Volta") {
|
2013-01-18 10:55:52 +01:00
|
|
|
Spanner* sp = static_cast<Spanner*>(Element::name2Element(tag, score()));
|
2013-06-10 11:03:34 +02:00
|
|
|
sp->setTrack(e.track());
|
|
|
|
sp->setTick(e.tick());
|
2014-06-18 20:57:45 +02:00
|
|
|
// ?? sp->setAnchor(Spanner::Anchor::SEGMENT);
|
2012-05-26 14:26:10 +02:00
|
|
|
sp->read(e);
|
2013-06-20 13:57:15 +02:00
|
|
|
score()->addSpanner(sp);
|
2013-10-13 13:06:32 +02:00
|
|
|
//
|
|
|
|
// check if we already saw "endSpanner"
|
|
|
|
//
|
2014-07-21 13:24:21 +02:00
|
|
|
int id = e.spannerId(sp);
|
|
|
|
const SpannerValues* sv = e.spannerValues(id);
|
2013-10-13 13:06:32 +02:00
|
|
|
if (sv) {
|
|
|
|
sp->setTick2(sv->tick2);
|
|
|
|
sp->setTrack2(sv->track2);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "RepeatMeasure") {
|
|
|
|
RepeatMeasure* rm = new RepeatMeasure(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
rm->setTrack(e.track());
|
2013-01-08 11:00:53 +01:00
|
|
|
rm->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(rm);
|
2014-07-21 14:16:16 +02:00
|
|
|
e.incTick(ticks());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Clef") {
|
|
|
|
Clef* clef = new Clef(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
clef->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
clef->read(e);
|
|
|
|
clef->setGenerated(false);
|
2014-05-12 17:59:24 +02:00
|
|
|
// in some 1.3 scores, clefs can be in score but not in cleflist
|
2014-07-25 17:13:27 +02:00
|
|
|
// if (score()->mscVersion() > 114)
|
|
|
|
// staff->setClef(e.tick(), clef->clefTypeList());
|
2013-07-12 18:41:33 +02:00
|
|
|
|
|
|
|
// there may be more than one clef segment for same tick position
|
2014-05-05 17:56:13 +02:00
|
|
|
if (!segment) {
|
|
|
|
// this is the first segment of measure
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::Clef, e.tick());
|
2014-05-05 17:56:13 +02:00
|
|
|
}
|
2013-07-12 18:41:33 +02:00
|
|
|
else {
|
2014-05-05 17:56:13 +02:00
|
|
|
bool firstSegment = false;
|
|
|
|
for (Segment* s = _segments.first(); s && s->tick() == e.tick(); s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::Clef) {
|
2014-05-05 17:56:13 +02:00
|
|
|
firstSegment = true;
|
2013-07-12 18:41:33 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-05-05 17:56:13 +02:00
|
|
|
if (firstSegment) {
|
|
|
|
Segment* ns = 0;
|
|
|
|
if (segment->next()) {
|
|
|
|
ns = segment->next();
|
|
|
|
while (ns && ns->tick() < e.tick())
|
|
|
|
ns = ns->next();
|
|
|
|
}
|
|
|
|
segment = 0;
|
|
|
|
for (Segment* s = ns; s && s->tick() == e.tick(); s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::Clef) {
|
2014-05-05 17:56:13 +02:00
|
|
|
segment = s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!segment) {
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = new Segment(this, Segment::Type::Clef, e.tick());
|
2014-05-05 17:56:13 +02:00
|
|
|
_segments.insert(segment, ns);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// this is the first clef: move to left
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::Clef, e.tick());
|
2013-07-12 18:41:33 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
segment->add(clef);
|
|
|
|
}
|
|
|
|
else if (tag == "TimeSig") {
|
|
|
|
TimeSig* ts = new TimeSig(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
ts->setTrack(e.track());
|
2012-10-24 13:15:46 +02:00
|
|
|
ts->read(e);
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
// if time sig not at begining of measure => courtesy time sig
|
2014-04-16 09:35:23 +02:00
|
|
|
int currTick = e.tick();
|
|
|
|
bool courtesySig = (currTick > tick());
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
if (courtesySig) {
|
|
|
|
// if courtesy sig., just add it without map processing
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::TimeSigAnnounce, currTick);
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
segment->add(ts);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// if 'real' time sig., do full process
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::TimeSig, currTick);
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
segment->add(ts);
|
|
|
|
timeStretch = ts->stretch().reduced();
|
2013-06-04 18:29:14 +02:00
|
|
|
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
_timesig = ts->sig() * timeStretch;
|
2012-10-17 12:42:00 +02:00
|
|
|
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
if (score()->mscVersion() > 114) {
|
|
|
|
if (irregular) {
|
|
|
|
score()->sigmap()->add(tick(), SigEvent(_len, _timesig));
|
|
|
|
score()->sigmap()->add(tick() + ticks(), SigEvent(_timesig));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_len = _timesig;
|
|
|
|
score()->sigmap()->add(tick(), SigEvent(_timesig));
|
|
|
|
}
|
2012-09-04 22:27:47 +02:00
|
|
|
}
|
2012-06-28 15:12:17 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "KeySig") {
|
|
|
|
KeySig* ks = new KeySig(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
ks->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
ks->read(e);
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
// if key sig not at beginning of measure => courtesy key sig
|
2014-04-16 09:35:23 +02:00
|
|
|
int currTick = e.tick();
|
|
|
|
bool courtesySig = (currTick > tick());
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(courtesySig ? Segment::Type::KeySigAnnounce : Segment::Type::KeySig, currTick);
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(ks);
|
Fix #14576 : hiding courtesy time sig corrupts score
See http://musescore.org/en/node/14576 for discussion and examples.
1) Edited courtesy time sig (in any parameter: visibility, colour, text, ...) are saved to the score
2) When read back from file, such a time sig is not recognized as courtesy time sig
3) If the edited courtesy time sig no longer is at the end of a system, it is not removed.
The straight approach could have been to disable any editing of courtesy time sig. Rather than loosing this flexibility, I tried to improve the management of courtesy sigs:
1) not changed
2) when reading a time sig, if not at the beginning of a measure, now it is turned into a courtesy time sig
3) courtesy time sig removal now depends on its position in the system and not on the generated status.
This patch also do the same changes, in the same code areas, for courtesy key signs, as they behave in a very similar way.
2014-04-16 00:55:11 +02:00
|
|
|
if (!courtesySig)
|
2014-06-03 15:28:10 +02:00
|
|
|
staff->setKey(currTick, ks->key());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-03-13 18:16:25 +01:00
|
|
|
else if (tag == "Lyrics") { // obsolete, keep for compatibility with version 114
|
|
|
|
Element* element = Element::name2Element(tag, score());
|
|
|
|
element->setTrack(e.track());
|
|
|
|
element->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2013-03-13 18:16:25 +01:00
|
|
|
ChordRest* cr = static_cast<ChordRest*>(segment->element(e.track()));
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!cr)
|
2014-02-27 19:57:24 +01:00
|
|
|
qDebug("Internal error: no chord/rest for lyrics");
|
2012-05-26 14:26:10 +02:00
|
|
|
else
|
2013-03-13 18:16:25 +01:00
|
|
|
cr->add(element);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Text") {
|
|
|
|
Text* t = new Text(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
t->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
t->read(e);
|
2013-03-06 09:49:33 +01:00
|
|
|
// previous versions stored measure number, delete it
|
2014-05-30 10:13:29 +02:00
|
|
|
if ((score()->mscVersion() <= 114) && (t->textStyleType() == TextStyleType::MEASURE_NUMBER))
|
2012-09-21 12:23:18 +02:00
|
|
|
delete t;
|
|
|
|
else {
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2012-09-21 12:23:18 +02:00
|
|
|
segment->add(t);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------
|
|
|
|
// Annotation
|
|
|
|
|
|
|
|
else if (tag == "Dynamic") {
|
|
|
|
Dynamic* dyn = new Dynamic(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
dyn->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
dyn->read(e);
|
2013-02-14 13:50:59 +01:00
|
|
|
if (score()->mscVersion() <= 114)
|
2013-03-05 20:23:59 +01:00
|
|
|
dyn->setDynamicType(dyn->text());
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(dyn);
|
|
|
|
}
|
|
|
|
else if (tag == "Harmony"
|
|
|
|
|| tag == "FretDiagram"
|
|
|
|
|| tag == "Symbol"
|
|
|
|
|| tag == "Tempo"
|
|
|
|
|| tag == "StaffText"
|
|
|
|
|| tag == "RehearsalMark"
|
|
|
|
|| tag == "InstrumentChange"
|
|
|
|
|| tag == "Marker"
|
|
|
|
|| tag == "Jump"
|
|
|
|
|| tag == "StaffState"
|
|
|
|
|| tag == "FiguredBass"
|
|
|
|
) {
|
2013-01-18 10:55:52 +01:00
|
|
|
Element* el = Element::name2Element(tag, score());
|
2013-01-21 20:21:41 +01:00
|
|
|
el->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
el->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(el);
|
|
|
|
}
|
2014-03-04 17:40:23 +01:00
|
|
|
else if (tag == "Image") {
|
|
|
|
if (MScore::noImages)
|
|
|
|
e.skipCurrentElement();
|
|
|
|
else {
|
|
|
|
Element* el = Element::name2Element(tag, score());
|
|
|
|
el->setTrack(e.track());
|
|
|
|
el->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::ChordRest, e.tick());
|
2014-03-04 17:40:23 +01:00
|
|
|
segment->add(el);
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
//----------------------------------------------------
|
|
|
|
else if (tag == "stretch")
|
2013-01-11 18:10:18 +01:00
|
|
|
_userStretch = e.readDouble();
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "LayoutBreak") {
|
|
|
|
LayoutBreak* lb = new LayoutBreak(score());
|
|
|
|
lb->read(e);
|
|
|
|
add(lb);
|
|
|
|
}
|
|
|
|
else if (tag == "noOffset")
|
2013-01-11 18:10:18 +01:00
|
|
|
_noOffset = e.readInt();
|
2013-01-17 12:56:14 +01:00
|
|
|
else if (tag == "irregular") {
|
2012-05-26 14:26:10 +02:00
|
|
|
_irregular = true;
|
2013-01-17 12:56:14 +01:00
|
|
|
e.readNext();
|
|
|
|
}
|
|
|
|
else if (tag == "breakMultiMeasureRest") {
|
2012-05-26 14:26:10 +02:00
|
|
|
_breakMultiMeasureRest = true;
|
2013-01-17 12:56:14 +01:00
|
|
|
e.readNext();
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "Tuplet") {
|
|
|
|
Tuplet* tuplet = new Tuplet(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
tuplet->setTrack(e.track());
|
|
|
|
tuplet->setTick(e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
tuplet->setParent(this);
|
2013-01-08 11:00:53 +01:00
|
|
|
tuplet->read(e);
|
2013-01-21 20:21:41 +01:00
|
|
|
e.addTuplet(tuplet);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-01-11 18:10:18 +01:00
|
|
|
else if (tag == "startRepeat") {
|
2014-07-17 09:32:30 +02:00
|
|
|
_repeatFlags = _repeatFlags | Repeat::START;
|
2013-01-11 18:10:18 +01:00
|
|
|
e.readNext();
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "endRepeat") {
|
2013-01-11 18:10:18 +01:00
|
|
|
_repeatCount = e.readInt();
|
2014-07-17 09:32:30 +02:00
|
|
|
_repeatFlags = _repeatFlags | Repeat::END;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "vspacer" || tag == "vspacerDown") {
|
|
|
|
if (staves[staffIdx]->_vspacerDown == 0) {
|
|
|
|
Spacer* spacer = new Spacer(score());
|
2014-05-26 12:46:24 +02:00
|
|
|
spacer->setSpacerType(SpacerType::DOWN);
|
2012-05-26 14:26:10 +02:00
|
|
|
spacer->setTrack(staffIdx * VOICES);
|
|
|
|
add(spacer);
|
|
|
|
}
|
2013-01-11 18:10:18 +01:00
|
|
|
staves[staffIdx]->_vspacerDown->setGap(e.readDouble() * _spatium);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "vspacer" || tag == "vspacerUp") {
|
|
|
|
if (staves[staffIdx]->_vspacerUp == 0) {
|
|
|
|
Spacer* spacer = new Spacer(score());
|
2014-05-26 12:46:24 +02:00
|
|
|
spacer->setSpacerType(SpacerType::UP);
|
2012-05-26 14:26:10 +02:00
|
|
|
spacer->setTrack(staffIdx * VOICES);
|
|
|
|
add(spacer);
|
|
|
|
}
|
2013-01-11 18:10:18 +01:00
|
|
|
staves[staffIdx]->_vspacerUp->setGap(e.readDouble() * _spatium);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "visible")
|
2013-01-11 18:10:18 +01:00
|
|
|
staves[staffIdx]->_visible = e.readInt();
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "slashStyle")
|
2013-01-11 18:10:18 +01:00
|
|
|
staves[staffIdx]->_slashStyle = e.readInt();
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "Beam") {
|
|
|
|
Beam* beam = new Beam(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
beam->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
beam->read(e);
|
|
|
|
beam->setParent(0);
|
2013-01-21 20:21:41 +01:00
|
|
|
e.addBeam(beam);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Segment")
|
2013-06-24 19:01:31 +02:00
|
|
|
segment->read(e);
|
2012-10-17 10:39:39 +02:00
|
|
|
else if (tag == "MeasureNumber") {
|
2013-03-08 16:07:03 +01:00
|
|
|
Text* noText = new Text(score());
|
|
|
|
noText->read(e);
|
2014-05-22 10:10:58 +02:00
|
|
|
noText->setFlag(ElementFlag::ON_STAFF, true);
|
|
|
|
// noText->setFlag(ElementFlag::MOVABLE, false); ??
|
2013-10-18 17:55:51 +02:00
|
|
|
noText->setTrack(e.track());
|
2013-03-08 16:07:03 +01:00
|
|
|
noText->setParent(this);
|
|
|
|
staves[noText->staffIdx()]->setNoText(noText);
|
2012-10-17 10:39:39 +02:00
|
|
|
}
|
2013-11-25 12:17:12 +01:00
|
|
|
else if (tag == "Ambitus") {
|
|
|
|
Ambitus* range = new Ambitus(score());
|
2013-10-29 23:41:38 +01:00
|
|
|
range->read(e);
|
2014-06-25 11:46:10 +02:00
|
|
|
segment = getSegment(Segment::Type::Ambitus, e.tick());
|
2013-10-29 23:41:38 +01:00
|
|
|
range->setParent(segment); // a parent segment is needed for setTrack() to work
|
|
|
|
range->setTrack(trackZeroVoice(e.track()));
|
|
|
|
segment->add(range);
|
|
|
|
}
|
2014-02-26 19:06:42 +01:00
|
|
|
else if (tag == "multiMeasureRest")
|
|
|
|
_mmRestCount = e.readInt();
|
2013-01-17 12:56:14 +01:00
|
|
|
else if (Element::readProperties(e))
|
|
|
|
;
|
2012-05-26 14:26:10 +02:00
|
|
|
else
|
2013-01-11 18:10:18 +01:00
|
|
|
e.unknown();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
if (staffIdx == 0) {
|
|
|
|
Segment* s = last();
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s && s->segmentType() == Segment::Type::BarLine) {
|
2012-05-26 14:26:10 +02:00
|
|
|
BarLine* b = static_cast<BarLine*>(s->element(0));
|
2013-03-05 20:23:59 +01:00
|
|
|
setEndBarLineType(b->barLineType(), false, b->visible(), b->color());
|
2012-05-26 14:26:10 +02:00
|
|
|
// s->remove(b);
|
|
|
|
// delete b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// for compatibility with 1.22:
|
|
|
|
//
|
2013-05-18 21:58:51 +02:00
|
|
|
if (score()->mscVersion() == 122) {
|
|
|
|
int ticks1 = 0;
|
2012-10-23 20:22:49 +02:00
|
|
|
for (Segment* s = last(); s; s = s->prev()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::ChordRest) {
|
2013-05-18 21:58:51 +02:00
|
|
|
if (s->element(0)) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(s->element(0));
|
2014-06-24 18:36:02 +02:00
|
|
|
if (cr->type() == Element::Type::REPEAT_MEASURE)
|
2013-05-18 21:58:51 +02:00
|
|
|
ticks1 = ticks();
|
|
|
|
else
|
|
|
|
ticks1 = s->rtick() + cr->actualTicks();
|
|
|
|
break;
|
|
|
|
}
|
2012-10-23 20:22:49 +02:00
|
|
|
}
|
|
|
|
}
|
2013-05-18 21:58:51 +02:00
|
|
|
if (ticks() != ticks1) {
|
|
|
|
// this is a irregular measure
|
|
|
|
_len = Fraction::fromTicks(ticks1);
|
|
|
|
_len.reduce();
|
|
|
|
for (Segment* s = last(); s; s = s->prev()) {
|
|
|
|
if (s->tick() < tick() + ticks())
|
|
|
|
break;
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::BarLine) {
|
2013-05-18 21:58:51 +02:00
|
|
|
qDebug("reduce BarLine to EndBarLine");
|
2014-06-25 11:46:10 +02:00
|
|
|
s->setSegmentType(Segment::Type::EndBarLine);
|
2013-05-18 21:58:51 +02:00
|
|
|
}
|
|
|
|
}
|
2012-10-23 20:22:49 +02:00
|
|
|
|
2013-05-18 21:58:51 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-01-21 20:21:41 +01:00
|
|
|
foreach (Tuplet* tuplet, e.tuplets()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (tuplet->elements().isEmpty()) {
|
|
|
|
// this should not happen and is a sign of input file corruption
|
2013-01-24 09:31:41 +01:00
|
|
|
qDebug("Measure:read(): empty tuplet id %d (%p), input file corrupted?",
|
|
|
|
tuplet->id(), tuplet);
|
2012-05-26 14:26:10 +02:00
|
|
|
delete tuplet;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tuplet->setParent(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// visible
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::visible(int staffIdx) const
|
|
|
|
{
|
|
|
|
if (system() && (system()->staves()->isEmpty() || !system()->staff(staffIdx)->show()))
|
|
|
|
return false;
|
|
|
|
return score()->staff(staffIdx)->show() && staves[staffIdx]->_visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// slashStyle
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::slashStyle(int staffIdx) const
|
|
|
|
{
|
2013-06-22 10:55:22 +02:00
|
|
|
return score()->staff(staffIdx)->slashStyle() || staves[staffIdx]->_slashStyle || score()->staff(staffIdx)->staffType()->slashStyle();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// scanElements
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::scanElements(void* data, void (*func)(void*, Element*), bool all)
|
|
|
|
{
|
|
|
|
MeasureBase::scanElements(data, func, all);
|
|
|
|
|
|
|
|
int nstaves = score()->nstaves();
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-08-04 20:30:26 +02:00
|
|
|
if (!all && !(visible(staffIdx) && score()->staff(staffIdx)->show()))
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
MStaff* ms = staves[staffIdx];
|
|
|
|
if (ms->lines)
|
|
|
|
func(data, ms->lines);
|
|
|
|
if (ms->_vspacerUp)
|
|
|
|
func(data, ms->_vspacerUp);
|
|
|
|
if (ms->_vspacerDown)
|
|
|
|
func(data, ms->_vspacerDown);
|
2013-03-08 16:07:03 +01:00
|
|
|
if (ms->noText())
|
|
|
|
func(data, ms->noText());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2014-07-15 18:42:31 +02:00
|
|
|
s->scanElements(data,func,all);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// createVoice
|
|
|
|
// Create a voice on demand by filling the measure
|
|
|
|
// with a whole measure rest.
|
|
|
|
// Check if there are any chord/rests in track; if
|
|
|
|
// not create a whole measure rest
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::createVoice(int track)
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() != Segment::Type::ChordRest)
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
if (s->element(track) == 0)
|
|
|
|
score()->setRest(s->tick(), track, len(), true, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setStartRepeatBarLine
|
|
|
|
// return true if bar line type changed
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::setStartRepeatBarLine(bool val)
|
|
|
|
{
|
2014-07-17 09:32:30 +02:00
|
|
|
bool changed = false;
|
|
|
|
Segment* s = findSegment(Segment::Type::StartRepeatBarLine, tick());
|
|
|
|
bool customSpan = false;
|
|
|
|
int numStaves = score()->nstaves();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-12-21 00:32:09 +01:00
|
|
|
for (int staffIdx = 0; staffIdx < numStaves;) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2013-12-21 00:32:09 +01:00
|
|
|
BarLine* bl = s ? static_cast<BarLine*>(s->element(track)) : nullptr;
|
|
|
|
int span, spanFrom, spanTo;
|
|
|
|
// if there is a bar line and has custom span, take span from it
|
|
|
|
if (bl && bl->customSpan()) {
|
2013-12-22 00:06:56 +01:00
|
|
|
span = bl->span();
|
|
|
|
spanFrom = bl->spanFrom();
|
|
|
|
spanTo = bl->spanTo();
|
|
|
|
customSpan = bl->customSpan();
|
2013-12-21 00:32:09 +01:00
|
|
|
}
|
|
|
|
else {
|
2013-12-22 00:06:56 +01:00
|
|
|
span = staff->barLineSpan();
|
|
|
|
spanFrom = staff->barLineFrom();
|
|
|
|
spanTo = staff->barLineTo();
|
|
|
|
if (span == 0 && customSpan) {
|
|
|
|
// spanned staves have already been skipped by the loop at the end;
|
|
|
|
// if a staff with span 0 is found and the previous bar line had custom span
|
|
|
|
// this staff shall have an aditional bar line, because the previous staff bar
|
|
|
|
// line has been shortened
|
|
|
|
int staffLines = staff->lines();
|
|
|
|
span = 1;
|
|
|
|
spanFrom = staffLines == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0;
|
|
|
|
spanTo = staffLines == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (staffLines-1) * 2;
|
|
|
|
}
|
|
|
|
customSpan = false;
|
2013-12-21 00:32:09 +01:00
|
|
|
}
|
|
|
|
// make sure we do not span more staves than actually exist
|
|
|
|
if (staffIdx + span > numStaves)
|
|
|
|
span = numStaves - staffIdx;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
if (span && val && (bl == 0)) {
|
|
|
|
// no barline were we need one:
|
|
|
|
bl = new BarLine(score());
|
|
|
|
bl->setTrack(track);
|
2014-05-30 10:14:09 +02:00
|
|
|
bl->setBarLineType(BarLineType::START_REPEAT);
|
2012-08-01 22:15:58 +02:00
|
|
|
if (s == 0) {
|
|
|
|
if (score()->undoRedo()) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-25 11:46:10 +02:00
|
|
|
s = undoGetSegment(Segment::Type::StartRepeatBarLine, tick());
|
2012-08-01 22:15:58 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
bl->setParent(s);
|
|
|
|
score()->undoAddElement(bl);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
else if (bl && !val) {
|
|
|
|
// barline were we do not need one:
|
2013-10-25 12:17:42 +02:00
|
|
|
if (!score()->undoRedo()) // DEBUG
|
|
|
|
score()->undoRemoveElement(bl);
|
2012-05-26 14:26:10 +02:00
|
|
|
changed = true;
|
|
|
|
}
|
2013-04-05 23:17:42 +02:00
|
|
|
if (bl && val && span) {
|
2012-05-26 14:26:10 +02:00
|
|
|
bl->setSpan(span);
|
2013-12-21 00:32:09 +01:00
|
|
|
bl->setSpanFrom(spanFrom);
|
|
|
|
bl->setSpanTo(spanTo);
|
2013-04-05 23:17:42 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
++staffIdx;
|
|
|
|
//
|
|
|
|
// remove any unwanted barlines:
|
|
|
|
//
|
2013-12-21 00:32:09 +01:00
|
|
|
// if spanning several staves but not entering INTO last staff,
|
|
|
|
if (span > 1 && spanTo <= 0)
|
|
|
|
span--; // count one span less
|
2012-05-26 14:26:10 +02:00
|
|
|
if (s) {
|
|
|
|
for (int i = 1; i < span; ++i) {
|
|
|
|
BarLine* bl = static_cast<BarLine*>(s->element(staffIdx * VOICES));
|
|
|
|
if (bl) {
|
|
|
|
score()->undoRemoveElement(bl);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
++staffIdx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// createEndBarLines
|
2013-05-15 10:23:07 +02:00
|
|
|
// actually creates or modifies barlines
|
|
|
|
// returns true if layout changes
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::createEndBarLines()
|
|
|
|
{
|
|
|
|
bool changed = false;
|
|
|
|
int nstaves = score()->nstaves();
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* seg = undoGetSegment(Segment::Type::EndBarLine, endTick());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2012-09-19 14:13:07 +02:00
|
|
|
BarLine* bl = 0;
|
2012-10-14 13:46:04 +02:00
|
|
|
int span = 0; // span counter
|
|
|
|
int aspan = 0; // actual span
|
2013-05-15 10:23:07 +02:00
|
|
|
bool mensur = false; // keep note of mensurstrich case
|
2012-10-14 13:46:04 +02:00
|
|
|
int spanTot; // to keep track of the target span
|
2012-10-14 09:25:33 +02:00
|
|
|
int spanFrom;
|
|
|
|
int spanTo;
|
2012-09-19 14:13:07 +02:00
|
|
|
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2014-07-17 09:32:30 +02:00
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
|
2012-10-14 09:25:33 +02:00
|
|
|
// get existing bar line for this staff, if any
|
2012-09-19 14:13:07 +02:00
|
|
|
BarLine* cbl = static_cast<BarLine*>(seg->element(track));
|
2014-07-17 09:32:30 +02:00
|
|
|
|
2012-10-14 13:46:04 +02:00
|
|
|
// if span counter has been counted off, get new span values
|
|
|
|
// and forget about any previous bar line
|
2014-07-17 09:32:30 +02:00
|
|
|
|
2012-09-19 14:13:07 +02:00
|
|
|
if (span == 0) {
|
2012-10-14 13:46:04 +02:00
|
|
|
if(cbl && cbl->customSpan()) { // if there is a bar line and has custom span,
|
|
|
|
span = cbl->span(); // get span values from it
|
|
|
|
spanFrom = cbl->spanFrom();
|
|
|
|
spanTo = cbl->spanTo();
|
|
|
|
// if bar span values == staff span values, set bar as not custom
|
|
|
|
if(span == staff->barLineSpan() && spanFrom == staff->barLineFrom()
|
|
|
|
&& spanTo == staff->barLineTo())
|
|
|
|
cbl->setCustomSpan(false);
|
|
|
|
}
|
|
|
|
else { // otherwise, get from staff
|
|
|
|
span = staff->barLineSpan();
|
2013-05-15 10:23:07 +02:00
|
|
|
// if some span OR last staff (span=0) of a mensurstrich case, get From/To from staff
|
|
|
|
if (span || mensur) {
|
2012-11-18 01:01:55 +01:00
|
|
|
spanFrom = staff->barLineFrom();
|
|
|
|
spanTo = staff->barLineTo();
|
2013-05-15 10:23:07 +02:00
|
|
|
mensur = false;
|
2012-11-18 01:01:55 +01:00
|
|
|
}
|
|
|
|
// but if staff is set to no span, a multi-staff spanning bar line
|
|
|
|
// has been shortened to span less staves and following staves left without bars;
|
|
|
|
// set bar line span values to default
|
|
|
|
else {
|
|
|
|
span = 1;
|
|
|
|
spanFrom = 0;
|
2013-05-15 10:23:07 +02:00
|
|
|
spanTo = (staff->lines()-1)*2;
|
2012-11-18 01:01:55 +01:00
|
|
|
}
|
2012-10-14 13:46:04 +02:00
|
|
|
}
|
2012-09-19 14:13:07 +02:00
|
|
|
if ((staffIdx + span) > nstaves)
|
|
|
|
span = nstaves - staffIdx;
|
2012-10-14 13:46:04 +02:00
|
|
|
spanTot = span;
|
2012-09-19 14:13:07 +02:00
|
|
|
bl = 0;
|
|
|
|
}
|
|
|
|
if (staff->show() && span) {
|
|
|
|
//
|
|
|
|
// there should be a barline in this staff
|
|
|
|
//
|
2012-10-14 13:46:04 +02:00
|
|
|
// if we already have a bar line, keep extending this bar line down until span exhausted;
|
|
|
|
// if no barline yet, re-use the bar line existing in this staff if any,
|
|
|
|
// restarting actual span
|
2012-09-19 14:13:07 +02:00
|
|
|
if (!bl) {
|
|
|
|
bl = cbl;
|
|
|
|
aspan = 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-09-19 14:13:07 +02:00
|
|
|
if (!bl) {
|
2012-10-14 13:46:04 +02:00
|
|
|
// no suitable bar line: create a new one
|
2012-09-19 14:13:07 +02:00
|
|
|
bl = new BarLine(score());
|
|
|
|
bl->setVisible(_endBarLineVisible);
|
|
|
|
bl->setColor(_endBarLineColor);
|
2014-07-17 09:32:30 +02:00
|
|
|
bl->setGenerated(_endBarLineGenerated);
|
2013-09-19 15:08:54 +02:00
|
|
|
bl->setBarLineType(_endBarLineType);
|
2012-09-19 14:13:07 +02:00
|
|
|
bl->setParent(seg);
|
|
|
|
bl->setTrack(track);
|
|
|
|
score()->undoAddElement(bl);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
else {
|
2012-10-14 13:46:04 +02:00
|
|
|
// a bar line is there (either existing or newly created):
|
|
|
|
// adjust subtype, if not fitting
|
2013-09-19 15:08:54 +02:00
|
|
|
if (bl->barLineType() != _endBarLineType && !bl->customSubtype()) {
|
2014-05-30 10:14:09 +02:00
|
|
|
score()->undoChangeProperty(bl, P_ID::SUBTYPE, int(_endBarLineType));
|
2013-03-25 16:27:20 +01:00
|
|
|
bl->setGenerated(bl->el()->empty() && _endBarLineGenerated);
|
2012-05-26 14:26:10 +02:00
|
|
|
changed = true;
|
|
|
|
}
|
2012-11-26 02:31:25 +01:00
|
|
|
// or clear custom subtype flag if same type as measure
|
2013-09-19 15:08:54 +02:00
|
|
|
if (bl->barLineType() == _endBarLineType && bl->customSubtype())
|
2012-11-26 02:31:25 +01:00
|
|
|
bl->setCustomSubtype(false);
|
2014-07-17 09:32:30 +02:00
|
|
|
|
2012-10-14 13:46:04 +02:00
|
|
|
// if a bar line exists for this staff (cbl) but
|
|
|
|
// it is not the bar line we are dealing with (bl),
|
|
|
|
// we are extending down the bar line of a staff above (bl)
|
2012-11-26 01:11:01 +01:00
|
|
|
// and the bar line for this staff (cbl) is not needed:
|
|
|
|
// DELETE it
|
2012-09-19 14:13:07 +02:00
|
|
|
if (cbl && cbl != bl) {
|
2012-11-02 10:03:07 +01:00
|
|
|
// mensurstrich special case:
|
2012-11-26 01:11:01 +01:00
|
|
|
// if span arrives inside the end staff (spanTo>0) OR
|
|
|
|
// span is not multi-staff (spanTot<=1) OR
|
|
|
|
// current staff is not the last spanned staff (span!=1) OR
|
|
|
|
// staff is the last score staff
|
|
|
|
// remove bar line for this staff
|
|
|
|
// If NONE of the above conditions holds, the staff is the last staff of
|
|
|
|
// a mensurstrich(-like) span: keep its bar line, as it may span to next staff
|
2013-01-02 20:13:58 +01:00
|
|
|
if (spanTo > 0 || spanTot <= 1 || span != 1 || staffIdx == nstaves-1) {
|
2012-11-02 10:03:07 +01:00
|
|
|
score()->undoRemoveElement(cbl);
|
|
|
|
changed = true;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-19 14:13:07 +02:00
|
|
|
else {
|
2012-10-14 13:46:04 +02:00
|
|
|
//
|
2012-09-19 14:13:07 +02:00
|
|
|
// there should be no barline in this staff
|
2012-10-14 13:46:04 +02:00
|
|
|
//
|
2012-09-19 14:13:07 +02:00
|
|
|
if (cbl) {
|
|
|
|
score()->undoRemoveElement(cbl);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
2012-10-14 13:46:04 +02:00
|
|
|
// if span not counted off AND we have a bar line AND this staff is shown,
|
|
|
|
// set bar line span values (this may result in extending down a bar line
|
|
|
|
// for a previous staff, if we are counting off a span > 1)
|
2012-09-19 14:13:07 +02:00
|
|
|
if (span) {
|
|
|
|
if (bl) {
|
|
|
|
++aspan;
|
2012-10-14 09:25:33 +02:00
|
|
|
if (staff->show()) { // update only if visible
|
2012-09-19 14:13:07 +02:00
|
|
|
bl->setSpan(aspan);
|
2012-10-14 09:25:33 +02:00
|
|
|
bl->setSpanFrom(spanFrom);
|
2012-10-14 13:46:04 +02:00
|
|
|
// if current actual span < target span, set spanTo to full staff height
|
|
|
|
if(aspan < spanTot)
|
2012-10-14 18:36:08 +02:00
|
|
|
bl->setSpanTo((staff->lines()-1)*2);
|
2012-10-14 13:46:04 +02:00
|
|
|
// if we reached target span, set spanTo to intended value
|
|
|
|
else
|
|
|
|
bl->setSpanTo(spanTo);
|
2012-10-14 09:25:33 +02:00
|
|
|
}
|
2012-09-19 14:13:07 +02:00
|
|
|
}
|
|
|
|
--span;
|
|
|
|
}
|
2012-11-26 01:11:01 +01:00
|
|
|
// if just finished (span==0) a multi-staff span (spanTot>1) ending at the top of a staff (spanTo<=0)
|
|
|
|
// scan this staff again, as it may have its own bar lines (mensurstich(-like) span)
|
2013-05-15 10:23:07 +02:00
|
|
|
if (spanTot > 1 && spanTo <= 0 && span == 0) {
|
|
|
|
mensur = true;
|
2012-11-26 01:11:01 +01:00
|
|
|
staffIdx--;
|
2013-05-15 10:23:07 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setEndBarLineType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::setEndBarLineType(BarLineType val, bool g, bool visible, QColor color)
|
|
|
|
{
|
|
|
|
_endBarLineType = val;
|
|
|
|
_endBarLineGenerated = g;
|
|
|
|
_endBarLineVisible = visible;
|
2014-07-17 09:32:30 +02:00
|
|
|
if (color.isValid())
|
2013-06-19 09:53:15 +02:00
|
|
|
_endBarLineColor = color;
|
|
|
|
else
|
|
|
|
_endBarLineColor = curColor();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// sortStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::sortStaves(QList<int>& dst)
|
|
|
|
{
|
|
|
|
QList<MStaff*> ms;
|
2013-09-20 12:59:31 +02:00
|
|
|
foreach (int idx, dst)
|
2012-05-26 14:26:10 +02:00
|
|
|
ms.push_back(staves[idx]);
|
|
|
|
staves = ms;
|
|
|
|
|
|
|
|
for (int staffIdx = 0; staffIdx < staves.size(); ++staffIdx) {
|
|
|
|
if (staves[staffIdx]->lines)
|
|
|
|
staves[staffIdx]->lines->setTrack(staffIdx * VOICES);
|
|
|
|
}
|
|
|
|
for (Segment* s = first(); s; s = s->next())
|
|
|
|
s->sortStaves(dst);
|
|
|
|
|
2013-10-14 15:34:46 +02:00
|
|
|
foreach (Element* e, _el) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e->track() == -1)
|
|
|
|
continue;
|
|
|
|
int voice = e->voice();
|
|
|
|
int staffIdx = e->staffIdx();
|
|
|
|
int idx = dst.indexOf(staffIdx);
|
|
|
|
e->setTrack(idx * VOICES + voice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// exchangeVoice
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::exchangeVoice(int v1, int v2, int staffIdx1, int staffIdx2)
|
|
|
|
{
|
|
|
|
for (int staffIdx = staffIdx1; staffIdx < staffIdx2; ++ staffIdx) {
|
2014-06-25 11:46:10 +02:00
|
|
|
for (Segment* s = first(Segment::Type::ChordRest); s; s = s->next(Segment::Type::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int strack = staffIdx * VOICES + v1;
|
|
|
|
int dtrack = staffIdx * VOICES + v2;
|
|
|
|
s->swapElements(strack, dtrack);
|
|
|
|
}
|
|
|
|
MStaff* ms = mstaff(staffIdx);
|
|
|
|
ms->hasVoices = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// checkMultiVoices
|
2012-08-02 18:33:43 +02:00
|
|
|
/// Check for more than on voice in this measure and staff and
|
|
|
|
/// set MStaff->hasVoices
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::checkMultiVoices(int staffIdx)
|
|
|
|
{
|
|
|
|
int strack = staffIdx * VOICES + 1;
|
|
|
|
int etrack = staffIdx * VOICES + VOICES;
|
|
|
|
staves[staffIdx]->hasVoices = false;
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() != Segment::Type::ChordRest)
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
if (s->element(track)) {
|
|
|
|
staves[staffIdx]->hasVoices = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// hasVoice
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::hasVoice(int track) const
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() != Segment::Type::ChordRest)
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
if (s->element(track))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-02 18:33:43 +02:00
|
|
|
//-------------------------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
// isMeasureRest
|
2012-08-02 18:33:43 +02:00
|
|
|
/// Check if the measure is filled by a full-measure rest or full
|
|
|
|
/// of rests on this staff. If staff is -1, then check for
|
|
|
|
/// all staves.
|
|
|
|
//-------------------------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
bool Measure::isMeasureRest(int staffIdx)
|
|
|
|
{
|
|
|
|
int strack;
|
|
|
|
int etrack;
|
|
|
|
if (staffIdx < 0) {
|
|
|
|
strack = 0;
|
|
|
|
etrack = score()->nstaves() * VOICES;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strack = staffIdx * VOICES;
|
|
|
|
etrack = staffIdx * VOICES + VOICES;
|
|
|
|
}
|
2014-06-25 11:46:10 +02:00
|
|
|
for (Segment* s = first(Segment::Type::ChordRest); s; s = s->next(Segment::Type::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* e = s->element(track);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e && e->type() != Element::Type::REST)
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// isFullMeasureRest
|
|
|
|
// Check for an empty measure, filled with full measure
|
|
|
|
// rests.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::isFullMeasureRest()
|
|
|
|
{
|
|
|
|
int strack = 0;
|
|
|
|
int etrack = score()->nstaves() * VOICES;
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* s = first(Segment::Type::ChordRest);
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* e = s->element(track);
|
|
|
|
if (e) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() != Element::Type::REST)
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
|
|
|
Rest* rest = static_cast<Rest*>(e);
|
2014-05-21 15:43:19 +02:00
|
|
|
if (rest->durationType().type() != TDuration::DurationType::V_MEASURE)
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// isRepeatMeasure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-07-21 12:53:18 +02:00
|
|
|
bool Measure::isRepeatMeasure(Part* part)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2012-07-21 12:53:18 +02:00
|
|
|
int firstStaffIdx = score()->staffIdx(part);
|
|
|
|
int nextStaffIdx = firstStaffIdx + part->nstaves();
|
2012-08-02 18:33:43 +02:00
|
|
|
int strack = firstStaffIdx * VOICES;
|
|
|
|
int etrack = nextStaffIdx * VOICES;
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* s = first(Segment::Type::ChordRest);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2012-08-02 18:33:43 +02:00
|
|
|
if (s == 0)
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
|
|
|
|
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* e = s->element(track);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e && e->type() == Element::Type::REPEAT_MEASURE)
|
2012-05-26 14:26:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-12-10 17:44:57 +01:00
|
|
|
// distanceDown
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-12-10 17:44:57 +01:00
|
|
|
qreal Measure::distanceDown(int i) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2012-12-10 17:44:57 +01:00
|
|
|
if (staves[i]->_vspacerDown)
|
|
|
|
return qMax(staves[i]->distanceDown, staves[i]->_vspacerDown->gap());
|
|
|
|
return staves[i]->distanceDown;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-12-10 17:44:57 +01:00
|
|
|
// distanceUp
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-12-10 17:44:57 +01:00
|
|
|
qreal Measure::distanceUp(int i) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2012-12-10 17:44:57 +01:00
|
|
|
if (staves[i]->_vspacerUp)
|
|
|
|
return qMax(staves[i]->distanceUp, staves[i]->_vspacerUp->gap());
|
|
|
|
return staves[i]->distanceUp;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// isEmpty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::isEmpty() const
|
|
|
|
{
|
|
|
|
if (_irregular)
|
|
|
|
return false;
|
|
|
|
int n = 0;
|
2012-09-21 14:29:34 +02:00
|
|
|
int tracks = staves.size() * VOICES;
|
2014-06-25 11:46:10 +02:00
|
|
|
static const Segment::Type st { Segment::Type::ChordRest };
|
2012-09-21 14:29:34 +02:00
|
|
|
for (const Segment* s = first(st); s; s = s->next(st)) {
|
|
|
|
bool restFound = false;
|
|
|
|
for (int track = 0; track < tracks; ++track) {
|
|
|
|
if ((track % VOICES) == 0 && !score()->staff(track/VOICES)->show()) {
|
|
|
|
track += VOICES-1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (s->element(track)) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (s->element(track)->type() != Element::Type::REST)
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
2012-09-21 14:29:34 +02:00
|
|
|
restFound = true;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2012-09-21 14:29:34 +02:00
|
|
|
if (restFound)
|
|
|
|
++n;
|
|
|
|
// measure is not empty if there is more than one rest
|
|
|
|
if (n > 1)
|
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-02-17 19:07:03 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// isOnlyRests
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::isOnlyRests(int track) const
|
|
|
|
{
|
2014-06-25 11:46:10 +02:00
|
|
|
static const Segment::Type st { Segment::Type::ChordRest };
|
2014-02-17 19:07:03 +01:00
|
|
|
for (const Segment* s = first(st); s; s = s->next(st)) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() != Segment::Type::ChordRest || !s->element(track))
|
2014-02-17 19:07:03 +01:00
|
|
|
continue;
|
2014-06-24 18:36:02 +02:00
|
|
|
if (s->element(track)->type() != Element::Type::REST)
|
2014-02-17 19:07:03 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Space::max
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Space::max(const Space& s)
|
|
|
|
{
|
|
|
|
if (s._lw > _lw)
|
|
|
|
_lw = s._lw;
|
|
|
|
if (s._rw > _rw)
|
|
|
|
_rw = s._rw;
|
|
|
|
}
|
|
|
|
|
2012-08-01 18:00:27 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setDirty
|
|
|
|
//---------------------------------------------------------
|
2012-07-31 09:48:37 +02:00
|
|
|
|
2012-08-01 18:00:27 +02:00
|
|
|
void Measure::setDirty()
|
|
|
|
{
|
|
|
|
_minWidth1 = 0.0;
|
|
|
|
_minWidth2 = 0.0;
|
2012-07-31 09:48:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-08-01 22:15:58 +02:00
|
|
|
// systemHeader
|
2012-08-02 18:33:43 +02:00
|
|
|
/// return true if the measure contains a system header
|
|
|
|
// The system header is identified by a generated Clef in
|
|
|
|
// the first segment.
|
2012-07-31 09:48:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-01 22:15:58 +02:00
|
|
|
bool Measure::systemHeader() const
|
2012-07-31 09:48:37 +02:00
|
|
|
{
|
2012-08-01 22:15:58 +02:00
|
|
|
Segment* s = first();
|
2014-06-25 11:46:10 +02:00
|
|
|
return s && (s->segmentType() == Segment::Type::Clef) && s->element(0) && s->element(0)->generated();
|
2012-07-31 09:48:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// minWidth1
|
2012-10-08 08:28:19 +02:00
|
|
|
/// return minimum width of measure excluding system
|
|
|
|
/// header
|
2012-07-31 09:48:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Measure::minWidth1() const
|
|
|
|
{
|
2012-10-08 09:34:46 +02:00
|
|
|
if (_minWidth1 == 0.0) {
|
2012-08-01 22:15:58 +02:00
|
|
|
Segment* s = first();
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type st = Segment::Type::Clef | Segment::Type::KeySig | Segment::Type::StartRepeatBarLine;
|
2013-03-05 20:23:59 +01:00
|
|
|
while ((s->segmentType() & st)
|
2013-03-04 12:00:02 +01:00
|
|
|
&& s->next()
|
|
|
|
&& (!s->element(0) || s->element(0)->generated())
|
|
|
|
) {
|
|
|
|
s = s->next();
|
2012-08-01 18:00:27 +02:00
|
|
|
}
|
2012-08-01 22:15:58 +02:00
|
|
|
_minWidth1 = score()->computeMinWidth(s);
|
2012-10-08 09:34:46 +02:00
|
|
|
}
|
2012-07-31 09:48:37 +02:00
|
|
|
return _minWidth1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// minWidth2
|
2012-10-08 08:28:19 +02:00
|
|
|
/// return minimum width of measure
|
2012-07-31 09:48:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Measure::minWidth2() const
|
|
|
|
{
|
2012-10-08 09:34:46 +02:00
|
|
|
if (_minWidth2 == 0.0)
|
2012-08-01 22:15:58 +02:00
|
|
|
_minWidth2 = score()->computeMinWidth(first());
|
2012-07-31 09:48:37 +02:00
|
|
|
return _minWidth2;
|
|
|
|
}
|
|
|
|
|
2013-03-26 16:25:07 +01:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// computeStretch
|
|
|
|
/// \brief distribute stretch across a range of segments
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void computeStretch(int minTick, qreal minimum, qreal stretch, int first, int last, int ticksList[], qreal xpos[], qreal width[])
|
|
|
|
{
|
|
|
|
SpringMap springs;
|
|
|
|
for (int i = first; i < last; ++i) {
|
|
|
|
qreal str = 1.0;
|
|
|
|
qreal d;
|
|
|
|
qreal w = width[i];
|
|
|
|
|
|
|
|
int t = ticksList[i];
|
|
|
|
if (t) {
|
|
|
|
if (minTick > 0)
|
|
|
|
// str += .6 * log(qreal(t) / qreal(minTick)) / log(2.0);
|
|
|
|
str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick));
|
|
|
|
d = w / str;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
str = 0.0; // dont stretch timeSig and key
|
|
|
|
d = 100000000.0; // CHECK
|
|
|
|
}
|
|
|
|
springs.insert(std::pair<qreal, Spring>(d, Spring(i, str, w)));
|
|
|
|
minimum += w;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------
|
|
|
|
// distribute stretch to segments
|
|
|
|
//---------------------------------------------------
|
|
|
|
|
|
|
|
qreal force = sff(stretch, minimum, springs);
|
|
|
|
|
|
|
|
for (iSpring i = springs.begin(); i != springs.end(); ++i) {
|
|
|
|
qreal stretch = force * i->second.stretch;
|
|
|
|
if (stretch < i->second.fix)
|
|
|
|
stretch = i->second.fix;
|
|
|
|
width[i->second.seg] = stretch;
|
|
|
|
}
|
|
|
|
qreal x = xpos[first];
|
|
|
|
for (int i = first; i < last; ++i) {
|
|
|
|
x += width[i];
|
|
|
|
xpos[i+1] = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// layoutX
|
|
|
|
/// \brief main layout routine for note spacing
|
|
|
|
/// Return width of measure (in MeasureWidth), taking into account \a stretch.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2012-07-31 09:48:37 +02:00
|
|
|
void Measure::layoutX(qreal stretch)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
int nstaves = _score->nstaves();
|
|
|
|
|
|
|
|
int segs = 0;
|
|
|
|
for (const Segment* s = first(); s; s = s->next()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (s->segmentType() == Segment::Type::Clef && (s != first()))
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
++segs;
|
|
|
|
}
|
|
|
|
|
2012-10-23 22:16:31 +02:00
|
|
|
if (nstaves == 0 || segs == 0)
|
2012-05-26 14:26:10 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
qreal _spatium = spatium();
|
|
|
|
int tracks = nstaves * VOICES;
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal clefKeyRightMargin = score()->styleS(StyleIdx::clefKeyRightMargin).val() * _spatium;
|
|
|
|
qreal minHarmonyDistance = score()->styleS(StyleIdx::minHarmonyDistance).val() * _spatium;
|
|
|
|
qreal maxHarmonyBarDistance = score()->styleS(StyleIdx::maxHarmonyBarDistance).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
qreal rest[nstaves]; // fixed space needed from previous segment
|
|
|
|
memset(rest, 0, nstaves * sizeof(qreal));
|
|
|
|
|
2013-03-14 16:52:10 +01:00
|
|
|
qreal hRest[nstaves]; // fixed space needed from previous harmony
|
|
|
|
memset(hRest, 0, nstaves * sizeof(qreal));
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//--------tick table for segments
|
|
|
|
int ticksList[segs];
|
|
|
|
memset(ticksList, 0, segs * sizeof(int));
|
|
|
|
|
|
|
|
qreal xpos[segs+1];
|
|
|
|
qreal width[segs];
|
|
|
|
|
|
|
|
int segmentIdx = 0;
|
|
|
|
qreal x = 0.0;
|
2013-03-26 16:25:07 +01:00
|
|
|
qreal lastx = 0.0;
|
2012-05-26 14:26:10 +02:00
|
|
|
int minTick = 100000;
|
2013-03-26 16:25:07 +01:00
|
|
|
int hMinTick = 100000;
|
|
|
|
int hLastIdx = -1;
|
2013-05-06 14:20:31 +02:00
|
|
|
int ntick = ticks(); // position of next measure
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-05-29 11:49:58 +02:00
|
|
|
if (system()->firstMeasure() == this && system()->barLine()) {
|
|
|
|
BarLine* bl = system()->barLine();
|
|
|
|
x += BarLine::layoutWidth(score(), bl->barLineType(), bl->magS());
|
|
|
|
}
|
2013-03-04 12:00:02 +01:00
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal minNoteDistance = score()->styleS(StyleIdx::minNoteDistance).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
qreal clefWidth[nstaves];
|
|
|
|
memset(clefWidth, 0, nstaves * sizeof(qreal));
|
|
|
|
|
2013-04-08 18:26:53 +02:00
|
|
|
std::vector<QRectF> hLastBbox(nstaves); // bbox of previous harmony to test vertical separation
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2012-07-31 09:48:37 +02:00
|
|
|
const Segment* s = first();
|
2012-10-23 20:22:49 +02:00
|
|
|
const Segment* pSeg = 0;
|
2012-07-31 09:48:37 +02:00
|
|
|
for (; s; s = s->next(), ++segmentIdx) {
|
|
|
|
qreal elsp = s->extraLeadingSpace().val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal etsp = s->extraTrailingSpace().val() * _spatium;
|
2014-06-25 11:46:10 +02:00
|
|
|
if ((s->segmentType() == Segment::Type::Clef) && (s != first())) {
|
2012-05-26 14:26:10 +02:00
|
|
|
--segmentIdx;
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-10-23 20:22:49 +02:00
|
|
|
if (!score()->staff(staffIdx)->show())
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Element* e = s->element(track);
|
|
|
|
if (e) {
|
|
|
|
clefWidth[staffIdx] = e->width() + _spatium + elsp;
|
|
|
|
}
|
|
|
|
}
|
2012-10-23 20:22:49 +02:00
|
|
|
pSeg = s;
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
}
|
2013-03-14 16:52:10 +01:00
|
|
|
bool rest2[nstaves];
|
|
|
|
bool hRest2[nstaves];
|
2014-06-01 20:24:29 +02:00
|
|
|
bool spaceHarmony = false;
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type segType = s->segmentType();
|
2014-06-01 20:24:29 +02:00
|
|
|
qreal segmentWidth = 0.0;
|
|
|
|
qreal harmonyWidth = 0.0;
|
|
|
|
qreal stretchDistance = 0.0;
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Type pt = pSeg ? pSeg->segmentType() : Segment::Type::BarLine;
|
2014-04-27 03:29:13 +02:00
|
|
|
#if 0
|
|
|
|
qreal firstHarmonyDistance = 0.0;
|
|
|
|
#endif
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-08-01 22:15:58 +02:00
|
|
|
if (!score()->staff(staffIdx)->show())
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal minDistance = 0.0;
|
|
|
|
Space space;
|
2013-03-14 16:52:10 +01:00
|
|
|
Space hSpace;
|
2013-03-26 16:25:07 +01:00
|
|
|
QRectF hBbox;
|
2012-05-26 14:26:10 +02:00
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
bool found = false;
|
2013-03-14 16:52:10 +01:00
|
|
|
bool hFound = false;
|
2013-03-26 16:25:07 +01:00
|
|
|
bool eFound = false;
|
2014-04-27 03:29:13 +02:00
|
|
|
#if 0
|
|
|
|
qreal harmonyCarryOver = system()->firstMeasure() == this ? 0.0 : // calculate value for this staff; but how to duplicate in Score::computeMinWidth?
|
|
|
|
#endif
|
2014-03-25 18:33:53 +01:00
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
if (segType & (Segment::Type::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal llw = 0.0;
|
|
|
|
qreal rrw = 0.0;
|
|
|
|
Lyrics* lyrics = 0;
|
2014-02-21 14:32:50 +01:00
|
|
|
bool accidentalStaff = false;
|
2014-03-25 18:33:53 +01:00
|
|
|
|
|
|
|
bool accidental = false;
|
2014-04-14 01:16:14 +02:00
|
|
|
bool grace = false;
|
2014-04-14 07:15:16 +02:00
|
|
|
qreal accidentalX = 0.0;
|
|
|
|
qreal noteX = 0.0;
|
2014-06-25 11:46:10 +02:00
|
|
|
if (pt & (Segment::Type::StartRepeatBarLine | Segment::Type::BarLine | Segment::Type::TimeSig) && !accidentalStaff) {
|
2014-03-25 18:33:53 +01:00
|
|
|
for (int voice = 0; voice < VOICES; ++voice) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(s->element(track+voice));
|
|
|
|
if (!cr)
|
|
|
|
continue;
|
2013-07-15 11:57:07 +02:00
|
|
|
// check for accidentals in chord
|
2014-06-24 18:36:02 +02:00
|
|
|
if (cr->type() == Element::Type::CHORD) {
|
2013-07-15 11:57:07 +02:00
|
|
|
Chord* c = static_cast<Chord*>(cr);
|
2014-05-21 03:14:06 +02:00
|
|
|
if (c->getGraceNotesBefore(0))
|
2014-04-14 01:16:14 +02:00
|
|
|
grace = true;
|
2013-07-15 11:57:07 +02:00
|
|
|
else {
|
|
|
|
for (Note* note : c->notes()) {
|
|
|
|
if (note->accidental()) {
|
|
|
|
accidental = true;
|
2014-05-21 00:43:28 +02:00
|
|
|
accidentalX = qMin(accidentalX, note->accidental()->x() + note->x() + c->x());
|
2013-07-15 11:57:07 +02:00
|
|
|
}
|
2014-04-14 01:16:14 +02:00
|
|
|
else
|
2014-05-21 00:43:28 +02:00
|
|
|
noteX = qMin(noteX, note->x() + c->x());
|
2013-07-15 11:57:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-25 18:33:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int voice = 0; voice < VOICES; ++voice) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(s->element(track+voice));
|
|
|
|
if (!cr)
|
|
|
|
continue;
|
|
|
|
found = true;
|
2014-06-25 11:46:10 +02:00
|
|
|
if (pt & (Segment::Type::StartRepeatBarLine | Segment::Type::BarLine | Segment::Type::TimeSig) && !accidentalStaff) {
|
2013-07-18 15:54:05 +02:00
|
|
|
// no distance to full measure rest
|
2014-06-24 18:36:02 +02:00
|
|
|
if (!(cr->type() == Element::Type::REST && static_cast<Rest*>(cr)->durationType() == TDuration::DurationType::V_MEASURE)) {
|
2014-02-21 14:32:50 +01:00
|
|
|
accidentalStaff = true;
|
2014-04-14 01:16:14 +02:00
|
|
|
qreal sp;
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal bnd = score()->styleS(StyleIdx::barNoteDistance).val() * _spatium;
|
2014-04-14 01:16:14 +02:00
|
|
|
if (accidental) {
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal bad = score()->styleS(StyleIdx::barAccidentalDistance).val() * _spatium;
|
2014-04-14 01:16:14 +02:00
|
|
|
qreal diff = qMax(noteX - accidentalX, 0.0);
|
|
|
|
sp = qMax(bad, bnd - diff);
|
|
|
|
}
|
|
|
|
else if (grace)
|
2014-05-26 15:31:36 +02:00
|
|
|
sp = score()->styleS(StyleIdx::barAccidentalDistance).val() * _spatium;
|
2014-04-14 01:16:14 +02:00
|
|
|
else
|
2014-04-14 07:15:16 +02:00
|
|
|
sp = bnd;
|
2014-06-25 11:46:10 +02:00
|
|
|
if (pt & Segment::Type::TimeSig)
|
2014-04-14 07:15:16 +02:00
|
|
|
sp += clefKeyRightMargin - bnd;
|
2013-07-18 15:54:05 +02:00
|
|
|
minDistance = qMax(minDistance, sp);
|
|
|
|
}
|
2014-06-25 11:46:10 +02:00
|
|
|
else if (pt & Segment::Type::TimeSig)
|
2014-04-14 20:35:02 +02:00
|
|
|
minDistance = qMax(minDistance, clefKeyRightMargin);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-25 11:46:10 +02:00
|
|
|
else if (pt & (Segment::Type::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
minDistance = qMax(minDistance, minNoteDistance);
|
|
|
|
}
|
|
|
|
else {
|
2014-06-25 11:46:10 +02:00
|
|
|
bool firstClef = (segmentIdx == 1) && (pt == Segment::Type::Clef);
|
|
|
|
if ((pt & Segment::Type::KeySig) || firstClef)
|
2012-05-26 14:26:10 +02:00
|
|
|
minDistance = qMax(minDistance, clefKeyRightMargin);
|
|
|
|
}
|
2014-05-21 00:43:28 +02:00
|
|
|
|
|
|
|
// calculate space needed for segment
|
|
|
|
// take cr position into account
|
|
|
|
// by converting to segment-relative space
|
2014-05-21 23:37:45 +02:00
|
|
|
// chord space itself already has ipos offset built in
|
|
|
|
// but lyrics do not
|
|
|
|
// and neither have user offsets
|
|
|
|
qreal cx = cr->ipos().x();
|
|
|
|
qreal cxu = cr->userOff().x();
|
|
|
|
qreal lx = qMax(cxu, 0.0); // nudge left shouldn't require more leading space
|
|
|
|
qreal rx = qMin(cxu, 0.0); // nudge right shouldn't require more trailing space
|
2014-05-21 00:43:28 +02:00
|
|
|
Space crSpace = cr->space();
|
|
|
|
Space segRelSpace(crSpace.lw()-lx, crSpace.rw()+rx);
|
|
|
|
space.max(segRelSpace);
|
|
|
|
|
|
|
|
// lyrics
|
2012-12-06 12:46:05 +01:00
|
|
|
int n = cr->lyricsList().size();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
Lyrics* l = cr->lyricsList().at(i);
|
2012-10-23 14:42:00 +02:00
|
|
|
if (!l || l->isEmpty())
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
2012-10-23 14:42:00 +02:00
|
|
|
lyrics = l;
|
|
|
|
if (!lyrics->isMelisma()) {
|
|
|
|
QRectF b(l->bbox().translated(l->pos()));
|
2014-05-21 23:37:45 +02:00
|
|
|
llw = qMax(llw, -(b.left()+lx+cx));
|
|
|
|
rrw = qMax(rrw, b.right()+rx+cx);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lyrics) {
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal y = lyrics->ipos().y() + score()->styleS(StyleIdx::lyricsMinBottomDistance).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
if (y > staves[staffIdx]->distanceDown)
|
|
|
|
staves[staffIdx]->distanceDown = y;
|
|
|
|
space.max(Space(llw, rrw));
|
|
|
|
}
|
2013-03-13 11:13:33 +01:00
|
|
|
|
2013-03-14 16:52:10 +01:00
|
|
|
// add spacing for chord symbols
|
2013-05-06 14:20:31 +02:00
|
|
|
foreach (const Element* e, s->annotations()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() != Element::Type::HARMONY || e->track() < track || e->track() >= track+VOICES)
|
2013-03-13 11:13:33 +01:00
|
|
|
continue;
|
2013-05-06 14:20:31 +02:00
|
|
|
const Harmony* h = static_cast<const Harmony*>(e);
|
2013-04-03 19:16:28 +02:00
|
|
|
QRectF b(h->bboxtight().translated(h->pos()));
|
2013-03-26 16:25:07 +01:00
|
|
|
if (hFound)
|
|
|
|
hBbox |= b;
|
|
|
|
else
|
|
|
|
hBbox = b;
|
|
|
|
hFound = true;
|
2014-04-27 03:29:13 +02:00
|
|
|
spaceHarmony = true;
|
|
|
|
// allow chord to be dragged
|
|
|
|
qreal xoff = h->pos().x();
|
|
|
|
qreal bl = -b.left() + qMin(xoff, 0.0);
|
|
|
|
qreal br = b.right() - qMax(xoff, 0.0);
|
|
|
|
hSpace.max(Space(bl, br));
|
|
|
|
#if 0
|
2013-03-14 16:52:10 +01:00
|
|
|
hSpace.max(Space(s->rtick()?-b.left():0.0, b.right()));
|
2014-04-27 03:29:13 +02:00
|
|
|
// account for carryover from last measure
|
|
|
|
if (harmonyCarryOver > 0.0) {
|
|
|
|
if (!s->rtick()) {
|
|
|
|
// first ChordRest of measure
|
|
|
|
// use minDistance to clear carryover harmony
|
|
|
|
minDistance = qMax(minDistance, harmonyCarryOver - x);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// otherwise, use stretch
|
|
|
|
firstHarmonyDistance = qMax(firstHarmonyDistance, harmonyCarryOver + minHarmonyDistance);
|
|
|
|
}
|
|
|
|
harmonyCarryOver = 0.0;
|
|
|
|
}
|
|
|
|
#endif
|
2013-03-13 11:13:33 +01:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
2014-04-27 03:29:13 +02:00
|
|
|
// current segment (s) is not a ChordRest
|
2012-05-26 14:26:10 +02:00
|
|
|
Element* e = s->element(track);
|
2014-06-25 11:46:10 +02:00
|
|
|
if ((segType == Segment::Type::Clef) && (pt != Segment::Type::ChordRest))
|
2014-05-26 15:31:36 +02:00
|
|
|
minDistance = score()->styleS(StyleIdx::clefLeftMargin).val() * _spatium;
|
2014-06-25 11:46:10 +02:00
|
|
|
else if (segType == Segment::Type::StartRepeatBarLine)
|
2012-05-26 14:26:10 +02:00
|
|
|
minDistance = .5 * _spatium;
|
2014-06-25 11:46:10 +02:00
|
|
|
else if ((segType == Segment::Type::EndBarLine) && segmentIdx) {
|
|
|
|
if (pt == Segment::Type::Clef)
|
2014-05-26 15:31:36 +02:00
|
|
|
minDistance = score()->styleS(StyleIdx::clefBarlineDistance).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
else
|
2014-05-26 15:31:36 +02:00
|
|
|
stretchDistance = score()->styleS(StyleIdx::noteBarDistance).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e == 0) {
|
|
|
|
// look for barline
|
|
|
|
for (int i = track - VOICES; i >= 0; i -= VOICES) {
|
|
|
|
e = s->element(i);
|
|
|
|
if (e)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (e) {
|
2013-03-26 16:25:07 +01:00
|
|
|
eFound = true;
|
2014-06-25 11:46:10 +02:00
|
|
|
if (!s->next()) // segType & Segment::Type::EndBarLine
|
2014-04-27 03:29:13 +02:00
|
|
|
spaceHarmony = true; // to space last Harmony to end of measure
|
2012-05-26 14:26:10 +02:00
|
|
|
space.max(e->space());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
space += Space(elsp, etsp);
|
2013-09-19 15:08:54 +02:00
|
|
|
if (isMMRest())
|
2013-07-17 12:17:49 +02:00
|
|
|
minDistance = 0;
|
2013-03-14 16:52:10 +01:00
|
|
|
|
2013-03-26 16:25:07 +01:00
|
|
|
if (found || eFound) {
|
2012-05-26 14:26:10 +02:00
|
|
|
space.rLw() += clefWidth[staffIdx];
|
2013-03-14 16:52:10 +01:00
|
|
|
qreal sp = minDistance + rest[staffIdx] + qMax(space.lw(), stretchDistance);
|
2012-05-26 14:26:10 +02:00
|
|
|
rest[staffIdx] = space.rw();
|
|
|
|
rest2[staffIdx] = false;
|
|
|
|
segmentWidth = qMax(segmentWidth, sp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rest2[staffIdx] = true;
|
2013-03-14 16:52:10 +01:00
|
|
|
|
|
|
|
// space chord symbols separately from segments
|
2013-03-26 16:25:07 +01:00
|
|
|
if (hFound || eFound) {
|
|
|
|
qreal sp = 0.0;
|
|
|
|
|
|
|
|
// space chord symbols unless they miss each other vertically
|
2014-04-28 03:50:21 +02:00
|
|
|
if (eFound || (hFound && hBbox.top() < hLastBbox[staffIdx].bottom() && hBbox.bottom() > hLastBbox[staffIdx].top()))
|
2013-03-26 16:34:58 +01:00
|
|
|
sp = hRest[staffIdx] + minHarmonyDistance + hSpace.lw();
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2014-04-28 03:50:21 +02:00
|
|
|
// barline: limit space to maxHarmonyBarDistance
|
|
|
|
if (eFound && !hFound && spaceHarmony)
|
|
|
|
sp = qMin(sp, maxHarmonyBarDistance);
|
2014-04-27 03:29:13 +02:00
|
|
|
|
|
|
|
hLastBbox[staffIdx] = hBbox;
|
2013-03-14 16:52:10 +01:00
|
|
|
hRest[staffIdx] = hSpace.rw();
|
|
|
|
hRest2[staffIdx] = false;
|
2013-03-26 16:25:07 +01:00
|
|
|
harmonyWidth = qMax(harmonyWidth, sp);
|
2013-03-14 16:52:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
hRest2[staffIdx] = true;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
clefWidth[staffIdx] = 0.0;
|
|
|
|
}
|
2014-04-27 03:29:13 +02:00
|
|
|
|
2013-03-26 16:34:58 +01:00
|
|
|
// set previous seg width before adding in harmony, to allow stretching
|
2012-05-26 14:26:10 +02:00
|
|
|
if (segmentIdx) {
|
|
|
|
width[segmentIdx-1] = segmentWidth;
|
2012-10-23 20:22:49 +02:00
|
|
|
if (pSeg)
|
|
|
|
pSeg->setbbox(QRectF(0.0, 0.0, segmentWidth, _spatium * 5)); //??
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-03-26 16:25:07 +01:00
|
|
|
// make room for harmony if needed
|
2014-04-27 03:29:13 +02:00
|
|
|
segmentWidth = qMax(segmentWidth, harmonyWidth);
|
2013-03-26 16:25:07 +01:00
|
|
|
|
|
|
|
x += segmentWidth;
|
|
|
|
xpos[segmentIdx] = x;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-08-01 22:15:58 +02:00
|
|
|
if (!score()->staff(staffIdx)->show())
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
if (rest2[staffIdx])
|
2014-04-27 03:29:13 +02:00
|
|
|
rest[staffIdx] -= qMin(rest[staffIdx], segmentWidth);
|
2013-03-14 16:52:10 +01:00
|
|
|
if (hRest2[staffIdx])
|
2014-04-27 03:29:13 +02:00
|
|
|
hRest[staffIdx] -= qMin(hRest[staffIdx], segmentWidth);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-04-27 03:29:13 +02:00
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
if ((s->segmentType() == Segment::Type::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
const Segment* nseg = s;
|
|
|
|
for (;;) {
|
|
|
|
nseg = nseg->next();
|
2014-06-25 11:46:10 +02:00
|
|
|
if (nseg == 0 || nseg->segmentType() == Segment::Type::ChordRest)
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
2013-05-06 14:20:31 +02:00
|
|
|
int nticks = (nseg ? nseg->rtick() : ntick) - s->rtick();
|
2012-05-26 14:26:10 +02:00
|
|
|
if (nticks == 0) {
|
|
|
|
// this happens for tremolo notes
|
|
|
|
qDebug("layoutX: empty segment(%p)%s: measure: tick %d ticks %d",
|
|
|
|
s, s->subTypeName(), tick(), ticks());
|
|
|
|
qDebug(" nticks==0 segmente %d, segmentIdx: %d, segTick: %d nsegTick(%p) %d",
|
|
|
|
size(), segmentIdx-1, s->tick(), nseg, ntick
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (nticks < minTick)
|
|
|
|
minTick = nticks;
|
2013-03-26 16:25:07 +01:00
|
|
|
if (nticks < hMinTick)
|
|
|
|
hMinTick = nticks;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
ticksList[segmentIdx] = nticks;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ticksList[segmentIdx] = 0;
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2013-03-26 16:34:58 +01:00
|
|
|
// if we are on a chord symbol, stretch the notes below it if necessary
|
2014-04-27 03:29:13 +02:00
|
|
|
if (spaceHarmony) {
|
|
|
|
if (hLastIdx >= 0) {
|
2013-03-26 16:25:07 +01:00
|
|
|
computeStretch(hMinTick, 0.0, x-lastx, hLastIdx, segmentIdx, ticksList, xpos, width);
|
2014-04-27 03:29:13 +02:00
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
else if (s->rtick() && firstHarmonyDistance > 0.0) {
|
|
|
|
// account for carryover from previous measure
|
|
|
|
qDebug("measure %d, initial %d segments: stretching to %f", _no, segmentIdx, firstHarmonyDistance);
|
|
|
|
computeStretch(0, 0.0, firstHarmonyDistance, 0, segmentIdx, ticksList, xpos, width);
|
|
|
|
firstHarmonyDistance = 0.0;
|
|
|
|
}
|
|
|
|
#endif
|
2013-03-26 16:25:07 +01:00
|
|
|
hMinTick = 10000;
|
|
|
|
lastx = x;
|
|
|
|
hLastIdx = segmentIdx;
|
|
|
|
}
|
|
|
|
|
2012-10-23 22:16:31 +02:00
|
|
|
//
|
|
|
|
// set pSeg only to used segments
|
|
|
|
//
|
|
|
|
for (int voice = 0; voice < nstaves * VOICES; ++voice) {
|
|
|
|
if (!score()->staff(voice/VOICES)->show()) {
|
|
|
|
voice += VOICES-1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (s->element(voice)) {
|
|
|
|
pSeg = s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-09-24 01:29:00 +02:00
|
|
|
//---------------------------------------------------
|
|
|
|
// TAB: compute distance above and below
|
|
|
|
//---------------------------------------------------
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-08-01 22:15:58 +02:00
|
|
|
if (!score()->staff(staffIdx)->show())
|
|
|
|
continue;
|
2012-09-24 01:29:00 +02:00
|
|
|
qreal distAbove = 0.0;
|
|
|
|
qreal distBelow = 0.0;
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff * staff = _score->staff(staffIdx);
|
2012-08-16 11:09:36 +02:00
|
|
|
if (staff->isTabStaff()) {
|
2014-04-28 18:38:50 +02:00
|
|
|
StaffType* stt = staff->staffType();
|
2012-09-24 01:29:00 +02:00
|
|
|
if (stt->slashStyle()) // if no stems
|
|
|
|
distAbove = stt->genDurations() ? -stt->durationBoxY() : 0.0;
|
|
|
|
else { // if stems
|
|
|
|
if (stt->stemsDown())
|
|
|
|
distBelow = (STAFFTYPE_TAB_DEFAULTSTEMLEN_UP + STAFFTYPE_TAB_DEFAULTSTEMDIST_UP)*_spatium;
|
|
|
|
else
|
|
|
|
distAbove = (STAFFTYPE_TAB_DEFAULTSTEMLEN_DN + STAFFTYPE_TAB_DEFAULTSTEMDIST_DN)*_spatium;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
if (distAbove > staves[staffIdx]->distanceUp)
|
|
|
|
staves[staffIdx]->distanceUp = distAbove;
|
2012-09-24 01:29:00 +02:00
|
|
|
if (distBelow > staves[staffIdx]->distanceDown)
|
|
|
|
staves[staffIdx]->distanceDown = distBelow;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal segmentWidth = 0.0;
|
2012-08-01 22:15:58 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
|
|
|
if (!score()->staff(staffIdx)->show())
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
segmentWidth = qMax(segmentWidth, rest[staffIdx]);
|
2013-03-14 16:52:10 +01:00
|
|
|
segmentWidth = qMax(segmentWidth, hRest[staffIdx]);
|
2012-08-01 22:15:58 +02:00
|
|
|
}
|
2013-03-26 16:25:07 +01:00
|
|
|
if (segmentIdx)
|
|
|
|
width[segmentIdx-1] = segmentWidth;
|
2012-05-26 14:26:10 +02:00
|
|
|
xpos[segmentIdx] = x + segmentWidth;
|
|
|
|
|
|
|
|
//---------------------------------------------------
|
2013-03-26 16:34:58 +01:00
|
|
|
// compute stretches for whole measure
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------
|
|
|
|
|
2013-03-26 16:25:07 +01:00
|
|
|
computeStretch(minTick, xpos[0], stretch, 0, segs, ticksList, xpos, width);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------
|
|
|
|
// layout individual elements
|
|
|
|
//---------------------------------------------------
|
|
|
|
|
|
|
|
int seg = 0;
|
|
|
|
for (Segment* s = first(); s; s = s->next(), ++seg) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if ((s->segmentType() == Segment::Type::Clef) && (s != first())) {
|
2013-07-18 15:54:05 +02:00
|
|
|
//
|
|
|
|
// clefs are not in xpos[] table
|
|
|
|
//
|
2012-05-26 14:26:10 +02:00
|
|
|
s->setPos(xpos[seg], 0.0);
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2012-08-01 22:15:58 +02:00
|
|
|
if (!score()->staff(staffIdx)->show())
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Element* e = s->element(track);
|
|
|
|
if (e) {
|
|
|
|
qreal lm = 0.0;
|
|
|
|
if (s->next()) {
|
|
|
|
for (int track = staffIdx * VOICES; track < staffIdx*VOICES+VOICES; ++track) {
|
|
|
|
if (s->next()->element(track)) {
|
|
|
|
qreal clm = s->next()->element(track)->space().lw();
|
|
|
|
lm = qMax(lm, clm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e->setPos(-e->width() - lm - _spatium*.5, 0.0);
|
|
|
|
e->adjustReadPos();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
--seg;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
s->setPos(xpos[seg], 0.0);
|
2013-07-18 15:54:05 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-07-18 15:54:05 +02:00
|
|
|
for (Segment* s = first(); s; s = s->next(), ++seg) {
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = 0; track < tracks; ++track) {
|
2012-10-23 20:22:49 +02:00
|
|
|
if (!score()->staff(track/VOICES)->show()) {
|
2012-10-23 22:16:31 +02:00
|
|
|
track += VOICES-1;
|
2012-08-01 22:15:58 +02:00
|
|
|
continue;
|
2012-10-23 20:22:49 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
Element* e = s->element(track);
|
|
|
|
if (e == 0)
|
|
|
|
continue;
|
2014-06-24 18:36:02 +02:00
|
|
|
Element::Type t = e->type();
|
2013-09-19 15:08:54 +02:00
|
|
|
Rest* rest = static_cast<Rest*>(e);
|
|
|
|
if (((track % VOICES) == 0) &&
|
2014-06-24 18:36:02 +02:00
|
|
|
(t == Element::Type::REPEAT_MEASURE || (t == Element::Type::REST && (isMMRest() || rest->isFullMeasureRest())))) {
|
2013-09-19 15:08:54 +02:00
|
|
|
//
|
|
|
|
// element has to be centered in free space
|
|
|
|
// x1 - left measure position of free space
|
|
|
|
// x2 - right measure position of free space
|
2013-09-10 15:11:30 +02:00
|
|
|
|
2013-09-19 15:08:54 +02:00
|
|
|
if (isMMRest()) {
|
|
|
|
//
|
|
|
|
// center multi measure rest
|
|
|
|
//
|
|
|
|
qreal x1 = 0.0, x2;
|
2013-09-19 17:17:22 +02:00
|
|
|
Segment* ss = first();
|
2014-06-25 11:46:10 +02:00
|
|
|
for (; ss->segmentType() != Segment::Type::ChordRest; ss = ss->next())
|
2013-09-19 17:17:22 +02:00
|
|
|
;
|
2014-03-24 17:03:37 +01:00
|
|
|
// if (s != first()) {
|
|
|
|
if (ss != first()) {
|
2013-09-19 17:17:22 +02:00
|
|
|
ss = ss->prev();
|
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
|
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Element* e = ss->element(track);
|
|
|
|
if (e)
|
|
|
|
x1 = qMax(x1, ss->x() + e->x() + e->width());
|
2013-09-19 15:08:54 +02:00
|
|
|
}
|
2013-09-10 13:11:56 +02:00
|
|
|
}
|
2013-09-19 15:08:54 +02:00
|
|
|
Segment* ns = s->next();
|
2013-09-20 15:03:35 +02:00
|
|
|
x2 = this->width();
|
2013-09-19 15:08:54 +02:00
|
|
|
if (ns) {
|
2013-07-19 12:13:58 +02:00
|
|
|
x2 = ns->x();
|
2014-06-25 11:46:10 +02:00
|
|
|
if (ns->segmentType() != Segment::Type::EndBarLine) {
|
2013-09-20 15:03:35 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
|
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Element* e = ns->element(track);
|
|
|
|
if (e)
|
|
|
|
x2 = qMin(x2, ns->x() + e->x());
|
|
|
|
}
|
2013-09-19 15:08:54 +02:00
|
|
|
}
|
2013-07-19 12:13:58 +02:00
|
|
|
}
|
2013-07-18 15:54:05 +02:00
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal d = point(score()->styleS(StyleIdx::multiMeasureRestMargin));
|
2013-09-19 15:08:54 +02:00
|
|
|
qreal w = x2 - x1 - 2 * d;
|
2013-07-17 12:17:49 +02:00
|
|
|
|
2013-09-19 15:08:54 +02:00
|
|
|
rest->setMMWidth(w);
|
|
|
|
StaffLines* sl = staves[track/VOICES]->lines;
|
|
|
|
qreal x = x1 - s->pos().x() + d;
|
|
|
|
e->setPos(x, sl->staffHeight() * .5); // center vertically in measure
|
|
|
|
}
|
2013-09-19 16:27:29 +02:00
|
|
|
else { // if (rest->isFullMeasureRest()) {
|
2013-09-19 15:08:54 +02:00
|
|
|
//
|
|
|
|
// center full measure rest
|
|
|
|
//
|
|
|
|
qreal x1 = 0.0;
|
|
|
|
qreal x2 = this->width();
|
2013-09-19 15:49:39 +02:00
|
|
|
Segment* ss = first();
|
2014-06-25 11:46:10 +02:00
|
|
|
for (; ss->segmentType() != Segment::Type::ChordRest; ss = ss->next())
|
2013-09-19 15:49:39 +02:00
|
|
|
;
|
|
|
|
if (ss != first()) {
|
|
|
|
ss = ss->prev();
|
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
|
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Element* e = ss->element(track);
|
|
|
|
if (e)
|
|
|
|
x1 = qMax(x1, ss->x() + e->x() + e->width());
|
2013-09-19 15:08:54 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-11-22 17:41:56 +01:00
|
|
|
|
|
|
|
Segment* ns = s->next();
|
2014-06-25 11:46:10 +02:00
|
|
|
while (ns && ns->segmentType() != Segment::Type::EndBarLine) {
|
2013-11-22 17:41:56 +01:00
|
|
|
ns = ns->next();
|
|
|
|
}
|
|
|
|
if (ns)
|
|
|
|
x2 = ns->x();
|
|
|
|
|
2013-09-19 15:08:54 +02:00
|
|
|
rest->rxpos() = (x2 - x1 - e->width()) * .5 + x1 - s->x();
|
|
|
|
rest->adjustReadPos();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (t == Element::Type::REST)
|
2013-07-18 15:54:05 +02:00
|
|
|
e->rxpos() = 0;
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (t == Element::Type::CHORD)
|
2012-06-09 10:50:51 +02:00
|
|
|
static_cast<Chord*>(e)->layout2();
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (t == Element::Type::CLEF) {
|
2013-07-18 15:54:05 +02:00
|
|
|
if (s == first()) {
|
|
|
|
// clef at the beginning of measure
|
|
|
|
qreal gap = 0.0;
|
|
|
|
Segment* ps = s->prev();
|
|
|
|
if (ps)
|
|
|
|
gap = s->x() - (ps->x() + ps->width());
|
|
|
|
e->rxpos() = -gap * .5;
|
|
|
|
e->adjustReadPos();
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (t == Element::Type::AMBITUS)
|
2014-04-08 19:54:05 +02:00
|
|
|
e->adjustReadPos();
|
2012-05-26 14:26:10 +02:00
|
|
|
else {
|
|
|
|
e->setPos(-e->bbox().x(), 0.0);
|
|
|
|
e->adjustReadPos();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// layoutStage1
|
2013-09-19 17:17:22 +02:00
|
|
|
// compute multi measure rest break
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::layoutStage1()
|
|
|
|
{
|
2012-08-24 18:00:12 +02:00
|
|
|
setDirty();
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
|
2014-05-26 15:31:36 +02:00
|
|
|
if (score()->styleB(StyleIdx::createMultiMeasureRests)) {
|
2014-07-24 12:37:08 +02:00
|
|
|
if (
|
|
|
|
(repeatFlags() & Repeat::START)
|
|
|
|
|| (prevMeasure() && (prevMeasure()->repeatFlags() & Repeat::END))
|
|
|
|
|| (prevMeasure() && (prevMeasure()->sectionBreak()))
|
|
|
|
)
|
2012-05-26 14:26:10 +02:00
|
|
|
setBreakMMRest(true);
|
2013-09-19 17:17:22 +02:00
|
|
|
else if (!breakMultiMeasureRest()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2013-10-15 15:39:01 +02:00
|
|
|
for (Element* e : s->annotations()) {
|
2014-03-03 14:54:53 +01:00
|
|
|
if (score()->staff(e->staffIdx())->show() || e->systemFlag()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
setBreakMMRest(true);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-09-19 17:17:22 +02:00
|
|
|
if (breakMultiMeasureRest()) // optimize
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
|
|
|
|
for (Segment* segment = first(); segment; segment = segment->next()) {
|
2014-03-03 14:54:53 +01:00
|
|
|
if (score()->staff(staffIdx)->show()) {
|
|
|
|
Element* e = segment->element(track);
|
|
|
|
if (e && !e->generated()) {
|
2014-06-25 11:46:10 +02:00
|
|
|
if (segment->segmentType() & (Segment::Type::StartRepeatBarLine))
|
2014-03-03 14:54:53 +01:00
|
|
|
setBreakMMRest(true);
|
2014-06-25 11:46:10 +02:00
|
|
|
if (segment->segmentType() & (Segment::Type::KeySig | Segment::Type::TimeSig) && tick())
|
2013-09-19 17:39:18 +02:00
|
|
|
setBreakMMRest(true);
|
2014-06-25 11:46:10 +02:00
|
|
|
else if (segment->segmentType() == Segment::Type::Clef) {
|
2014-03-03 14:54:53 +01:00
|
|
|
if (segment->tick() == endTick()) {
|
|
|
|
Measure* m = nextMeasure();
|
|
|
|
if (m)
|
|
|
|
m->setBreakMMRest(true);
|
|
|
|
}
|
|
|
|
else if (tick())
|
|
|
|
setBreakMMRest(true);
|
|
|
|
}
|
2013-09-19 17:39:18 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
if (segment->segmentType() == Segment::Type::ChordRest) {
|
2013-10-15 15:39:01 +02:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
qreal staffMag = staff->mag();
|
|
|
|
|
|
|
|
int endTrack = track + VOICES;
|
|
|
|
for (int t = track; t < endTrack; ++t) {
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(segment->element(t));
|
|
|
|
if (!cr)
|
|
|
|
continue;
|
|
|
|
layoutCR0(cr, staffMag);
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-27 18:31:00 +02:00
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
if (!score()->styleB(StyleIdx::createMultiMeasureRests) || breakMultiMeasureRest())
|
2013-10-15 15:39:01 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
// break mm rest on any spanner
|
|
|
|
#if 0
|
|
|
|
for (auto i : sl) {
|
|
|
|
Spanner* sp = i.value;
|
|
|
|
if (sp->type() == Element::VOLTA) {
|
|
|
|
setBreakMMRest(true);
|
|
|
|
break;
|
2013-06-27 18:31:00 +02:00
|
|
|
}
|
|
|
|
}
|
2013-10-15 15:39:01 +02:00
|
|
|
#endif
|
2012-12-06 12:46:05 +01:00
|
|
|
MeasureBase* mb = prev();
|
2014-06-24 18:36:02 +02:00
|
|
|
if (mb && mb->type() == Element::Type::MEASURE) {
|
2012-12-06 12:46:05 +01:00
|
|
|
Measure* pm = static_cast<Measure*>(mb);
|
2014-05-30 10:14:09 +02:00
|
|
|
if (pm->endBarLineType() != BarLineType::NORMAL
|
|
|
|
&& pm->endBarLineType() != BarLineType::BROKEN && pm->endBarLineType() != BarLineType::DOTTED)
|
2012-12-06 12:46:05 +01:00
|
|
|
setBreakMMRest(true);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2014-04-22 17:02:03 +02:00
|
|
|
// updateNotes
|
|
|
|
// recompute note lines and accidentals
|
|
|
|
/// not undoable add/remove
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
void Measure::updateNotes(int staffIdx)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-04-22 17:02:03 +02:00
|
|
|
AccidentalState as; // state of already set accidentals for this measure
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2014-06-03 15:28:10 +02:00
|
|
|
as.init(staff->key(tick()));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
int startTrack = staffIdx * VOICES;
|
|
|
|
int endTrack = startTrack + VOICES;
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
for (Segment* s = first(Segment::Type::ChordRest); s; s = s->next(Segment::Type::ChordRest)) {
|
2014-03-26 11:02:23 +01:00
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
2014-04-22 17:02:03 +02:00
|
|
|
Chord* chord = static_cast<Chord*>(s->element(track));
|
2014-06-24 18:36:02 +02:00
|
|
|
if (!chord || chord->type() != Element::Type::CHORD)
|
2014-03-26 11:02:23 +01:00
|
|
|
continue;
|
2014-04-22 17:02:03 +02:00
|
|
|
chord->updateNotes(&as);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// cmdUpdateNotes
|
|
|
|
/// recompute note lines and accidental
|
|
|
|
/// undoable add/remove
|
|
|
|
//---------------------------------------------------------
|
2013-11-03 01:17:46 +01:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
void Measure::cmdUpdateNotes(int staffIdx)
|
|
|
|
{
|
|
|
|
AccidentalState as; // list of already set accidentals for this measure
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2014-06-03 15:28:10 +02:00
|
|
|
as.init(staff->key(tick()));
|
2014-04-18 11:28:04 +02:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
int startTrack = staffIdx * VOICES;
|
|
|
|
int endTrack = startTrack + VOICES;
|
2014-03-26 11:02:23 +01:00
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
for (Segment* segment = first(Segment::Type::ChordRest); segment; segment = segment->next(Segment::Type::ChordRest)) {
|
2014-04-22 17:02:03 +02:00
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
Chord* chord = static_cast<Chord*>(segment->element(track));
|
2014-06-24 18:36:02 +02:00
|
|
|
if (!chord || chord->type() != Element::Type::CHORD)
|
2014-04-22 17:02:03 +02:00
|
|
|
continue;
|
|
|
|
chord->cmdUpdateNotes(&as);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// stretchedLen
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Fraction Measure::stretchedLen(Staff* staff) const
|
|
|
|
{
|
|
|
|
return len() / staff->timeStretch(tick());
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// cloneMeasure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-07-05 11:23:52 +02:00
|
|
|
Measure* Measure::cloneMeasure(Score* sc, TieMap* tieMap)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Measure* m = new Measure(sc);
|
|
|
|
m->_timesig = _timesig;
|
|
|
|
m->_len = _len;
|
|
|
|
m->_repeatCount = _repeatCount;
|
|
|
|
m->_repeatFlags = _repeatFlags;
|
|
|
|
|
|
|
|
foreach(MStaff* ms, staves)
|
|
|
|
m->staves.append(new MStaff(*ms));
|
|
|
|
|
|
|
|
m->_no = _no;
|
|
|
|
m->_noOffset = _noOffset;
|
|
|
|
m->_userStretch = _userStretch;
|
|
|
|
m->_irregular = _irregular;
|
|
|
|
m->_breakMultiMeasureRest = _breakMultiMeasureRest;
|
|
|
|
m->_breakMMRest = _breakMMRest;
|
|
|
|
m->_endBarLineGenerated = _endBarLineGenerated;
|
|
|
|
m->_endBarLineVisible = _endBarLineVisible;
|
|
|
|
m->_endBarLineType = _endBarLineType;
|
|
|
|
m->_playbackCount = _playbackCount;
|
|
|
|
m->_endBarLineColor = _endBarLineColor;
|
|
|
|
|
2012-07-31 09:48:37 +02:00
|
|
|
m->_minWidth1 = _minWidth1;
|
|
|
|
m->_minWidth2 = _minWidth2;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
m->setTick(tick());
|
|
|
|
m->setLineBreak(lineBreak());
|
|
|
|
m->setPageBreak(pageBreak());
|
|
|
|
m->setSectionBreak(sectionBreak() ? new LayoutBreak(*sectionBreak()) : 0);
|
|
|
|
|
|
|
|
int tracks = sc->nstaves() * VOICES;
|
|
|
|
TupletMap tupletMap;
|
|
|
|
|
|
|
|
for (Segment* oseg = first(); oseg; oseg = oseg->next()) {
|
|
|
|
Segment* s = new Segment(m);
|
2013-03-05 20:23:59 +01:00
|
|
|
s->setSegmentType(oseg->segmentType());
|
2012-05-26 14:26:10 +02:00
|
|
|
s->setRtick(oseg->rtick());
|
|
|
|
m->_segments.push_back(s);
|
|
|
|
for (int track = 0; track < tracks; ++track) {
|
|
|
|
Element* oe = oseg->element(track);
|
|
|
|
if (oe) {
|
|
|
|
Element* ne = oe->clone();
|
|
|
|
if (oe->isChordRest()) {
|
|
|
|
ChordRest* ocr = static_cast<ChordRest*>(oe);
|
|
|
|
ChordRest* ncr = static_cast<ChordRest*>(ne);
|
|
|
|
Tuplet* ot = ocr->tuplet();
|
|
|
|
if (ot) {
|
|
|
|
Tuplet* nt = tupletMap.findNew(ot);
|
|
|
|
if (nt == 0) {
|
|
|
|
nt = new Tuplet(*ot);
|
|
|
|
nt->clear();
|
|
|
|
nt->setTrack(track);
|
|
|
|
nt->setScore(sc);
|
|
|
|
m->add(nt);
|
|
|
|
tupletMap.add(ot, nt);
|
|
|
|
}
|
|
|
|
ncr->setTuplet(nt);
|
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
if (oe->type() == Element::Type::CHORD) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Chord* och = static_cast<Chord*>(ocr);
|
|
|
|
Chord* nch = static_cast<Chord*>(ncr);
|
|
|
|
int n = och->notes().size();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
Note* on = och->notes().at(i);
|
|
|
|
Note* nn = nch->notes().at(i);
|
|
|
|
if (on->tieFor()) {
|
|
|
|
Tie* tie = new Tie(sc);
|
|
|
|
nn->setTieFor(tie);
|
|
|
|
tie->setStartNote(nn);
|
|
|
|
tieMap->add(on->tieFor(), tie);
|
|
|
|
}
|
|
|
|
if (on->tieBack()) {
|
|
|
|
Tie* tie = tieMap->findNew(on->tieBack());
|
|
|
|
if (tie) {
|
|
|
|
nn->setTieBack(tie);
|
|
|
|
tie->setEndNote(nn);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
qDebug("cloneMeasure: cannot find tie, track %d", track);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-30 21:46:27 +02:00
|
|
|
ne->setUserOff(oe->userOff());
|
2012-05-26 14:26:10 +02:00
|
|
|
s->add(ne);
|
|
|
|
}
|
|
|
|
foreach(Element* e, oseg->annotations()) {
|
|
|
|
if (e->generated() || e->track() != track)
|
|
|
|
continue;
|
|
|
|
Element* ne = e->clone();
|
|
|
|
ne->setTrack(track);
|
2014-05-30 21:46:27 +02:00
|
|
|
ne->setUserOff(e->userOff());
|
2012-05-26 14:26:10 +02:00
|
|
|
s->add(ne);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach(Element* e, *el()) {
|
|
|
|
Element* ne = e->clone();
|
|
|
|
ne->setScore(sc);
|
2014-05-30 21:46:27 +02:00
|
|
|
ne->setUserOff(e->userOff());
|
2012-05-26 14:26:10 +02:00
|
|
|
m->add(ne);
|
|
|
|
}
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// pos2sel
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Measure::snap(int tick, const QPointF p) const
|
|
|
|
{
|
|
|
|
Segment* s = first();
|
|
|
|
for (; s->next(); s = s->next()) {
|
|
|
|
qreal x = s->x();
|
|
|
|
qreal dx = s->next()->x() - x;
|
|
|
|
if (s->tick() == tick)
|
|
|
|
x += dx / 3.0 * 2.0;
|
|
|
|
else if (s->next()->tick() == tick)
|
|
|
|
x += dx / 3.0;
|
|
|
|
else
|
|
|
|
x += dx * .5;
|
|
|
|
if (p.x() < x)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return s->tick();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// snapNote
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Measure::snapNote(int /*tick*/, const QPointF p, int staff) const
|
|
|
|
{
|
|
|
|
Segment* s = first();
|
|
|
|
for (;;) {
|
|
|
|
Segment* ns = s->next();
|
|
|
|
while (ns && ns->element(staff) == 0)
|
|
|
|
ns = ns->next();
|
|
|
|
if (ns == 0)
|
|
|
|
break;
|
|
|
|
qreal x = s->x();
|
|
|
|
qreal nx = x + (ns->x() - x) * .5;
|
|
|
|
if (p.x() < nx)
|
|
|
|
break;
|
|
|
|
s = ns;
|
|
|
|
}
|
|
|
|
return s->tick();
|
|
|
|
}
|
|
|
|
|
2012-08-01 22:15:58 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// getProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Measure::getProperty(P_ID propertyId) const
|
2014-04-09 09:40:25 +02:00
|
|
|
{
|
2012-08-01 22:15:58 +02:00
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TIMESIG_NOMINAL:
|
2012-08-01 22:15:58 +02:00
|
|
|
return QVariant::fromValue(_timesig);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TIMESIG_ACTUAL:
|
2012-08-01 22:15:58 +02:00
|
|
|
return QVariant::fromValue(_len);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::REPEAT_FLAGS:
|
2014-06-02 12:18:28 +02:00
|
|
|
return int(repeatFlags());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::MEASURE_NUMBER_MODE:
|
2013-03-08 12:55:12 +01:00
|
|
|
return int(measureNumberMode());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BREAK_MMR:
|
2014-05-20 17:26:26 +02:00
|
|
|
return breakMultiMeasureRest();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::REPEAT_COUNT:
|
2014-05-20 17:26:26 +02:00
|
|
|
return repeatCount();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::USER_STRETCH:
|
2014-05-20 17:26:26 +02:00
|
|
|
return userStretch();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::NO_OFFSET:
|
2014-05-20 17:26:26 +02:00
|
|
|
return noOffset();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::IRREGULAR:
|
2014-05-20 17:26:26 +02:00
|
|
|
return irregular();
|
2012-08-01 22:15:58 +02:00
|
|
|
default:
|
|
|
|
return MeasureBase::getProperty(propertyId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::setProperty(P_ID propertyId, const QVariant& value)
|
|
|
|
{
|
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TIMESIG_NOMINAL:
|
2012-08-01 22:15:58 +02:00
|
|
|
_timesig = value.value<Fraction>();
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TIMESIG_ACTUAL:
|
2012-08-01 22:15:58 +02:00
|
|
|
_len = value.value<Fraction>();
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::REPEAT_FLAGS:
|
2014-06-02 12:18:28 +02:00
|
|
|
setRepeatFlags(Repeat(value.toInt()));
|
2013-02-27 14:41:04 +01:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::MEASURE_NUMBER_MODE:
|
2013-03-08 12:55:12 +01:00
|
|
|
setMeasureNumberMode(MeasureNumberMode(value.toInt()));
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BREAK_MMR:
|
2014-05-20 17:26:26 +02:00
|
|
|
setBreakMultiMeasureRest(value.toBool());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::REPEAT_COUNT:
|
2014-05-20 17:26:26 +02:00
|
|
|
setRepeatCount(value.toInt());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::USER_STRETCH:
|
2014-05-20 17:26:26 +02:00
|
|
|
setUserStretch(value.toDouble());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::NO_OFFSET:
|
2014-05-20 17:26:26 +02:00
|
|
|
setNoOffset(value.toInt());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::IRREGULAR:
|
2014-05-20 17:26:26 +02:00
|
|
|
setIrregular(value.toBool());
|
|
|
|
break;
|
2012-08-01 22:15:58 +02:00
|
|
|
default:
|
|
|
|
return MeasureBase::setProperty(propertyId, value);
|
|
|
|
}
|
2014-05-20 17:26:26 +02:00
|
|
|
score()->setLayoutAll(true);
|
2012-08-01 22:15:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// propertyDefault
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-03-08 12:55:12 +01:00
|
|
|
QVariant Measure::propertyDefault(P_ID propertyId) const
|
2012-08-01 22:15:58 +02:00
|
|
|
{
|
2013-03-08 12:55:12 +01:00
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TIMESIG_NOMINAL:
|
|
|
|
case P_ID::TIMESIG_ACTUAL:
|
2013-03-08 12:55:12 +01:00
|
|
|
return QVariant();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::REPEAT_FLAGS:
|
2013-03-08 12:55:12 +01:00
|
|
|
return 0;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::MEASURE_NUMBER_MODE:
|
2013-03-08 12:55:12 +01:00
|
|
|
return int(MeasureNumberMode::AUTO);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BREAK_MMR:
|
2014-05-20 17:26:26 +02:00
|
|
|
return false;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::REPEAT_COUNT:
|
2014-05-20 17:26:26 +02:00
|
|
|
return 2;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::USER_STRETCH:
|
2014-05-20 17:26:26 +02:00
|
|
|
return 1.0;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::NO_OFFSET:
|
2014-05-20 17:26:26 +02:00
|
|
|
return 0;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::IRREGULAR:
|
2014-05-20 17:26:26 +02:00
|
|
|
return false;
|
2013-03-08 12:55:12 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return MeasureBase::getProperty(propertyId);
|
2012-08-01 22:15:58 +02:00
|
|
|
}
|
2013-01-03 16:56:56 +01:00
|
|
|
|
2013-10-30 14:21:08 +01:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// mmRestFirst
|
|
|
|
// this is a multi measure rest
|
|
|
|
// returns first measure of replaced sequence of empty measures
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
Measure* Measure::mmRestFirst() const
|
|
|
|
{
|
|
|
|
Q_ASSERT(isMMRest());
|
|
|
|
if (prev())
|
|
|
|
return static_cast<Measure*>(prev()->next());
|
|
|
|
return score()->firstMeasure();
|
|
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// mmRestLast
|
|
|
|
// this is a multi measure rest
|
|
|
|
// returns last measure of replaced sequence of empty measures
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
Measure* Measure::mmRestLast() const
|
|
|
|
{
|
|
|
|
Q_ASSERT(isMMRest());
|
|
|
|
if (next())
|
|
|
|
return static_cast<Measure*>(next()->prev());
|
|
|
|
return score()->lastMeasure();
|
|
|
|
}
|
|
|
|
|
2014-04-24 10:42:42 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// mmRest1
|
|
|
|
// return the multi measure rest this measure is covered
|
|
|
|
// by
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure* Measure::mmRest1() const
|
|
|
|
{
|
|
|
|
if (_mmRest)
|
|
|
|
return _mmRest;
|
|
|
|
if (_mmRestCount != -1)
|
2014-04-24 17:09:42 +02:00
|
|
|
return const_cast<Measure*>(this);
|
2014-04-24 10:42:42 +02:00
|
|
|
const Measure* m = this;
|
|
|
|
while (m && !m->_mmRest)
|
|
|
|
m = m->prevMeasure();
|
|
|
|
if (m)
|
|
|
|
return const_cast<Measure*>(m->_mmRest);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-05-17 18:40:05 +02:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// userStretch
|
|
|
|
//-------------------------------------------------------------------
|
2014-05-20 17:26:26 +02:00
|
|
|
|
2014-05-17 18:40:05 +02:00
|
|
|
qreal Measure::userStretch() const
|
|
|
|
{
|
2014-05-30 10:15:36 +02:00
|
|
|
return (score()->layoutMode() == LayoutMode::FLOAT ? 1.0 : _userStretch);
|
2014-05-17 18:40:05 +02:00
|
|
|
}
|
2014-04-24 10:42:42 +02:00
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|