2012-05-26 14:26:10 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
|
|
|
// Copyright (C) 2002-2011 Werner Schweer
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License version 2
|
|
|
|
// as published by the Free Software Foundation and appearing in
|
|
|
|
// the file LICENCE.GPL
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#include "mscore.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "element.h"
|
|
|
|
#include "chord.h"
|
|
|
|
#include "note.h"
|
|
|
|
#include "score.h"
|
|
|
|
#include "beam.h"
|
|
|
|
#include "tuplet.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "measure.h"
|
|
|
|
#include "barline.h"
|
|
|
|
#include "part.h"
|
|
|
|
#include "repeat.h"
|
|
|
|
#include "staff.h"
|
|
|
|
#include "line.h"
|
|
|
|
#include "hairpin.h"
|
|
|
|
#include "ottava.h"
|
|
|
|
#include "sig.h"
|
2014-06-02 13:07:19 +02:00
|
|
|
#include "keysig.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "staffstate.h"
|
|
|
|
#include "instrchange.h"
|
|
|
|
#include "clef.h"
|
|
|
|
#include "timesig.h"
|
|
|
|
#include "system.h"
|
2014-04-09 16:09:21 +02:00
|
|
|
#include "xml.h"
|
2014-08-05 14:10:22 +02:00
|
|
|
#include "undo.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
|
|
|
//---------------------------------------------------------
|
|
|
|
// subTypeName
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
const char* Segment::subTypeName() const
|
|
|
|
{
|
2013-06-25 19:52:00 +02:00
|
|
|
return subTypeName(_segmentType);
|
2013-06-24 13:02:45 +02:00
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
const char* Segment::subTypeName(Type t)
|
2013-06-24 13:02:45 +02:00
|
|
|
{
|
|
|
|
switch(t) {
|
2014-06-25 11:46:10 +02:00
|
|
|
case Type::Invalid: return "Invalid";
|
2016-02-04 11:27:47 +01:00
|
|
|
case Type::BeginBarLine: return "BeginBarLine";
|
2016-10-25 17:30:55 +02:00
|
|
|
case Type::HeaderClef: return "HeaderClef";
|
2014-06-25 11:46:10 +02:00
|
|
|
case Type::Clef: return "Clef";
|
|
|
|
case Type::KeySig: return "Key Signature";
|
|
|
|
case Type::Ambitus: return "Ambitus";
|
|
|
|
case Type::TimeSig: return "Time Signature";
|
|
|
|
case Type::StartRepeatBarLine: return "Begin Repeat";
|
|
|
|
case Type::BarLine: return "BarLine";
|
|
|
|
case Type::Breath: return "Breath";
|
2016-02-04 11:27:47 +01:00
|
|
|
case Type::ChordRest: return "ChordRest";
|
2014-06-25 11:46:10 +02:00
|
|
|
case Type::EndBarLine: return "EndBarLine";
|
|
|
|
case Type::KeySigAnnounce: return "Key Sig Precaution";
|
2016-02-04 11:27:47 +01:00
|
|
|
case Type::TimeSigAnnounce: return "Time Sig Precaution";
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2014-06-17 15:34:11 +02:00
|
|
|
return "??";
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setElement
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::setElement(int track, Element* el)
|
|
|
|
{
|
|
|
|
if (el) {
|
|
|
|
el->setParent(this);
|
|
|
|
_elist[track] = el;
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
_elist[track] = 0;
|
|
|
|
checkEmpty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::removeElement(int track)
|
|
|
|
{
|
|
|
|
Element* el = element(track);
|
|
|
|
if (el->isChordRest()) {
|
|
|
|
ChordRest* cr = (ChordRest*)el;
|
|
|
|
Beam* beam = cr->beam();
|
|
|
|
if (beam)
|
|
|
|
beam->remove(cr);
|
|
|
|
Tuplet* tuplet = cr->tuplet();
|
|
|
|
if (tuplet)
|
|
|
|
tuplet->remove(cr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Segment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Segment::Segment(Measure* m)
|
|
|
|
: Element(m->score())
|
|
|
|
{
|
|
|
|
setParent(m);
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment::Segment(Measure* m, Type st, int t)
|
2012-05-26 14:26:10 +02:00
|
|
|
: Element(m->score())
|
|
|
|
{
|
|
|
|
setParent(m);
|
2013-06-25 19:52:00 +02:00
|
|
|
_segmentType = st;
|
2016-10-20 11:32:07 +02:00
|
|
|
_tick = t;
|
2012-05-26 14:26:10 +02:00
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Segment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Segment::Segment(const Segment& s)
|
|
|
|
: Element(s)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
_next = 0;
|
|
|
|
_prev = 0;
|
2013-06-25 19:52:00 +02:00
|
|
|
_segmentType = s._segmentType;
|
|
|
|
_tick = s._tick;
|
|
|
|
_extraLeadingSpace = s._extraLeadingSpace;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : s._annotations)
|
|
|
|
add(e->clone());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
_elist.reserve(s._elist.size());
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : s._elist) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Element* ne = 0;
|
|
|
|
if (e) {
|
|
|
|
ne = e->clone();
|
|
|
|
ne->setParent(this);
|
|
|
|
}
|
2016-02-06 22:03:43 +01:00
|
|
|
_elist.push_back(ne);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
_dotPosX = s._dotPosX;
|
2016-01-04 14:48:58 +01:00
|
|
|
_shapes = s._shapes;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2016-02-06 22:03:43 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setSegmentType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
void Segment::setSegmentType(Type t)
|
2013-06-25 19:52:00 +02:00
|
|
|
{
|
2014-06-25 11:46:10 +02:00
|
|
|
Q_ASSERT(_segmentType != Type::Clef || t != Type::ChordRest);
|
2013-06-25 19:52:00 +02:00
|
|
|
_segmentType = t;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setScore
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::setScore(Score* score)
|
|
|
|
{
|
|
|
|
Element::setScore(score);
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : _elist) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e)
|
|
|
|
e->setScore(score);
|
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : _annotations)
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setScore(score);
|
|
|
|
}
|
|
|
|
|
|
|
|
Segment::~Segment()
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : _elist) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!e)
|
|
|
|
continue;
|
2016-10-25 17:30:55 +02:00
|
|
|
if (e->isTimeSig())
|
|
|
|
e->staff()->removeTimeSig(toTimeSig(e));
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// init
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::init()
|
|
|
|
{
|
|
|
|
int staves = score()->nstaves();
|
|
|
|
int tracks = staves * VOICES;
|
2016-02-06 22:03:43 +01:00
|
|
|
_elist.assign(tracks, 0);
|
|
|
|
_dotPosX.assign(staves, 0.0);
|
|
|
|
_shapes.assign(staves, Shape());
|
2012-05-26 14:26:10 +02:00
|
|
|
_prev = 0;
|
|
|
|
_next = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// next1
|
2012-08-01 18:00:27 +02:00
|
|
|
/// return next \a Segment, dont stop searching at end
|
|
|
|
/// of \a Measure
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-02 16:07:08 +02:00
|
|
|
Segment* Segment::next1() const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
if (next())
|
|
|
|
return next();
|
2012-08-01 18:00:27 +02:00
|
|
|
Measure* m = measure()->nextMeasure();
|
2016-10-25 17:30:55 +02:00
|
|
|
return m ? m->first() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// next1enabled
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Segment* Segment::next1enabled() const
|
|
|
|
{
|
|
|
|
Segment* s = next1();
|
|
|
|
while (s && !s->enabled())
|
|
|
|
s = s->next1();
|
|
|
|
return s;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-09-23 12:26:16 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// next1MM
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Segment* Segment::next1MM() const
|
|
|
|
{
|
|
|
|
if (next())
|
|
|
|
return next();
|
|
|
|
Measure* m = measure()->nextMeasureMM();
|
2016-10-25 17:30:55 +02:00
|
|
|
return m ? m->first() : 0;
|
2013-09-23 12:26:16 +02:00
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Segment::next1(Type types) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = next1(); s; s = s->next1()) {
|
2013-03-05 20:23:59 +01:00
|
|
|
if (s->segmentType() & types)
|
2012-05-26 14:26:10 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Segment::next1MM(Type types) const
|
2013-09-27 18:43:25 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = next1MM(); s; s = s->next1MM()) {
|
|
|
|
if (s->segmentType() & types)
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// next
|
|
|
|
// got to next segment which has subtype in types
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Segment::next(Type types) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = next(); s; s = s->next()) {
|
2013-03-05 20:23:59 +01:00
|
|
|
if (s->segmentType() & types)
|
2012-05-26 14:26:10 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// prev
|
|
|
|
// got to previous segment which has subtype in types
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Segment::prev(Type types) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = prev(); s; s = s->prev()) {
|
2013-03-05 20:23:59 +01:00
|
|
|
if (s->segmentType() & types)
|
2012-05-26 14:26:10 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// prev1
|
2012-08-01 18:00:27 +02:00
|
|
|
/// return previous \a Segment, dont stop searching at
|
|
|
|
/// \a Measure begin
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Segment* Segment::prev1() const
|
|
|
|
{
|
|
|
|
if (prev())
|
|
|
|
return prev();
|
|
|
|
Measure* m = measure()->prevMeasure();
|
2016-10-25 17:30:55 +02:00
|
|
|
return m ? m->last() : 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-09-27 18:43:25 +02:00
|
|
|
Segment* Segment::prev1MM() const
|
|
|
|
{
|
|
|
|
if (prev())
|
|
|
|
return prev();
|
|
|
|
Measure* m = measure()->prevMeasureMM();
|
2016-10-25 17:30:55 +02:00
|
|
|
return m ? m->last() : 0;
|
2013-09-27 18:43:25 +02:00
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Segment::prev1(Type types) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = prev1(); s; s = s->prev1()) {
|
2013-03-05 20:23:59 +01:00
|
|
|
if (s->segmentType() & types)
|
2012-05-26 14:26:10 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-06-25 11:46:10 +02:00
|
|
|
Segment* Segment::prev1MM(Type types) const
|
2013-09-27 18:43:25 +02:00
|
|
|
{
|
|
|
|
for (Segment* s = prev1MM(); s; s = s->prev1MM()) {
|
|
|
|
if (s->segmentType() & types)
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// nextCR
|
|
|
|
// get next ChordRest Segment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-03-15 18:34:58 +01:00
|
|
|
Segment* Segment::nextCR(int track, bool sameStaff) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2015-03-15 18:34:58 +01:00
|
|
|
int strack = track;
|
2016-10-25 17:30:55 +02:00
|
|
|
int etrack;
|
|
|
|
if (sameStaff) {
|
|
|
|
strack &= ~(VOICES-1);
|
2015-03-15 18:34:58 +01:00
|
|
|
etrack = strack + VOICES;
|
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
else {
|
|
|
|
etrack = strack + 1;
|
|
|
|
}
|
|
|
|
for (Segment* seg = next1(); seg; seg = seg->next1()) {
|
|
|
|
if (seg->isChordRestType()) {
|
2015-03-15 23:36:18 +01:00
|
|
|
if (track == -1)
|
|
|
|
return seg;
|
2015-03-15 18:34:58 +01:00
|
|
|
for (int t = strack; t < etrack; ++t) {
|
2015-03-15 23:36:18 +01:00
|
|
|
if (seg->element(t))
|
2015-03-15 18:34:58 +01:00
|
|
|
return seg;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// nextChordRest
|
|
|
|
// get the next ChordRest, start at this segment
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
ChordRest* Segment::nextChordRest(int track, bool backwards) const
|
|
|
|
{
|
|
|
|
for (const Segment* seg = this; seg; seg = backwards ? seg->prev1() : seg->next1()) {
|
|
|
|
Element* el = seg->element(track);
|
|
|
|
if (el && el->isChordRest())
|
2016-10-25 17:30:55 +02:00
|
|
|
return toChordRest(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::insertStaff(int staff)
|
|
|
|
{
|
|
|
|
int track = staff * VOICES;
|
|
|
|
for (int voice = 0; voice < VOICES; ++voice)
|
2016-02-06 22:03:43 +01:00
|
|
|
_elist.insert(_elist.begin() + track, 0);
|
|
|
|
_dotPosX.insert(_dotPosX.begin()+staff, 0.0);
|
|
|
|
_shapes.insert(_shapes.begin()+staff, Shape());
|
2013-08-09 11:22:02 +02:00
|
|
|
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : _annotations) {
|
2013-08-09 11:22:02 +02:00
|
|
|
int staffIdx = e->staffIdx();
|
2013-08-09 12:03:15 +02:00
|
|
|
if (staffIdx >= staff && !e->systemFlag())
|
2013-08-09 11:22:02 +02:00
|
|
|
e->setTrack(e->track() + VOICES);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
fixStaffIdx();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::removeStaff(int staff)
|
|
|
|
{
|
|
|
|
int track = staff * VOICES;
|
|
|
|
_elist.erase(_elist.begin() + track, _elist.begin() + track + VOICES);
|
2016-02-06 22:03:43 +01:00
|
|
|
_dotPosX.erase(_dotPosX.begin() + staff);
|
|
|
|
_shapes.erase(_shapes.begin()+staff);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : _annotations) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int staffIdx = e->staffIdx();
|
2013-08-09 12:03:15 +02:00
|
|
|
if (staffIdx > staff && !e->systemFlag())
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setTrack(e->track() - VOICES);
|
|
|
|
}
|
|
|
|
|
|
|
|
fixStaffIdx();
|
|
|
|
}
|
|
|
|
|
2014-06-02 13:07:19 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// checkElement
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::checkElement(Element* el, int track)
|
|
|
|
{
|
|
|
|
if (_elist[track]) {
|
|
|
|
qDebug("Segment::add(%s) there is already a %s at %s(%d) track %d. score %p",
|
|
|
|
el->name(), _elist[track]->name(),
|
2014-08-07 10:18:50 +02:00
|
|
|
qPrintable(score()->sigmap()->pos(tick())), tick(), track, score());
|
2016-03-02 13:20:19 +01:00
|
|
|
// abort();
|
2014-06-02 13:07:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// add
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::add(Element* el)
|
|
|
|
{
|
2015-01-26 12:48:32 +01:00
|
|
|
// qDebug("%p segment %s add(%d, %d, %s)", this, subTypeName(), tick(), el->track(), el->name());
|
2016-03-31 14:31:39 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
el->setParent(this);
|
|
|
|
|
|
|
|
int track = el->track();
|
2013-06-25 19:52:00 +02:00
|
|
|
Q_ASSERT(track != -1);
|
2014-08-25 19:30:56 +02:00
|
|
|
Q_ASSERT(el->score() == score());
|
2016-02-08 15:10:03 +01:00
|
|
|
Q_ASSERT(score()->nstaves() * VOICES == int(_elist.size()));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-06-25 19:52:00 +02:00
|
|
|
switch (el->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::REPEAT_MEASURE:
|
2012-05-26 14:26:10 +02:00
|
|
|
_elist[track] = el;
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::DYNAMIC:
|
|
|
|
case ElementType::HARMONY:
|
|
|
|
case ElementType::SYMBOL:
|
|
|
|
case ElementType::FRET_DIAGRAM:
|
|
|
|
case ElementType::TEMPO_TEXT:
|
|
|
|
case ElementType::STAFF_TEXT:
|
2017-01-20 11:05:52 +01:00
|
|
|
case ElementType::SYSTEM_TEXT:
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::REHEARSAL_MARK:
|
|
|
|
case ElementType::MARKER:
|
|
|
|
case ElementType::IMAGE:
|
|
|
|
case ElementType::TEXT:
|
|
|
|
case ElementType::TREMOLOBAR:
|
|
|
|
case ElementType::TAB_DURATION_SYMBOL:
|
|
|
|
case ElementType::FIGURED_BASS:
|
2013-05-06 14:20:31 +02:00
|
|
|
_annotations.push_back(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2016-02-06 11:41:16 +01:00
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::STAFF_STATE:
|
2016-10-25 17:30:55 +02:00
|
|
|
if (toStaffState(el)->staffStateType() == StaffStateType::INSTRUMENT) {
|
|
|
|
StaffState* ss = toStaffState(el);
|
2015-03-13 11:16:43 +01:00
|
|
|
Part* part = el->part();
|
2012-05-26 14:26:10 +02:00
|
|
|
part->setInstrument(ss->instrument(), tick());
|
|
|
|
}
|
2013-05-06 14:20:31 +02:00
|
|
|
_annotations.push_back(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::INSTRUMENT_CHANGE: {
|
2016-10-25 17:30:55 +02:00
|
|
|
InstrumentChange* is = toInstrumentChange(el);
|
2015-03-13 11:16:43 +01:00
|
|
|
Part* part = is->part();
|
2012-05-26 14:26:10 +02:00
|
|
|
part->setInstrument(is->instrument(), tick());
|
2013-05-06 14:20:31 +02:00
|
|
|
_annotations.push_back(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CLEF:
|
2016-10-25 17:30:55 +02:00
|
|
|
Q_ASSERT(_segmentType == Type::Clef || _segmentType == Type::HeaderClef);
|
2014-06-02 13:07:19 +02:00
|
|
|
checkElement(el, track);
|
2012-05-26 14:26:10 +02:00
|
|
|
_elist[track] = el;
|
2014-08-05 14:10:22 +02:00
|
|
|
if (!el->generated()) {
|
2016-10-25 17:30:55 +02:00
|
|
|
el->staff()->setClef(toClef(el));
|
2014-08-05 14:10:22 +02:00
|
|
|
updateNoteLines(this, el->track());
|
|
|
|
}
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::TIMESIG:
|
2014-06-25 11:46:10 +02:00
|
|
|
Q_ASSERT(segmentType() == Type::TimeSig || segmentType() == Type::TimeSigAnnounce);
|
2014-06-02 13:07:19 +02:00
|
|
|
checkElement(el, track);
|
2012-05-26 14:26:10 +02:00
|
|
|
_elist[track] = el;
|
2016-10-25 17:30:55 +02:00
|
|
|
el->staff()->addTimeSig(toTimeSig(el));
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::KEYSIG:
|
2014-06-25 11:46:10 +02:00
|
|
|
Q_ASSERT(_segmentType == Type::KeySig || _segmentType == Type::KeySigAnnounce);
|
2014-06-02 13:07:19 +02:00
|
|
|
checkElement(el, track);
|
|
|
|
_elist[track] = el;
|
2014-06-04 10:20:14 +02:00
|
|
|
if (!el->generated())
|
2016-10-25 17:30:55 +02:00
|
|
|
el->staff()->setKey(tick(), toKeySig(el)->keySigEvent());
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2014-06-02 13:07:19 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CHORD:
|
|
|
|
case ElementType::REST:
|
2014-06-25 11:46:10 +02:00
|
|
|
Q_ASSERT(_segmentType == Type::ChordRest);
|
2016-11-09 13:29:27 +01:00
|
|
|
{
|
2015-01-26 22:58:46 +01:00
|
|
|
if (track % VOICES) {
|
|
|
|
bool v;
|
2016-10-25 17:30:55 +02:00
|
|
|
if (el->isChord()) {
|
2015-01-26 22:58:46 +01:00
|
|
|
v = false;
|
|
|
|
// consider chord visible if any note is visible
|
2016-10-25 17:30:55 +02:00
|
|
|
Chord* c = toChord(el);
|
2015-01-26 22:58:46 +01:00
|
|
|
for (Note* n : c->notes()) {
|
|
|
|
if (n->visible()) {
|
|
|
|
v = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
v = el->visible();
|
2016-07-31 15:23:11 +02:00
|
|
|
|
2016-12-12 14:55:35 +01:00
|
|
|
if (v && measure()->score()->ntracks() > track)
|
2016-12-12 12:02:18 +01:00
|
|
|
measure()->setHasVoices(track / VOICES, true);
|
2015-01-26 22:58:46 +01:00
|
|
|
}
|
2016-11-09 13:29:27 +01:00
|
|
|
// the tick position of a tuplet is the tick position of its
|
|
|
|
// first element:
|
|
|
|
ChordRest* cr = toChordRest(el);
|
2016-11-21 13:46:47 +01:00
|
|
|
if (cr->tuplet() && !cr->tuplet()->elements().empty() && cr->tuplet()->elements().front() == cr && cr->tuplet()->tick() < 0)
|
2016-11-09 13:29:27 +01:00
|
|
|
cr->tuplet()->setTick(cr->tick());
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
// fall through
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BAR_LINE:
|
|
|
|
case ElementType::BREATH:
|
2014-08-25 19:30:56 +02:00
|
|
|
if (track < score()->nstaves() * VOICES) {
|
|
|
|
checkElement(el, track);
|
|
|
|
_elist[track] = el;
|
|
|
|
}
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-06-02 13:07:19 +02:00
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::AMBITUS:
|
2014-06-25 11:46:10 +02:00
|
|
|
Q_ASSERT(_segmentType == Type::Ambitus);
|
2014-06-02 13:07:19 +02:00
|
|
|
checkElement(el, track);
|
2013-10-29 23:41:38 +01:00
|
|
|
_elist[track] = el;
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2013-10-29 23:41:38 +01:00
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
default:
|
2014-03-04 13:06:23 +01:00
|
|
|
qFatal("Segment::add() unknown %s", el->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::remove(Element* el)
|
|
|
|
{
|
2012-09-11 21:10:44 +02:00
|
|
|
// qDebug("%p Segment::remove %s %p", this, el->name(), el);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
int track = el->track();
|
|
|
|
|
|
|
|
switch(el->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CHORD:
|
|
|
|
case ElementType::REST:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
_elist[track] = 0;
|
|
|
|
int staffIdx = el->staffIdx();
|
|
|
|
measure()->checkMultiVoices(staffIdx);
|
2016-01-13 20:13:08 +01:00
|
|
|
// spanners with this cr as start or end element will need relayout
|
|
|
|
SpannerMap& smap = score()->spannerMap();
|
|
|
|
auto spanners = smap.findOverlapping(tick(), tick());
|
|
|
|
for (auto interval : spanners) {
|
|
|
|
Spanner* s = interval.value;
|
|
|
|
if (s->startElement() == el)
|
|
|
|
s->setStartElement(nullptr);
|
|
|
|
if (s->endElement() == el)
|
|
|
|
s->setEndElement(nullptr);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::REPEAT_MEASURE:
|
2012-05-26 14:26:10 +02:00
|
|
|
_elist[track] = 0;
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::DYNAMIC:
|
|
|
|
case ElementType::FIGURED_BASS:
|
|
|
|
case ElementType::FRET_DIAGRAM:
|
|
|
|
case ElementType::HARMONY:
|
|
|
|
case ElementType::IMAGE:
|
|
|
|
case ElementType::MARKER:
|
|
|
|
case ElementType::REHEARSAL_MARK:
|
|
|
|
case ElementType::STAFF_TEXT:
|
2017-01-20 11:05:52 +01:00
|
|
|
case ElementType::SYSTEM_TEXT:
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::SYMBOL:
|
|
|
|
case ElementType::TAB_DURATION_SYMBOL:
|
|
|
|
case ElementType::TEMPO_TEXT:
|
|
|
|
case ElementType::TEXT:
|
|
|
|
case ElementType::TREMOLOBAR:
|
2013-05-06 14:20:31 +02:00
|
|
|
removeAnnotation(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::STAFF_STATE:
|
2016-10-25 17:30:55 +02:00
|
|
|
if (toStaffState(el)->staffStateType() == StaffStateType::INSTRUMENT) {
|
2015-03-13 11:16:43 +01:00
|
|
|
Part* part = el->part();
|
2012-05-26 14:26:10 +02:00
|
|
|
part->removeInstrument(tick());
|
|
|
|
}
|
2013-05-06 14:20:31 +02:00
|
|
|
removeAnnotation(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::INSTRUMENT_CHANGE:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-25 17:30:55 +02:00
|
|
|
InstrumentChange* is = toInstrumentChange(el);
|
2015-03-13 11:16:43 +01:00
|
|
|
Part* part = is->part();
|
2012-05-26 14:26:10 +02:00
|
|
|
part->removeInstrument(tick());
|
|
|
|
}
|
2013-05-06 14:20:31 +02:00
|
|
|
removeAnnotation(el);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::TIMESIG:
|
2012-05-26 14:26:10 +02:00
|
|
|
_elist[track] = 0;
|
2016-10-25 17:30:55 +02:00
|
|
|
el->staff()->removeTimeSig(toTimeSig(el));
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::KEYSIG:
|
2014-06-04 10:20:14 +02:00
|
|
|
Q_ASSERT(_elist[track] == el);
|
|
|
|
|
|
|
|
_elist[track] = 0;
|
|
|
|
if (!el->generated())
|
|
|
|
el->staff()->removeKey(tick());
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CLEF:
|
2016-10-25 17:30:55 +02:00
|
|
|
el->staff()->removeClef(toClef(el));
|
2016-03-18 09:29:16 +01:00
|
|
|
// updateNoteLines(this, el->track());
|
2014-08-05 14:10:22 +02:00
|
|
|
// fall through
|
2014-07-25 17:13:27 +02:00
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BAR_LINE:
|
|
|
|
case ElementType::AMBITUS:
|
2012-05-26 14:26:10 +02:00
|
|
|
_elist[track] = 0;
|
|
|
|
break;
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BREATH:
|
2015-01-29 22:37:39 +01:00
|
|
|
_elist[track] = 0;
|
|
|
|
score()->setPause(tick(), 0);
|
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2014-03-04 13:06:23 +01:00
|
|
|
qFatal("Segment::remove() unknown %s", el->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
}
|
2016-03-08 09:46:33 +01:00
|
|
|
score()->setLayout(tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
checkEmpty();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// segmentType
|
|
|
|
// returns segment type suitable for storage of Element
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
Segment::Type Segment::segmentType(ElementType type)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
switch (type) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CHORD:
|
|
|
|
case ElementType::REST:
|
|
|
|
case ElementType::REPEAT_MEASURE:
|
|
|
|
case ElementType::JUMP:
|
|
|
|
case ElementType::MARKER:
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::ChordRest;
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::CLEF:
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::Clef;
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::KEYSIG:
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::KeySig;
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::TIMESIG:
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::TimeSig;
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BAR_LINE:
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::StartRepeatBarLine;
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::BREATH:
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::Breath;
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2012-09-11 21:10:44 +02:00
|
|
|
qDebug("Segment:segmentType(): bad type: <%s>", Element::name(type));
|
2014-06-25 11:46:10 +02:00
|
|
|
return Type::Invalid;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// sortStaves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::sortStaves(QList<int>& dst)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
std::vector<Element*> dl;
|
|
|
|
dl.reserve(dst.size());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < dst.size(); ++i) {
|
|
|
|
int startTrack = dst[i] * VOICES;
|
|
|
|
int endTrack = startTrack + VOICES;
|
|
|
|
for (int k = startTrack; k < endTrack; ++k)
|
2016-02-06 22:03:43 +01:00
|
|
|
dl.push_back(_elist[k]);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2016-02-06 22:03:43 +01:00
|
|
|
std::swap(_elist, dl);
|
2013-08-09 12:03:15 +02:00
|
|
|
QMap<int, int> map;
|
|
|
|
for (int k = 0; k < dst.size(); ++k) {
|
|
|
|
map.insert(dst[k], k);
|
|
|
|
}
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : _annotations) {
|
|
|
|
if (!e->systemFlag())
|
2013-08-09 12:03:15 +02:00
|
|
|
e->setTrack(map[e->staffIdx()] * VOICES + e->voice());
|
2013-08-08 23:08:22 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
fixStaffIdx();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// fixStaffIdx
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::fixStaffIdx()
|
|
|
|
{
|
|
|
|
int track = 0;
|
2016-01-04 14:48:58 +01:00
|
|
|
for (Element* e : _elist) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e)
|
|
|
|
e->setTrack(track);
|
|
|
|
++track;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// checkEmpty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::checkEmpty() const
|
|
|
|
{
|
2014-02-24 13:53:43 +01:00
|
|
|
if (!_annotations.empty()) {
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2014-02-24 13:53:43 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(true);
|
2016-01-04 14:48:58 +01:00
|
|
|
for (const Element* e : _elist) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (e) {
|
2016-10-20 11:32:07 +02:00
|
|
|
setEmpty(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 08:55:54 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// fpos
|
|
|
|
// return relative position of segment in measure
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Fraction Segment::fpos() const
|
|
|
|
{
|
|
|
|
return Fraction::fromTicks(_tick);
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// swapElements
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::swapElements(int i1, int i2)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
std::iter_swap(_elist.begin() + i1, _elist.begin() + i2);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (_elist[i1])
|
|
|
|
_elist[i1]->setTrack(i1);
|
|
|
|
if (_elist[i2])
|
|
|
|
_elist[i2]->setTrack(i2);
|
2016-08-24 14:49:34 +02:00
|
|
|
score()->setLayout(tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-11-19 11:51:21 +01:00
|
|
|
void Segment::write(XmlWriter& xml) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2016-10-20 11:32:07 +02:00
|
|
|
if (written())
|
2012-05-26 14:26:10 +02:00
|
|
|
return;
|
2016-10-20 11:32:07 +02:00
|
|
|
setWritten(true);
|
2016-01-04 14:48:58 +01:00
|
|
|
if (_extraLeadingSpace.isZero())
|
2012-05-26 14:26:10 +02:00
|
|
|
return;
|
|
|
|
xml.stag(name());
|
|
|
|
xml.tag("leadingSpace", _extraLeadingSpace.val());
|
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// read
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
void Segment::read(XmlReader& e)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
const QStringRef& tag(e.name());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-06-25 19:52:00 +02:00
|
|
|
if (tag == "subtype")
|
|
|
|
e.skipCurrentElement();
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "leadingSpace")
|
2013-01-11 18:10:18 +01:00
|
|
|
_extraLeadingSpace = Spatium(e.readDouble());
|
2016-01-04 14:48:58 +01:00
|
|
|
else if (tag == "trailingSpace") // obsolete
|
|
|
|
e.readDouble();
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// getProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Segment::getProperty(P_ID propertyId) const
|
|
|
|
{
|
2016-08-02 17:00:49 +02:00
|
|
|
switch (propertyId) {
|
|
|
|
case P_ID::TICK:
|
|
|
|
return _tick;
|
2016-03-05 15:31:26 +01:00
|
|
|
case P_ID::LEADING_SPACE:
|
|
|
|
return extraLeadingSpace();
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
|
|
|
return Element::getProperty(propertyId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-14 13:30:25 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// propertyDefault
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Segment::propertyDefault(P_ID propertyId) const
|
|
|
|
{
|
2016-08-07 11:26:15 +02:00
|
|
|
switch (propertyId) {
|
|
|
|
case P_ID::LEADING_SPACE:
|
|
|
|
return Spatium(0.0);
|
2013-03-14 13:30:25 +01:00
|
|
|
default:
|
|
|
|
return Element::getProperty(propertyId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Segment::setProperty(P_ID propertyId, const QVariant& v)
|
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
switch (propertyId) {
|
2016-08-02 17:00:49 +02:00
|
|
|
case P_ID::TICK:
|
|
|
|
_tick = v.toInt();
|
|
|
|
break;
|
2016-03-05 15:31:26 +01:00
|
|
|
case P_ID::LEADING_SPACE:
|
|
|
|
setExtraLeadingSpace(v.value<Spatium>());
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
|
|
|
return Element::setProperty(propertyId, v);
|
|
|
|
}
|
2016-08-02 17:00:49 +02:00
|
|
|
score()->setLayout(tick());
|
2012-05-26 14:26:10 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// splitsTuplet
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Segment::splitsTuplet() const
|
|
|
|
{
|
2016-11-28 17:25:26 +01:00
|
|
|
for (Element* e : _elist) {
|
|
|
|
if (!(e && e->isChordRest()))
|
2012-05-26 14:26:10 +02:00
|
|
|
continue;
|
2016-11-28 17:25:26 +01:00
|
|
|
ChordRest* cr = toChordRest(e);
|
|
|
|
Tuplet* t = cr->tuplet();
|
|
|
|
while (t) {
|
|
|
|
if (cr != t->elements().front())
|
|
|
|
return true;
|
|
|
|
t = t->tuplet();
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-09 12:12:43 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// operator<
|
|
|
|
/// return true if segment is before s in list
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Segment::operator<(const Segment& s) const
|
|
|
|
{
|
|
|
|
if (tick() < s.tick())
|
|
|
|
return true;
|
|
|
|
if (tick() > s.tick())
|
|
|
|
return false;
|
|
|
|
for (Segment* ns = next1(); ns && (ns->tick() == s.tick()); ns = ns->next1()) {
|
|
|
|
if (ns == &s)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// operator>
|
|
|
|
/// return true if segment is after s in list
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Segment::operator>(const Segment& s) const
|
|
|
|
{
|
|
|
|
if (tick() > s.tick())
|
|
|
|
return true;
|
|
|
|
if (tick() < s.tick())
|
|
|
|
return false;
|
|
|
|
for (Segment* ns = prev1(); ns && (ns->tick() == s.tick()); ns = ns->prev1()) {
|
|
|
|
if (ns == &s)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-03 16:56:56 +01:00
|
|
|
//---------------------------------------------------------
|
2013-03-16 12:57:43 +01:00
|
|
|
// findAnnotationOrElement
|
|
|
|
/// return true if an annotation of type type or and element is found in the track range
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2017-01-18 14:16:33 +01:00
|
|
|
bool Segment::findAnnotationOrElement(ElementType type, int minTrack, int maxTrack)
|
2013-03-16 12:57:43 +01:00
|
|
|
{
|
2013-05-06 14:20:31 +02:00
|
|
|
for (const Element* e : _annotations)
|
2013-03-16 12:57:43 +01:00
|
|
|
if (e->type() == type && e->track() >= minTrack && e->track() <= maxTrack)
|
|
|
|
return true;
|
|
|
|
for (int curTrack = minTrack; curTrack <= maxTrack; curTrack++)
|
|
|
|
if (element(curTrack))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-09 12:12:43 +02:00
|
|
|
|
2013-05-06 14:20:31 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeAnnotation
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::removeAnnotation(Element* e)
|
|
|
|
{
|
|
|
|
for (auto i = _annotations.begin(); i != _annotations.end(); ++i) {
|
2013-05-07 12:58:21 +02:00
|
|
|
if (*i == e) {
|
2013-05-06 14:20:31 +02:00
|
|
|
_annotations.erase(i);
|
2013-05-07 12:58:21 +02:00
|
|
|
break;
|
|
|
|
}
|
2013-05-06 14:20:31 +02:00
|
|
|
}
|
|
|
|
}
|
2013-10-30 14:21:08 +01:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// clearAnnotations
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::clearAnnotations()
|
|
|
|
{
|
|
|
|
_annotations.clear();
|
|
|
|
}
|
|
|
|
|
2014-07-06 01:56:30 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// elementAt
|
|
|
|
// A variant of the element(int) function,
|
|
|
|
// specifically intended to be called from QML plugins
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-02-06 22:03:43 +01:00
|
|
|
Ms::Element* Segment::elementAt(int track) const
|
|
|
|
{
|
2016-02-08 15:10:03 +01:00
|
|
|
Element* e = track < int(_elist.size()) ? _elist[track] : 0;
|
2016-02-06 22:03:43 +01:00
|
|
|
|
2014-07-06 01:56:30 +02:00
|
|
|
#ifdef SCRIPT_INTERFACE
|
|
|
|
// if called from QML/JS, tell QML engine not to garbage collect this object
|
2017-02-17 15:09:28 +01:00
|
|
|
// if (e)
|
|
|
|
// QQmlEngine::setObjectOwnership(e, QQmlEngine::CppOwnership);
|
2014-07-06 01:56:30 +02:00
|
|
|
#endif
|
|
|
|
return e;
|
|
|
|
}
|
2013-05-13 18:49:17 +02:00
|
|
|
|
2014-07-15 18:42:31 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// scanElements
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::scanElements(void* data, void (*func)(void*, Element*), bool all)
|
|
|
|
{
|
2016-12-23 12:05:18 +01:00
|
|
|
for (int track = 0; track < score()->nstaves() * VOICES; ++track) {
|
|
|
|
int staffIdx = track/VOICES;
|
|
|
|
if (!all && !(measure()->visible(staffIdx) && score()->staff(staffIdx)->show())) {
|
|
|
|
track += VOICES - 1;
|
|
|
|
continue;
|
2014-07-15 18:42:31 +02:00
|
|
|
}
|
2016-12-23 12:05:18 +01:00
|
|
|
Element* e = element(track);
|
|
|
|
if (e == 0)
|
|
|
|
continue;
|
|
|
|
e->scanElements(data, func, all);
|
2014-07-15 18:42:31 +02:00
|
|
|
}
|
2016-02-06 22:03:43 +01:00
|
|
|
for (Element* e : annotations()) {
|
2014-07-15 18:42:31 +02:00
|
|
|
if (all || e->systemFlag() || measure()->visible(e->staffIdx()))
|
|
|
|
e->scanElements(data, func, all);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-20 22:48:34 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// firstElement
|
|
|
|
// This function returns the first main element from a
|
|
|
|
// segment, or a barline if it spanns in the staff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* Segment::firstElement(int staff)
|
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
if (segmentType() == Segment::Type::ChordRest) {
|
2014-06-20 22:48:34 +02:00
|
|
|
for (int v = staff * VOICES; v/VOICES == staff; v++) {
|
2016-01-04 14:48:58 +01:00
|
|
|
Element* el = element(v);
|
2014-06-20 22:48:34 +02:00
|
|
|
if (!el) { //there is no chord or rest on this voice
|
|
|
|
continue;
|
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
if (el->isChord()) {
|
|
|
|
return toChord(el)->notes().back();
|
2014-06-20 22:48:34 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return el;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2016-01-04 14:48:58 +01:00
|
|
|
return getElement(staff);
|
2014-06-20 22:48:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// lastElement
|
|
|
|
// This function returns the last main element from a
|
|
|
|
// segment, or a barline if it spanns in the staff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* Segment::lastElement(int staff)
|
|
|
|
{
|
2016-01-04 14:48:58 +01:00
|
|
|
if (segmentType() == Segment::Type::ChordRest) {
|
2014-06-20 22:48:34 +02:00
|
|
|
for (int voice = staff * VOICES + (VOICES - 1); voice/VOICES == staff; voice--) {
|
2016-01-04 14:48:58 +01:00
|
|
|
Element* el = element(voice);
|
2014-06-20 22:48:34 +02:00
|
|
|
if (!el) { //there is no chord or rest on this voice
|
|
|
|
continue;
|
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
if (el->isChord()) {
|
|
|
|
return toChord(el)->notes().front();
|
2014-06-20 22:48:34 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
return el;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2016-01-04 14:48:58 +01:00
|
|
|
return getElement(staff);
|
2014-06-20 22:48:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// getElement
|
|
|
|
// protected because it is used by the firstElement and
|
|
|
|
// lastElement functions when segment types that have
|
|
|
|
// just one elemnt to avoid duplicated code
|
|
|
|
//
|
|
|
|
// Use firstElement, or lastElement instead of this
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2015-02-20 11:56:13 +01:00
|
|
|
Element* Segment::getElement(int staff)
|
2014-06-20 22:48:34 +02:00
|
|
|
{
|
2016-02-04 11:27:47 +01:00
|
|
|
if (segmentType() == Segment::Type::ChordRest)
|
2015-02-20 11:56:13 +01:00
|
|
|
return firstElement(staff);
|
2016-02-04 11:27:47 +01:00
|
|
|
else if (segmentType() & (Type::EndBarLine | Type::BarLine | Type::StartRepeatBarLine)) {
|
2014-06-20 22:48:34 +02:00
|
|
|
for (int i = staff; i >= 0; i--) {
|
2016-02-04 11:27:47 +01:00
|
|
|
if (!element(i * VOICES))
|
2014-06-20 22:48:34 +02:00
|
|
|
continue;
|
2016-10-25 17:30:55 +02:00
|
|
|
BarLine* b = toBarLine(element(i*VOICES));
|
2016-12-23 12:05:18 +01:00
|
|
|
if (i + b->spanStaff() >= staff)
|
2016-01-04 14:48:58 +01:00
|
|
|
return element(i*VOICES);
|
2014-06-20 22:48:34 +02:00
|
|
|
}
|
|
|
|
}
|
2016-02-04 11:27:47 +01:00
|
|
|
else
|
|
|
|
return element(staff * VOICES);
|
2014-06-20 22:48:34 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-20 11:56:13 +01:00
|
|
|
//--------------------------------------------------------
|
|
|
|
// firstInNextSegments
|
|
|
|
// Searches for the next segment that has elements on the
|
|
|
|
// active staff and returns its first element
|
|
|
|
//
|
|
|
|
// Uses firstElement so it also returns a barline if it
|
|
|
|
// spans into the active staff
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
Element* Segment::firstInNextSegments(int activeStaff)
|
|
|
|
{
|
|
|
|
Element* re = 0;
|
|
|
|
Segment* seg = this;
|
|
|
|
while (!re) {
|
|
|
|
seg = seg->next1MM(Segment::Type::All);
|
|
|
|
if (!seg) //end of staff, or score
|
|
|
|
break;
|
|
|
|
|
|
|
|
re = seg->firstElement(activeStaff);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (re)
|
|
|
|
return re;
|
|
|
|
|
|
|
|
if (!seg) { //end of staff
|
|
|
|
seg = score()->firstSegment();
|
|
|
|
return seg->element( (activeStaff + 1) * VOICES );
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// firstInNextSegments
|
|
|
|
// Searches for the previous segment that has elements on
|
|
|
|
// the active staff and returns its last element
|
|
|
|
//
|
|
|
|
// Uses lastElement so it also returns a barline if it
|
|
|
|
// spans into the active staff
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
Element* Segment::lastInPrevSegments(int activeStaff)
|
|
|
|
{
|
|
|
|
Element* re = 0;
|
|
|
|
Segment* seg = this;
|
|
|
|
|
|
|
|
while (!re) {
|
|
|
|
seg = seg->prev1MM(Segment::Type::All);
|
|
|
|
if (!seg) //end of staff, or score
|
|
|
|
break;
|
|
|
|
|
|
|
|
re = seg->lastElement(activeStaff);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (re)
|
|
|
|
return re;
|
|
|
|
|
|
|
|
if (!seg) { //end of staff
|
|
|
|
if (activeStaff -1 < 0) //end of score
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
re = 0;
|
|
|
|
seg = score()->lastSegment();
|
|
|
|
while (true) {
|
|
|
|
if (seg->segmentType() == Segment::Type::EndBarLine)
|
|
|
|
score()->inputState().setTrack( (activeStaff -1) * VOICES ); //correction
|
|
|
|
|
|
|
|
if ((re = seg->lastElement(activeStaff -1)) != 0)
|
|
|
|
return re;
|
|
|
|
|
|
|
|
seg = seg->prev1(Segment::Type::All);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// accessibleExtraInfo
|
|
|
|
//---------------------------------------------------------
|
2014-06-20 22:48:34 +02:00
|
|
|
|
2016-02-04 17:06:32 +01:00
|
|
|
QString Segment::accessibleExtraInfo() const
|
2014-07-10 14:13:37 +02:00
|
|
|
{
|
|
|
|
QString rez = "";
|
2016-01-04 14:48:58 +01:00
|
|
|
if (!annotations().empty()) {
|
2015-02-03 01:55:37 +01:00
|
|
|
QString temp = "";
|
2016-02-06 22:03:43 +01:00
|
|
|
for (const Element* a : annotations()) {
|
2015-02-03 01:55:37 +01:00
|
|
|
if (!score()->selectionFilter().canSelect(a)) continue;
|
2014-07-10 14:13:37 +02:00
|
|
|
switch(a->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::DYNAMIC:
|
2014-07-10 14:13:37 +02:00
|
|
|
//they are added in the chordrest, because they are for only one staff
|
|
|
|
break;
|
|
|
|
default:
|
2015-02-03 01:55:37 +01:00
|
|
|
temp = temp + " " + a->accessibleInfo();
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-03 01:55:37 +01:00
|
|
|
if(!temp.isEmpty())
|
2017-02-17 15:09:28 +01:00
|
|
|
rez = rez + QObject::tr("Annotations:") + temp;
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QString startSpanners = "";
|
|
|
|
QString endSpanners = "";
|
2014-08-19 14:35:27 +02:00
|
|
|
|
2016-01-13 20:13:08 +01:00
|
|
|
auto spanners = score()->spannerMap().findOverlapping(this->tick(), this->tick());
|
|
|
|
for (auto interval : spanners) {
|
2014-07-10 14:13:37 +02:00
|
|
|
Spanner* s = interval.value;
|
2015-02-03 01:55:37 +01:00
|
|
|
if (!score()->selectionFilter().canSelect(s)) continue;
|
2016-01-04 14:48:58 +01:00
|
|
|
if (segmentType() == Segment::Type::EndBarLine ||
|
|
|
|
segmentType() == Segment::Type::BarLine ||
|
|
|
|
segmentType() == Segment::Type::StartRepeatBarLine) {
|
2016-10-25 17:30:55 +02:00
|
|
|
if (s->isVolta())
|
2014-07-10 14:13:37 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else {
|
2016-10-25 17:30:55 +02:00
|
|
|
if (s->isVolta() || s->isTie()) //ties are added in Note
|
2014-07-10 14:13:37 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
if (s->tick() == tick())
|
2017-02-17 15:09:28 +01:00
|
|
|
startSpanners += QObject::tr("Start of ") + s->accessibleInfo();
|
2014-07-10 14:13:37 +02:00
|
|
|
|
2016-02-04 17:06:32 +01:00
|
|
|
const Segment* seg = 0;
|
2014-07-10 14:13:37 +02:00
|
|
|
switch (s->type()) {
|
2017-01-18 14:16:33 +01:00
|
|
|
case ElementType::VOLTA:
|
|
|
|
case ElementType::SLUR:
|
2014-07-10 14:13:37 +02:00
|
|
|
seg = this;
|
|
|
|
break;
|
|
|
|
default:
|
2016-01-04 14:48:58 +01:00
|
|
|
seg = next1MM(Segment::Type::ChordRest);
|
2014-07-10 14:13:37 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (seg && s->tick2() == seg->tick())
|
2017-02-17 15:09:28 +01:00
|
|
|
endSpanners += QObject::tr("End of ") + s->accessibleInfo();
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
return rez + " " + startSpanners + " " + endSpanners;
|
|
|
|
}
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// createShapes
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::createShapes()
|
|
|
|
{
|
|
|
|
for (int staffIdx = 0; staffIdx < score()->nstaves(); ++staffIdx)
|
|
|
|
createShape(staffIdx);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// createShape
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Segment::createShape(int staffIdx)
|
|
|
|
{
|
|
|
|
Shape& s = _shapes[staffIdx];
|
|
|
|
s.clear();
|
2016-12-29 15:11:28 +01:00
|
|
|
#if 1
|
2016-02-04 11:27:47 +01:00
|
|
|
if (segmentType() & (Type::BarLine | Type::EndBarLine | Type::StartRepeatBarLine | Type::BeginBarLine)) {
|
2016-10-25 17:30:55 +02:00
|
|
|
BarLine* bl = toBarLine(element(0));
|
2016-02-04 11:27:47 +01:00
|
|
|
if (bl) {
|
|
|
|
qreal w = BarLine::layoutWidth(score(), bl->barLineType(), 1.0);
|
|
|
|
s.add(QRectF(bl->x(), 0.0, w, spatium() * 4.0));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2016-12-23 12:05:18 +01:00
|
|
|
#endif
|
|
|
|
|
2016-03-18 14:35:15 +01:00
|
|
|
for (Element* e : _elist) {
|
2016-10-26 10:55:24 +02:00
|
|
|
if (e && e->vStaffIdx() == staffIdx)
|
2016-12-29 16:42:10 +01:00
|
|
|
s.add(e->shape().translated(e->pos()));
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
2016-02-06 11:41:16 +01:00
|
|
|
for (Element* e : _annotations) {
|
2016-05-11 15:02:30 +02:00
|
|
|
// probably only allow for lyrics and chordnames
|
2016-06-01 13:24:32 +02:00
|
|
|
if (e->staffIdx() == staffIdx
|
|
|
|
&& !e->isRehearsalMark()
|
|
|
|
&& !e->isTempoText()
|
2016-06-14 16:00:16 +02:00
|
|
|
&& !e->isDynamic()
|
2016-08-30 15:07:01 +02:00
|
|
|
&& !e->isSymbol()
|
|
|
|
&& !e->isFSymbol()
|
2017-01-20 11:05:52 +01:00
|
|
|
&& !e->isSystemText()
|
2016-06-01 13:24:32 +02:00
|
|
|
&& !e->isStaffText())
|
2016-12-29 16:42:10 +01:00
|
|
|
s.add(e->shape().translated(e->pos()));
|
2016-02-06 11:41:16 +01:00
|
|
|
}
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// minRight
|
|
|
|
// calculate minimum distance needed to the right
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Segment::minRight() const
|
|
|
|
{
|
|
|
|
qreal distance = 0.0;
|
|
|
|
for (const Shape& sh : shapes())
|
|
|
|
distance = qMax(distance, sh.right());
|
2016-10-31 10:55:11 +01:00
|
|
|
if (isClefType())
|
|
|
|
distance += score()->styleP(StyleIdx::clefBarlineDistance);
|
2016-01-04 14:48:58 +01:00
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// minLeft
|
2016-02-12 14:42:06 +01:00
|
|
|
// Calculate minimum distance needed to the left shape
|
|
|
|
// sl. Sl is the same for all staves.
|
2016-01-04 14:48:58 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-02-12 14:42:06 +01:00
|
|
|
qreal Segment::minLeft(const Shape& sl) const
|
|
|
|
{
|
|
|
|
qreal distance = 0.0;
|
2016-05-02 13:41:41 +02:00
|
|
|
for (const Shape& sh : shapes()) {
|
|
|
|
qreal d = sl.minHorizontalDistance(sh);
|
|
|
|
if (d > distance)
|
|
|
|
distance = d;
|
|
|
|
}
|
2016-02-12 14:42:06 +01:00
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
2016-01-04 14:48:58 +01:00
|
|
|
qreal Segment::minLeft() const
|
|
|
|
{
|
|
|
|
qreal distance = 0.0;
|
2016-05-02 13:41:41 +02:00
|
|
|
for (const Shape& sh : shapes()) {
|
|
|
|
qreal l = sh.left();
|
|
|
|
if (l > distance)
|
|
|
|
distance = l;
|
|
|
|
}
|
2016-02-12 14:42:06 +01:00
|
|
|
return distance;
|
2016-01-04 14:48:58 +01:00
|
|
|
}
|
|
|
|
|
2016-02-04 11:27:47 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// minHorizontalDistance
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2016-04-19 15:18:17 +02:00
|
|
|
qreal Segment::minHorizontalDistance(Segment* ns, bool systemHeaderGap) const
|
2016-02-04 11:27:47 +01:00
|
|
|
{
|
|
|
|
Segment::Type st = segmentType();
|
|
|
|
Segment::Type nst = ns ? ns->segmentType() : Segment::Type::Invalid;
|
|
|
|
|
|
|
|
qreal w = 0.0;
|
2016-02-06 22:03:43 +01:00
|
|
|
for (unsigned staffIdx = 0; staffIdx < _shapes.size(); ++staffIdx) {
|
2016-04-18 20:26:43 +02:00
|
|
|
qreal d = staffShape(staffIdx).minHorizontalDistance(ns->staffShape(staffIdx));
|
2016-02-04 11:27:47 +01:00
|
|
|
w = qMax(w, d);
|
|
|
|
}
|
2016-03-02 13:20:19 +01:00
|
|
|
|
2016-08-29 14:49:59 +02:00
|
|
|
if (isChordRestType()) {
|
2016-02-04 11:27:47 +01:00
|
|
|
if (nst == Segment::Type::EndBarLine)
|
2016-04-15 16:44:48 +02:00
|
|
|
w += score()->styleP(StyleIdx::noteBarDistance);
|
2016-02-04 11:27:47 +01:00
|
|
|
else if (nst == Segment::Type::Clef)
|
2016-03-02 13:20:19 +01:00
|
|
|
w = qMax(w, score()->styleP(StyleIdx::clefLeftMargin));
|
2016-05-17 22:14:29 +02:00
|
|
|
else {
|
|
|
|
bool isGap = false;
|
|
|
|
for (int i = 0; i < score()->nstaves() * VOICES; i++) {
|
|
|
|
Element* el = element(i);
|
|
|
|
if (el && el->isRest() && toRest(el)->isGap())
|
|
|
|
isGap = true;
|
|
|
|
else if (el) {
|
|
|
|
isGap = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isGap)
|
|
|
|
return 0.0;
|
|
|
|
|
2016-03-02 13:20:19 +01:00
|
|
|
w = qMax(w, score()->noteHeadWidth()) + score()->styleP(StyleIdx::minNoteDistance);
|
2016-05-17 22:14:29 +02:00
|
|
|
}
|
2016-02-04 11:27:47 +01:00
|
|
|
}
|
2016-08-29 14:49:59 +02:00
|
|
|
else if (nst == Segment::Type::ChordRest) {
|
2016-04-20 18:56:08 +02:00
|
|
|
qreal d;
|
|
|
|
if (systemHeaderGap) {
|
|
|
|
if (st == Segment::Type::TimeSig)
|
|
|
|
d = score()->styleP(StyleIdx::systemHeaderTimeSigDistance);
|
|
|
|
else
|
|
|
|
d = score()->styleP(StyleIdx::systemHeaderDistance);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
d = score()->styleP(StyleIdx::barNoteDistance);
|
2016-05-02 13:41:41 +02:00
|
|
|
qreal dd = minRight() + ns->minLeft() + spatium();
|
|
|
|
w = qMax(d, dd);
|
2016-04-28 16:23:32 +02:00
|
|
|
// d -= ns->minLeft() * .7; // hack
|
|
|
|
// d = qMax(d, ns->minLeft());
|
|
|
|
// d = qMax(d, spatium()); // minimum distance is one spatium
|
|
|
|
// w = qMax(w, minRight()) + d;
|
2016-04-19 15:18:17 +02:00
|
|
|
}
|
2016-10-25 17:30:55 +02:00
|
|
|
else if (st & (Segment::Type::Clef | Segment::Type::HeaderClef)) {
|
2016-04-06 15:28:10 +02:00
|
|
|
if (nst == Segment::Type::KeySig)
|
|
|
|
w += score()->styleP(StyleIdx::clefKeyDistance);
|
|
|
|
else if (nst == Segment::Type::TimeSig)
|
|
|
|
w += score()->styleP(StyleIdx::clefTimesigDistance);
|
|
|
|
else if (nst & (Segment::Type::EndBarLine | Segment::Type::StartRepeatBarLine))
|
|
|
|
w += score()->styleP(StyleIdx::clefBarlineDistance);
|
2016-05-25 12:10:52 +02:00
|
|
|
else if (nst == Segment::Type::Ambitus)
|
|
|
|
w += score()->styleP(StyleIdx::ambitusMargin);
|
2016-04-06 15:28:10 +02:00
|
|
|
}
|
2016-04-20 18:56:08 +02:00
|
|
|
else if ((st & (Segment::Type::KeySig | Segment::Type::KeySigAnnounce))
|
|
|
|
&& (nst & (Segment::Type::TimeSig | Segment::Type::TimeSigAnnounce))) {
|
2016-03-02 13:20:19 +01:00
|
|
|
w += score()->styleP(StyleIdx::keyTimesigDistance);
|
2016-04-20 18:56:08 +02:00
|
|
|
}
|
2016-03-05 19:50:55 +01:00
|
|
|
else if (st == Segment::Type::KeySig && nst == Segment::Type::StartRepeatBarLine)
|
|
|
|
w += score()->styleP(StyleIdx::keyBarlineDistance);
|
2016-02-04 11:27:47 +01:00
|
|
|
else if (st == Segment::Type::StartRepeatBarLine)
|
2016-03-02 13:20:19 +01:00
|
|
|
w += score()->styleP(StyleIdx::noteBarDistance);
|
2016-10-25 17:30:55 +02:00
|
|
|
else if (st == Segment::Type::BeginBarLine && (nst & (Segment::Type::HeaderClef | Segment::Type::Clef)))
|
2016-03-02 13:20:19 +01:00
|
|
|
w += score()->styleP(StyleIdx::clefLeftMargin);
|
2016-05-04 10:27:40 +02:00
|
|
|
else if (st == Segment::Type::EndBarLine) {
|
|
|
|
if (nst == Segment::Type::KeySigAnnounce)
|
|
|
|
w += score()->styleP(StyleIdx::keysigLeftMargin);
|
|
|
|
else if (nst == Segment::Type::TimeSigAnnounce)
|
|
|
|
w += score()->styleP(StyleIdx::timesigLeftMargin);
|
|
|
|
}
|
|
|
|
else if (st == Segment::Type::TimeSig && nst == Segment::Type::StartRepeatBarLine)
|
|
|
|
w += score()->styleP(StyleIdx::timesigBarlineDistance);
|
2016-02-15 13:34:19 +01:00
|
|
|
else if (st == Segment::Type::Breath)
|
2016-03-02 13:20:19 +01:00
|
|
|
w += spatium() * 1.5;
|
2016-05-25 12:10:52 +02:00
|
|
|
else if (st == Segment::Type::Ambitus)
|
|
|
|
w += score()->styleP(StyleIdx::ambitusMargin);
|
2016-05-04 10:27:40 +02:00
|
|
|
|
2016-02-04 11:27:47 +01:00
|
|
|
if (w < 0.0)
|
|
|
|
w = 0.0;
|
2016-03-05 19:50:55 +01:00
|
|
|
if (ns)
|
2016-03-02 13:20:19 +01:00
|
|
|
w += ns->extraLeadingSpace().val() * spatium();
|
2016-02-04 11:27:47 +01:00
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
2014-07-06 01:56:30 +02:00
|
|
|
} // namespace Ms
|