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 "staff.h"
|
|
|
|
#include "part.h"
|
|
|
|
#include "clef.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "score.h"
|
|
|
|
#include "bracket.h"
|
|
|
|
#include "keysig.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "style.h"
|
|
|
|
#include "measure.h"
|
2013-12-05 21:37:28 +01:00
|
|
|
#include "stringdata.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "stafftype.h"
|
|
|
|
#include "undo.h"
|
|
|
|
#include "cleflist.h"
|
|
|
|
#include "timesig.h"
|
|
|
|
#include "instrtemplate.h"
|
2012-10-20 20:32:40 +02:00
|
|
|
#include "barline.h"
|
2013-07-16 09:03:47 +02:00
|
|
|
#include "ottava.h"
|
2015-02-20 11:56:13 +01:00
|
|
|
#include "harmony.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2015-06-26 11:55:44 +02:00
|
|
|
// #define DEBUG_CLEFS
|
|
|
|
|
|
|
|
#ifdef DEBUG_CLEFS
|
|
|
|
#define DUMP_CLEFS(s) dumpClefs(s)
|
|
|
|
#else
|
|
|
|
#define DUMP_CLEFS(s)
|
|
|
|
#endif
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// idx
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::idx() const
|
|
|
|
{
|
|
|
|
return _score->staffIdx(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// bracket
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
BracketType Staff::bracket(int idx) const
|
|
|
|
{
|
|
|
|
if (idx < _brackets.size())
|
|
|
|
return _brackets[idx]._bracket;
|
2014-05-26 22:25:34 +02:00
|
|
|
return BracketType::NO_BRACKET;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// bracketSpan
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::bracketSpan(int idx) const
|
|
|
|
{
|
|
|
|
if (idx < _brackets.size())
|
|
|
|
return _brackets[idx]._bracketSpan;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setBracket
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::setBracket(int idx, BracketType val)
|
|
|
|
{
|
2012-10-12 15:36:57 +02:00
|
|
|
for (int i = _brackets.size(); i <= idx; ++i)
|
|
|
|
_brackets.append(BracketItem());
|
2012-05-26 14:26:10 +02:00
|
|
|
_brackets[idx]._bracket = val;
|
2016-02-06 22:03:43 +01:00
|
|
|
while (!_brackets.empty() && (_brackets.last()._bracket == BracketType::NO_BRACKET))
|
2012-05-26 14:26:10 +02:00
|
|
|
_brackets.removeLast();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setBracketSpan
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::setBracketSpan(int idx, int val)
|
|
|
|
{
|
2012-10-12 15:36:57 +02:00
|
|
|
Q_ASSERT(idx >= 0);
|
|
|
|
Q_ASSERT(val >= 0);
|
|
|
|
for (int i = _brackets.size(); i <= idx; ++i)
|
|
|
|
_brackets.append(BracketItem());
|
2012-05-26 14:26:10 +02:00
|
|
|
_brackets[idx]._bracketSpan = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// addBracket
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::addBracket(BracketItem b)
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
if (!_brackets.empty() && _brackets[0]._bracket == BracketType::NO_BRACKET) {
|
2012-05-26 14:26:10 +02:00
|
|
|
_brackets[0] = b;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
|
|
// create new bracket level
|
|
|
|
//
|
|
|
|
foreach(Staff* s, _score->staves()) {
|
|
|
|
if (s == this)
|
|
|
|
s->_brackets.append(b);
|
|
|
|
else
|
|
|
|
s->_brackets.append(BracketItem());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-02 13:20:19 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// innerBracket
|
|
|
|
// Return type inner bracket.
|
|
|
|
// The bracket type determines the staff distance.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
BracketType Staff::innerBracket() const
|
|
|
|
{
|
|
|
|
int staffIdx = idx();
|
|
|
|
|
|
|
|
BracketType t = BracketType::NO_BRACKET;
|
|
|
|
int level = 1000;
|
|
|
|
for (int i = 0; i < score()->nstaves(); ++i) {
|
|
|
|
Staff* staff = score()->staff(i);
|
|
|
|
for (int k = 0; k < staff->brackets().size(); ++k) {
|
2016-03-05 10:29:38 +01:00
|
|
|
const BracketItem& bi = staff->brackets().at(k);
|
2016-03-02 13:20:19 +01:00
|
|
|
if (bi._bracket != BracketType::NO_BRACKET) {
|
|
|
|
if (i < staffIdx && ((i + bi._bracketSpan) > staffIdx) && k < level) {
|
|
|
|
t = bi._bracket;
|
|
|
|
level = k;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// cleanupBrackets
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::cleanupBrackets()
|
|
|
|
{
|
|
|
|
int index = idx();
|
|
|
|
int n = _score->nstaves();
|
|
|
|
for (int i = 0; i < _brackets.size(); ++i) {
|
2014-05-26 22:25:34 +02:00
|
|
|
if (_brackets[i]._bracket == BracketType::NO_BRACKET)
|
2013-06-05 15:47:34 +02:00
|
|
|
continue;
|
|
|
|
int span = _brackets[i]._bracketSpan;
|
|
|
|
if (span > (n - index)) {
|
|
|
|
span = n - index;
|
|
|
|
_brackets[i]._bracketSpan = span;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = 0; i < _brackets.size(); ++i) {
|
2014-05-26 22:25:34 +02:00
|
|
|
if (_brackets[i]._bracket == BracketType::NO_BRACKET)
|
2013-06-05 15:47:34 +02:00
|
|
|
continue;
|
|
|
|
int span = _brackets[i]._bracketSpan;
|
|
|
|
if (span <= 1)
|
|
|
|
_brackets[i] = BracketItem();
|
|
|
|
else {
|
|
|
|
// delete all other brackets with same span
|
|
|
|
for (int k = i + 1; k < _brackets.size(); ++k) {
|
|
|
|
if (span == _brackets[k]._bracketSpan)
|
|
|
|
_brackets[k] = BracketItem();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// partName
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QString Staff::partName() const
|
|
|
|
{
|
|
|
|
return _part->partName();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Staff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-07-06 14:21:05 +02:00
|
|
|
Staff::Staff(Score* s)
|
2015-02-04 22:12:13 +01:00
|
|
|
: ScoreElement(s)
|
2012-07-06 14:21:05 +02:00
|
|
|
{
|
2014-12-18 13:21:29 +01:00
|
|
|
_barLineTo = (lines() - 1) * 2;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// ~Staff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Staff::~Staff()
|
|
|
|
{
|
|
|
|
if (_linkedStaves) {
|
|
|
|
_linkedStaves->remove(this);
|
2016-02-06 22:03:43 +01:00
|
|
|
if (_linkedStaves->empty())
|
2012-05-26 14:26:10 +02:00
|
|
|
delete _linkedStaves;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2014-08-16 11:21:56 +02:00
|
|
|
// Staff::clefType
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-08-16 11:21:56 +02:00
|
|
|
ClefTypeList Staff::clefType(int tick) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-08-14 14:29:35 +02:00
|
|
|
ClefTypeList ct = clefs.clef(tick);
|
|
|
|
if (ct._concertClef == ClefType::INVALID) {
|
|
|
|
switch(_staffType.group()) {
|
2014-08-16 11:21:56 +02:00
|
|
|
case StaffGroup::TAB:
|
|
|
|
ct = ClefTypeList(ClefType(score()->styleI(StyleIdx::tabClef)));
|
2014-08-14 14:29:35 +02:00
|
|
|
break;
|
|
|
|
case StaffGroup::STANDARD:
|
2014-08-16 11:21:56 +02:00
|
|
|
ct = defaultClefType();
|
2014-08-14 14:29:35 +02:00
|
|
|
break;
|
|
|
|
case StaffGroup::PERCUSSION:
|
2014-08-16 11:21:56 +02:00
|
|
|
ct = ClefTypeList(ClefType::PERC);
|
2014-08-14 14:29:35 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ct;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Staff::clef
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
ClefType Staff::clef(int tick) const
|
|
|
|
{
|
2014-08-16 11:21:56 +02:00
|
|
|
ClefTypeList c = clefType(tick);
|
2014-05-26 15:31:36 +02:00
|
|
|
return score()->styleB(StyleIdx::concertPitch) ? c._concertClef : c._transposingClef;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2015-02-14 15:10:35 +01:00
|
|
|
#ifndef NDEBUG
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// dumpClef
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::dumpClefs(const char* title) const
|
|
|
|
{
|
2015-02-14 17:17:07 +01:00
|
|
|
qDebug("dump clefs (%zd): %s", clefs.size(), title);
|
2015-02-14 15:10:35 +01:00
|
|
|
for (auto& i : clefs) {
|
2015-02-14 16:24:29 +01:00
|
|
|
qDebug(" %d: %d %d", i.first, int(i.second._concertClef), int(i.second._transposingClef));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// dumpKeys
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::dumpKeys(const char* title) const
|
|
|
|
{
|
2015-02-14 17:17:07 +01:00
|
|
|
qDebug("dump keys (%zd): %s", _keys.size(), title);
|
2015-02-14 16:24:29 +01:00
|
|
|
for (auto& i : _keys) {
|
|
|
|
qDebug(" %d: %d", i.first, int(i.second.key()));
|
2015-02-14 15:10:35 +01:00
|
|
|
}
|
|
|
|
}
|
2015-02-16 12:12:23 +01:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// dumpTimeSigs
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::dumpTimeSigs(const char* title) const
|
|
|
|
{
|
|
|
|
qDebug("dump timesig size (%zd) staffIdx %d: %s", timesigs.size(), idx(), title);
|
|
|
|
for (auto& i : timesigs) {
|
|
|
|
qDebug(" %d: %d/%d", i.first, i.second->sig().numerator(), i.second->sig().denominator());
|
|
|
|
}
|
|
|
|
}
|
2015-02-14 15:10:35 +01:00
|
|
|
#endif
|
|
|
|
|
2013-09-05 16:37:49 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setClef
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-07-25 17:13:27 +02:00
|
|
|
void Staff::setClef(Clef* clef)
|
2013-09-05 16:37:49 +02:00
|
|
|
{
|
2014-08-05 14:10:22 +02:00
|
|
|
if (clef->generated())
|
|
|
|
return;
|
2014-07-25 17:13:27 +02:00
|
|
|
int tick = clef->segment()->tick();
|
|
|
|
for (Segment* s = clef->segment()->next(); s && s->tick() == tick; s = s->next()) {
|
|
|
|
if (s->segmentType() == Segment::Type::Clef && s->element(clef->track())) {
|
|
|
|
// adding this clef has no effect on the clefs list
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clefs.setClef(clef->segment()->tick(), clef->clefTypeList());
|
2015-06-26 11:55:44 +02:00
|
|
|
DUMP_CLEFS("setClef");
|
2013-09-05 16:37:49 +02:00
|
|
|
}
|
|
|
|
|
2014-05-08 17:59:24 +02:00
|
|
|
//---------------------------------------------------------
|
2014-07-25 17:13:27 +02:00
|
|
|
// removeClef
|
2014-05-08 17:59:24 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-07-25 17:13:27 +02:00
|
|
|
void Staff::removeClef(Clef* clef)
|
2013-09-05 16:37:49 +02:00
|
|
|
{
|
2014-08-05 14:10:22 +02:00
|
|
|
if (clef->generated())
|
|
|
|
return;
|
2014-07-25 17:13:27 +02:00
|
|
|
int tick = clef->segment()->tick();
|
|
|
|
for (Segment* s = clef->segment()->next(); s && s->tick() == tick; s = s->next()) {
|
|
|
|
if (s->segmentType() == Segment::Type::Clef && s->element(clef->track())) {
|
|
|
|
// removal of this clef has no effect on the clefs list
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clefs.erase(clef->segment()->tick());
|
|
|
|
for (Segment* s = clef->segment()->prev(); s && s->tick() == tick; s = s->prev()) {
|
2015-02-14 15:10:35 +01:00
|
|
|
if (s->segmentType() == Segment::Type::Clef
|
|
|
|
&& s->element(clef->track())
|
|
|
|
&& !s->element(clef->track())->generated()) {
|
2014-07-25 17:13:27 +02:00
|
|
|
// a previous clef at the same tick position gets valid
|
|
|
|
clefs.setClef(tick, static_cast<Clef*>(s->element(clef->track()))->clefTypeList());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-06-26 11:55:44 +02:00
|
|
|
DUMP_CLEFS("removeClef");
|
2013-09-05 16:37:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2014-05-08 17:59:24 +02:00
|
|
|
// timeStretch
|
2013-09-05 16:37:49 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-05-08 17:59:24 +02:00
|
|
|
Fraction Staff::timeStretch(int tick) const
|
2013-09-05 16:37:49 +02:00
|
|
|
{
|
2014-05-08 17:59:24 +02:00
|
|
|
TimeSig* timesig = timeSig(tick);
|
|
|
|
return timesig == 0 ? Fraction(1,1) : timesig->stretch();
|
2013-09-05 16:37:49 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// timeSig
|
2012-06-27 12:53:40 +02:00
|
|
|
// lookup time signature before or at tick
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
TimeSig* Staff::timeSig(int tick) const
|
|
|
|
{
|
2013-05-06 14:20:31 +02:00
|
|
|
auto i = timesigs.upper_bound(tick);
|
|
|
|
if (i != timesigs.begin())
|
|
|
|
--i;
|
2014-11-27 13:04:03 +01:00
|
|
|
else if (tick < i->first)
|
|
|
|
return 0;
|
2013-05-06 14:20:31 +02:00
|
|
|
return (i == timesigs.end()) ? 0 : i->second;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-04-29 15:31:22 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// group
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
const Groups& Staff::group(int tick) const
|
|
|
|
{
|
|
|
|
TimeSig* ts = timeSig(tick);
|
|
|
|
if (ts) {
|
|
|
|
if (!ts->groups().empty())
|
|
|
|
return ts->groups();
|
2013-05-06 14:20:31 +02:00
|
|
|
return Groups::endings(ts->sig());
|
2013-04-29 15:31:22 +02:00
|
|
|
}
|
|
|
|
Measure* m = score()->tick2measure(tick);
|
2014-05-03 10:10:46 +02:00
|
|
|
return Groups::endings(m ? m->timesig() : Fraction(4,4));
|
2013-04-29 15:31:22 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// addTimeSig
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::addTimeSig(TimeSig* timesig)
|
|
|
|
{
|
2014-07-22 19:28:49 +02:00
|
|
|
if (timesig->segment()->segmentType() == Segment::Type::TimeSig)
|
|
|
|
timesigs[timesig->segment()->tick()] = timesig;
|
2015-02-16 12:12:23 +01:00
|
|
|
// dumpTimeSigs("after addTimeSig");
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeTimeSig
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::removeTimeSig(TimeSig* timesig)
|
|
|
|
{
|
2014-07-22 19:28:49 +02:00
|
|
|
if (timesig->segment()->segmentType() == Segment::Type::TimeSig)
|
|
|
|
timesigs.erase(timesig->segment()->tick());
|
2015-02-16 12:12:23 +01:00
|
|
|
// dumpTimeSigs("after removeTimeSig");
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2014-11-27 13:04:03 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// clearTimeSig
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::clearTimeSig()
|
|
|
|
{
|
|
|
|
timesigs.clear();
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
2015-06-13 17:57:57 +02:00
|
|
|
// Staff::keySigEvent
|
2013-05-08 11:21:59 +02:00
|
|
|
//
|
|
|
|
// locates the key sig currently in effect at tick
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-12-08 18:02:17 +01:00
|
|
|
KeySigEvent Staff::keySigEvent(int tick) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-06-03 15:28:10 +02:00
|
|
|
return _keys.key(tick);
|
|
|
|
}
|
|
|
|
|
2014-06-04 10:20:14 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setKey
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-12-08 18:02:17 +01:00
|
|
|
void Staff::setKey(int tick, KeySigEvent k)
|
2014-06-04 10:20:14 +02:00
|
|
|
{
|
|
|
|
_keys.setKey(tick, k);
|
2015-03-09 18:31:28 +01:00
|
|
|
// dumpKeys("setKey");
|
2014-06-04 10:20:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeKey
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::removeKey(int tick)
|
|
|
|
{
|
2014-07-17 09:32:30 +02:00
|
|
|
_keys.erase(tick);
|
2015-03-09 18:31:28 +01:00
|
|
|
// dumpKeys("removeKey");
|
2014-06-04 10:20:14 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 15:28:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// prevkey
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-12-08 18:02:17 +01:00
|
|
|
KeySigEvent Staff::prevKey(int tick) const
|
2014-06-03 15:28:10 +02:00
|
|
|
{
|
|
|
|
return _keys.prevKey(tick);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2013-05-08 11:21:59 +02:00
|
|
|
// Staff::nextKeyTick
|
|
|
|
//
|
|
|
|
// return the tick at which the key sig after tick is located
|
|
|
|
// return 0, if no such a key sig
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::nextKeyTick(int tick) const
|
|
|
|
{
|
2014-06-03 15:28:10 +02:00
|
|
|
return _keys.nextKeyTick(tick);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Staff::currentKeyTick
|
|
|
|
//
|
|
|
|
// return the tick position of the key currently
|
|
|
|
// in effect at tick
|
|
|
|
// return 0, if no such a key sig
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::currentKeyTick(int tick) const
|
|
|
|
{
|
|
|
|
return _keys.currentKeyTick(tick);
|
2013-05-08 11:21:59 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::write(Xml& xml) const
|
|
|
|
{
|
|
|
|
int idx = score()->staffIdx(this);
|
2013-01-24 14:38:35 +01:00
|
|
|
xml.stag(QString("Staff id=\"%1\"").arg(idx + 1));
|
2012-05-26 14:26:10 +02:00
|
|
|
if (linkedStaves()) {
|
|
|
|
Score* s = score();
|
|
|
|
if (s->parentScore())
|
|
|
|
s = s->parentScore();
|
|
|
|
foreach(Staff* staff, linkedStaves()->staves()) {
|
|
|
|
if ((staff->score() == s) && (staff != this))
|
|
|
|
xml.tag("linkedTo", s->staffIdx(staff) + 1);
|
|
|
|
}
|
|
|
|
}
|
2014-04-30 10:08:38 +02:00
|
|
|
|
2014-05-05 15:38:40 +02:00
|
|
|
// for copy/paste we need to know the actual transposition
|
|
|
|
if (xml.clipboardmode) {
|
2015-09-21 02:13:22 +02:00
|
|
|
Interval v = part()->instrument()->transpose(); // TODO: tick?
|
2014-05-05 15:38:40 +02:00
|
|
|
if (v.diatonic)
|
|
|
|
xml.tag("transposeDiatonic", v.diatonic);
|
|
|
|
if (v.chromatic)
|
|
|
|
xml.tag("transposeChromatic", v.chromatic);
|
|
|
|
}
|
|
|
|
|
2014-04-28 18:38:50 +02:00
|
|
|
_staffType.write(xml);
|
2014-08-16 11:21:56 +02:00
|
|
|
ClefTypeList ct = _defaultClefType;
|
|
|
|
if (ct._concertClef == ct._transposingClef) {
|
|
|
|
if (ct._concertClef != ClefType::G)
|
|
|
|
xml.tag("defaultClef", ClefInfo::tag(ct._concertClef));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
xml.tag("defaultConcertClef", ClefInfo::tag(ct._concertClef));
|
|
|
|
xml.tag("defaultTransposingClef", ClefInfo::tag(ct._transposingClef));
|
|
|
|
}
|
2014-04-30 10:08:38 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
if (small() && !xml.excerptmode) // switch small staves to normal ones when extracting part
|
|
|
|
xml.tag("small", small());
|
|
|
|
if (invisible())
|
|
|
|
xml.tag("invisible", invisible());
|
2015-08-04 19:53:54 +02:00
|
|
|
if (hideWhenEmpty() != HideMode::AUTO)
|
|
|
|
xml.tag("hideWhenEmpty", int(hideWhenEmpty()));
|
|
|
|
if (cutaway())
|
|
|
|
xml.tag("cutaway", cutaway());
|
2014-08-06 16:37:41 +02:00
|
|
|
if (showIfEmpty())
|
|
|
|
xml.tag("showIfSystemEmpty", showIfEmpty());
|
2015-01-05 17:55:06 +01:00
|
|
|
if (_hideSystemBarLine)
|
|
|
|
xml.tag("hideSystemBarLine", _hideSystemBarLine);
|
2014-07-31 18:46:41 +02:00
|
|
|
|
2015-04-26 19:09:33 +02:00
|
|
|
for (const BracketItem& i : _brackets)
|
|
|
|
xml.tagE(QString("bracket type=\"%1\" span=\"%2\"").arg((signed char)(i._bracket)).arg(i._bracketSpan));
|
2013-01-24 14:38:35 +01:00
|
|
|
|
2012-10-20 20:32:40 +02:00
|
|
|
// for economy and consistency, only output "from" and "to" attributes if different from default
|
2012-12-10 12:56:54 +01:00
|
|
|
int defaultLineFrom = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0);
|
|
|
|
int defaultLineTo;
|
|
|
|
if (_barLineSpan == 0) // if no bar line at all
|
|
|
|
defaultLineTo = _barLineTo; // whatever the current spanTo is, use as default
|
|
|
|
else { // if some bar line, default is the default for span target staff
|
2013-01-24 14:38:35 +01:00
|
|
|
int targetStaffIdx = idx + _barLineSpan - 1;
|
|
|
|
if (targetStaffIdx >= score()->nstaves()) {
|
|
|
|
qFatal("bad _barLineSpan %d for staff %d (nstaves %d)",
|
|
|
|
_barLineSpan, idx, score()->nstaves());
|
|
|
|
}
|
|
|
|
int targetStaffLines = score()->staff(targetStaffIdx)->lines();
|
2012-12-10 12:56:54 +01:00
|
|
|
defaultLineTo = (targetStaffLines == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (targetStaffLines-1) * 2);
|
|
|
|
}
|
|
|
|
if (_barLineSpan != 1 || _barLineFrom != defaultLineFrom || _barLineTo != defaultLineTo) {
|
|
|
|
if(_barLineFrom != defaultLineFrom || _barLineTo != defaultLineTo)
|
2012-10-20 20:32:40 +02:00
|
|
|
xml.tag(QString("barLineSpan from=\"%1\" to=\"%2\"").arg(_barLineFrom).arg(_barLineTo), _barLineSpan);
|
|
|
|
else
|
|
|
|
xml.tag("barLineSpan", _barLineSpan);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
if (_userDist != 0.0)
|
2016-02-12 06:10:26 +01:00
|
|
|
xml.tag("distOffset", _userDist / score()->spatium());
|
2015-02-04 22:12:13 +01:00
|
|
|
|
|
|
|
writeProperty(xml, P_ID::MAG);
|
|
|
|
writeProperty(xml, P_ID::COLOR);
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// read
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
void Staff::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());
|
2014-04-30 10:08:38 +02:00
|
|
|
if (tag == "type") { // obsolete
|
|
|
|
int staffTypeIdx = e.readInt();
|
2014-08-13 15:42:40 +02:00
|
|
|
qDebug("obsolete: Staff::read staffTypeIdx %d", staffTypeIdx);
|
2014-05-26 19:19:29 +02:00
|
|
|
_staffType = *StaffType::preset(StaffTypes(staffTypeIdx));
|
2014-05-16 10:32:35 +02:00
|
|
|
// set default barLineFrom and barLineTo according to staff type num. of lines
|
|
|
|
// (1-line staff bar lines are special)
|
|
|
|
_barLineFrom = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0);
|
|
|
|
_barLineTo = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (lines() - 1) * 2);
|
2014-04-30 10:08:38 +02:00
|
|
|
}
|
2014-05-08 17:59:24 +02:00
|
|
|
else if (tag == "StaffType") {
|
2014-04-28 18:38:50 +02:00
|
|
|
_staffType.read(e);
|
2014-05-16 10:32:35 +02:00
|
|
|
// set default barLineFrom and barLineTo according to staff type num. of lines
|
|
|
|
// (1-line staff bar lines are special)
|
|
|
|
_barLineFrom = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0);
|
|
|
|
_barLineTo = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (lines() - 1) * 2);
|
2014-05-08 17:59:24 +02:00
|
|
|
}
|
2014-08-16 11:21:56 +02:00
|
|
|
else if (tag == "defaultClef") { // sets both default transposing and concert clef
|
|
|
|
QString val(e.readElementText());
|
|
|
|
ClefType ct = Clef::clefType(val);
|
|
|
|
setDefaultClefType(ClefTypeList(ct, ct));
|
|
|
|
}
|
|
|
|
else if (tag == "defaultConcertClef") {
|
|
|
|
QString val(e.readElementText());
|
|
|
|
setDefaultClefType(ClefTypeList(Clef::clefType(val), defaultClefType()._transposingClef));
|
|
|
|
}
|
|
|
|
else if (tag == "defaultTransposingClef") {
|
|
|
|
QString val(e.readElementText());
|
|
|
|
setDefaultClefType(ClefTypeList(defaultClefType()._concertClef, Clef::clefType(val)));
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "small")
|
2013-01-11 18:10:18 +01:00
|
|
|
setSmall(e.readInt());
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "invisible")
|
2013-01-11 18:10:18 +01:00
|
|
|
setInvisible(e.readInt());
|
2015-08-04 19:53:54 +02:00
|
|
|
else if (tag == "hideWhenEmpty")
|
|
|
|
setHideWhenEmpty(HideMode(e.readInt()));
|
|
|
|
else if (tag == "neverHide") { // 2.0 compatibility
|
|
|
|
bool v = e.readInt();
|
|
|
|
if (v)
|
|
|
|
setHideWhenEmpty(HideMode::NEVER);
|
|
|
|
}
|
|
|
|
else if (tag == "cutaway")
|
|
|
|
setCutaway(e.readInt());
|
2014-08-06 16:37:41 +02:00
|
|
|
else if (tag == "showIfSystemEmpty")
|
|
|
|
setShowIfEmpty(e.readInt());
|
2015-01-05 17:55:06 +01:00
|
|
|
else if (tag == "hideSystemBarLine")
|
|
|
|
_hideSystemBarLine = e.readInt();
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "keylist")
|
2014-06-03 15:28:10 +02:00
|
|
|
_keys.read(e, _score);
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "bracket") {
|
|
|
|
BracketItem b;
|
2013-01-17 12:56:14 +01:00
|
|
|
b._bracket = BracketType(e.intAttribute("type", -1));
|
2013-01-11 18:10:18 +01:00
|
|
|
b._bracketSpan = e.intAttribute("span", 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
_brackets.append(b);
|
2013-01-17 12:56:14 +01:00
|
|
|
e.readNext();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-10-14 00:35:11 +02:00
|
|
|
else if (tag == "barLineSpan") {
|
2013-05-14 14:55:03 +02:00
|
|
|
// WARNING: following statement assumes number of staff lines to be correctly set
|
2014-05-16 10:32:35 +02:00
|
|
|
// must read <StaffType> before reading the <barLineSpan>
|
2012-12-10 12:56:54 +01:00
|
|
|
int defaultSpan = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0);
|
2014-12-18 13:21:29 +01:00
|
|
|
_barLineFrom = e.intAttribute("from", defaultSpan);
|
|
|
|
|
2013-05-14 14:55:03 +02:00
|
|
|
// the proper default SpanTo depends upon the barLineSpan
|
|
|
|
// as we do not know it yet, set a generic (UNKNOWN) default
|
|
|
|
defaultSpan = UNKNOWN_BARLINE_TO;
|
|
|
|
_barLineTo = e.intAttribute("to", defaultSpan);
|
2014-12-18 13:21:29 +01:00
|
|
|
|
2013-05-14 14:55:03 +02:00
|
|
|
// ready to read the main value...
|
|
|
|
_barLineSpan = e.readInt();
|
2014-12-18 13:21:29 +01:00
|
|
|
|
2013-05-14 14:55:03 +02:00
|
|
|
//...and to adjust the SpanTo value if the source did not provide an explicit value
|
2012-10-20 20:32:40 +02:00
|
|
|
// if no bar line or single staff span, set _barLineTo to this staff height
|
2013-05-14 14:55:03 +02:00
|
|
|
// if span to another staff (yet to be read), leave as unknown
|
2012-10-20 20:32:40 +02:00
|
|
|
// (Score::read() will retrieve the correct height of the target staff)
|
2013-05-14 14:55:03 +02:00
|
|
|
if (_barLineTo == UNKNOWN_BARLINE_TO && _barLineSpan <= 1)
|
|
|
|
_barLineTo = lines() == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (lines() - 1) * 2;
|
2012-10-14 00:35:11 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "distOffset")
|
2016-02-12 06:10:26 +01:00
|
|
|
_userDist = e.readDouble() * score()->spatium();
|
2015-01-15 14:50:50 +01:00
|
|
|
else if (tag == "mag")
|
|
|
|
_userMag = e.readDouble(0.1, 10.0);
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "linkedTo") {
|
2013-01-11 18:10:18 +01:00
|
|
|
int v = e.readInt() - 1;
|
2012-05-26 14:26:10 +02:00
|
|
|
//
|
|
|
|
// if this is an excerpt, link staff to parentScore()
|
|
|
|
//
|
|
|
|
if (score()->parentScore()) {
|
2012-09-03 21:15:38 +02:00
|
|
|
Staff* st = score()->parentScore()->staff(v);
|
|
|
|
if (st)
|
|
|
|
linkTo(st);
|
|
|
|
else {
|
2012-09-20 11:35:34 +02:00
|
|
|
qDebug("staff %d not found in parent", v);
|
2012-09-03 21:15:38 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
int idx = score()->staffIdx(this);
|
2013-07-01 15:15:14 +02:00
|
|
|
if (v >= 0 && v < idx)
|
2012-05-26 14:26:10 +02:00
|
|
|
linkTo(score()->staff(v));
|
|
|
|
}
|
|
|
|
}
|
2013-10-26 13:47:05 +02:00
|
|
|
else if (tag == "color")
|
|
|
|
_color = e.readColor();
|
2014-05-05 15:38:40 +02:00
|
|
|
else if (tag == "transposeDiatonic")
|
|
|
|
e.setTransposeDiatonic(e.readInt());
|
|
|
|
else if (tag == "transposeChromatic")
|
|
|
|
e.setTransposeChromatic(e.readInt());
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// height
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Staff::height() const
|
|
|
|
{
|
2014-06-19 15:27:44 +02:00
|
|
|
return (lines() == 1 ? 2 : lines()-1) * spatium() * _staffType.lineDistance().val();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// spatium
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Staff::spatium() const
|
|
|
|
{
|
|
|
|
return _score->spatium() * mag();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// mag
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Staff::mag() const
|
|
|
|
{
|
2014-08-14 16:52:58 +02:00
|
|
|
return (_small ? score()->styleD(StyleIdx::smallStaffMag) : 1.0) * userMag();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2014-07-24 20:09:49 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// swing
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
SwingParameters Staff::swing(int tick) const
|
|
|
|
{
|
|
|
|
SwingParameters sp;
|
2014-12-18 20:41:15 +01:00
|
|
|
int swingUnit = 0;
|
2014-07-24 20:09:49 +02:00
|
|
|
QString unit = score()->styleSt(StyleIdx::swingUnit);
|
|
|
|
int swingRatio = score()->styleI(StyleIdx::swingRatio);
|
2014-08-15 18:32:48 +02:00
|
|
|
if (unit == TDuration(TDuration::DurationType::V_EIGHTH).name()) {
|
2014-07-24 20:09:49 +02:00
|
|
|
swingUnit = MScore::division / 2;
|
|
|
|
}
|
|
|
|
else if (unit == TDuration(TDuration::DurationType::V_16TH).name())
|
|
|
|
swingUnit = MScore::division / 4;
|
|
|
|
else if (unit == TDuration(TDuration::DurationType::V_ZERO).name())
|
|
|
|
swingUnit = 0;
|
|
|
|
sp.swingRatio = swingRatio;
|
|
|
|
sp.swingUnit = swingUnit;
|
2016-02-06 22:03:43 +01:00
|
|
|
if (_swingList.empty())
|
2014-07-24 20:09:49 +02:00
|
|
|
return sp;
|
|
|
|
QMap<int, SwingParameters>::const_iterator i = _swingList.upperBound(tick);
|
|
|
|
if (i == _swingList.begin())
|
|
|
|
return sp;
|
|
|
|
--i;
|
|
|
|
return i.value();
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// channel
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::channel(int tick, int voice) const
|
|
|
|
{
|
2016-02-06 22:03:43 +01:00
|
|
|
if (_channelList[voice].empty())
|
2012-05-26 14:26:10 +02:00
|
|
|
return 0;
|
2014-02-01 22:17:20 +01:00
|
|
|
QMap<int, int>::const_iterator i = _channelList[voice].upperBound(tick);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (i == _channelList[voice].begin())
|
2014-02-01 22:17:20 +01:00
|
|
|
return 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
--i;
|
|
|
|
return i.value();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// lines
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::lines() const
|
|
|
|
{
|
2014-04-28 18:38:50 +02:00
|
|
|
return _staffType.lines();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setLines
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::setLines(int val)
|
|
|
|
{
|
|
|
|
if (val == lines())
|
|
|
|
return;
|
2014-04-28 18:38:50 +02:00
|
|
|
_staffType.setLines(val); // TODO: make undoable
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-10-14 00:35:11 +02:00
|
|
|
//---------------------------------------------------------
|
2015-06-13 17:57:57 +02:00
|
|
|
// lineDistance
|
2015-09-01 06:19:20 +02:00
|
|
|
// distance between staff lines
|
2012-10-14 00:35:11 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Staff::lineDistance() const
|
|
|
|
{
|
2014-04-28 18:38:50 +02:00
|
|
|
return _staffType.lineDistance().val();
|
2012-10-14 00:35:11 +02:00
|
|
|
}
|
|
|
|
|
2015-09-01 06:19:20 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// logicalLineDistance
|
|
|
|
// distance between logical (note) lines
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Staff::logicalLineDistance() const
|
|
|
|
{
|
|
|
|
return scaleNotesToLines() ? _staffType.lineDistance().val() : 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// scaleNotesToLines
|
|
|
|
// returns true if logical line = physical line
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Staff::scaleNotesToLines() const
|
|
|
|
{
|
|
|
|
// TODO: make style option
|
2015-09-01 20:18:28 +02:00
|
|
|
return !isDrumStaff();
|
2015-09-01 06:19:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// middleLine
|
|
|
|
// returns logical line number of middle staff line
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::middleLine() const
|
|
|
|
{
|
|
|
|
int line = lines() - 1;
|
2015-09-01 20:18:28 +02:00
|
|
|
if (scaleNotesToLines())
|
2015-09-01 06:19:20 +02:00
|
|
|
return line;
|
|
|
|
else
|
|
|
|
return line * lineDistance() / logicalLineDistance();
|
|
|
|
//return isTabStaff() ? line : line * lineDistance() / logicalLineDistance();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// bottomLine
|
|
|
|
// returns logical line number of bottom staff line
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::bottomLine() const
|
|
|
|
{
|
|
|
|
int line = (lines() - 1) * 2;
|
2015-09-01 20:18:28 +02:00
|
|
|
if (scaleNotesToLines())
|
2015-09-01 06:19:20 +02:00
|
|
|
return line;
|
|
|
|
else
|
|
|
|
return line * lineDistance() / logicalLineDistance();
|
|
|
|
//return isTabStaff() ? line : line * lineDistance() / logicalLineDistance();
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// slashStyle
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Staff::slashStyle() const
|
|
|
|
{
|
2014-04-28 18:38:50 +02:00
|
|
|
return _staffType.slashStyle();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setSlashStyle
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::setSlashStyle(bool val)
|
|
|
|
{
|
2014-04-28 18:38:50 +02:00
|
|
|
_staffType.setSlashStyle(val);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// linkTo
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::linkTo(Staff* staff)
|
|
|
|
{
|
|
|
|
if (!_linkedStaves) {
|
|
|
|
if (staff->linkedStaves()) {
|
|
|
|
_linkedStaves = staff->linkedStaves();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_linkedStaves = new LinkedStaves;
|
|
|
|
_linkedStaves->add(staff);
|
|
|
|
staff->setLinkedStaves(_linkedStaves);
|
|
|
|
}
|
|
|
|
_linkedStaves->add(this);
|
|
|
|
}
|
|
|
|
else {
|
2013-07-16 18:16:16 +02:00
|
|
|
_linkedStaves->add(staff);
|
2014-05-22 16:18:35 +02:00
|
|
|
if (!staff->linkedStaves())
|
|
|
|
staff->_linkedStaves = _linkedStaves;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 16:21:39 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// unlink
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::unlink(Staff* staff)
|
|
|
|
{
|
2014-08-11 15:25:55 +02:00
|
|
|
if (!_linkedStaves)
|
|
|
|
return;
|
2016-03-17 13:42:52 +01:00
|
|
|
if (!_linkedStaves->staves().contains(staff))
|
|
|
|
return;
|
2014-08-01 16:21:39 +02:00
|
|
|
_linkedStaves->remove(staff);
|
2014-08-07 19:39:18 +02:00
|
|
|
if (_linkedStaves->staves().size() <= 1) {
|
|
|
|
delete _linkedStaves;
|
|
|
|
_linkedStaves = 0;
|
|
|
|
}
|
|
|
|
staff->_linkedStaves = 0;
|
2014-08-01 16:21:39 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// add
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void LinkedStaves::add(Staff* staff)
|
|
|
|
{
|
2016-02-19 13:47:21 +01:00
|
|
|
if (!_staves.contains(staff))
|
|
|
|
_staves.append(staff);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void LinkedStaves::remove(Staff* staff)
|
|
|
|
{
|
|
|
|
_staves.removeOne(staff);
|
|
|
|
}
|
|
|
|
|
2013-10-10 15:41:25 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// isLinked
|
|
|
|
/// return true if staff is different and
|
|
|
|
/// linked to this staff
|
|
|
|
//---------------------------------------------------------
|
2014-04-24 15:03:03 +02:00
|
|
|
|
2013-10-10 15:41:25 +02:00
|
|
|
bool Staff::isLinked(Staff* staff)
|
|
|
|
{
|
|
|
|
if (staff == this || !_linkedStaves)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for(Staff* s : _linkedStaves->staves()) {
|
|
|
|
if(s == staff)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// primaryStaff
|
|
|
|
/// if there are linked staves, the primary staff is
|
2015-06-22 17:59:08 +02:00
|
|
|
/// the one who is played back and it's not a tab staff
|
|
|
|
/// because we don't have enough information to play
|
|
|
|
/// e.g ornaments. NOTE: it's not necessarily the top staff!
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Staff::primaryStaff() const
|
|
|
|
{
|
|
|
|
if (!_linkedStaves)
|
|
|
|
return true;
|
2015-06-22 18:19:05 +02:00
|
|
|
QList<Staff*> s;
|
|
|
|
QList<Staff*> ss;
|
2012-05-26 14:26:10 +02:00
|
|
|
foreach(Staff* staff, _linkedStaves->staves()) {
|
2015-06-22 18:19:05 +02:00
|
|
|
if (staff->score() == score()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
s.append(staff);
|
2015-06-22 18:19:05 +02:00
|
|
|
if (!staff->isTabStaff())
|
|
|
|
ss.append(staff);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2015-06-22 18:19:05 +02:00
|
|
|
if (s.size() == 1) // the linked staves are in different scores
|
|
|
|
return s.front() == this;
|
|
|
|
else // return a non tab linked staff in this score
|
|
|
|
return ss.front() == this;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setStaffType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-04-28 18:38:50 +02:00
|
|
|
void Staff::setStaffType(const StaffType* st)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-03 11:33:47 +02:00
|
|
|
if (_staffType == *st)
|
|
|
|
return;
|
2012-11-05 20:31:57 +01:00
|
|
|
int linesOld = lines();
|
|
|
|
int linesNew = st->lines();
|
2014-04-28 18:38:50 +02:00
|
|
|
_staffType = *st;
|
|
|
|
|
2012-12-10 12:56:54 +01:00
|
|
|
if (linesNew != linesOld) {
|
2012-11-05 20:31:57 +01:00
|
|
|
int sIdx = score()->staffIdx(this);
|
2012-12-10 12:56:54 +01:00
|
|
|
if (sIdx < 0) { // staff does not belong to score (yet?)
|
|
|
|
if (linesNew == 1) { // 1-line staves have special bar lines
|
|
|
|
_barLineFrom = BARLINE_SPAN_1LINESTAFF_FROM;
|
|
|
|
_barLineTo = BARLINE_SPAN_1LINESTAFF_TO;
|
|
|
|
}
|
|
|
|
else { // set default barLineFrom/to (from first to last staff line)
|
|
|
|
_barLineFrom = 0;
|
|
|
|
_barLineTo = (linesNew-1)*2;
|
|
|
|
}
|
2012-11-05 20:31:57 +01:00
|
|
|
}
|
|
|
|
else // update barLineFrom/To in whole score context
|
|
|
|
score()->updateBarLineSpans(sIdx, linesOld, linesNew /*, true*/);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// init
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-03-25 20:39:24 +01:00
|
|
|
void Staff::init(const InstrumentTemplate* t, const StaffType* staffType, int cidx)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
// set staff-type-independent parameters
|
|
|
|
if (cidx > MAX_STAVES) {
|
|
|
|
setSmall(false);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setSmall(t->smallStaff[cidx]);
|
|
|
|
setBracket(0, t->bracket[cidx]);
|
|
|
|
setBracketSpan(0, t->bracketSpan[cidx]);
|
|
|
|
setBarLineSpan(t->barlineSpan[cidx]);
|
|
|
|
}
|
2014-04-30 10:08:38 +02:00
|
|
|
const StaffType* pst = staffType ? staffType : t->staffTypePreset;
|
|
|
|
if (!pst)
|
|
|
|
pst = StaffType::getDefaultPreset(t->staffGroup);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-04-30 10:08:38 +02:00
|
|
|
setStaffType(pst);
|
2014-08-16 11:21:56 +02:00
|
|
|
setDefaultClefType(t->clefType(cidx));
|
2015-03-03 17:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// init
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::init(const Staff* s)
|
|
|
|
{
|
|
|
|
setStaffType(s->staffType());
|
|
|
|
setDefaultClefType(s->defaultClefType());
|
|
|
|
setSmall(s->small());
|
2015-03-04 16:38:34 +01:00
|
|
|
_brackets = s->_brackets;
|
|
|
|
_barLineSpan = s->_barLineSpan;
|
|
|
|
_barLineFrom = s->_barLineFrom;
|
|
|
|
_barLineTo = s->_barLineTo;
|
|
|
|
_invisible = s->_invisible;
|
2015-08-04 19:53:54 +02:00
|
|
|
_hideWhenEmpty = s->_hideWhenEmpty;
|
|
|
|
_cutaway = s->_cutaway;
|
2015-03-04 16:38:34 +01:00
|
|
|
_showIfEmpty = s->_showIfEmpty;
|
|
|
|
_hideSystemBarLine = s->_hideSystemBarLine;
|
|
|
|
_color = s->_color;
|
|
|
|
_userDist = s->_userDist;
|
|
|
|
_userMag = s->_userMag;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-04-05 15:52:35 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// initFromStaffType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::initFromStaffType(const StaffType* staffType)
|
|
|
|
{
|
|
|
|
// get staff type if given (if none, get default preset for default staff group)
|
2014-04-30 10:08:38 +02:00
|
|
|
if (!staffType)
|
2014-05-27 13:30:23 +02:00
|
|
|
staffType = StaffType::getDefaultPreset(StaffGroup::STANDARD);
|
2013-04-05 15:52:35 +02:00
|
|
|
|
|
|
|
// use selected staff type
|
2014-04-28 18:38:50 +02:00
|
|
|
setStaffType(staffType);
|
2013-04-05 15:52:35 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// spatiumChanged
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::spatiumChanged(qreal oldValue, qreal newValue)
|
|
|
|
{
|
|
|
|
_userDist = (_userDist / oldValue) * newValue;
|
|
|
|
}
|
|
|
|
|
2012-08-01 22:15:58 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// show
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Staff::show() const
|
|
|
|
{
|
|
|
|
return _part->show();
|
|
|
|
}
|
|
|
|
|
2013-07-16 09:03:47 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// genKeySig
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-06-22 10:55:22 +02:00
|
|
|
bool Staff::genKeySig()
|
|
|
|
{
|
2014-05-27 13:30:23 +02:00
|
|
|
if (_staffType.group() == StaffGroup::TAB)
|
2014-04-28 18:38:50 +02:00
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return _staffType.genKeysig();
|
2013-06-22 10:55:22 +02:00
|
|
|
}
|
|
|
|
|
2013-07-16 09:03:47 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// showLedgerLines
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-06-22 10:55:22 +02:00
|
|
|
bool Staff::showLedgerLines()
|
|
|
|
{
|
TAB: Support for input and display of bass string notations
Supports 'standard' configuration for bass string notations in historic tablatures (lutes and other plucked instruments, as well as viols), both of the French and of the Italian style. This should fill the last 'big hole' in historic TAB support.
Bass strings (or bourdons) are extra strings in addition to the 6 'standard' strings, which are not represented by tab lines and were indicated by other typograhic devices in historic sources. Among the innumerable variations shown in sources, this implementation supports the following styles, chosen to be general enough to suit the majority of cases, without requiring new parameters in the TAB style dialogue box:
- French: the first 4 bass courses are indicated by a fret mark in the 'seventh' TAB position (below bottom string) with 0, 1, 2 or 3 slashes prefixed; other bass courses are indicated, also in the 'seventh' TAB position, by the string number (from 4 on) and cannot contain a fret mark (as they didn't in historic sources).
- Italian: the first 2 bass courses are indicated by a fret mark in the 'seventh' TAB position (abover top string) with 1 or 2 'ledger lines' underneath; other bass courses are indicated, also in the 'seventh' TAB position, by the string number (from 9 on) and cannot contain a fret mark (as they didn't in historic sources). Rhythm marks above these indication are raised to leave room for them.
Both styles do not blindly assume that French style is top-to-bottom and Italian is 'upside-down' -- as historic sources are -- but adapt to the actual string order of the TAB. The choice between the two styles depends on the TAB using numbers or letters for the fret marks.
The implementation does not try to detect if the TAB is really of a historic style and applies either bass string notation whenever more strings are used than there are TAB lines. If this proves unsuitable to modern usage, some better heuristics can probably be found.
For a discussion and some screen shots, see: https://musescore.org/en/node/67261
**Note entry**
During TAB note entry, if the instruments has more strings than the TAB has lines, the string cursor can be moved outside of the TAB body, one position below for 'top-to-bottom' TAB's and one position above for 'upside-down' TAB's.
Further up or down movements add, to the 'blue cursor rectangle', markers indicating which is the actual target string (the cursor does not actually move), equal to the marks a note in that string will receive (slashes, ledger lines or string ordinal, according to the style and the string); during input the user will then receive the same info as when reading entered notes.
Other Notes:
- the `InputStatus::_string` variable, holding the current target TAB string in TAB note entry, changed meaning from the __visual__ string index to the __physical__ string index: this allows a better containment of the peculiarities of the individual TAB styles within the `StaffStyle` class, leaving other classes somehow freer of concern about TAB visual order and other peculiarities. As this variable is only used with TAB's, this change should not affect other functions.
- Some calculation for rhythm symbols have been moved from `TabDurationSymbol::draw()` to `TabDurationSymbol::layout()`, hopefully speeding up the drawing process.
- In fonts for historic styles, '10' has been replaced by 'X' both in fret numbers and in string ordinals, as this is more common in historic sources. Currently, this is not configurable; an additional style parameter could be added in future, if there will be enough request for it.
2015-07-06 17:40:02 +02:00
|
|
|
return _staffType.showLedgerLines();
|
2013-06-22 10:55:22 +02:00
|
|
|
}
|
|
|
|
|
2013-07-16 09:03:47 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateOttava
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-07-15 12:49:51 +02:00
|
|
|
void Staff::updateOttava()
|
|
|
|
{
|
|
|
|
int staffIdx = idx();
|
|
|
|
_pitchOffsets.clear();
|
|
|
|
for (auto i : score()->spanner()) {
|
|
|
|
const Spanner* s = i.second;
|
|
|
|
if (s->type() == Element::Type::OTTAVA && s->staffIdx() == staffIdx) {
|
|
|
|
const Ottava* o = static_cast<const Ottava*>(s);
|
|
|
|
_pitchOffsets.setPitchOffset(o->tick(), o->pitchShift());
|
|
|
|
_pitchOffsets.setPitchOffset(o->tick2(), 0);
|
|
|
|
}
|
|
|
|
}
|
2013-07-16 09:03:47 +02:00
|
|
|
}
|
2013-10-26 13:47:05 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetColor
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-01-15 22:05:05 +01:00
|
|
|
void Staff::undoSetColor(const QColor& /*val*/)
|
2013-10-26 13:47:05 +02:00
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
// score()->undoChangeProperty(this, P_ID::COLOR, val);
|
2013-10-26 13:47:05 +02:00
|
|
|
}
|
|
|
|
|
2014-05-08 17:59:24 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// insertTime
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::insertTime(int tick, int len)
|
|
|
|
{
|
2015-02-17 21:12:19 +01:00
|
|
|
if (len == 0)
|
|
|
|
return;
|
2015-02-14 16:24:29 +01:00
|
|
|
|
2015-03-09 18:31:28 +01:00
|
|
|
// move all keys and clefs >= tick
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
// remove entries between tickpos >= tick and tickpos < (tick+len)
|
|
|
|
_keys.erase(_keys.lower_bound(tick), _keys.lower_bound(tick-len));
|
|
|
|
clefs.erase(clefs.lower_bound(tick), clefs.lower_bound(tick-len));
|
|
|
|
}
|
2014-12-08 18:02:17 +01:00
|
|
|
|
2014-05-08 17:59:24 +02:00
|
|
|
KeyList kl2;
|
2015-03-09 18:31:28 +01:00
|
|
|
for (auto i = _keys.lower_bound(tick); i != _keys.end();) {
|
2014-12-08 18:02:17 +01:00
|
|
|
KeySigEvent kse = i->second;
|
2015-03-09 18:31:28 +01:00
|
|
|
int tick = i->first;
|
2014-06-03 15:28:10 +02:00
|
|
|
_keys.erase(i++);
|
2015-03-09 18:31:28 +01:00
|
|
|
kl2[tick + len] = kse;
|
2014-05-08 17:59:24 +02:00
|
|
|
}
|
2014-06-03 15:28:10 +02:00
|
|
|
_keys.insert(kl2.begin(), kl2.end());
|
2014-05-08 17:59:24 +02:00
|
|
|
|
2015-06-26 11:55:44 +02:00
|
|
|
// check if there is a clef at the end of measure
|
|
|
|
// before tick
|
|
|
|
Clef* clef = 0;
|
|
|
|
Measure* m = _score->tick2measure(tick);
|
|
|
|
if (m && (m->tick() == tick) && (m->prevMeasure())) {
|
|
|
|
m = m->prevMeasure();
|
|
|
|
Segment* s = m->findSegment(Segment::Type::Clef, tick);
|
|
|
|
if (s) {
|
|
|
|
int track = idx() * VOICES;
|
|
|
|
clef = static_cast<Clef*>(s->element(track));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-08 17:59:24 +02:00
|
|
|
ClefList cl2;
|
2015-03-09 18:31:28 +01:00
|
|
|
for (auto i = clefs.lower_bound(tick); i != clefs.end();) {
|
2014-05-08 17:59:24 +02:00
|
|
|
ClefTypeList ctl = i->second;
|
2015-06-26 11:55:44 +02:00
|
|
|
int t = i->first;
|
|
|
|
if (clef && tick == t) {
|
|
|
|
++i;
|
|
|
|
continue;
|
|
|
|
}
|
2014-05-08 17:59:24 +02:00
|
|
|
clefs.erase(i++);
|
2015-06-26 11:55:44 +02:00
|
|
|
cl2.setClef(t + len, ctl);
|
2014-05-08 17:59:24 +02:00
|
|
|
}
|
|
|
|
clefs.insert(cl2.begin(), cl2.end());
|
2015-06-09 17:20:17 +02:00
|
|
|
|
|
|
|
// check if there is a clef at the end of measure
|
|
|
|
// before tick: do not remove from clefs list
|
|
|
|
|
2015-06-26 11:55:44 +02:00
|
|
|
if (clef)
|
|
|
|
setClef(clef);
|
2015-06-09 17:20:17 +02:00
|
|
|
|
2015-02-21 16:07:37 +01:00
|
|
|
updateOttava();
|
2015-06-26 11:55:44 +02:00
|
|
|
DUMP_CLEFS(" insertTime");
|
2014-05-08 17:59:24 +02:00
|
|
|
}
|
|
|
|
|
2014-05-21 20:08:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// staffList
|
|
|
|
// return list of linked staves
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QList<Staff*> Staff::staffList() const
|
|
|
|
{
|
|
|
|
QList<Staff*> staffList;
|
|
|
|
if (_linkedStaves)
|
|
|
|
staffList = _linkedStaves->staves();
|
|
|
|
else
|
|
|
|
staffList.append(const_cast<Staff*>(this));
|
|
|
|
return staffList;
|
|
|
|
}
|
|
|
|
|
2014-08-05 16:09:14 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setBarLineTo
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::setBarLineTo(int val)
|
|
|
|
{
|
|
|
|
_barLineTo = val;
|
|
|
|
}
|
|
|
|
|
2014-08-11 15:25:55 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// rstaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Staff::rstaff() const
|
|
|
|
{
|
|
|
|
return _part->staves()->indexOf((Staff*)this, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// isTop
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Staff::isTop() const
|
|
|
|
{
|
|
|
|
return _part->staves()->front() == this;
|
|
|
|
}
|
2014-12-22 13:28:09 +01:00
|
|
|
|
2015-02-04 22:12:13 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// getProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Staff::getProperty(P_ID id) const
|
|
|
|
{
|
|
|
|
switch (id) {
|
|
|
|
case P_ID::MAG:
|
|
|
|
return userMag();
|
|
|
|
case P_ID::COLOR:
|
|
|
|
return color();
|
2015-02-20 11:56:13 +01:00
|
|
|
case P_ID::SMALL:
|
|
|
|
return small();
|
2015-02-04 22:12:13 +01:00
|
|
|
default:
|
2015-10-01 15:03:32 +02:00
|
|
|
qDebug("Staff::getProperty: unhandled id");
|
2015-02-04 22:12:13 +01:00
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Staff::setProperty(P_ID id, const QVariant& v)
|
|
|
|
{
|
|
|
|
switch (id) {
|
2015-02-20 11:56:13 +01:00
|
|
|
case P_ID::MAG: {
|
|
|
|
double oldVal = mag();
|
2015-02-04 22:12:13 +01:00
|
|
|
setUserMag(v.toDouble());
|
2015-02-20 11:56:13 +01:00
|
|
|
scaleChanged(oldVal, mag());
|
|
|
|
}
|
2015-02-04 22:12:13 +01:00
|
|
|
break;
|
|
|
|
case P_ID::COLOR:
|
|
|
|
setColor(v.value<QColor>());
|
|
|
|
break;
|
2015-02-20 11:56:13 +01:00
|
|
|
case P_ID::SMALL: {
|
|
|
|
double oldVal = mag();
|
|
|
|
setSmall(v.toBool());
|
|
|
|
scaleChanged(oldVal, mag());
|
|
|
|
}
|
|
|
|
break;
|
2015-02-04 22:12:13 +01:00
|
|
|
default:
|
|
|
|
qDebug("Staff::setProperty: unhandled id");
|
|
|
|
break;
|
|
|
|
}
|
2016-03-02 13:20:19 +01:00
|
|
|
score()->setLayoutAll();
|
2015-02-04 22:12:13 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// propertyDefault
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Staff::propertyDefault(P_ID id) const
|
|
|
|
{
|
|
|
|
switch (id) {
|
|
|
|
case P_ID::MAG:
|
|
|
|
return 1.0;
|
|
|
|
case P_ID::COLOR:
|
|
|
|
return QColor(Qt::black);
|
2015-02-20 11:56:13 +01:00
|
|
|
case P_ID::SMALL:
|
|
|
|
return false;
|
2015-02-04 22:12:13 +01:00
|
|
|
default:
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
}
|
2015-02-20 11:56:13 +01:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// scaleChanged
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Staff::scaleChanged(double oldVal, double newVal)
|
|
|
|
{
|
|
|
|
int staffIdx = idx();
|
|
|
|
int startTrack = staffIdx * VOICES;
|
|
|
|
int endTrack = startTrack + VOICES;
|
|
|
|
for (Segment* s = score()->firstSegment(); s; s = s->next1()) {
|
|
|
|
for (Element* e : s->annotations())
|
|
|
|
e->localSpatiumChanged(oldVal, newVal);
|
|
|
|
for (int track = startTrack; track < endTrack; ++track) {
|
|
|
|
if (s->element(track))
|
|
|
|
s->element(track)->localSpatiumChanged(oldVal, newVal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (auto i : score()->spanner()) {
|
|
|
|
Spanner* spanner = i.second;
|
|
|
|
if (spanner->staffIdx() == staffIdx) {
|
|
|
|
for (auto k : spanner->spannerSegments())
|
|
|
|
k->localSpatiumChanged(oldVal, newVal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|