2012-05-26 14:26:10 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
2016-11-02 08:55:54 +01:00
|
|
|
// Copyright (C) 2002-2016 Werner Schweer
|
2012-05-26 14:26:10 +02:00
|
|
|
//
|
|
|
|
// 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"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "accidental.h"
|
|
|
|
#include "ambitus.h"
|
|
|
|
#include "articulation.h"
|
|
|
|
#include "barline.h"
|
|
|
|
#include "beam.h"
|
|
|
|
#include "box.h"
|
|
|
|
#include "bracket.h"
|
|
|
|
#include "breath.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "chord.h"
|
|
|
|
#include "clef.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "drumset.h"
|
|
|
|
#include "duration.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "dynamic.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "fret.h"
|
|
|
|
#include "glissando.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "hairpin.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "harmony.h"
|
|
|
|
#include "hook.h"
|
|
|
|
#include "icon.h"
|
|
|
|
#include "image.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "keysig.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "layoutbreak.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "layout.h"
|
|
|
|
#include "note.h"
|
|
|
|
#include "ottava.h"
|
|
|
|
#include "page.h"
|
|
|
|
#include "part.h"
|
|
|
|
#include "pedal.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "pitchspelling.h"
|
|
|
|
#include "repeat.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "rest.h"
|
|
|
|
#include "score.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "select.h"
|
|
|
|
#include "sig.h"
|
|
|
|
#include "slur.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "spacer.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "staff.h"
|
|
|
|
#include "stafftext.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "stafftype.h"
|
2013-12-05 21:37:28 +01:00
|
|
|
#include "stringdata.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "style.h"
|
|
|
|
#include "sym.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "tempotext.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "tie.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "tiemap.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "timesig.h"
|
|
|
|
#include "tremolo.h"
|
|
|
|
#include "trill.h"
|
|
|
|
#include "tuplet.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "tupletmap.h"
|
2014-12-13 17:40:39 +01:00
|
|
|
#include "undo.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "volta.h"
|
|
|
|
#include "xml.h"
|
2016-02-10 13:40:34 +01:00
|
|
|
#include "systemdivider.h"
|
2016-12-18 14:31:13 +01:00
|
|
|
#include "stafftypechange.h"
|
2016-12-23 12:05:18 +01:00
|
|
|
#include "stafflines.h"
|
2017-03-31 13:03:15 +02:00
|
|
|
#include "bracketItem.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
|
2016-12-12 14:55:35 +01:00
|
|
|
/// Per staff values of measure.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
class MStaff {
|
|
|
|
Shape _shape;
|
|
|
|
Text* _noText { 0 }; ///< Measure number text object
|
|
|
|
StaffLines* _lines { 0 };
|
|
|
|
Spacer* _vspacerUp { 0 };
|
|
|
|
Spacer* _vspacerDown { 0 };
|
|
|
|
bool _hasVoices { false }; ///< indicates that MStaff contains more than one voice,
|
|
|
|
///< this changes some layout rules
|
|
|
|
bool _visible { true };
|
|
|
|
bool _slashStyle { false };
|
|
|
|
#ifndef NDEBUG
|
|
|
|
bool _corrupted { false };
|
|
|
|
#endif
|
|
|
|
|
|
|
|
public:
|
|
|
|
MStaff() {}
|
|
|
|
~MStaff();
|
|
|
|
MStaff(const MStaff&);
|
|
|
|
|
|
|
|
void setScore(Score*);
|
|
|
|
void setTrack(int);
|
|
|
|
|
|
|
|
Shape shape() const { return _shape; }
|
|
|
|
Shape& shape() { return _shape; }
|
|
|
|
|
|
|
|
Text* noText() const { return _noText; }
|
|
|
|
void setNoText(Text* t) { _noText = t; }
|
|
|
|
|
|
|
|
StaffLines* lines() const { return _lines; }
|
|
|
|
void setLines(StaffLines* l) { _lines = l; }
|
|
|
|
|
|
|
|
Spacer* vspacerUp() const { return _vspacerUp; }
|
|
|
|
void setVspacerUp(Spacer* s) { _vspacerUp = s; }
|
|
|
|
Spacer* vspacerDown() const { return _vspacerDown; }
|
|
|
|
void setVspacerDown(Spacer* s) { _vspacerDown = s; }
|
|
|
|
|
|
|
|
bool hasVoices() const { return _hasVoices; }
|
|
|
|
void setHasVoices(bool val) { _hasVoices = val; }
|
|
|
|
|
|
|
|
bool visible() const { return _visible; }
|
|
|
|
void setVisible(bool val) { _visible = val; }
|
|
|
|
|
|
|
|
bool slashStyle() const { return _slashStyle; }
|
|
|
|
void setSlashStyle(bool val) { _slashStyle = val; }
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2016-12-15 14:21:32 +01:00
|
|
|
bool corrupted() const { return _corrupted; }
|
|
|
|
void setCorrupted(bool val) { _corrupted = val; }
|
2016-12-12 14:55:35 +01:00
|
|
|
#endif
|
|
|
|
};
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
MStaff::~MStaff()
|
|
|
|
{
|
2013-03-08 16:07:03 +01:00
|
|
|
delete _noText;
|
2016-12-12 12:02:18 +01:00
|
|
|
delete _lines;
|
2012-05-26 14:26:10 +02:00
|
|
|
delete _vspacerUp;
|
|
|
|
delete _vspacerDown;
|
|
|
|
}
|
|
|
|
|
2013-03-08 16:07:03 +01:00
|
|
|
MStaff::MStaff(const MStaff& m)
|
|
|
|
{
|
|
|
|
_noText = 0;
|
2016-12-12 12:02:18 +01:00
|
|
|
_lines = new StaffLines(*m._lines);
|
|
|
|
_hasVoices = m._hasVoices;
|
2013-03-08 16:07:03 +01:00
|
|
|
_vspacerUp = 0;
|
|
|
|
_vspacerDown = 0;
|
|
|
|
_visible = m._visible;
|
|
|
|
_slashStyle = m._slashStyle;
|
2016-06-03 18:26:51 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
_corrupted = m._corrupted;
|
|
|
|
#endif
|
2013-03-08 16:07:03 +01:00
|
|
|
}
|
|
|
|
|
2016-12-12 12:02:18 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// MStaff::setScore
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void MStaff::setScore(Score* score)
|
|
|
|
{
|
|
|
|
if (_lines)
|
|
|
|
_lines->setScore(score);
|
|
|
|
if (_vspacerUp)
|
|
|
|
_vspacerUp->setScore(score);
|
|
|
|
if (_vspacerDown)
|
|
|
|
_vspacerDown->setScore(score);
|
|
|
|
if (_noText)
|
|
|
|
_noText->setScore(score);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setTrack
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void MStaff::setTrack(int track)
|
|
|
|
{
|
|
|
|
if (_lines)
|
|
|
|
_lines->setTrack(track);
|
|
|
|
if (_vspacerUp)
|
|
|
|
_vspacerUp->setTrack(track);
|
|
|
|
if (_vspacerDown)
|
|
|
|
_vspacerDown->setTrack(track);
|
|
|
|
if (_noText)
|
|
|
|
_noText->setTrack(track);
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure::Measure(Score* s)
|
2016-01-04 14:48:58 +01:00
|
|
|
: MeasureBase(s), _timesig(4,4), _len(4,4)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
_repeatCount = 2;
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
int n = score()->nstaves();
|
2016-01-04 14:48:58 +01:00
|
|
|
_mstaves.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);
|
2016-12-12 12:02:18 +01:00
|
|
|
s->setLines(new StaffLines(score()));
|
|
|
|
s->lines()->setTrack(staffIdx * VOICES);
|
|
|
|
s->lines()->setParent(this);
|
|
|
|
s->lines()->setVisible(!staff->invisible());
|
2016-01-04 14:48:58 +01:00
|
|
|
_mstaves.push_back(s);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
setIrregular(false);
|
2016-02-04 11:27:47 +01:00
|
|
|
_noMode = MeasureNumberMode::AUTO;
|
2016-02-09 09:20:54 +01:00
|
|
|
_userStretch = 1.0;
|
2016-02-04 11:27:47 +01:00
|
|
|
_breakMultiMeasureRest = false;
|
|
|
|
_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)
|
|
|
|
{
|
2016-02-04 11:27:47 +01:00
|
|
|
_segments = m._segments.clone();
|
|
|
|
_timesig = m._timesig;
|
|
|
|
_len = m._len;
|
|
|
|
_repeatCount = m._repeatCount;
|
|
|
|
_userStretch = m._userStretch;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
_mstaves.reserve(m._mstaves.size());
|
|
|
|
for (MStaff* ms : m._mstaves)
|
2016-02-06 22:03:43 +01:00
|
|
|
_mstaves.push_back(new MStaff(*ms));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
_breakMultiMeasureRest = m._breakMultiMeasureRest;
|
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;
|
|
|
|
}
|
|
|
|
|
2016-12-12 14:55:35 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// layoutStaffLines
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::layoutStaffLines()
|
|
|
|
{
|
|
|
|
for (MStaff* ms : _mstaves)
|
|
|
|
ms->lines()->layout();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// createStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::createStaves(int staffIdx)
|
|
|
|
{
|
|
|
|
for (int n = _mstaves.size(); n <= staffIdx; ++n) {
|
|
|
|
Staff* staff = score()->staff(n);
|
|
|
|
MStaff* s = new MStaff;
|
|
|
|
s->setLines(new StaffLines(score()));
|
|
|
|
s->lines()->setParent(this);
|
|
|
|
s->lines()->setTrack(n * VOICES);
|
|
|
|
s->lines()->setVisible(!staff->invisible());
|
|
|
|
_mstaves.push_back(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setScore
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::setScore(Score* score)
|
|
|
|
{
|
|
|
|
MeasureBase::setScore(score);
|
|
|
|
for (Segment* s = first(); s; s = s->next())
|
|
|
|
s->setScore(score);
|
|
|
|
}
|
|
|
|
|
2016-12-12 14:55:35 +01:00
|
|
|
bool Measure::hasVoices(int staffIdx) const { return _mstaves[staffIdx]->hasVoices(); }
|
|
|
|
void Measure::setHasVoices(int staffIdx, bool v) { return _mstaves[staffIdx]->setHasVoices(v); }
|
|
|
|
StaffLines* Measure::staffLines(int staffIdx) { return _mstaves[staffIdx]->lines(); }
|
|
|
|
Spacer* Measure::vspacerDown(int staffIdx) const { return _mstaves[staffIdx]->vspacerDown(); }
|
|
|
|
Spacer* Measure::vspacerUp(int staffIdx) const { return _mstaves[staffIdx]->vspacerUp(); }
|
|
|
|
void Measure::setStaffVisible(int staffIdx, bool visible) { _mstaves[staffIdx]->setVisible(visible); }
|
|
|
|
void Measure::setStaffSlashStyle(int staffIdx, bool slashStyle) { _mstaves[staffIdx]->setSlashStyle(slashStyle); }
|
2016-12-15 14:21:32 +01:00
|
|
|
#ifndef NDEBUG
|
2016-12-12 14:55:35 +01:00
|
|
|
bool Measure::corrupted(int staffIdx) const { return _mstaves[staffIdx]->corrupted(); }
|
|
|
|
void Measure::setCorrupted(int staffIdx, bool val) { _mstaves[staffIdx]->setCorrupted(val); }
|
2016-12-15 14:21:32 +01:00
|
|
|
#endif
|
2016-12-12 14:55:35 +01:00
|
|
|
void Measure::setNoText(int staffIdx, Text* t) { _mstaves[staffIdx]->setNoText(t); }
|
|
|
|
Text* Measure::noText(int staffIdx) const { return _mstaves[staffIdx]->noText(); }
|
2017-09-19 15:20:06 +02:00
|
|
|
const Shape& Measure::staffShape(int staffIdx) const { return _mstaves[staffIdx]->shape(); }
|
2016-12-12 14:55:35 +01:00
|
|
|
Shape& Measure::staffShape(int staffIdx) { return _mstaves[staffIdx]->shape(); }
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Measure::~Measure()
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s;) {
|
|
|
|
Segment* ns = s->next();
|
|
|
|
delete s;
|
|
|
|
s = ns;
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
qDeleteAll(_mstaves);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// AcEl
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
struct AcEl {
|
|
|
|
Note* note;
|
|
|
|
qreal x;
|
|
|
|
};
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// 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
|
|
|
{
|
2015-07-19 17:18:38 +02:00
|
|
|
Chord* chord = note->chord();
|
2012-05-26 14:26:10 +02:00
|
|
|
AccidentalState tversatz; // state of already set accidentals for this measure
|
2017-02-13 12:42:54 +01:00
|
|
|
tversatz.init(chord->staff()->keySigEvent(tick()), chord->staff()->clef(tick()));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2015-07-19 17:18:38 +02:00
|
|
|
for (Segment* segment = first(); segment; segment = segment->next()) {
|
|
|
|
int startTrack = chord->staffIdx() * VOICES;
|
2016-10-18 15:41:00 +02:00
|
|
|
if (segment->isKeySigType()) {
|
|
|
|
KeySig* ks = toKeySig(segment->element(startTrack));
|
2015-07-19 17:18:38 +02:00
|
|
|
if (!ks)
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
2017-02-13 12:42:54 +01:00
|
|
|
tversatz.init(chord->staff()->keySigEvent(segment->tick()), chord->staff()->clef(segment->tick()));
|
2015-07-19 17:18:38 +02:00
|
|
|
}
|
2017-03-08 13:12:26 +01:00
|
|
|
else if (segment->segmentType() == SegmentType::ChordRest) {
|
2015-07-19 17:18:38 +02:00
|
|
|
int endTrack = startTrack + VOICES;
|
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
Element* e = segment->element(track);
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!e || !e->isChord())
|
2015-07-19 17:18:38 +02:00
|
|
|
continue;
|
2016-10-18 15:41:00 +02:00
|
|
|
Chord* chord = toChord(e);
|
2015-07-19 17:18:38 +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->epitch());
|
|
|
|
|
|
|
|
if (note == note1)
|
|
|
|
return tversatz.accidentalVal(line);
|
|
|
|
tversatz.setAccidentalVal(line, tpc2alter(tpc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (Note* note1 : chord->notes()) {
|
2013-09-02 12:13:46 +02:00
|
|
|
if (note1->tieBack())
|
|
|
|
continue;
|
|
|
|
//
|
|
|
|
// compute accidental
|
|
|
|
//
|
|
|
|
int tpc = note1->tpc();
|
2015-01-21 18:31:12 +01:00
|
|
|
int line = absStep(tpc, note1->epitch());
|
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));
|
|
|
|
}
|
|
|
|
}
|
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.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-01-21 14:33:32 +01:00
|
|
|
AccidentalVal Measure::findAccidental(Segment* s, int staffIdx, int line, bool &error) const
|
2012-08-06 21:55:51 +02:00
|
|
|
{
|
|
|
|
AccidentalState tversatz; // state of already set accidentals for this measure
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2017-02-13 12:42:54 +01:00
|
|
|
tversatz.init(staff->keySigEvent(tick()), staff->clef(tick()));
|
2012-08-06 21:55:51 +02:00
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
SegmentType st = SegmentType::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)) {
|
2016-12-13 13:16:17 +01:00
|
|
|
if (segment == s && staff->isPitchedStaff(tick())) {
|
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);
|
2016-01-21 14:33:32 +01:00
|
|
|
return tversatz.accidentalVal(l, error);
|
2012-08-06 21:55:51 +02:00
|
|
|
}
|
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
Element* e = segment->element(track);
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!e || !e->isChord())
|
2012-08-06 21:55:51 +02:00
|
|
|
continue;
|
2016-10-18 15:41:00 +02:00
|
|
|
Chord* chord = toChord(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();
|
2015-01-21 18:31:12 +01:00
|
|
|
int l = absStep(tpc, note->epitch());
|
2013-09-02 12:13:46 +02:00
|
|
|
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();
|
2015-01-21 18:31:12 +01:00
|
|
|
int l = absStep(tpc, note->epitch());
|
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
|
|
|
//---------------------------------------------------------
|
|
|
|
// 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
|
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
tck -= ticks();
|
2013-09-19 15:08:54 +02:00
|
|
|
if (isMMRest()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* s = first(SegmentType::ChordRest);
|
2016-10-20 11:32:07 +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;
|
2016-10-20 11:32:07 +02:00
|
|
|
qreal x1 = 0;
|
|
|
|
qreal x2 = 0;
|
|
|
|
int tick1 = 0;
|
|
|
|
int tick2 = 0;
|
2017-03-08 13:12:26 +01:00
|
|
|
for (s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
2013-06-19 16:25:29 +02:00
|
|
|
x2 = s->x();
|
2016-10-20 11:32:07 +02:00
|
|
|
tick2 = s->rtick();
|
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();
|
2016-10-20 11:32:07 +02:00
|
|
|
tick2 = ticks();
|
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
|
2016-01-04 14:48:58 +01:00
|
|
|
// called after layout of page
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::layout2()
|
|
|
|
{
|
2016-02-09 09:20:54 +01:00
|
|
|
Q_ASSERT(parent());
|
2016-02-08 15:10:03 +01:00
|
|
|
Q_ASSERT(score()->nstaves() == int(_mstaves.size()));
|
2013-09-20 12:59:31 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal _spatium = spatium();
|
2016-01-04 14:48:58 +01:00
|
|
|
|
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
|
|
|
|
MStaff* ms = _mstaves[staffIdx];
|
2016-12-12 12:02:18 +01:00
|
|
|
Spacer* sp = ms->vspacerDown();
|
2016-01-04 14:48:58 +01:00
|
|
|
if (sp) {
|
|
|
|
sp->layout();
|
2016-12-13 13:16:17 +01:00
|
|
|
int n = score()->staff(staffIdx)->lines(tick()) - 1;
|
2016-01-04 14:48:58 +01:00
|
|
|
qreal y = system()->staff(staffIdx)->y();
|
|
|
|
sp->setPos(_spatium * .5, y + n * _spatium);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-12-12 12:02:18 +01:00
|
|
|
sp = ms->vspacerUp();
|
2016-01-04 14:48:58 +01:00
|
|
|
if (sp) {
|
|
|
|
sp->layout();
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal y = system()->staff(staffIdx)->y();
|
2016-01-04 14:48:58 +01:00
|
|
|
sp->setPos(_spatium * .5, y - sp->gap());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MeasureBase::layout(); // layout LAYOUT_BREAK elements
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------
|
2012-05-26 14:26:10 +02:00
|
|
|
// set measure number
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
bool smn = false;
|
2012-10-17 10:39:39 +02:00
|
|
|
|
2014-08-11 15:25:55 +02:00
|
|
|
if (_noMode == MeasureNumberMode::SHOW)
|
|
|
|
smn = true;
|
|
|
|
else if (_noMode == MeasureNumberMode::HIDE)
|
|
|
|
smn = false;
|
|
|
|
else {
|
|
|
|
if (score()->styleB(StyleIdx::showMeasureNumber)
|
2016-01-04 14:48:58 +01:00
|
|
|
&& !irregular()
|
|
|
|
&& (no() || score()->styleB(StyleIdx::showMeasureNumberOne))) {
|
2014-08-11 15:25:55 +02:00
|
|
|
if (score()->styleB(StyleIdx::measureNumberSystem))
|
|
|
|
smn = system()->firstMeasure() == this;
|
|
|
|
else {
|
2016-01-04 14:48:58 +01:00
|
|
|
smn = (no() == 0 && score()->styleB(StyleIdx::showMeasureNumberOne)) ||
|
2017-01-05 11:23:47 +01:00
|
|
|
( ((no()+1) % score()->styleI(StyleIdx::measureNumberInterval)) == 0 );
|
2013-05-01 22:44:49 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-11 15:25:55 +02:00
|
|
|
}
|
|
|
|
QString s;
|
|
|
|
if (smn)
|
2016-01-04 14:48:58 +01:00
|
|
|
s = QString("%1").arg(no() + 1);
|
2014-08-11 15:25:55 +02:00
|
|
|
int nn = 1;
|
|
|
|
bool nas = score()->styleB(StyleIdx::measureNumberAllStaffs);
|
|
|
|
|
|
|
|
if (!nas) {
|
|
|
|
//find first non invisible staff
|
2016-02-06 22:03:43 +01:00
|
|
|
for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx) {
|
|
|
|
MStaff* ms = _mstaves[staffIdx];
|
2014-08-11 15:25:55 +02:00
|
|
|
SysStaff* s = system()->staff(staffIdx);
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
if (ms->visible() && staff->show() && s->show()) {
|
|
|
|
nn = staffIdx;
|
|
|
|
break;
|
2013-03-08 16:07:03 +01:00
|
|
|
}
|
2014-08-11 15:25:55 +02:00
|
|
|
}
|
|
|
|
}
|
2016-02-08 15:10:03 +01:00
|
|
|
for (int staffIdx = 0; staffIdx < int(_mstaves.size()); ++staffIdx) {
|
2016-02-06 22:03:43 +01:00
|
|
|
MStaff* ms = _mstaves[staffIdx];
|
2014-08-11 15:25:55 +02:00
|
|
|
Text* t = ms->noText();
|
2016-02-04 11:27:47 +01:00
|
|
|
if (t)
|
2014-08-11 15:25:55 +02:00
|
|
|
t->setTrack(staffIdx * VOICES);
|
|
|
|
if (smn && ((staffIdx == nn) || nas)) {
|
|
|
|
if (t == 0) {
|
2017-01-16 20:51:12 +01:00
|
|
|
t = new Text(SubStyle::MEASURE_NUMBER, score());
|
2014-08-11 15:25:55 +02:00
|
|
|
t->setFlag(ElementFlag::ON_STAFF, true);
|
|
|
|
t->setTrack(staffIdx * VOICES);
|
|
|
|
t->setGenerated(true);
|
|
|
|
t->setParent(this);
|
2016-10-18 15:41:00 +02:00
|
|
|
add(t);
|
2012-10-17 10:39:39 +02:00
|
|
|
}
|
2015-04-27 12:59:30 +02:00
|
|
|
t->setXmlText(s);
|
2014-08-11 15:25:55 +02:00
|
|
|
t->layout();
|
|
|
|
}
|
|
|
|
else {
|
2016-10-18 15:41:00 +02:00
|
|
|
if (t) {
|
|
|
|
if (t->generated())
|
|
|
|
score()->removeElement(t);
|
|
|
|
else
|
|
|
|
score()->undo(new RemoveElement(t));
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-08-11 15:25:55 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------
|
|
|
|
// layout ties, spanners and tuples
|
|
|
|
//---------------------------------------------------
|
|
|
|
|
|
|
|
int tracks = score()->ntracks();
|
2017-03-08 13:12:26 +01:00
|
|
|
static const SegmentType st { SegmentType::ChordRest };
|
2016-01-04 14:48:58 +01:00
|
|
|
for (int track = 0; track < tracks; ++track) {
|
|
|
|
if (!score()->staff(track / VOICES)->show()) {
|
|
|
|
track += VOICES-1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (Segment* s = first(st); s; s = s->next(st)) {
|
|
|
|
ChordRest* cr = s->cr(track);
|
2014-07-02 09:55:50 +02:00
|
|
|
if (!cr)
|
|
|
|
continue;
|
|
|
|
|
2016-10-18 15:41:00 +02:00
|
|
|
if (cr->isChord()) {
|
|
|
|
Chord* c = toChord(cr);
|
2014-07-02 09:55:50 +02:00
|
|
|
for (const Note* note : c->notes()) {
|
|
|
|
Tie* tie = note->tieFor();
|
|
|
|
if (tie)
|
|
|
|
tie->layout();
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Spanner* sp : note->spannerFor())
|
2014-07-02 09:55:50 +02:00
|
|
|
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
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-10-20 11:32:07 +02:00
|
|
|
Chord* Measure::findChord(int t, int track)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
t -= tick();
|
2012-05-26 14:26:10 +02:00
|
|
|
for (Segment* seg = last(); seg; seg = seg->prev()) {
|
2016-10-20 11:32:07 +02:00
|
|
|
if (seg->rtick() < t)
|
2012-05-26 14:26:10 +02:00
|
|
|
return 0;
|
2016-10-20 11:32:07 +02:00
|
|
|
if (seg->rtick() == t) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Element* el = seg->element(track);
|
2016-03-08 17:58:04 +01:00
|
|
|
if (el && el->isChord())
|
2016-02-17 14:54:23 +01:00
|
|
|
return toChord(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
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-10-20 11:32:07 +02:00
|
|
|
ChordRest* Measure::findChordRest(int t, int track)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
t -= tick();
|
2016-02-09 09:20:54 +01:00
|
|
|
for (const Segment& seg : _segments) {
|
2016-10-20 11:32:07 +02:00
|
|
|
if (seg.rtick() > t)
|
2012-05-26 14:26:10 +02:00
|
|
|
return 0;
|
2016-10-20 11:32:07 +02:00
|
|
|
if (seg.rtick() == t) {
|
2016-02-09 09:20:54 +01:00
|
|
|
Element* el = seg.element(track);
|
2016-04-21 10:14:42 +02:00
|
|
|
if (el && el->isChordRest())
|
2016-02-17 14:54:23 +01:00
|
|
|
return toChordRest(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// tick2segment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::tick2segment(int t, SegmentType st)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
t -= tick();
|
2016-02-09 09:20:54 +01:00
|
|
|
for (Segment& s : _segments) {
|
2016-10-20 11:32:07 +02:00
|
|
|
if (s.rtick() == t) {
|
2016-02-09 09:20:54 +01:00
|
|
|
if (s.segmentType() & st)
|
|
|
|
return &s;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-10-20 11:32:07 +02:00
|
|
|
if (s.rtick() > t)
|
2016-02-09 09:20:54 +01:00
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
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
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::findSegment(SegmentType st, int t) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
t -= tick();
|
2012-05-26 14:26:10 +02:00
|
|
|
Segment* s;
|
2016-10-20 11:32:07 +02:00
|
|
|
if (t > ticks()/2) {
|
|
|
|
// search backwards
|
|
|
|
for (s = last(); s && s->rtick() > t; s = s->prev())
|
|
|
|
;
|
|
|
|
while (s && s->prev() && s->prev()->rtick() == t)
|
|
|
|
s = s->prev();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// search forwards
|
|
|
|
for (s = first(); s && s->rtick() < t; s = s->next())
|
|
|
|
;
|
|
|
|
}
|
|
|
|
for (; s && s->rtick() == t; s = s->next()) {
|
2014-08-21 15:01:54 +02:00
|
|
|
if (s->segmentType() & st)
|
2013-05-24 12:36:32 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
2016-10-20 11:32:07 +02:00
|
|
|
// getSegment
|
|
|
|
/// 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
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::getSegment(SegmentType st, int t)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
return getSegmentR(st, t - tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2016-10-20 11:32:07 +02:00
|
|
|
// findSegmentR
|
|
|
|
// Search for a segment of type st at relative
|
|
|
|
// position t.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::findSegmentR(SegmentType st, int t) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
Segment* s;
|
|
|
|
if (t > ticks()/2) {
|
|
|
|
// search backwards
|
|
|
|
for (s = last(); s && s->rtick() > t; s = s->prev())
|
|
|
|
;
|
|
|
|
while (s && s->prev() && s->prev()->rtick() == t)
|
|
|
|
s = s->prev();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// search forwards
|
|
|
|
for (s = first(); s && s->rtick() < t; s = s->next())
|
|
|
|
;
|
|
|
|
}
|
|
|
|
for (; s && s->rtick() == t; s = s->next()) {
|
|
|
|
if (s->segmentType() & st)
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// findFirst
|
|
|
|
// return first segment of type st at relative
|
|
|
|
// position t.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::findFirst(SegmentType st, int t) const
|
2016-10-25 17:30:55 +02:00
|
|
|
{
|
|
|
|
Segment* s;
|
|
|
|
// search forwards
|
|
|
|
for (s = first(); s && s->rtick() <= t; s = s->next()) {
|
|
|
|
if (s->segmentType() == st)
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
2016-10-20 11:32:07 +02:00
|
|
|
// getSegmentR
|
|
|
|
/// Get a segment of type \a st at relative tick position \a t.
|
2012-09-10 16:10:25 +02:00
|
|
|
/// If the segment does not exist, it is created.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::getSegmentR(SegmentType st, int t)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
Segment* s = findSegmentR(st, t);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!s) {
|
2016-10-20 11:32:07 +02:00
|
|
|
s = new Segment(this, st, t);
|
2012-05-26 14:26:10 +02:00
|
|
|
add(s);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2016-10-20 11:32:07 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoGetSegment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::undoGetSegment(SegmentType type, int t)
|
2016-10-20 11:32:07 +02:00
|
|
|
{
|
|
|
|
return undoGetSegmentR(type, t-tick());
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoGetSegmentR
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* Measure::undoGetSegmentR(SegmentType type, int t)
|
2016-10-20 11:32:07 +02:00
|
|
|
{
|
|
|
|
Segment* s = findSegmentR(type, t);
|
|
|
|
if (s == 0) {
|
|
|
|
s = new Segment(this, type, t);
|
|
|
|
score()->undoAddElement(s);
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// add
|
2012-07-31 09:48:37 +02:00
|
|
|
/// Add new Element \a el to Measure.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
void Measure::add(Element* e)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
e->setParent(this);
|
2017-01-18 14:16:33 +01:00
|
|
|
ElementType type = e->type();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
switch (type) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::SEGMENT:
|
2016-10-25 17:30:55 +02:00
|
|
|
{
|
|
|
|
Segment* seg = toSegment(e);
|
|
|
|
int t = seg->rtick();
|
2017-03-08 13:12:26 +01:00
|
|
|
SegmentType st = seg->segmentType();
|
2016-10-25 17:30:55 +02:00
|
|
|
Segment* s;
|
|
|
|
|
|
|
|
for (s = first(); s && s->rtick() < t; s = s->next())
|
|
|
|
;
|
|
|
|
while (s && s->rtick() == t) {
|
|
|
|
if (s->segmentType() > st)
|
|
|
|
break;
|
|
|
|
s = s->next();
|
|
|
|
}
|
|
|
|
seg->setParent(this);
|
|
|
|
_segments.insert(seg, s);
|
|
|
|
//
|
|
|
|
// update measure flags
|
|
|
|
//
|
|
|
|
if (seg->header())
|
|
|
|
seg->measure()->setHeader(true);
|
|
|
|
if (seg->trailer())
|
|
|
|
seg->measure()->setTrailer(true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::TEXT:
|
2016-02-08 15:10:03 +01:00
|
|
|
if (e->staffIdx() < int(_mstaves.size()))
|
2016-10-18 15:41:00 +02:00
|
|
|
_mstaves[e->staffIdx()]->setNoText(toText(e));
|
2012-10-17 10:39:39 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::SPACER:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-12 20:06:46 +02:00
|
|
|
Spacer* sp = toSpacer(e);
|
|
|
|
switch (sp->spacerType()) {
|
|
|
|
case SpacerType::UP:
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[e->staffIdx()]->setVspacerUp(sp);
|
2016-10-12 20:06:46 +02:00
|
|
|
break;
|
|
|
|
case SpacerType::DOWN:
|
|
|
|
case SpacerType::FIXED:
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[e->staffIdx()]->setVspacerDown(sp);
|
2016-10-12 20:06:46 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::JUMP:
|
2016-02-04 11:27:47 +01:00
|
|
|
setRepeatJump(true);
|
2014-08-05 20:40:43 +02:00
|
|
|
// fall through
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MARKER:
|
2016-01-04 14:48:58 +01:00
|
|
|
el().push_back(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::HBOX:
|
2016-01-04 14:48:58 +01:00
|
|
|
if (e->staff())
|
2016-12-23 12:05:18 +01:00
|
|
|
e->setMag(e->staff()->mag(tick())); // ?!
|
2016-01-04 14:48:58 +01:00
|
|
|
el().push_back(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MEASURE:
|
2016-10-18 15:41:00 +02:00
|
|
|
_mmRest = toMeasure(e);
|
2013-10-30 14:21:08 +01:00
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2016-01-04 14:48:58 +01:00
|
|
|
MeasureBase::add(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
2012-08-08 20:46:29 +02:00
|
|
|
/// Remove Element \a el from Measure.
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
void Measure::remove(Element* e)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
Q_ASSERT(e->parent() == this);
|
|
|
|
Q_ASSERT(e->score() == score());
|
2014-08-25 19:30:56 +02:00
|
|
|
|
2016-10-12 20:06:46 +02:00
|
|
|
switch (e->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::SEGMENT:
|
2016-10-25 17:30:55 +02:00
|
|
|
{
|
|
|
|
Segment* s = toSegment(e);
|
|
|
|
_segments.remove(s);
|
|
|
|
//
|
|
|
|
// update measure flags
|
|
|
|
//
|
|
|
|
if (s->header())
|
|
|
|
s->measure()->checkHeader();
|
|
|
|
if (s->trailer())
|
|
|
|
s->measure()->checkTrailer();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::TEXT:
|
2016-10-18 15:41:00 +02:00
|
|
|
_mstaves[e->staffIdx()]->setNoText(nullptr);
|
2012-10-17 10:39:39 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::SPACER:
|
2016-10-12 20:06:46 +02:00
|
|
|
switch (toSpacer(e)->spacerType()) {
|
|
|
|
case SpacerType::DOWN:
|
|
|
|
case SpacerType::FIXED:
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[e->staffIdx()]->setVspacerDown(0);
|
2016-10-12 20:06:46 +02:00
|
|
|
break;
|
|
|
|
case SpacerType::UP:
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[e->staffIdx()]->setVspacerUp(0);
|
2016-10-12 20:06:46 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::JUMP:
|
2016-02-04 11:27:47 +01:00
|
|
|
setRepeatJump(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
// fall through
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MARKER:
|
|
|
|
case ElementType::HBOX:
|
2016-01-04 14:48:58 +01:00
|
|
|
if (!el().remove(e)) {
|
|
|
|
qDebug("Measure(%p)::remove(%s,%p) not found", this, e->name(), e);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CLEF:
|
|
|
|
case ElementType::CHORD:
|
|
|
|
case ElementType::REST:
|
|
|
|
case ElementType::TIMESIG:
|
2012-05-26 14:26:10 +02:00
|
|
|
for (Segment* segment = first(); segment; segment = segment->next()) {
|
2016-03-10 10:41:31 +01:00
|
|
|
int staves = score()->nstaves();
|
2012-05-26 14:26:10 +02:00
|
|
|
int tracks = staves * VOICES;
|
|
|
|
for (int track = 0; track < tracks; ++track) {
|
2016-01-04 14:48:58 +01:00
|
|
|
Element* ee = segment->element(track);
|
|
|
|
if (ee == e) {
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->setElement(track, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
qDebug("Measure::remove: %s %p not found", e->name(), e);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MEASURE:
|
2013-10-30 14:21:08 +01:00
|
|
|
_mmRest = 0;
|
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2016-01-04 14:48:58 +01:00
|
|
|
MeasureBase::remove(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// change
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::change(Element* o, Element* n)
|
|
|
|
{
|
2016-10-18 15:41:00 +02:00
|
|
|
if (o->isTuplet()) {
|
|
|
|
Tuplet* t = toTuplet(n);
|
2016-02-09 09:20:54 +01:00
|
|
|
for (DurationElement* e : t->elements())
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setTuplet(t);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
remove(o);
|
|
|
|
add(n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-30 00:59:01 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// spatiumChanged
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::spatiumChanged(qreal /*oldValue*/, qreal /*newValue*/)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// 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);
|
2016-05-19 13:15:34 +02:00
|
|
|
for (Segment* segment = last(); segment; segment = segment->prev()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
if (segment->segmentType() & (SegmentType::EndBarLine | SegmentType::TimeSigAnnounce))
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->setTick(tick() + ticks());
|
2016-05-19 13:15:34 +02:00
|
|
|
else if (segment->isChordRestType())
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
for (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)
|
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : el()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e->track() == -1)
|
|
|
|
continue;
|
|
|
|
int staffIdx = e->staffIdx();
|
2014-12-20 20:56:40 +01:00
|
|
|
if (staffIdx >= sStaff && !e->systemFlag()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
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();
|
2016-03-10 10:41:31 +01:00
|
|
|
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();
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undo(new RemoveElement(e));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : el()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e->track() == -1)
|
|
|
|
continue;
|
|
|
|
int staffIdx = e->staffIdx();
|
2014-12-20 20:56:40 +01:00
|
|
|
if (staffIdx >= sStaff && (staffIdx < eStaff) && !e->systemFlag()) {
|
2014-05-21 20:08:37 +02:00
|
|
|
e->undoUnlink();
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undo(new RemoveElement(e));
|
2014-05-21 20:08:37 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undo(new RemoveStaves(this, sStaff, eStaff));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-08-25 19:30:56 +02:00
|
|
|
for (int i = eStaff - 1; i >= sStaff; --i) {
|
2016-01-04 14:48:58 +01:00
|
|
|
MStaff* ms = *(_mstaves.begin()+i);
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undo(new RemoveMStaff(this, ms, i));
|
2014-08-25 19:30:56 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
// barLine
|
|
|
|
// TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// cmdAddStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::cmdAddStaves(int sStaff, int eStaff, bool createRest)
|
|
|
|
{
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undo(new InsertStaves(this, sStaff, eStaff));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* ts = findSegment(SegmentType::TimeSig, tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
for (int i = sStaff; i < eStaff; ++i) {
|
2016-03-10 10:41:31 +01:00
|
|
|
Staff* staff = score()->staff(i);
|
2012-05-26 14:26:10 +02:00
|
|
|
MStaff* ms = new MStaff;
|
2016-12-12 12:02:18 +01:00
|
|
|
ms->setLines(new StaffLines(score()));
|
|
|
|
ms->lines()->setTrack(i * VOICES);
|
|
|
|
ms->lines()->setParent(this);
|
|
|
|
ms->lines()->setVisible(!staff->invisible());
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undo(new InsertMStaff(this, ms, i));
|
2014-07-27 15:06:49 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-07-27 15:06:49 +02:00
|
|
|
if (!createRest && !ts)
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// create list of unique staves (only one instance for linked staves):
|
|
|
|
|
|
|
|
QList<int> sl;
|
|
|
|
for (int staffIdx = sStaff; staffIdx < eStaff; ++staffIdx) {
|
2016-03-10 10:41:31 +01:00
|
|
|
Staff* s = score()->staff(staffIdx);
|
2014-07-27 15:06:49 +02:00
|
|
|
if (s->linkedStaves()) {
|
|
|
|
bool alreadyInList = false;
|
|
|
|
for (int idx : sl) {
|
2016-03-10 10:41:31 +01:00
|
|
|
if (s->linkedStaves()->staves().contains(score()->staff(idx))) {
|
2014-07-27 15:06:49 +02:00
|
|
|
alreadyInList = true;
|
|
|
|
break;
|
|
|
|
}
|
2014-02-17 23:06:11 +01:00
|
|
|
}
|
2014-07-27 15:06:49 +02:00
|
|
|
if (alreadyInList)
|
|
|
|
continue;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-07-27 15:06:49 +02:00
|
|
|
sl.append(staffIdx);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int staffIdx : sl) {
|
|
|
|
if (createRest)
|
|
|
|
score()->setRest(tick(), staffIdx * VOICES, len(), false, 0, _timesig == len());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
// replicate time signature
|
|
|
|
if (ts) {
|
|
|
|
TimeSig* ots = 0;
|
2016-01-03 20:40:36 +01:00
|
|
|
bool constructed = false;
|
2016-02-08 15:10:03 +01:00
|
|
|
for (unsigned track = 0; track < _mstaves.size() * VOICES; ++track) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (ts->element(track)) {
|
2016-10-18 15:41:00 +02:00
|
|
|
ots = toTimeSig(ts->element(track));
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-01-03 20:40:36 +01:00
|
|
|
if (!ots) {
|
|
|
|
// no time signature found; use measure length to construct one
|
|
|
|
ots = new TimeSig(score());
|
|
|
|
ots->setSig(len());
|
|
|
|
constructed = true;
|
|
|
|
}
|
2015-01-26 12:48:32 +01:00
|
|
|
// do no replicate local time signatures
|
|
|
|
if (ots && !ots->isLocal()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
TimeSig* timesig = new TimeSig(*ots);
|
2014-07-27 15:06:49 +02:00
|
|
|
timesig->setTrack(staffIdx * VOICES);
|
|
|
|
timesig->setParent(ts);
|
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);
|
2016-01-03 20:40:36 +01:00
|
|
|
if (constructed)
|
|
|
|
delete ots;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertMStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::insertMStaff(MStaff* staff, int idx)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
_mstaves.insert(_mstaves.begin()+idx, staff);
|
2016-02-08 15:10:03 +01:00
|
|
|
for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx)
|
2016-01-04 14:48:58 +01:00
|
|
|
_mstaves[staffIdx]->setTrack(staffIdx * VOICES);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeMStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::removeMStaff(MStaff* /*staff*/, int idx)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
_mstaves.erase(_mstaves.begin()+idx);
|
2016-02-08 15:10:03 +01:00
|
|
|
for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx)
|
2016-01-04 14:48:58 +01:00
|
|
|
_mstaves[staffIdx]->setTrack(staffIdx * VOICES);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::insertStaff(Staff* staff, int staffIdx)
|
|
|
|
{
|
|
|
|
for (Segment* s = first(); s; s = s->next())
|
|
|
|
s->insertStaff(staffIdx);
|
|
|
|
|
|
|
|
MStaff* ms = new MStaff;
|
2016-12-12 12:02:18 +01:00
|
|
|
ms->setLines(new StaffLines(score()));
|
|
|
|
ms->lines()->setParent(this);
|
|
|
|
ms->lines()->setTrack(staffIdx * VOICES);
|
|
|
|
ms->lines()->setVisible(!staff->invisible());
|
2012-05-26 14:26:10 +02:00
|
|
|
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
|
|
|
|
*/
|
|
|
|
|
2017-03-31 13:03:15 +02:00
|
|
|
bool Measure::acceptDrop(EditData& data) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-08-13 21:01:21 +02:00
|
|
|
MuseScoreView* viewer = data.view;
|
|
|
|
QPointF pos = data.pos;
|
|
|
|
Element* e = data.element;
|
|
|
|
|
2016-12-18 14:31:13 +01:00
|
|
|
|
2014-08-13 21:01:21 +02:00
|
|
|
int staffIdx;
|
|
|
|
Segment* seg;
|
2016-12-18 14:31:13 +01:00
|
|
|
if (!score()->pos2measure(pos, &staffIdx, 0, &seg, 0))
|
2014-10-04 18:22:36 +02:00
|
|
|
return false;
|
|
|
|
|
2014-08-13 21:01:21 +02:00
|
|
|
QRectF staffR = system()->staff(staffIdx)->bbox().translated(system()->canvasPos());
|
|
|
|
staffR &= canvasBoundingRect();
|
|
|
|
|
2014-06-19 15:27:44 +02:00
|
|
|
switch (e->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MEASURE_LIST:
|
|
|
|
case ElementType::JUMP:
|
|
|
|
case ElementType::MARKER:
|
|
|
|
case ElementType::LAYOUT_BREAK:
|
|
|
|
case ElementType::STAFF_LIST:
|
2014-08-13 21:01:21 +02:00
|
|
|
viewer->setDropRectangle(canvasBoundingRect());
|
|
|
|
return true;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::KEYSIG:
|
|
|
|
case ElementType::TIMESIG:
|
2014-08-13 21:01:21 +02:00
|
|
|
if (data.modifiers & Qt::ControlModifier)
|
|
|
|
viewer->setDropRectangle(staffR);
|
|
|
|
else
|
|
|
|
viewer->setDropRectangle(canvasBoundingRect());
|
|
|
|
return true;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BRACKET:
|
|
|
|
case ElementType::REPEAT_MEASURE:
|
|
|
|
case ElementType::MEASURE:
|
|
|
|
case ElementType::SPACER:
|
|
|
|
case ElementType::IMAGE:
|
|
|
|
case ElementType::BAR_LINE:
|
|
|
|
case ElementType::SYMBOL:
|
|
|
|
case ElementType::CLEF:
|
|
|
|
case ElementType::STAFFTYPE_CHANGE:
|
2014-08-13 21:01:21 +02:00
|
|
|
viewer->setDropRectangle(staffR);
|
2012-05-26 14:26:10 +02:00
|
|
|
return true;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::ICON:
|
2016-10-18 15:41:00 +02:00
|
|
|
switch (toIcon(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.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-31 13:03:15 +02:00
|
|
|
Element* Measure::drop(EditData& data)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Element* e = data.element;
|
2015-09-05 15:16:03 +02:00
|
|
|
int staffIdx = -1;
|
2012-05-26 14:26:10 +02:00
|
|
|
Segment* seg;
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->pos2measure(data.pos, &staffIdx, 0, &seg, 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
if (e->systemFlag())
|
|
|
|
staffIdx = 0;
|
2015-09-05 15:16:03 +02:00
|
|
|
if (staffIdx < 0)
|
|
|
|
return 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2017-01-16 22:16:10 +01:00
|
|
|
//bool fromPalette = (e->track() == -1);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-09-22 17:28:44 +02:00
|
|
|
switch (e->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MEASURE_LIST:
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::STAFF_LIST:
|
2012-05-26 14:26:10 +02:00
|
|
|
//TODO score()->pasteStaff(e, this, staffIdx);
|
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::MARKER:
|
|
|
|
case ElementType::JUMP:
|
2014-08-05 20:40:43 +02:00
|
|
|
e->setParent(this);
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setTrack(0);
|
2015-09-18 17:56:20 +02:00
|
|
|
{
|
|
|
|
// code borrowed from ChordRest::drop()
|
2017-01-16 20:51:12 +01:00
|
|
|
// Text* t = static_cast<Text*>(e);
|
|
|
|
// StyledPropertyListIdx st = t->textStyleType();
|
2015-09-18 17:56:20 +02:00
|
|
|
// for palette items, we want to use current score text style settings
|
|
|
|
// except where the source element had explicitly overridden these via text properties
|
|
|
|
// palette text style will be relative to baseStyle, so rebase this to score
|
2017-01-16 20:51:12 +01:00
|
|
|
// if (st >= StyledPropertyListIdx::DEFAULT && fromPalette)
|
|
|
|
// t->textStyle().restyle(MScore::baseStyle().textStyle(st), score()->textStyle(st));
|
2015-09-18 17:56:20 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::DYNAMIC:
|
|
|
|
case ElementType::FRET_DIAGRAM:
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setParent(seg);
|
|
|
|
e->setTrack(staffIdx * VOICES);
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::IMAGE:
|
|
|
|
case ElementType::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;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BRACKET:
|
2013-06-28 17:46:24 +02:00
|
|
|
{
|
2016-10-18 15:41:00 +02:00
|
|
|
Bracket* b = toBracket(e);
|
2013-06-28 17:46:24 +02:00
|
|
|
int level = 0;
|
|
|
|
int firstStaff = 0;
|
2016-02-09 09:20:54 +01:00
|
|
|
for (Staff* s : score()->staves()) {
|
2017-03-31 13:03:15 +02:00
|
|
|
for (const BracketItem* bi : s->brackets()) {
|
|
|
|
int lastStaff = firstStaff + bi->bracketSpan() - 1;
|
2013-06-28 17:46:24 +02:00
|
|
|
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
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CLEF:
|
2016-10-18 15:41:00 +02:00
|
|
|
score()->undoChangeClef(staff, first(), toClef(e)->clefType());
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::KEYSIG:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-05-18 16:32:53 +02:00
|
|
|
KeySigEvent k = toKeySig(e)->keySigEvent();
|
|
|
|
delete e;
|
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-12-04 14:40:26 +01:00
|
|
|
score()->undoChangeKeySig(staff, tick(), k);
|
2012-08-09 21:54:27 +02:00
|
|
|
}
|
|
|
|
else {
|
2012-05-26 14:26:10 +02:00
|
|
|
// apply to all staves:
|
2016-05-18 16:32:53 +02:00
|
|
|
for (Staff* s : score()->staves())
|
2014-12-04 14:40:26 +01:00
|
|
|
score()->undoChangeKeySig(s, tick(), k);
|
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;
|
|
|
|
}
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::TIMESIG:
|
2016-10-18 15:41:00 +02:00
|
|
|
score()->cmdAddTimeSig(this, staffIdx, toTimeSig(e),
|
2012-06-28 09:28:13 +02:00
|
|
|
data.modifiers & Qt::ControlModifier);
|
2012-05-26 14:26:10 +02:00
|
|
|
return 0;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::LAYOUT_BREAK: {
|
2016-10-12 17:56:05 +02:00
|
|
|
LayoutBreak* b = toLayoutBreak(e);
|
2016-12-05 15:18:36 +01:00
|
|
|
Measure* measure = isMMRest() ? mmRestLast() : this;
|
2016-10-12 17:56:05 +02:00
|
|
|
switch (b->layoutBreakType()) {
|
|
|
|
case LayoutBreak::PAGE:
|
2016-12-05 15:18:36 +01:00
|
|
|
if (measure->pageBreak()) {
|
2016-10-12 17:56:05 +02:00
|
|
|
delete b;
|
|
|
|
b = 0;
|
|
|
|
}
|
|
|
|
else
|
2016-12-05 15:18:36 +01:00
|
|
|
measure->setLineBreak(false);
|
2016-10-12 17:56:05 +02:00
|
|
|
break;
|
|
|
|
case LayoutBreak::LINE:
|
2016-12-05 15:18:36 +01:00
|
|
|
if (measure->lineBreak()) {
|
2016-10-12 17:56:05 +02:00
|
|
|
delete b;
|
|
|
|
b = 0;
|
|
|
|
}
|
|
|
|
else
|
2016-12-05 15:18:36 +01:00
|
|
|
measure->setPageBreak(false);
|
2016-10-12 17:56:05 +02:00
|
|
|
break;
|
|
|
|
case LayoutBreak::SECTION:
|
2016-12-05 15:18:36 +01:00
|
|
|
if (measure->sectionBreak()) {
|
2016-10-12 17:56:05 +02:00
|
|
|
delete b;
|
|
|
|
b = 0;
|
|
|
|
}
|
|
|
|
else
|
2016-12-05 15:18:36 +01:00
|
|
|
measure->setLineBreak(false);
|
2016-10-12 17:56:05 +02:00
|
|
|
break;
|
|
|
|
case LayoutBreak::NOBREAK:
|
2016-12-05 15:18:36 +01:00
|
|
|
if (measure->noBreak()) {
|
2016-10-12 17:56:05 +02:00
|
|
|
delete b;
|
|
|
|
b = 0;
|
|
|
|
}
|
|
|
|
else {
|
2016-12-05 15:18:36 +01:00
|
|
|
measure->setLineBreak(false);
|
|
|
|
measure->setPageBreak(false);
|
2016-10-12 17:56:05 +02:00
|
|
|
}
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-10-12 17:56:05 +02:00
|
|
|
if (b) {
|
|
|
|
b->setTrack(-1); // these are system elements
|
2016-12-05 15:18:36 +01:00
|
|
|
b->setParent(measure);
|
2016-10-12 17:56:05 +02:00
|
|
|
score()->undoAddElement(b);
|
|
|
|
}
|
2016-12-05 15:18:36 +01:00
|
|
|
measure->cleanupLayoutBreaks(true);
|
2016-10-12 17:56:05 +02:00
|
|
|
return b;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::SPACER:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-18 15:41:00 +02:00
|
|
|
Spacer* spacer = toSpacer(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
spacer->setTrack(staffIdx * VOICES);
|
|
|
|
spacer->setParent(this);
|
2016-10-12 20:06:46 +02:00
|
|
|
if (spacer->spacerType() == SpacerType::FIXED) {
|
|
|
|
qreal gap = spatium() * 10;
|
|
|
|
System* s = system();
|
|
|
|
if (staffIdx == score()->nstaves()-1) {
|
|
|
|
System* ns = 0;
|
|
|
|
for (System* ts : score()->systems()) {
|
|
|
|
if (ns) {
|
|
|
|
ns = ts;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ts == s)
|
|
|
|
ns = ts;
|
|
|
|
}
|
|
|
|
if (ns) {
|
|
|
|
qreal y1 = s->staffYpage(staffIdx);
|
|
|
|
qreal y2 = ns->staffYpage(0);
|
|
|
|
gap = y2 - y1 - score()->staff(staffIdx)->height();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
qreal y1 = s->staffYpage(staffIdx);
|
|
|
|
qreal y2 = s->staffYpage(staffIdx+1);
|
|
|
|
gap = y2 - y1 - score()->staff(staffIdx)->height();
|
|
|
|
}
|
|
|
|
spacer->setGap(gap);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoAddElement(spacer);
|
|
|
|
return spacer;
|
|
|
|
}
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BAR_LINE:
|
2012-11-09 17:31:50 +01:00
|
|
|
{
|
2016-10-18 15:41:00 +02:00
|
|
|
BarLine* bl = toBarLine(e);
|
2016-02-04 11:27:47 +01:00
|
|
|
|
2012-11-09 17:31:50 +01:00
|
|
|
// if dropped bar line refers to span rather than to subtype
|
2014-12-07 00:11:50 +01:00
|
|
|
// or if Ctrl key used
|
2016-12-18 14:31:13 +01:00
|
|
|
if ((bl->spanFrom() && bl->spanTo()) || data.control()) {
|
2012-11-09 17:31:50 +01:00
|
|
|
// get existing bar line for this staff, and drop the change to it
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* seg = undoGetSegment(SegmentType::EndBarLine, tick() + ticks());
|
2016-10-18 15:41:00 +02:00
|
|
|
BarLine* cbl = toBarLine(seg->element(staffIdx * VOICES));
|
2012-11-09 17:31:50 +01:00
|
|
|
if (cbl)
|
|
|
|
cbl->drop(data);
|
|
|
|
}
|
|
|
|
else {
|
2016-02-04 11:27:47 +01:00
|
|
|
// if dropped bar line refers to line subtype
|
2017-03-08 13:12:26 +01:00
|
|
|
score()->undoChangeBarLine(this, bl->barLineType(), SegmentType::EndBarLine);
|
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
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::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
|
|
|
}
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::ICON:
|
2016-10-18 15:41:00 +02:00
|
|
|
switch(toIcon(e)->iconType()) {
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::VFRAME:
|
2017-01-18 14:16:33 +01:00
|
|
|
score()->insertMeasure(ElementType::VBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::HFRAME:
|
2017-01-18 14:16:33 +01:00
|
|
|
score()->insertMeasure(ElementType::HBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::TFRAME:
|
2017-01-18 14:16:33 +01:00
|
|
|
score()->insertMeasure(ElementType::TBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::FFRAME:
|
2017-01-18 14:16:33 +01:00
|
|
|
score()->insertMeasure(ElementType::FBOX, this);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::MEASURE:
|
2017-01-18 14:16:33 +01:00
|
|
|
score()->insertMeasure(ElementType::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;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::STAFFTYPE_CHANGE:
|
2016-12-18 14:31:13 +01:00
|
|
|
{
|
|
|
|
StaffTypeChange* stc = toStaffTypeChange(e);
|
|
|
|
e->setParent(this);
|
|
|
|
e->setTrack(staffIdx * VOICES);
|
|
|
|
StaffType* st = stc->staffType();
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
|
|
|
|
StaffType* nst;
|
|
|
|
if (st) {
|
|
|
|
nst = staff->setStaffType(tick(), st);
|
|
|
|
delete st;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// dragged from palette
|
|
|
|
st = staff->staffType(tick());
|
|
|
|
nst = staff->setStaffType(tick(), st);
|
|
|
|
}
|
|
|
|
stc->setStaffType(nst);
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
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()
|
|
|
|
//
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->select(0, SelectType::SINGLE, 0);
|
2013-09-26 20:07:58 +02:00
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
if (s->segmentType() & SegmentType::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)
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undoRemoveElement(el);
|
2013-09-26 20:07:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// add repeat measure
|
|
|
|
//
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* seg = undoGetSegment(SegmentType::ChordRest, tick());
|
2016-03-10 10:41:31 +01:00
|
|
|
RepeatMeasure* rm = new RepeatMeasure(score());
|
2013-09-26 20:07:58 +02:00
|
|
|
rm->setTrack(staffIdx * VOICES);
|
|
|
|
rm->setParent(seg);
|
2015-06-09 22:25:02 +02:00
|
|
|
rm->setDurationType(TDuration::DurationType::V_MEASURE);
|
2016-03-10 10:41:31 +01:00
|
|
|
rm->setDuration(stretchedLen(score()->staff(staffIdx)));
|
|
|
|
score()->undoAddCR(rm, this, tick());
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : el()) {
|
2016-10-18 15:41:00 +02:00
|
|
|
if (e->isSlur() && e->staffIdx() == staffIdx)
|
2016-03-10 10:41:31 +01:00
|
|
|
score()->undoRemoveElement(e);
|
2013-09-26 20:07:58 +02:00
|
|
|
}
|
|
|
|
return rm;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// adjustToLen
|
|
|
|
// change actual measure len, adjust elements to
|
|
|
|
// new len
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-24 17:31:25 +01:00
|
|
|
void Measure::adjustToLen(Fraction nf, bool appendRestsIfNecessary)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
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);
|
2014-07-27 12:38:45 +02:00
|
|
|
score()->undo(new InsertTime(score(), 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()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
if (s->segmentType() & (SegmentType::EndBarLine|SegmentType::TimeSigAnnounce|SegmentType::KeySigAnnounce)) {
|
2014-05-20 17:26:26 +02:00
|
|
|
s->setTick(tick() + nl);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-10 10:41:31 +01:00
|
|
|
Score* s = score()->masterScore();
|
2016-09-17 12:51:39 +02:00
|
|
|
Measure* m = s->tick2measure(tick());
|
2014-05-22 16:18:35 +02:00
|
|
|
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) {
|
2016-09-17 12:51:39 +02:00
|
|
|
if (e->isRest()) {
|
2013-10-21 13:11:04 +02:00
|
|
|
++rests;
|
2016-09-17 12:51:39 +02:00
|
|
|
rest = toRest(e);
|
2013-10-21 13:11:04 +02:00
|
|
|
}
|
2016-09-17 12:51:39 +02:00
|
|
|
else if (e->isChord())
|
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
|
2015-03-13 01:07:34 +01:00
|
|
|
if (_timesig == nf) {
|
|
|
|
rest->undoChangeProperty(P_ID::DURATION, QVariant::fromValue<Fraction>(nf));
|
|
|
|
rest->undoChangeProperty(P_ID::DURATION_TYPE, QVariant::fromValue<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)
|
2016-02-06 22:03:43 +01:00
|
|
|
std::vector<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
|
2015-02-12 11:41:39 +01:00
|
|
|
for (ScoreElement* e : rest->linkList()) {
|
2015-02-16 09:44:21 +01:00
|
|
|
e->undoChangeProperty(P_ID::DURATION, QVariant::fromValue<Fraction>(durList[0].fraction()));
|
|
|
|
e->undoChangeProperty(P_ID::DURATION_TYPE, QVariant::fromValue<TDuration>(durList[0]));
|
2014-09-29 11:58:44 +02:00
|
|
|
}
|
2014-05-20 17:26:26 +02:00
|
|
|
|
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();
|
2016-02-08 15:10:03 +01:00
|
|
|
for (unsigned i = 1; i < durList.size(); 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();
|
2017-03-08 13:12:26 +01:00
|
|
|
if (segment->segmentType() == SegmentType::ChordRest) {
|
2016-12-05 10:18:23 +01:00
|
|
|
for (Element* a : segment->annotations())
|
|
|
|
if (a->track() == trk)
|
|
|
|
s->undoRemoveElement(a);
|
|
|
|
Element* e = segment->element(trk);
|
|
|
|
if (e && e->isChordRest()) {
|
|
|
|
ChordRest* cr = toChordRest(e);
|
|
|
|
if (cr->durationType() == TDuration::DurationType::V_MEASURE) {
|
|
|
|
int actualTicks = cr->actualTicks();
|
|
|
|
n += actualTicks;
|
|
|
|
cr->setDurationType(TDuration(actualTicks));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
n += cr->actualTicks();
|
|
|
|
s->undoRemoveElement(e);
|
|
|
|
if (n >= 0)
|
|
|
|
break;
|
2014-02-17 23:06:11 +01:00
|
|
|
}
|
2016-12-05 10:18:23 +01:00
|
|
|
}
|
2017-03-08 13:12:26 +01:00
|
|
|
else if (segment->segmentType() == SegmentType::Breath) {
|
2016-12-05 10:18:23 +01:00
|
|
|
Element* e = segment->element(trk);
|
|
|
|
if (e)
|
|
|
|
s->undoRemoveElement(e);
|
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;
|
2017-03-24 17:31:25 +01:00
|
|
|
if (appendRestsIfNecessary && (n > 0) && (rFlag || voice == 0)) {
|
2013-10-21 13:11:04 +02:00
|
|
|
// 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
|
|
|
|
//
|
2016-10-18 15:41:00 +02:00
|
|
|
foreach (Element* e, m->el()) {
|
|
|
|
if (e->isSlur())
|
2014-05-20 17:26:26 +02:00
|
|
|
s->undoRemoveElement(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-03-09 23:55:10 +01:00
|
|
|
void Measure::write(XmlWriter& xml, int staff, bool writeSystemElements, bool forceTimeSig) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
int mno = no() + 1;
|
2012-05-26 14:26:10 +02:00
|
|
|
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
|
|
|
|
2016-11-19 10:31:14 +01:00
|
|
|
xml.setCurTick(tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
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) {
|
2016-02-04 11:27:47 +01:00
|
|
|
if (repeatStart())
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.tagE("startRepeat");
|
2016-02-04 11:27:47 +01:00
|
|
|
if (repeatEnd())
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.tag("endRepeat", _repeatCount);
|
2015-03-30 11:11:47 +02:00
|
|
|
writeProperty(xml, P_ID::IRREGULAR);
|
|
|
|
writeProperty(xml, P_ID::BREAK_MMR);
|
|
|
|
writeProperty(xml, P_ID::USER_STRETCH);
|
|
|
|
writeProperty(xml, P_ID::NO_OFFSET);
|
|
|
|
writeProperty(xml, P_ID::MEASURE_NUMBER_MODE);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
qreal _spatium = spatium();
|
2016-01-04 14:48:58 +01:00
|
|
|
MStaff* mstaff = _mstaves[staff];
|
2013-03-08 16:07:03 +01:00
|
|
|
if (mstaff->noText() && !mstaff->noText()->generated()) {
|
|
|
|
xml.stag("MeasureNumber");
|
|
|
|
mstaff->noText()->writeProperties(xml);
|
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
2016-12-12 12:02:18 +01:00
|
|
|
if (mstaff->vspacerUp())
|
|
|
|
xml.tag("vspacerUp", mstaff->vspacerUp()->gap() / _spatium);
|
|
|
|
if (mstaff->vspacerDown()) {
|
|
|
|
if (mstaff->vspacerDown()->spacerType() == SpacerType::FIXED)
|
|
|
|
xml.tag("vspacerFixed", mstaff->vspacerDown()->gap() / _spatium);
|
2016-10-12 20:06:46 +02:00
|
|
|
else
|
2016-12-12 12:02:18 +01:00
|
|
|
xml.tag("vspacerDown", mstaff->vspacerDown()->gap() / _spatium);
|
2016-10-12 20:06:46 +02:00
|
|
|
}
|
2016-12-12 12:02:18 +01:00
|
|
|
if (!mstaff->visible())
|
|
|
|
xml.tag("visible", mstaff->visible());
|
|
|
|
if (mstaff->slashStyle())
|
|
|
|
xml.tag("slashStyle", mstaff->slashStyle());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
int strack = staff * VOICES;
|
|
|
|
int etrack = strack + VOICES;
|
2016-01-04 14:48:58 +01:00
|
|
|
for (const Element* e : el()) {
|
|
|
|
if (!e->generated() && ((e->staffIdx() == staff) || (e->systemFlag() && writeSystemElements)))
|
|
|
|
e->write(xml);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-09-19 15:08:54 +02:00
|
|
|
Q_ASSERT(first());
|
|
|
|
Q_ASSERT(last());
|
2017-03-09 23:55:10 +01:00
|
|
|
score()->writeSegments(xml, strack, etrack, first(), last()->next1(), writeSystemElements, false, false, forceTimeSig);
|
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-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
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
for (int n = _mstaves.size(); n <= staffIdx; ++n) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff* staff = score()->staff(n);
|
2012-09-14 10:09:06 +02:00
|
|
|
MStaff* s = new MStaff;
|
2016-12-12 12:02:18 +01:00
|
|
|
s->setLines(new StaffLines(score()));
|
|
|
|
s->lines()->setParent(this);
|
|
|
|
s->lines()->setTrack(n * VOICES);
|
|
|
|
s->lines()->setVisible(!staff->invisible());
|
2016-02-06 22:03:43 +01:00
|
|
|
_mstaves.push_back(s);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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")));
|
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
|
|
|
|
2016-07-07 16:20:16 +02:00
|
|
|
if (tag == "move")
|
|
|
|
e.initTick(e.readFraction().ticks() + tick());
|
|
|
|
else if (tag == "tick") {
|
2015-01-12 14:07:05 +01:00
|
|
|
e.initTick(score()->fileDivision(e.readInt()));
|
2014-11-27 00:40:51 +01:00
|
|
|
}
|
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());
|
2014-01-07 11:42:17 +01:00
|
|
|
|
|
|
|
//
|
2016-10-25 17:30:55 +02:00
|
|
|
// StartRepeatBarLine: at rtick == 0, always BarLineType::START_REPEAT
|
2016-03-08 09:46:33 +01:00
|
|
|
// BarLine: in the middle of a measure, has no semantic
|
2016-10-25 17:30:55 +02:00
|
|
|
// EndBarLine: at the end of a measure
|
|
|
|
// BeginBarLine: first segment of a measure, systemic barline
|
2014-01-07 11:42:17 +01:00
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
SegmentType st;
|
2016-10-20 11:32:07 +02:00
|
|
|
int t = e.tick() - tick();
|
|
|
|
if (t && (t != ticks()))
|
2017-03-08 13:12:26 +01:00
|
|
|
st = SegmentType::BarLine;
|
2017-03-20 18:24:16 +01:00
|
|
|
else if (barLine->barLineType() == BarLineType::START_REPEAT && t == 0)
|
2017-03-08 13:12:26 +01:00
|
|
|
st = SegmentType::StartRepeatBarLine;
|
2016-10-25 17:30:55 +02:00
|
|
|
else if (barLine->barLineType() == BarLineType::START_REPEAT && t == ticks()) {
|
|
|
|
// old version, ignore
|
|
|
|
delete barLine;
|
|
|
|
barLine = 0;
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
2016-10-20 11:32:07 +02:00
|
|
|
else if (t == 0 && segment == 0)
|
2017-03-08 13:12:26 +01:00
|
|
|
st = SegmentType::BeginBarLine;
|
2014-10-10 14:24:37 +02:00
|
|
|
else
|
2017-03-08 13:12:26 +01:00
|
|
|
st = SegmentType::EndBarLine;
|
2016-10-25 17:30:55 +02:00
|
|
|
if (barLine) {
|
|
|
|
segment = getSegmentR(st, t);
|
|
|
|
segment->add(barLine);
|
|
|
|
}
|
2016-12-28 17:20:02 +01:00
|
|
|
barLine->read(e);
|
2016-12-23 12:05:18 +01:00
|
|
|
barLine->layout();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Chord") {
|
2013-06-16 23:33:37 +02:00
|
|
|
Chord* chord = new Chord(score());
|
|
|
|
chord->setTrack(e.track());
|
|
|
|
chord->read(e);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::ChordRest, e.tick());
|
2016-09-22 12:02:27 +02:00
|
|
|
if (chord->noteType() != NoteType::NORMAL)
|
2014-11-28 22:35:25 +01: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);
|
|
|
|
for (int i = 0; i < graceNotes.size(); ++i) {
|
|
|
|
Chord* gc = graceNotes[i];
|
|
|
|
gc->setGraceIndex(i);
|
|
|
|
chord->add(gc);
|
|
|
|
}
|
|
|
|
graceNotes.clear();
|
2014-07-28 15:54:47 +02:00
|
|
|
int crticks = chord->actualTicks();
|
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);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::ChordRest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(rest);
|
2014-07-28 15:54:47 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!rest->duration().isValid()) // hack
|
|
|
|
rest->setDuration(timesig()/timeStretch);
|
|
|
|
|
2014-07-28 15:54:47 +02:00
|
|
|
e.incTick(rest->actualTicks());
|
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());
|
2014-11-27 00:40:51 +01:00
|
|
|
int tick = e.tick();
|
2012-05-26 14:26:10 +02:00
|
|
|
breath->read(e);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::Breath, 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) {
|
2014-08-13 15:42:40 +02:00
|
|
|
spanner->setTicks(e.tick() - spanner->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());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
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);
|
|
|
|
//
|
|
|
|
// 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);
|
2015-03-03 15:45:25 +01:00
|
|
|
sl->setTrack2(sv->track2);
|
2014-01-21 22:30:59 +01:00
|
|
|
}
|
2015-03-03 15:45:25 +01:00
|
|
|
score()->addSpanner(sl);
|
2014-01-21 22:30:59 +01:00
|
|
|
}
|
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) {
|
2014-08-13 15:42:40 +02:00
|
|
|
sp->setTicks(sv->tick2 - sp->tick());
|
2013-10-13 13:06:32 +02:00
|
|
|
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);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::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);
|
2013-07-12 18:41:33 +02:00
|
|
|
|
|
|
|
// there may be more than one clef segment for same tick position
|
2016-10-25 17:30:55 +02:00
|
|
|
// the first clef may be missing and is added later in layout
|
|
|
|
|
|
|
|
bool header;
|
|
|
|
if (e.tick() != tick())
|
|
|
|
header = false;
|
|
|
|
else if (!segment)
|
|
|
|
header = true;
|
2013-07-12 18:41:33 +02:00
|
|
|
else {
|
2016-10-25 17:30:55 +02:00
|
|
|
header = true;
|
|
|
|
for (Segment* s = _segments.first(); s && !s->rtick(); s = s->next()) {
|
|
|
|
if (s->isKeySigType() || s->isTimeSigType()) {
|
2015-02-14 15:10:35 +01:00
|
|
|
// hack: there may be other segment types which should
|
|
|
|
// generate a clef at current position
|
2016-10-25 17:30:55 +02:00
|
|
|
header = false;
|
2013-07-12 18:41:33 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(header ? SegmentType::HeaderClef : SegmentType::Clef, e.tick());
|
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
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::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);
|
2014-07-28 15:54:47 +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
|
|
|
else {
|
|
|
|
// if 'real' time sig., do full process
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::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);
|
2013-06-04 18:29:14 +02:00
|
|
|
|
2014-10-08 10:57:24 +02:00
|
|
|
timeStretch = ts->stretch().reduced();
|
|
|
|
_timesig = ts->sig() / timeStretch;
|
2012-10-17 12:42:00 +02:00
|
|
|
|
2016-09-13 09:39:50 +02:00
|
|
|
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);
|
2014-08-24 13:10:51 +02:00
|
|
|
int curTick = e.tick();
|
2015-06-05 01:53:47 +02:00
|
|
|
if (!ks->isCustom() && !ks->isAtonal() && ks->key() == Key::C && curTick == 0) {
|
2014-08-24 13:10:51 +02:00
|
|
|
// ignore empty key signature
|
|
|
|
qDebug("remove keysig c at tick 0");
|
2016-03-30 22:33:04 +02:00
|
|
|
if (ks->links()) {
|
|
|
|
if (ks->links()->size() == 1)
|
|
|
|
e.linkIds().remove(ks->links()->lid());
|
|
|
|
}
|
2014-08-24 13:10:51 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// if key sig not at beginning of measure => courtesy key sig
|
2015-07-19 17:18:38 +02:00
|
|
|
// bool courtesySig = (curTick > tick());
|
|
|
|
bool courtesySig = (curTick == endTick());
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(courtesySig ? SegmentType::KeySigAnnounce : SegmentType::KeySig, curTick);
|
2014-08-24 13:10:51 +02:00
|
|
|
segment->add(ks);
|
|
|
|
if (!courtesySig)
|
2014-12-08 18:02:17 +01:00
|
|
|
staff->setKey(curTick, ks->keySigEvent());
|
2014-08-24 13:10:51 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Text") {
|
2014-10-06 18:44:08 +02:00
|
|
|
Text* t = new StaffText(score());
|
2013-01-21 20:21:41 +01:00
|
|
|
t->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
t->read(e);
|
2016-03-30 22:33:04 +02:00
|
|
|
if (t->empty()) {
|
2014-07-31 13:45:05 +02:00
|
|
|
qDebug("reading empty text: deleted");
|
|
|
|
delete t;
|
|
|
|
}
|
2012-09-21 12:23:18 +02:00
|
|
|
else {
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::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);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::ChordRest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(dyn);
|
|
|
|
}
|
|
|
|
else if (tag == "Harmony"
|
|
|
|
|| tag == "FretDiagram"
|
2014-08-26 15:07:24 +02:00
|
|
|
|| tag == "TremoloBar"
|
2012-05-26 14:26:10 +02:00
|
|
|
|| tag == "Symbol"
|
|
|
|
|| tag == "Tempo"
|
|
|
|
|| tag == "StaffText"
|
2017-01-20 11:05:52 +01:00
|
|
|
|| tag == "SystemText"
|
2012-05-26 14:26:10 +02:00
|
|
|
|| tag == "RehearsalMark"
|
|
|
|
|| tag == "InstrumentChange"
|
|
|
|
|| tag == "StaffState"
|
|
|
|
|| tag == "FiguredBass"
|
|
|
|
) {
|
2013-01-18 10:55:52 +01:00
|
|
|
Element* el = Element::name2Element(tag, score());
|
2015-04-12 22:14:41 +02:00
|
|
|
// hack - needed because tick tags are unreliable in 1.3 scores
|
|
|
|
// for symbols attached to anything but a measure
|
2013-01-21 20:21:41 +01:00
|
|
|
el->setTrack(e.track());
|
2012-05-26 14:26:10 +02:00
|
|
|
el->read(e);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::ChordRest, e.tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
segment->add(el);
|
|
|
|
}
|
2016-10-20 11:32:07 +02:00
|
|
|
else if (tag == "Marker" || tag == "Jump"
|
2014-08-05 20:40:43 +02:00
|
|
|
) {
|
|
|
|
Element* el = Element::name2Element(tag, score());
|
|
|
|
el->setTrack(e.track());
|
|
|
|
el->read(e);
|
|
|
|
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);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::ChordRest, e.tick());
|
2014-03-04 17:40:23 +01:00
|
|
|
segment->add(el);
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
//----------------------------------------------------
|
2015-06-17 09:55:45 +02:00
|
|
|
else if (tag == "stretch") {
|
|
|
|
double val = e.readDouble();
|
|
|
|
if (val < 0.0)
|
|
|
|
val = 0;
|
|
|
|
setUserStretch(val);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "noOffset")
|
2016-01-04 14:48:58 +01:00
|
|
|
setNoOffset(e.readInt());
|
2015-03-30 11:11:47 +02:00
|
|
|
else if (tag == "measureNumberMode")
|
|
|
|
setMeasureNumberMode(MeasureNumberMode(e.readInt()));
|
2015-04-08 11:58:10 +02:00
|
|
|
else if (tag == "irregular")
|
2016-01-04 14:48:58 +01:00
|
|
|
setIrregular(e.readBool());
|
2015-04-08 11:58:10 +02:00
|
|
|
else if (tag == "breakMultiMeasureRest")
|
|
|
|
_breakMultiMeasureRest = e.readBool();
|
2014-09-16 13:20:15 +02:00
|
|
|
else if (tag == "sysInitBarLineType") {
|
2016-01-04 14:48:58 +01:00
|
|
|
const QString& val(e.readElementText());
|
2016-02-04 11:27:47 +01:00
|
|
|
BarLine* barLine = new BarLine(score());
|
|
|
|
barLine->setTrack(e.track());
|
|
|
|
barLine->setBarLineType(val);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegmentR(SegmentType::BeginBarLine, 0);
|
2016-02-04 11:27:47 +01:00
|
|
|
segment->add(barLine);
|
2014-09-16 13:20:15 +02:00
|
|
|
}
|
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") {
|
2016-02-04 11:27:47 +01:00
|
|
|
setRepeatStart(true);
|
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();
|
2016-02-04 11:27:47 +01:00
|
|
|
setRepeatEnd(true);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "vspacer" || tag == "vspacerDown") {
|
2016-12-12 12:02:18 +01:00
|
|
|
if (!_mstaves[staffIdx]->vspacerDown()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
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);
|
|
|
|
}
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->vspacerDown()->setGap(e.readDouble() * _spatium);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-10-12 20:06:46 +02:00
|
|
|
else if (tag == "vspacerFixed") {
|
2016-12-12 12:02:18 +01:00
|
|
|
if (!_mstaves[staffIdx]->vspacerDown()) {
|
2016-10-12 20:06:46 +02:00
|
|
|
Spacer* spacer = new Spacer(score());
|
|
|
|
spacer->setSpacerType(SpacerType::FIXED);
|
|
|
|
spacer->setTrack(staffIdx * VOICES);
|
|
|
|
add(spacer);
|
|
|
|
}
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->vspacerDown()->setGap(e.readDouble() * _spatium);
|
2016-10-12 20:06:46 +02:00
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
else if (tag == "vspacerUp") {
|
2016-12-12 12:02:18 +01:00
|
|
|
if (!_mstaves[staffIdx]->vspacerUp()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
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);
|
|
|
|
}
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->vspacerUp()->setGap(e.readDouble() * _spatium);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "visible")
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->setVisible(e.readInt());
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "slashStyle")
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->setSlashStyle(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") {
|
2017-01-16 20:51:12 +01:00
|
|
|
Text* noText = new Text(SubStyle::MEASURE_NUMBER, score());
|
2013-03-08 16:07:03 +01:00
|
|
|
noText->read(e);
|
2014-05-22 10:10:58 +02:00
|
|
|
noText->setFlag(ElementFlag::ON_STAFF, true);
|
2013-10-18 17:55:51 +02:00
|
|
|
noText->setTrack(e.track());
|
2013-03-08 16:07:03 +01:00
|
|
|
noText->setParent(this);
|
2016-01-04 14:48:58 +01:00
|
|
|
_mstaves[noText->staffIdx()]->setNoText(noText);
|
2012-10-17 10:39:39 +02:00
|
|
|
}
|
2015-07-25 08:43:02 +02:00
|
|
|
else if (tag == "SystemDivider") {
|
|
|
|
SystemDivider* sd = new SystemDivider(score());
|
|
|
|
sd->read(e);
|
|
|
|
add(sd);
|
|
|
|
}
|
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);
|
2017-03-08 13:12:26 +01:00
|
|
|
segment = getSegment(SegmentType::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);
|
|
|
|
}
|
2015-04-09 13:48:32 +02:00
|
|
|
else if (tag == "multiMeasureRest") {
|
2014-02-26 19:06:42 +01:00
|
|
|
_mmRestCount = e.readInt();
|
2015-04-09 13:48:32 +02:00
|
|
|
// set tick to previous measure
|
|
|
|
setTick(e.lastMeasure()->tick());
|
|
|
|
e.initTick(e.lastMeasure()->tick());
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
else if (MeasureBase::readProperties(e))
|
2013-01-17 12:56:14 +01:00
|
|
|
;
|
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
|
|
|
}
|
2016-09-26 10:15:20 +02:00
|
|
|
e.checkTuplets();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// visible
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::visible(int staffIdx) const
|
|
|
|
{
|
2014-11-10 14:18:42 +01:00
|
|
|
if (staffIdx >= score()->staves().size()) {
|
|
|
|
qDebug("Measure::visible: bad staffIdx: %d", staffIdx);
|
|
|
|
return false;
|
|
|
|
}
|
2016-02-06 22:03:43 +01:00
|
|
|
if (system() && (system()->staves()->empty() || !system()->staff(staffIdx)->show()))
|
2015-08-04 19:53:54 +02:00
|
|
|
return false;
|
|
|
|
if (score()->staff(staffIdx)->cutaway() && isMeasureRest(staffIdx))
|
2015-08-01 01:28:55 +02:00
|
|
|
return false;
|
2016-12-12 12:02:18 +01:00
|
|
|
return score()->staff(staffIdx)->show() && _mstaves[staffIdx]->visible();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// slashStyle
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::slashStyle(int staffIdx) const
|
|
|
|
{
|
2016-12-13 13:16:17 +01:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
return staff->slashStyle(tick()) || _mstaves[staffIdx]->slashStyle() || staff->staffType(tick())->slashStyle();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2015-09-19 11:53:40 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// isFinalMeasureOfSection
|
|
|
|
// returns true if this measure is final actual measure of a section
|
2016-04-14 11:45:12 +02:00
|
|
|
// takes into consideration fact that subsequent measures base objects
|
|
|
|
// may have section break before encountering next actual measure
|
2015-09-19 11:53:40 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::isFinalMeasureOfSection() const
|
|
|
|
{
|
|
|
|
const MeasureBase* mb = static_cast<const MeasureBase*>(this);
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (mb->sectionBreak())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
mb = mb->next();
|
|
|
|
} while (mb && !mb->isMeasure()); // loop until reach next actual measure or end of score
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-08-08 17:46:56 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// isAnacrusis
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::isAnacrusis() const
|
|
|
|
{
|
|
|
|
TimeSigFrac timeSig = score()->sigmap()->timesig(tick()).nominal();
|
|
|
|
return irregular() && ticks() < timeSig.ticksPerMeasure();
|
|
|
|
}
|
|
|
|
|
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;
|
2016-01-04 14:48:58 +01:00
|
|
|
MStaff* ms = _mstaves[staffIdx];
|
2016-12-12 12:02:18 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-10-20 11:32:07 +02:00
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
|
|
|
if (!s->enabled())
|
|
|
|
continue;
|
2014-12-30 00:59:01 +01:00
|
|
|
s->scanElements(data, func, all);
|
2016-10-20 11:32:07 +02:00
|
|
|
}
|
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()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
if (s->segmentType() != SegmentType::ChordRest)
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
if (s->element(track) == 0)
|
|
|
|
score()->setRest(s->tick(), track, len(), true, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// sortStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::sortStaves(QList<int>& dst)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
std::vector<MStaff*> ms;
|
2016-02-09 09:20:54 +01:00
|
|
|
for (int idx : dst)
|
2016-01-04 14:48:58 +01:00
|
|
|
ms.push_back(_mstaves[idx]);
|
|
|
|
_mstaves = ms;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-02-08 15:10:03 +01:00
|
|
|
for (unsigned staffIdx = 0; staffIdx < _mstaves.size(); ++staffIdx)
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->lines()->setTrack(staffIdx * VOICES);
|
2016-02-09 09:20:54 +01:00
|
|
|
for (Segment& s : _segments)
|
|
|
|
s.sortStaves(dst);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : el()) {
|
2014-12-20 20:56:40 +01:00
|
|
|
if (e->track() == -1 || e->systemFlag())
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
|
|
|
int voice = e->voice();
|
|
|
|
int staffIdx = e->staffIdx();
|
|
|
|
int idx = dst.indexOf(staffIdx);
|
|
|
|
e->setTrack(idx * VOICES + voice);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// exchangeVoice
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-07-31 15:23:11 +02:00
|
|
|
void Measure::exchangeVoice(int strack, int dtrack, int staffIdx)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2017-03-08 13:12:26 +01:00
|
|
|
for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
2014-08-29 10:35:17 +02:00
|
|
|
s->swapElements(strack, dtrack);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-04-15 18:20:37 +02:00
|
|
|
|
2016-07-11 18:29:02 +02:00
|
|
|
auto spanners = score()->spannerMap().findOverlapping(tick(), endTick()-1);
|
|
|
|
int start = tick();
|
|
|
|
int end = start + ticks();
|
2016-04-15 18:20:37 +02:00
|
|
|
for (auto i = spanners.begin(); i < spanners.end(); i++) {
|
|
|
|
Spanner* sp = i->value;
|
|
|
|
int spStart = sp->tick();
|
|
|
|
int spEnd = spStart + sp->ticks();
|
|
|
|
qDebug("Start %d End %d Diff %d \n Measure Start %d End %d", spStart, spEnd, spEnd-spStart, start, end);
|
2016-10-18 15:41:00 +02:00
|
|
|
if (sp->isSlur() && (spStart >= start || spEnd < end)) {
|
2016-04-15 18:20:37 +02:00
|
|
|
if (sp->track() == strack && spStart >= start){
|
|
|
|
sp->setTrack(dtrack);
|
|
|
|
}
|
|
|
|
else if (sp->track() == dtrack && spStart >= start){
|
|
|
|
sp->setTrack(strack);
|
|
|
|
}
|
|
|
|
if (sp->track2() == strack && spEnd < end){
|
|
|
|
sp->setTrack2(dtrack);
|
|
|
|
}
|
|
|
|
else if (sp->track2() == dtrack && spEnd < end){
|
|
|
|
sp->setTrack2(strack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-01-26 22:58:46 +01:00
|
|
|
checkMultiVoices(staffIdx); // probably true, but check for invisible notes & rests
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// 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;
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->setHasVoices(false);
|
2016-04-18 11:00:06 +02:00
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = strack; track < etrack; ++track) {
|
2015-01-26 22:58:46 +01:00
|
|
|
Element* e = s->element(track);
|
|
|
|
if (e) {
|
|
|
|
bool v;
|
2016-04-18 11:00:06 +02:00
|
|
|
if (e->isChord()) {
|
2015-01-26 22:58:46 +01:00
|
|
|
v = false;
|
|
|
|
// consider chord visible if any note is visible
|
2016-04-18 11:00:06 +02:00
|
|
|
Chord* c = toChord(e);
|
2015-01-26 22:58:46 +01:00
|
|
|
for (Note* n : c->notes()) {
|
|
|
|
if (n->visible()) {
|
|
|
|
v = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
v = e->visible();
|
|
|
|
if (v) {
|
2016-12-12 12:02:18 +01:00
|
|
|
_mstaves[staffIdx]->setHasVoices(true);
|
2015-01-26 22:58:46 +01:00
|
|
|
return;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// hasVoice
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::hasVoice(int track) const
|
|
|
|
{
|
2016-12-12 14:55:35 +01:00
|
|
|
if (track >= score()->ntracks())
|
2016-07-31 15:23:11 +02:00
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
for (Segment* s = first(); s; s = s->next()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
if (s->segmentType() != SegmentType::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
|
|
|
|
2015-08-04 19:53:54 +02:00
|
|
|
bool Measure::isMeasureRest(int staffIdx) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
int strack;
|
|
|
|
int etrack;
|
|
|
|
if (staffIdx < 0) {
|
|
|
|
strack = 0;
|
|
|
|
etrack = score()->nstaves() * VOICES;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
strack = staffIdx * VOICES;
|
2014-08-26 21:01:21 +02:00
|
|
|
etrack = strack + VOICES;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2017-03-08 13:12:26 +01:00
|
|
|
for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* e = s->element(track);
|
2016-10-18 15:41:00 +02:00
|
|
|
if (e && !e->isRest())
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
|
|
|
}
|
2015-12-12 23:38:32 +01:00
|
|
|
for (Element* a : s->annotations()) {
|
|
|
|
if (!a || a->systemFlag())
|
|
|
|
continue;
|
|
|
|
int atrack = a->track();
|
|
|
|
if (atrack >= strack && atrack < etrack)
|
|
|
|
return false;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// isFullMeasureRest
|
|
|
|
// Check for an empty measure, filled with full measure
|
|
|
|
// rests.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-08-04 19:53:54 +02:00
|
|
|
bool Measure::isFullMeasureRest() const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
int strack = 0;
|
|
|
|
int etrack = score()->nstaves() * VOICES;
|
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* s = first(SegmentType::ChordRest);
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int track = strack; track < etrack; ++track) {
|
|
|
|
Element* e = s->element(track);
|
|
|
|
if (e) {
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!e->isRest())
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
2016-10-18 15:41:00 +02:00
|
|
|
Rest* rest = toRest(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
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-08-04 19:53:54 +02:00
|
|
|
bool Measure::isRepeatMeasure(Staff* staff) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-09-28 21:13:05 +02:00
|
|
|
int staffIdx = staff->idx();
|
|
|
|
int strack = staffIdx * VOICES;
|
|
|
|
int etrack = (staffIdx + 1) * VOICES;
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* s = first(SegmentType::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);
|
2016-10-18 15:41:00 +02:00
|
|
|
if (e && e->isRepeatMeasure())
|
2012-05-26 14:26:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// isEmpty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-02-06 22:03:43 +01:00
|
|
|
bool Measure::empty() const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
if (irregular())
|
2012-05-26 14:26:10 +02:00
|
|
|
return false;
|
|
|
|
int n = 0;
|
2016-01-04 14:48:58 +01:00
|
|
|
int tracks = _mstaves.size() * VOICES;
|
2017-03-08 13:12:26 +01:00
|
|
|
static const SegmentType st = SegmentType::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)) {
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!s->element(track)->isRest())
|
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
|
|
|
|
{
|
2017-03-08 13:12:26 +01:00
|
|
|
static const SegmentType st = SegmentType::ChordRest;
|
2014-02-17 19:07:03 +01:00
|
|
|
for (const Segment* s = first(st); s; s = s->next(st)) {
|
2016-05-17 22:14:29 +02:00
|
|
|
if (s->segmentType() != st || !s->element(track))
|
2014-02-17 19:07:03 +01:00
|
|
|
continue;
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!s->element(track)->isRest())
|
2014-02-17 19:07:03 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-05-17 22:14:29 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// isOnlyDeletedRests
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Measure::isOnlyDeletedRests(int track) const
|
|
|
|
{
|
2017-03-08 13:12:26 +01:00
|
|
|
static const SegmentType st { SegmentType::ChordRest };
|
2016-05-17 22:14:29 +02:00
|
|
|
for (const Segment* s = first(st); s; s = s->next(st)) {
|
|
|
|
if (s->segmentType() != st || !s->element(track))
|
|
|
|
continue;
|
|
|
|
if (s->element(track)->isRest() ? !toRest(s->element(track))->isGap() : !s->element(track)->isRest())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-07-31 09:48:37 +02:00
|
|
|
//---------------------------------------------------------
|
2016-01-04 14:48:58 +01:00
|
|
|
// stretchedLen
|
2012-07-31 09:48:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
Fraction Measure::stretchedLen(Staff* staff) const
|
2012-07-31 09:48:37 +02:00
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
return len() * staff->timeStretch(tick());
|
2012-07-31 09:48:37 +02:00
|
|
|
}
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// cloneMeasure
|
|
|
|
//---------------------------------------------------------
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
Measure* Measure::cloneMeasure(Score* sc, TieMap* tieMap)
|
2013-03-26 16:25:07 +01:00
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
Measure* m = new Measure(sc);
|
|
|
|
m->_timesig = _timesig;
|
|
|
|
m->_len = _len;
|
|
|
|
m->_repeatCount = _repeatCount;
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2016-02-09 09:20:54 +01:00
|
|
|
for (MStaff* ms : _mstaves)
|
2016-02-06 22:03:43 +01:00
|
|
|
m->_mstaves.push_back(new MStaff(*ms));
|
2013-03-26 16:25:07 +01:00
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
m->setNo(no());
|
|
|
|
m->setNoOffset(noOffset());
|
|
|
|
m->setIrregular(irregular());
|
2012-05-26 14:26:10 +02:00
|
|
|
m->_userStretch = _userStretch;
|
|
|
|
m->_breakMultiMeasureRest = _breakMultiMeasureRest;
|
|
|
|
m->_playbackCount = _playbackCount;
|
2012-07-31 09:48:37 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
m->setTick(tick());
|
|
|
|
m->setLineBreak(lineBreak());
|
|
|
|
m->setPageBreak(pageBreak());
|
2016-10-13 14:28:00 +02:00
|
|
|
m->setSectionBreak(sectionBreak() ? new LayoutBreak(*sectionBreakElement()) : 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
int tracks = sc->nstaves() * VOICES;
|
|
|
|
TupletMap tupletMap;
|
|
|
|
|
|
|
|
for (Segment* oseg = first(); oseg; oseg = oseg->next()) {
|
2016-10-20 11:32:07 +02:00
|
|
|
Segment* s = new Segment(m, oseg->segmentType(), oseg->rtick());
|
2012-05-26 14:26:10 +02:00
|
|
|
m->_segments.push_back(s);
|
|
|
|
for (int track = 0; track < tracks; ++track) {
|
|
|
|
Element* oe = oseg->element(track);
|
2016-12-28 16:23:10 +01:00
|
|
|
for (Element* e : oseg->annotations()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
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());
|
2014-11-10 13:33:32 +01:00
|
|
|
ne->setScore(sc);
|
2012-05-26 14:26:10 +02:00
|
|
|
s->add(ne);
|
|
|
|
}
|
2014-08-13 17:45:53 +02:00
|
|
|
if (!oe)
|
|
|
|
continue;
|
|
|
|
Element* ne = oe->clone();
|
|
|
|
if (oe->isChordRest()) {
|
2016-10-18 15:41:00 +02:00
|
|
|
ChordRest* ocr = toChordRest(oe);
|
|
|
|
ChordRest* ncr = toChordRest(ne);
|
2014-08-13 17:45:53 +02:00
|
|
|
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);
|
|
|
|
tupletMap.add(ot, nt);
|
|
|
|
}
|
|
|
|
ncr->setTuplet(nt);
|
|
|
|
nt->add(ncr);
|
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
if (oe->isChord()) {
|
|
|
|
Chord* och = toChord(ocr);
|
|
|
|
Chord* nch = toChord(ncr);
|
2014-08-13 17:45:53 +02:00
|
|
|
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()) {
|
2014-11-25 16:53:43 +01:00
|
|
|
Tie* tie = on->tieFor()->clone();
|
|
|
|
tie->setScore(sc);
|
2014-08-13 17:45:53 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ne->setUserOff(oe->userOff());
|
2014-11-10 13:33:32 +01:00
|
|
|
ne->setScore(sc);
|
2014-08-13 17:45:53 +02:00
|
|
|
s->add(ne);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-17 20:22:24 +01:00
|
|
|
foreach(Element* e, el()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
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::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:
|
2016-01-04 14:48:58 +01: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)
|
|
|
|
{
|
2016-11-02 17:48:13 +01:00
|
|
|
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::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);
|
|
|
|
}
|
2016-11-02 17:48:13 +01:00
|
|
|
score()->setLayout(tick());
|
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::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;
|
|
|
|
}
|
2016-02-04 11:27:47 +01:00
|
|
|
return MeasureBase::propertyDefault(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())
|
2016-10-18 15:41:00 +02:00
|
|
|
return toMeasure(prev()->next());
|
2013-10-30 14:21:08 +01:00
|
|
|
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())
|
2016-10-18 15:41:00 +02:00
|
|
|
return toMeasure(next()->prev());
|
2013-10-30 14:21:08 +01:00
|
|
|
return score()->lastMeasure();
|
|
|
|
}
|
|
|
|
|
2014-04-24 10:42:42 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// mmRest1
|
|
|
|
// return the multi measure rest this measure is covered
|
|
|
|
// by
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-01-19 12:37:17 +01:00
|
|
|
const Measure* Measure::mmRest1() const
|
2014-04-24 10:42:42 +02:00
|
|
|
{
|
|
|
|
if (_mmRest)
|
|
|
|
return _mmRest;
|
|
|
|
if (_mmRestCount != -1)
|
2015-01-19 12:37:17 +01:00
|
|
|
// return const_cast<Measure*>(this);
|
|
|
|
return 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
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// nextElementStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-05-05 18:28:39 +02:00
|
|
|
Element* Measure::nextElementStaff(int staff)
|
2014-06-20 22:48:34 +02:00
|
|
|
{
|
2017-05-12 20:16:02 +02:00
|
|
|
Element* e = score()->selection().element();
|
|
|
|
if (!e && !score()->selection().elements().isEmpty())
|
|
|
|
e = score()->selection().elements().first();
|
|
|
|
for (; e && e->type() != ElementType::SEGMENT; e = e->parent()) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
Segment* seg = static_cast<Segment*>(e);
|
|
|
|
Segment* nextSegment = seg->next();
|
|
|
|
Element* next = seg->firstElementOfSegment(nextSegment, staff);
|
|
|
|
if (next)
|
|
|
|
return next;
|
|
|
|
|
2014-06-20 22:48:34 +02:00
|
|
|
return score()->firstElement();
|
|
|
|
}
|
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// prevElementStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-05-05 18:28:39 +02:00
|
|
|
Element* Measure::prevElementStaff(int staff)
|
2014-06-20 22:48:34 +02:00
|
|
|
{
|
|
|
|
Measure* prevM = prevMeasureMM();
|
|
|
|
if (prevM) {
|
|
|
|
Segment* seg = prevM->last();
|
|
|
|
if (seg)
|
|
|
|
seg->lastElement(staff);
|
|
|
|
}
|
|
|
|
return score()->lastElement();
|
|
|
|
}
|
|
|
|
|
2014-07-10 14:13:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// accessibleInfo
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-02-04 17:06:32 +01:00
|
|
|
QString Measure::accessibleInfo() const
|
2014-07-10 14:13:37 +02:00
|
|
|
{
|
2014-08-21 18:32:52 +02:00
|
|
|
return QString("%1: %2").arg(Element::accessibleInfo()).arg(QString::number(no() + 1));
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// stretchMeasure
|
2016-05-02 13:41:41 +02:00
|
|
|
// resize width of measure to targetWidth
|
2016-01-04 14:48:58 +01:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
void Measure::stretchMeasure(qreal targetWidth)
|
2016-01-04 14:48:58 +01:00
|
|
|
{
|
2016-05-02 13:41:41 +02:00
|
|
|
bbox().setWidth(targetWidth);
|
2016-01-04 14:48:58 +01:00
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
//---------------------------------------------------
|
|
|
|
// compute minTick and set ticks for all segments
|
|
|
|
//---------------------------------------------------
|
2016-01-04 14:48:58 +01:00
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
int minTick = ticks();
|
2016-08-04 17:29:07 +02:00
|
|
|
if (minTick <= 0) {
|
|
|
|
qDebug("=====minTick %d measure %p", minTick, this);
|
|
|
|
}
|
|
|
|
Q_ASSERT(minTick > 0);
|
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
Segment* ns = first();
|
2016-10-25 17:30:55 +02:00
|
|
|
while (ns && !ns->enabled())
|
|
|
|
ns = ns->next();
|
2016-05-02 13:41:41 +02:00
|
|
|
while (ns) {
|
|
|
|
Segment* s = ns;
|
2016-10-31 10:55:11 +01:00
|
|
|
ns = s->nextEnabled();
|
2016-05-02 13:41:41 +02:00
|
|
|
int nticks = (ns ? ns->rtick() : ticks()) - s->rtick();
|
|
|
|
if (nticks) {
|
|
|
|
if (nticks < minTick)
|
|
|
|
minTick = nticks;
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
2016-05-02 13:41:41 +02:00
|
|
|
s->setTicks(nticks);
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------
|
2016-05-02 13:41:41 +02:00
|
|
|
// compute stretch
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------
|
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
std::multimap<qreal, Segment*> springs;
|
2016-02-08 15:10:03 +01:00
|
|
|
|
2016-10-31 10:55:11 +01:00
|
|
|
Segment* s = first();
|
|
|
|
while (s && !s->enabled())
|
|
|
|
s = s->next();
|
|
|
|
qreal minimumWidth = s ? s->x() : 0.0;
|
2016-05-02 13:41:41 +02:00
|
|
|
for (Segment& s : _segments) {
|
2016-10-25 17:30:55 +02:00
|
|
|
if (!s.enabled())
|
|
|
|
continue;
|
2016-02-08 15:10:03 +01:00
|
|
|
int t = s.ticks();
|
2016-01-04 14:48:58 +01:00
|
|
|
if (t) {
|
2016-05-02 13:41:41 +02:00
|
|
|
qreal str = 1.0 + 0.865617 * log(qreal(t) / qreal(minTick)); // .6 * log(t / minTick) / log(2);
|
|
|
|
qreal d = s.width() / str;
|
|
|
|
s.setStretch(str);
|
|
|
|
springs.insert(std::pair<qreal, Segment*>(d, &s));
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
2016-05-02 13:41:41 +02:00
|
|
|
minimumWidth += s.width();
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------
|
2016-05-02 13:41:41 +02:00
|
|
|
// compute 1/Force for a given Extend
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------
|
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
if (targetWidth > minimumWidth) {
|
|
|
|
qreal force = 0;
|
|
|
|
qreal c = 0.0;
|
|
|
|
for (auto i = springs.begin();;) {
|
|
|
|
c += i->second->stretch();
|
|
|
|
minimumWidth -= i->second->width();
|
|
|
|
qreal f = (targetWidth - minimumWidth) / c;
|
|
|
|
++i;
|
|
|
|
if (i == springs.end() || f <= i->first) {
|
|
|
|
force = f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-09-28 20:20:14 +02:00
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
//---------------------------------------------------
|
|
|
|
// distribute stretch to segments
|
|
|
|
//---------------------------------------------------
|
2016-01-04 14:48:58 +01:00
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
for (auto& i : springs) {
|
|
|
|
qreal width = force * i.second->stretch();
|
|
|
|
if (width > i.second->width())
|
|
|
|
i.second->setWidth(width);
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
//---------------------------------------------------
|
|
|
|
// move segments to final position
|
|
|
|
//---------------------------------------------------
|
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
Segment* s = first();
|
|
|
|
while (s && !s->enabled())
|
|
|
|
s = s->next();
|
|
|
|
qreal x = s->pos().x();
|
|
|
|
while (s) {
|
|
|
|
s->rxpos() = x;
|
|
|
|
x += s->width();
|
2016-10-31 10:55:11 +01:00
|
|
|
s = s->nextEnabled();
|
2016-05-02 13:41:41 +02:00
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------
|
|
|
|
// layout individual elements
|
|
|
|
//---------------------------------------------------
|
|
|
|
|
2016-05-02 13:41:41 +02:00
|
|
|
for (Segment& s : _segments) {
|
2016-10-25 17:30:55 +02:00
|
|
|
if (!s.enabled())
|
|
|
|
continue;
|
2016-05-02 13:41:41 +02:00
|
|
|
for (Element* e : s.elist()) {
|
|
|
|
if (!e)
|
2016-01-04 14:48:58 +01:00
|
|
|
continue;
|
2017-01-18 14:16:33 +01:00
|
|
|
ElementType t = e->type();
|
2016-05-02 13:41:41 +02:00
|
|
|
int staffIdx = e->staffIdx();
|
2017-01-18 14:16:33 +01:00
|
|
|
if (t == ElementType::REPEAT_MEASURE || (t == ElementType::REST && (isMMRest() || toRest(e)->isFullMeasureRest()))) {
|
2016-01-04 14:48:58 +01:00
|
|
|
//
|
|
|
|
// element has to be centered in free space
|
|
|
|
// x1 - left measure position of free space
|
|
|
|
// x2 - right measure position of free space
|
|
|
|
|
2016-10-31 10:55:11 +01:00
|
|
|
Segment* s1;
|
|
|
|
for (s1 = s.prev(); s1 && !s1->enabled(); s1 = s1->prev())
|
|
|
|
;
|
2016-02-17 12:48:53 +01:00
|
|
|
Segment* s2;
|
2016-05-02 13:41:41 +02:00
|
|
|
for (s2 = s.next(); s2; s2 = s2->next()) {
|
2016-10-31 10:55:11 +01:00
|
|
|
if (s2->enabled() && !s2->isChordRestType() && s2->element(staffIdx * VOICES))
|
2016-01-04 14:48:58 +01:00
|
|
|
break;
|
|
|
|
}
|
2016-02-17 12:48:53 +01:00
|
|
|
qreal x1 = s1 ? s1->x() + s1->minRight() : 0;
|
2016-05-02 13:41:41 +02:00
|
|
|
qreal x2 = s2 ? s2->x() - s2->minLeft() : targetWidth;
|
2016-01-04 14:48:58 +01:00
|
|
|
|
|
|
|
if (isMMRest()) {
|
2016-05-02 13:41:41 +02:00
|
|
|
Rest* rest = toRest(e);
|
2016-01-04 14:48:58 +01:00
|
|
|
//
|
|
|
|
// center multi measure rest
|
|
|
|
//
|
2017-10-17 14:28:03 +02:00
|
|
|
qreal d = score()->styleP(StyleIdx::multiMeasureRestMargin);
|
2016-01-04 14:48:58 +01:00
|
|
|
qreal w = x2 - x1 - 2 * d;
|
|
|
|
|
2017-10-17 14:28:03 +02:00
|
|
|
rest->layoutMMRest(w);
|
|
|
|
e->setPos(x1 - s.x() + d, e->staff()->height() * .5); // center vertically in measure
|
2016-05-02 13:41:41 +02:00
|
|
|
s.createShape(staffIdx);
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
else { // if (rest->isFullMeasureRest()) {
|
|
|
|
//
|
|
|
|
// center full measure rest
|
|
|
|
//
|
2016-05-02 13:41:41 +02:00
|
|
|
e->rxpos() = (x2 - x1 - e->width()) * .5 + x1 - s.x() - e->bbox().x();
|
|
|
|
e->adjustReadPos();
|
|
|
|
s.createShape(staffIdx); // DEBUG
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
}
|
2017-01-18 14:16:33 +01:00
|
|
|
else if (t == ElementType::REST)
|
2016-01-04 14:48:58 +01:00
|
|
|
e->rxpos() = 0;
|
2017-01-18 14:16:33 +01:00
|
|
|
else if (t == ElementType::CHORD) {
|
2016-02-17 14:54:23 +01:00
|
|
|
Chord* c = toChord(e);
|
2016-02-16 21:21:28 +01:00
|
|
|
c->layout2();
|
|
|
|
if (c->tremolo())
|
|
|
|
c->tremolo()->layout();
|
|
|
|
}
|
2017-01-18 14:16:33 +01:00
|
|
|
else if (t == ElementType::BAR_LINE) {
|
2017-08-02 18:19:08 +02:00
|
|
|
e->rypos() = 0.0;
|
2017-08-04 12:05:30 +02:00
|
|
|
e->rxpos() = 0.0;
|
|
|
|
// e->rxpos() = s.isEndBarLineType() ? s.width() * .5 : 0.0;
|
2016-01-04 14:48:58 +01:00
|
|
|
e->adjustReadPos();
|
|
|
|
}
|
2016-02-04 11:27:47 +01:00
|
|
|
else
|
2016-01-04 14:48:58 +01:00
|
|
|
e->adjustReadPos();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// endBarLine
|
|
|
|
// return the first one
|
|
|
|
//---------------------------------------------------------
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
const BarLine* Measure::endBarLine() const
|
2016-01-04 14:48:58 +01:00
|
|
|
{
|
2016-10-25 17:30:55 +02:00
|
|
|
// search barline segment:
|
|
|
|
Segment* s = last();
|
|
|
|
while (s && !s->isEndBarLineType())
|
|
|
|
s = s->prev();
|
|
|
|
// search first element
|
|
|
|
if (s) {
|
|
|
|
for (const Element* e : s->elist()) {
|
|
|
|
if (e)
|
|
|
|
return toBarLine(e);
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// endBarLineType
|
|
|
|
// Assume all barlines have same type if there is more
|
|
|
|
// than one.
|
|
|
|
//---------------------------------------------------------
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
BarLineType Measure::endBarLineType() const
|
|
|
|
{
|
|
|
|
const BarLine* bl = endBarLine();
|
|
|
|
return bl ? bl->barLineType() : BarLineType::NORMAL;
|
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// endBarLineType
|
|
|
|
// Assume all barlines have same visiblity if there is more
|
|
|
|
// than one.
|
|
|
|
//---------------------------------------------------------
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
bool Measure::endBarLineVisible() const
|
|
|
|
{
|
|
|
|
const BarLine* bl = endBarLine();
|
|
|
|
return bl ? bl->visible() : true;
|
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// triggerLayout
|
|
|
|
//---------------------------------------------------------
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
void Measure::triggerLayout() const
|
|
|
|
{
|
|
|
|
score()->setLayout(tick());
|
|
|
|
score()->setLayout(endTick());
|
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setEndBarLineType
|
|
|
|
// Create a *generated* barline with the given type and
|
|
|
|
// properties if none exists. Modify if it exists.
|
|
|
|
// Useful for import filters.
|
|
|
|
//---------------------------------------------------------
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
void Measure::setEndBarLineType(BarLineType val, int track, bool visible, QColor color)
|
|
|
|
{
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* seg = undoGetSegment(SegmentType::EndBarLine, endTick());
|
2016-10-25 17:30:55 +02:00
|
|
|
// get existing bar line for this staff, if any
|
|
|
|
BarLine* bl = toBarLine(seg->element(track));
|
|
|
|
if (!bl) {
|
|
|
|
// no suitable bar line: create a new one
|
|
|
|
bl = new BarLine(score());
|
|
|
|
bl->setParent(seg);
|
|
|
|
bl->setTrack(track);
|
|
|
|
score()->addElement(bl);
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
bl->setGenerated(false);
|
|
|
|
bl->setBarLineType(val);
|
|
|
|
bl->setVisible(visible);
|
|
|
|
bl->setColor(color.isValid() ? color : curColor());
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2016-10-25 17:30:55 +02:00
|
|
|
// barLinesSetSpan
|
2016-10-18 15:41:00 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
void Measure::barLinesSetSpan(Segment* seg)
|
2016-10-18 15:41:00 +02:00
|
|
|
{
|
2016-12-23 12:05:18 +01:00
|
|
|
int track = 0;
|
|
|
|
for (Staff* staff : score()->staves()) {
|
|
|
|
BarLine* bl = toBarLine(seg->element(track)); // get existing bar line for this staff, if any
|
2016-12-28 19:08:54 +01:00
|
|
|
if (bl) {
|
|
|
|
if (bl->generated()) {
|
|
|
|
bl->setSpanStaff(staff->barLineSpan());
|
|
|
|
bl->setSpanFrom(staff->barLineFrom());
|
|
|
|
bl->setSpanTo(staff->barLineTo());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2016-12-23 12:05:18 +01:00
|
|
|
bl = new BarLine(score());
|
|
|
|
bl->setParent(seg);
|
|
|
|
bl->setTrack(track);
|
|
|
|
bl->setGenerated(true);
|
|
|
|
bl->setSpanStaff(staff->barLineSpan());
|
|
|
|
bl->setSpanFrom(staff->barLineFrom());
|
|
|
|
bl->setSpanTo(staff->barLineTo());
|
|
|
|
bl->layout();
|
|
|
|
score()->addElement(bl);
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
2016-12-23 12:05:18 +01:00
|
|
|
track += VOICES;
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// createEndBarLines
|
|
|
|
// actually creates or modifies barlines
|
|
|
|
// return the width change for measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Measure::createEndBarLines(bool isLastMeasureInSystem)
|
|
|
|
{
|
2016-12-23 12:05:18 +01:00
|
|
|
int nstaves = score()->nstaves();
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* seg = findSegmentR(SegmentType::EndBarLine, ticks());
|
2016-12-23 12:05:18 +01:00
|
|
|
Measure* nm = nextMeasure();
|
2016-10-25 17:30:55 +02:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
computeMinWidth();
|
|
|
|
#endif
|
|
|
|
qreal oldWidth = width();
|
2016-10-18 15:41:00 +02:00
|
|
|
|
|
|
|
if (nm && nm->repeatStart() && !isLastMeasureInSystem && !repeatEnd()) {
|
2016-10-20 11:32:07 +02:00
|
|
|
// no barline, use StartBarLine of next measure
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!seg)
|
|
|
|
return 0.0;
|
2016-10-20 11:32:07 +02:00
|
|
|
seg->setEnabled(false);
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
|
|
|
else {
|
2016-10-20 11:32:07 +02:00
|
|
|
BarLineType t = nm ? BarLineType::NORMAL : BarLineType::END;
|
2016-10-18 15:41:00 +02:00
|
|
|
if (!seg)
|
2017-03-08 13:12:26 +01:00
|
|
|
seg = undoGetSegmentR(SegmentType::EndBarLine, ticks());
|
2016-10-20 11:32:07 +02:00
|
|
|
seg->setEnabled(true);
|
2016-10-18 15:41:00 +02:00
|
|
|
//
|
|
|
|
// Set flag "hasCourtesyKeySig" if this measure needs a courtesy key sig.
|
|
|
|
// This flag is later used to set a double end bar line and to actually
|
|
|
|
// create the courtesy key sig.
|
|
|
|
//
|
|
|
|
|
2016-11-07 09:59:06 +01:00
|
|
|
bool show = score()->styleB(StyleIdx::genCourtesyKeysig) && !sectionBreak() && nm;
|
2016-10-18 15:41:00 +02:00
|
|
|
|
|
|
|
setHasCourtesyKeySig(false);
|
|
|
|
|
|
|
|
if (isLastMeasureInSystem && show) {
|
|
|
|
int tick = endTick();
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
KeySigEvent key1 = staff->keySigEvent(tick - 1);
|
|
|
|
KeySigEvent key2 = staff->keySigEvent(tick);
|
|
|
|
if (!(key1 == key2)) {
|
|
|
|
// locate a key sig. in next measure and, if found,
|
|
|
|
// check if it has court. sig turned off
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* s = nm->findSegment(SegmentType::KeySig, tick);
|
2016-10-18 15:41:00 +02:00
|
|
|
if (s) {
|
|
|
|
KeySig* ks = toKeySig(s->element(staffIdx * VOICES));
|
|
|
|
if (ks && !ks->showCourtesy())
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
setHasCourtesyKeySig(true);
|
|
|
|
t = BarLineType::DOUBLE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool force = false;
|
2017-03-20 18:24:16 +01:00
|
|
|
if (repeatEnd()) {
|
2016-10-18 15:41:00 +02:00
|
|
|
t = BarLineType::END_REPEAT;
|
|
|
|
force = true;
|
|
|
|
}
|
|
|
|
else if (isLastMeasureInSystem && nextMeasure() && nextMeasure()->repeatStart()) {
|
|
|
|
t = BarLineType::NORMAL;
|
|
|
|
force = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
|
2017-03-07 18:01:56 +01:00
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
BarLine* bl = toBarLine(seg->element(track));
|
2016-12-28 19:08:54 +01:00
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2016-12-23 12:05:18 +01:00
|
|
|
if (!bl) {
|
|
|
|
bl = new BarLine(score());
|
|
|
|
bl->setParent(seg);
|
|
|
|
bl->setTrack(track);
|
|
|
|
bl->setGenerated(true);
|
|
|
|
bl->setSpanStaff(staff->barLineSpan());
|
|
|
|
bl->setSpanFrom(staff->barLineFrom());
|
|
|
|
bl->setSpanTo(staff->barLineTo());
|
|
|
|
bl->setBarLineType(t);
|
|
|
|
score()->addElement(bl);
|
|
|
|
}
|
|
|
|
else {
|
2016-10-18 15:41:00 +02:00
|
|
|
// do not change bar line type if bar line is user modified
|
|
|
|
// and its not a repeat start/end barline (forced)
|
|
|
|
|
2016-12-28 19:08:54 +01:00
|
|
|
if (bl->generated()) {
|
|
|
|
bl->setSpanStaff(staff->barLineSpan());
|
|
|
|
bl->setSpanFrom(staff->barLineFrom());
|
|
|
|
bl->setSpanTo(staff->barLineTo());
|
|
|
|
bl->setBarLineType(t);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (bl->barLineType() != t) {
|
2017-03-07 18:01:56 +01:00
|
|
|
if (force) {
|
|
|
|
bl->undoChangeProperty(P_ID::BARLINE_TYPE, QVariant::fromValue(t));
|
|
|
|
bl->setGenerated(true);
|
2016-12-23 12:05:18 +01:00
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-03-07 18:01:56 +01:00
|
|
|
bl->layout();
|
2016-10-18 15:41:00 +02:00
|
|
|
}
|
|
|
|
seg->createShapes();
|
2016-10-20 11:32:07 +02:00
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2016-10-20 11:32:07 +02:00
|
|
|
// fix segment layout
|
2016-11-07 09:59:06 +01:00
|
|
|
Segment* s = seg->prevEnabled();
|
|
|
|
qreal x = s->rxpos();
|
|
|
|
computeMinWidth(s, x, false);
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2017-02-23 11:41:53 +01:00
|
|
|
#if 0
|
2016-10-25 17:30:55 +02:00
|
|
|
#ifndef NDEBUG
|
|
|
|
qreal w = width();
|
|
|
|
computeMinWidth();
|
|
|
|
if (!qFuzzyCompare(w, width()))
|
|
|
|
qDebug("width mismatch %f != %f at %d", w, width(), tick());
|
2017-02-23 11:41:53 +01:00
|
|
|
#endif
|
2016-10-25 17:30:55 +02:00
|
|
|
#endif
|
2016-10-18 15:41:00 +02:00
|
|
|
return width() - oldWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// basicStretch
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Measure::basicStretch() const
|
|
|
|
{
|
|
|
|
qreal stretch = userStretch() * score()->styleD(StyleIdx::measureSpacing);
|
|
|
|
if (stretch < 1.0)
|
|
|
|
stretch = 1.0;
|
|
|
|
return stretch;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// basicWidth
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Measure::basicWidth() const
|
|
|
|
{
|
|
|
|
Segment* ls = last();
|
|
|
|
qreal w = (ls->x() + ls->width()) * basicStretch();
|
|
|
|
qreal minMeasureWidth = score()->styleP(StyleIdx::minMeasureWidth);
|
|
|
|
if (w < minMeasureWidth)
|
|
|
|
w = minMeasureWidth;
|
|
|
|
return w;
|
2016-06-14 10:32:34 +02:00
|
|
|
}
|
2016-05-18 15:43:25 +02:00
|
|
|
|
2016-10-25 17:30:55 +02:00
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// addSystemHeader
|
|
|
|
/// Add elements to make this measure suitable as the first measure
|
|
|
|
/// of a system.
|
|
|
|
// The system header can contain a starting BarLine, a Clef,
|
|
|
|
// and a KeySig
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::addSystemHeader(bool isFirstSystem)
|
|
|
|
{
|
|
|
|
int staffIdx = 0;
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* kSegment = findFirst(SegmentType::KeySig, 0);
|
|
|
|
Segment* cSegment = findFirst(SegmentType::HeaderClef, 0);
|
2016-10-25 17:30:55 +02:00
|
|
|
|
|
|
|
for (Staff* staff : score()->staves()) {
|
|
|
|
const int track = staffIdx * VOICES;
|
|
|
|
|
|
|
|
// keep key sigs in TABs: TABs themselves should hide them
|
|
|
|
bool needKeysig = isFirstSystem || score()->styleB(StyleIdx::genKeysig);
|
|
|
|
|
|
|
|
// If we need a Key::C KeySig (which would be invisible) and there is
|
|
|
|
// a courtesy key sig, dont create it and switch generated flags.
|
|
|
|
// This avoids creating an invisible KeySig which can distort layout.
|
|
|
|
|
|
|
|
KeySigEvent keyIdx = staff->keySigEvent(tick());
|
|
|
|
KeySig* ksAnnounce = 0;
|
|
|
|
if (needKeysig && (keyIdx.key() == Key::C)) {
|
|
|
|
Measure* pm = prevMeasure();
|
|
|
|
if (pm && pm->hasCourtesyKeySig()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* ks = pm->first(SegmentType::KeySigAnnounce);
|
2016-10-25 17:30:55 +02:00
|
|
|
if (ks) {
|
|
|
|
ksAnnounce = toKeySig(ks->element(track));
|
|
|
|
if (ksAnnounce) {
|
|
|
|
needKeysig = false;
|
|
|
|
// if (keysig) {
|
|
|
|
// ksAnnounce->setGenerated(false);
|
2016-11-07 09:59:06 +01:00
|
|
|
//TODO keysig->setGenerated(true);
|
2016-10-25 17:30:55 +02:00
|
|
|
// }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
needKeysig = needKeysig && (keyIdx.key() != Key::C || keyIdx.custom() || keyIdx.isAtonal());
|
|
|
|
|
|
|
|
if (needKeysig) {
|
|
|
|
KeySig* keysig;
|
|
|
|
if (!kSegment) {
|
2017-03-08 13:12:26 +01:00
|
|
|
kSegment = new Segment(this, SegmentType::KeySig, 0);
|
2016-10-25 17:30:55 +02:00
|
|
|
kSegment->setHeader(true);
|
|
|
|
add(kSegment);
|
|
|
|
keysig = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
keysig = toKeySig(kSegment->element(track));
|
|
|
|
if (!keysig) {
|
|
|
|
//
|
|
|
|
// create missing key signature
|
|
|
|
//
|
|
|
|
keysig = new KeySig(score());
|
|
|
|
keysig->setTrack(track);
|
|
|
|
keysig->setGenerated(true);
|
|
|
|
keysig->setParent(kSegment);
|
|
|
|
kSegment->add(keysig);
|
|
|
|
}
|
|
|
|
keysig->setKeySigEvent(keyIdx);
|
|
|
|
keysig->layout();
|
|
|
|
kSegment->createShape(staffIdx);
|
|
|
|
kSegment->setEnabled(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (kSegment) {
|
|
|
|
// do not disable user modified keysigs
|
|
|
|
bool disable = true;
|
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx) {
|
|
|
|
Element* e = kSegment->element(staffIdx * VOICES);
|
|
|
|
if (e && !e->generated()) {
|
|
|
|
disable = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (disable)
|
|
|
|
kSegment->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-29 18:39:29 +01:00
|
|
|
if (isFirstSystem || score()->styleB(StyleIdx::genClef)) {
|
2016-10-25 17:30:55 +02:00
|
|
|
ClefTypeList cl = staff->clefType(tick());
|
|
|
|
Clef* clef;
|
|
|
|
if (!cSegment) {
|
2017-03-08 13:12:26 +01:00
|
|
|
cSegment = new Segment(this, SegmentType::HeaderClef, 0);
|
2016-10-25 17:30:55 +02:00
|
|
|
cSegment->setHeader(true);
|
|
|
|
add(cSegment);
|
|
|
|
clef = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
clef = toClef(cSegment->element(track));
|
2016-12-13 13:16:17 +01:00
|
|
|
if (staff->staffType(tick())->genClef()) {
|
2016-11-29 18:39:29 +01:00
|
|
|
if (!clef) {
|
|
|
|
//
|
|
|
|
// create missing clef
|
|
|
|
//
|
|
|
|
clef = new Clef(score());
|
|
|
|
clef->setTrack(track);
|
|
|
|
clef->setGenerated(true);
|
|
|
|
clef->setParent(cSegment);
|
|
|
|
cSegment->add(clef);
|
|
|
|
}
|
|
|
|
if (clef->generated())
|
|
|
|
clef->setClefType(cl);
|
|
|
|
clef->setSmall(false);
|
|
|
|
clef->layout();
|
|
|
|
}
|
|
|
|
else if (clef) {
|
|
|
|
clef->parent()->remove(clef);
|
|
|
|
delete clef;
|
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
cSegment->createShape(staffIdx);
|
|
|
|
cSegment->setEnabled(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (cSegment)
|
|
|
|
cSegment->setEnabled(false);
|
|
|
|
}
|
|
|
|
++staffIdx;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// create systemic barline
|
|
|
|
//
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* s = findSegment(SegmentType::BeginBarLine, tick());
|
2016-10-25 17:30:55 +02:00
|
|
|
int n = score()->nstaves();
|
|
|
|
if ((n > 1 && score()->styleB(StyleIdx::startBarlineMultiple)) || (n == 1 && score()->styleB(StyleIdx::startBarlineSingle))) {
|
2016-12-23 12:05:18 +01:00
|
|
|
if (!s) {
|
2017-03-08 13:12:26 +01:00
|
|
|
s = new Segment(this, SegmentType::BeginBarLine, 0);
|
2016-12-23 12:05:18 +01:00
|
|
|
add(s);
|
|
|
|
}
|
|
|
|
for (int track = 0; track < score()->ntracks(); track += VOICES) {
|
|
|
|
BarLine* bl = toBarLine(s->element(track));
|
|
|
|
if (!bl) {
|
|
|
|
bl = new BarLine(score());
|
|
|
|
bl->setTrack(track);
|
|
|
|
bl->setGenerated(true);
|
|
|
|
bl->setParent(s);
|
2016-12-29 15:11:28 +01:00
|
|
|
bl->setBarLineType(BarLineType::NORMAL);
|
|
|
|
bl->setSpanStaff(true);
|
2016-12-23 12:05:18 +01:00
|
|
|
bl->layout();
|
|
|
|
s->add(bl);
|
|
|
|
s->createShapes();
|
2016-10-25 17:30:55 +02:00
|
|
|
}
|
|
|
|
}
|
2016-12-23 12:05:18 +01:00
|
|
|
s->setEnabled(true);
|
|
|
|
s->setHeader(true);
|
2016-10-25 17:30:55 +02:00
|
|
|
setHeader(true);
|
|
|
|
}
|
|
|
|
else if (s)
|
|
|
|
s->setEnabled(false);
|
|
|
|
checkHeader();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// addSystemTrailer
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::addSystemTrailer(Measure* nm)
|
|
|
|
{
|
|
|
|
int _rtick = ticks();
|
|
|
|
bool isFinalMeasure = isFinalMeasureOfSection();
|
|
|
|
|
|
|
|
// locate a time sig. in the next measure and, if found,
|
|
|
|
// check if it has court. sig. turned off
|
|
|
|
TimeSig* ts;
|
2016-11-16 15:41:55 +01:00
|
|
|
bool showCourtesySig = false;
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* s = findSegmentR(SegmentType::TimeSigAnnounce, _rtick);
|
2016-11-16 15:41:55 +01:00
|
|
|
if (score()->genCourtesyTimesig() && !isFinalMeasure && !score()->floatMode()) {
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* tss = nm->findSegmentR(SegmentType::TimeSig, 0);
|
2016-11-16 15:41:55 +01:00
|
|
|
if (tss) {
|
|
|
|
ts = toTimeSig(tss->element(0));
|
|
|
|
if (ts && ts->showCourtesySig()) {
|
|
|
|
showCourtesySig = true;
|
|
|
|
// if due, create a new courtesy time signature for each staff
|
|
|
|
if (!s) {
|
2017-03-08 13:12:26 +01:00
|
|
|
s = new Segment(this, SegmentType::TimeSigAnnounce, _rtick);
|
2016-11-16 15:41:55 +01:00
|
|
|
s->setTrailer(true);
|
|
|
|
add(s);
|
|
|
|
}
|
|
|
|
s->setEnabled(true);
|
|
|
|
int nstaves = score()->nstaves();
|
|
|
|
for (int track = 0; track < nstaves * VOICES; track += VOICES) {
|
|
|
|
TimeSig* nts = toTimeSig(tss->element(track));
|
|
|
|
if (!nts)
|
|
|
|
continue;
|
|
|
|
ts = toTimeSig(s->element(track));
|
|
|
|
if (!ts) {
|
|
|
|
ts = new TimeSig(score());
|
|
|
|
ts->setTrack(track);
|
|
|
|
ts->setGenerated(true);
|
|
|
|
ts->setParent(s);
|
|
|
|
score()->undoAddElement(ts);
|
|
|
|
}
|
|
|
|
ts->setFrom(nts);
|
|
|
|
ts->layout();
|
|
|
|
s->createShape(track / VOICES);
|
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-16 15:41:55 +01:00
|
|
|
if (!showCourtesySig && s) {
|
2016-10-25 17:30:55 +02:00
|
|
|
// remove any existing time signatures
|
2016-11-16 15:41:55 +01:00
|
|
|
s->setEnabled(false);
|
2016-10-25 17:30:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// courtesy key signatures
|
|
|
|
|
|
|
|
int n = score()->nstaves();
|
|
|
|
bool show = hasCourtesyKeySig();
|
2017-03-08 13:12:26 +01:00
|
|
|
s = findSegmentR(SegmentType::KeySigAnnounce, _rtick);
|
2016-10-25 17:30:55 +02:00
|
|
|
|
2017-03-08 13:12:26 +01:00
|
|
|
Segment* clefSegment = findSegmentR(SegmentType::Clef, ticks());
|
2016-10-25 17:30:55 +02:00
|
|
|
|
|
|
|
for (int staffIdx = 0; staffIdx < n; ++staffIdx) {
|
|
|
|
int track = staffIdx * VOICES;
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
|
|
|
|
|
|
|
if (show) {
|
|
|
|
if (!s) {
|
2017-03-08 13:12:26 +01:00
|
|
|
s = new Segment(this, SegmentType::KeySigAnnounce, _rtick);
|
2016-10-25 17:30:55 +02:00
|
|
|
s->setTrailer(true);
|
|
|
|
add(s);
|
|
|
|
}
|
|
|
|
KeySig* ks = toKeySig(s->element(track));
|
|
|
|
KeySigEvent key2 = staff->keySigEvent(endTick());
|
|
|
|
|
|
|
|
if (!ks) {
|
|
|
|
ks = new KeySig(score());
|
|
|
|
ks->setTrack(track);
|
|
|
|
ks->setGenerated(true);
|
|
|
|
ks->setParent(s);
|
|
|
|
s->add(ks);
|
|
|
|
}
|
|
|
|
//else if (!(ks->keySigEvent() == key2)) {
|
|
|
|
// score()->undo(new ChangeKeySig(ks, key2, ks->showCourtesy()));
|
|
|
|
// }
|
|
|
|
ks->setKeySigEvent(key2);
|
|
|
|
ks->layout();
|
|
|
|
s->createShape(track / VOICES);
|
|
|
|
s->setEnabled(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// remove any existent courtesy key signature
|
|
|
|
if (s)
|
|
|
|
s->setEnabled(false);
|
|
|
|
}
|
|
|
|
if (clefSegment) {
|
|
|
|
Clef* clef = toClef(clefSegment->element(track));
|
2016-11-02 08:55:54 +01:00
|
|
|
if (clef) {
|
|
|
|
clef->setSmall(true);
|
|
|
|
if (!score()->genCourtesyClef() || repeatEnd() || isFinalMeasure || !clef->showCourtesy())
|
|
|
|
clef->clear(); // make invisible
|
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
checkTrailer();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeSystemHeader
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::removeSystemHeader()
|
|
|
|
{
|
|
|
|
if (!header())
|
|
|
|
return;
|
|
|
|
for (Segment* seg = first(); seg; seg = seg->next()) {
|
|
|
|
if (!seg->header())
|
|
|
|
break;
|
|
|
|
seg->setEnabled(false);
|
|
|
|
}
|
|
|
|
setHeader(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeSystemTrailer
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::removeSystemTrailer()
|
|
|
|
{
|
|
|
|
bool changed = false;
|
|
|
|
for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
|
|
|
|
if (!seg->trailer())
|
|
|
|
break;
|
|
|
|
if (seg->enabled())
|
|
|
|
seg->setEnabled(false);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
setTrailer(false);
|
2016-10-31 10:55:11 +01:00
|
|
|
if (changed)
|
2016-10-25 17:30:55 +02:00
|
|
|
computeMinWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// checkHeader
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::checkHeader()
|
|
|
|
{
|
|
|
|
for (Segment* seg = first(); seg; seg = seg->next()) {
|
|
|
|
if (seg->enabled() && seg->header()) {
|
|
|
|
setHeader(seg->header());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// checkTrailer
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::checkTrailer()
|
|
|
|
{
|
|
|
|
for (Segment* seg = last(); seg != first(); seg = seg->prev()) {
|
|
|
|
if (seg->enabled() && seg->trailer()) {
|
|
|
|
setTrailer(seg->trailer());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-31 10:55:11 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setStretchedWidth
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Measure::setStretchedWidth(qreal w)
|
|
|
|
{
|
|
|
|
qreal minWidth = score()->styleP(StyleIdx::minMeasureWidth);
|
|
|
|
if (w < minWidth)
|
|
|
|
w = minWidth;
|
2017-10-18 13:09:35 +02:00
|
|
|
|
|
|
|
// multi measure rests are not stretched depending on their
|
|
|
|
// tick length
|
|
|
|
|
|
|
|
if (!isMMRest()) {
|
|
|
|
qreal stretchableWidth = 0.0;
|
|
|
|
for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
|
|
|
if (!s->enabled())
|
|
|
|
continue;
|
|
|
|
stretchableWidth += s->width();
|
|
|
|
}
|
|
|
|
w += stretchableWidth * (basicStretch()-1.0) * ticks() / 1920.0;
|
2016-12-01 13:35:38 +01:00
|
|
|
}
|
2016-10-31 10:55:11 +01:00
|
|
|
setWidth(w);
|
|
|
|
}
|
2016-10-18 15:41:00 +02:00
|
|
|
|
2017-10-18 13:09:35 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// hasAccidental
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
static bool hasAccidental(Segment* s)
|
|
|
|
{
|
|
|
|
for (int track = 0; track < s->score()->ntracks(); ++track) {
|
|
|
|
Element* e = s->element(track);
|
|
|
|
if (!e || !e->isChord())
|
|
|
|
continue;
|
|
|
|
Chord* c = toChord(e);
|
|
|
|
for (Note* n : c->notes()) {
|
|
|
|
if (n->accidental())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// dumpMeasure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
static void dumpMeasure(Measure* m)
|
|
|
|
{
|
|
|
|
printf("Measure tick %d width %f\n", m->tick(), m->width());
|
|
|
|
for (Segment* s = m->first(); s; s = s->next()) {
|
|
|
|
printf(" %04d %16s %f %f\n", s->rtick(), s->subTypeName(), s->x(), s->width());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-11-02 08:55:54 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// computeMinWidth
|
|
|
|
// sets the minimum stretched width of segment list s
|
|
|
|
// set the width and x position for all segments
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-11-07 09:59:06 +01:00
|
|
|
void Measure::computeMinWidth(Segment* s, qreal x, bool isSystemHeader)
|
2016-11-02 08:55:54 +01:00
|
|
|
{
|
2016-11-02 14:07:39 +01:00
|
|
|
Segment* fs = s;
|
2017-07-06 13:28:37 +02:00
|
|
|
bool first = system()->firstMeasure() == this;
|
2016-11-07 09:59:06 +01:00
|
|
|
const Shape ls(first ? QRectF(0.0, -1000000.0, 0.0, 2000000.0) : QRectF(0.0, 0.0, 0.0, spatium() * 4));
|
2016-11-02 08:55:54 +01:00
|
|
|
while (s) {
|
|
|
|
s->rxpos() = x;
|
|
|
|
if (!s->enabled()) {
|
|
|
|
s->setWidth(0);
|
|
|
|
s = s->next();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Segment* ns = s->nextEnabled();
|
|
|
|
qreal w;
|
|
|
|
|
|
|
|
if (ns) {
|
|
|
|
if (isSystemHeader && !ns->header()) { // this is the system header gap
|
|
|
|
w = s->minHorizontalDistance(ns, true);
|
|
|
|
isSystemHeader = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
w = s->minHorizontalDistance(ns, false);
|
|
|
|
}
|
|
|
|
// printf(" min %f <%s>(%d) <%s>(%d)\n", s->x(), s->subTypeName(), s->enabled(), ns->subTypeName(), ns->enabled());
|
|
|
|
#if 1
|
|
|
|
// look back for collisions with previous segments
|
|
|
|
// this is time consuming (ca. +5%) and probably requires more optimization
|
|
|
|
|
|
|
|
int n = 1;
|
2016-11-02 14:07:39 +01:00
|
|
|
for (Segment* ps = s; ps != fs;) {
|
2016-11-02 08:55:54 +01:00
|
|
|
qreal ww;
|
2016-11-02 14:07:39 +01:00
|
|
|
ps = ps->prevEnabled();
|
|
|
|
if (ps == fs)
|
2016-11-02 08:55:54 +01:00
|
|
|
ww = ns->minLeft(ls) - s->x();
|
|
|
|
else {
|
|
|
|
if (ps->isChordRestType())
|
|
|
|
++n;
|
|
|
|
ww = ps->minHorizontalDistance(ns, false) - (s->x() - ps->x());
|
|
|
|
}
|
|
|
|
if (ww > w) {
|
|
|
|
// overlap !
|
|
|
|
// distribute extra space between segments ps - ss;
|
|
|
|
// only ChordRest segments get more space
|
|
|
|
// TODO: is there a special case n == 0 ?
|
|
|
|
|
|
|
|
qreal d = (ww - w) / n;
|
|
|
|
qreal xx = ps->x();
|
|
|
|
for (Segment* ss = ps; ss != s;) {
|
2016-11-02 14:07:39 +01:00
|
|
|
Segment* ns = ss->nextEnabled();
|
2016-11-02 08:55:54 +01:00
|
|
|
qreal ww = ss->width();
|
|
|
|
if (ss->isChordRestType()) {
|
|
|
|
ww += d;
|
|
|
|
ss->setWidth(ww);
|
|
|
|
}
|
|
|
|
xx += ww;
|
|
|
|
ns->rxpos() = xx;
|
|
|
|
ss = ns;
|
|
|
|
}
|
|
|
|
w += d;
|
|
|
|
x = xx;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
w = s->minRight();
|
|
|
|
s->setWidth(w);
|
|
|
|
x += w;
|
2016-11-07 09:59:06 +01:00
|
|
|
s = s->next();
|
2016-11-02 08:55:54 +01:00
|
|
|
}
|
|
|
|
setStretchedWidth(x);
|
|
|
|
}
|
|
|
|
|
2016-11-07 09:59:06 +01:00
|
|
|
void Measure::computeMinWidth()
|
|
|
|
{
|
|
|
|
Segment* s;
|
|
|
|
|
|
|
|
//
|
|
|
|
// skip disabled segment
|
|
|
|
//
|
|
|
|
for (s = first(); s && !s->enabled(); s = s->next()) {
|
|
|
|
s->rxpos() = 0;
|
|
|
|
s->setWidth(0);
|
|
|
|
}
|
|
|
|
if (!s) {
|
|
|
|
setWidth(0.0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
qreal x;
|
|
|
|
bool first = system()->firstMeasure() == this;
|
|
|
|
|
|
|
|
// left barriere:
|
|
|
|
// Make sure no elements crosses the left boarder if first measure in a system.
|
|
|
|
//
|
|
|
|
Shape ls(first ? QRectF(0.0, -1000000.0, 0.0, 2000000.0) : QRectF(0.0, 0.0, 0.0, spatium() * 4));
|
|
|
|
|
|
|
|
x = s->minLeft(ls);
|
2017-07-06 13:28:37 +02:00
|
|
|
if (s->isChordRestType()) {
|
|
|
|
x += score()->styleP(hasAccidental(s) ? StyleIdx::barAccidentalDistance : StyleIdx::barNoteDistance);
|
|
|
|
}
|
2017-10-09 11:47:17 +02:00
|
|
|
else if (s->isClefType() || s->isHeaderClefType())
|
2016-11-07 09:59:06 +01:00
|
|
|
x += score()->styleP(StyleIdx::clefLeftMargin);
|
|
|
|
else if (s->isKeySigType())
|
|
|
|
x = qMax(x, score()->styleP(StyleIdx::keysigLeftMargin));
|
|
|
|
else if (s->isTimeSigType())
|
|
|
|
x = qMax(x, score()->styleP(StyleIdx::timesigLeftMargin));
|
|
|
|
x += s->extraLeadingSpace().val() * spatium();
|
|
|
|
bool isSystemHeader = s->header();
|
|
|
|
|
|
|
|
computeMinWidth(s, x, isSystemHeader);
|
|
|
|
}
|
2016-11-02 08:55:54 +01:00
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|