MuseScore/libmscore/staff.cpp

895 lines
29 KiB
C++
Raw Normal View History

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"
#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"
#include "barline.h"
2013-07-16 09:03:47 +02:00
#include "ottava.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
//---------------------------------------------------------
// idx
//---------------------------------------------------------
int Staff::idx() const
{
return _score->staffIdx(this);
}
//---------------------------------------------------------
// bracket
//---------------------------------------------------------
BracketType Staff::bracket(int idx) const
{
if (idx < _brackets.size())
return _brackets[idx]._bracket;
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;
while (!_brackets.isEmpty() && (_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)
{
if (!_brackets.isEmpty() && _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());
}
}
}
//---------------------------------------------------------
// cleanupBrackets
//---------------------------------------------------------
void Staff::cleanupBrackets()
{
int index = idx();
int n = _score->nstaves();
for (int i = 0; i < _brackets.size(); ++i) {
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) {
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)
{
_score = s;
_rstaff = 0;
_part = 0;
_small = false;
_invisible = false;
_userDist = .0;
_barLineSpan = 1;
2012-10-14 00:35:11 +02:00
_barLineFrom = 0;
_barLineTo = (lines()-1)*2;
2012-07-06 14:21:05 +02:00
_linkedStaves = 0;
_color = MScore::defaultColor;
2012-07-06 14:21:05 +02:00
}
2012-05-26 14:26:10 +02:00
Staff::Staff(Score* s, Part* p, int rs)
{
_score = s;
_rstaff = rs;
_part = p;
_small = false;
_invisible = false;
_userDist = .0;
_barLineSpan = 1;
2012-10-14 09:25:33 +02:00
_barLineFrom = 0;
_barLineTo = (lines()-1)*2;
2012-05-26 14:26:10 +02:00
_linkedStaves = 0;
_color = MScore::defaultColor;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// ~Staff
//---------------------------------------------------------
Staff::~Staff()
{
if (_linkedStaves) {
_linkedStaves->remove(this);
if (_linkedStaves->isEmpty())
delete _linkedStaves;
}
}
//---------------------------------------------------------
// Staff::clefTypeList
//---------------------------------------------------------
ClefTypeList Staff::clefTypeList(int tick) const
{
2013-09-05 16:37:49 +02:00
return clefs.clef(tick);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// Staff::clef
//---------------------------------------------------------
ClefType Staff::clef(int tick) const
{
2014-05-08 17:59:24 +02:00
ClefTypeList c = clefTypeList(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
}
2013-09-05 16:37:49 +02:00
//---------------------------------------------------------
// setClef
//---------------------------------------------------------
void Staff::setClef(int tick, const ClefTypeList& ctl)
{
clefs.setClef(tick, ctl);
}
2014-05-08 17:59:24 +02:00
//---------------------------------------------------------
// undoSetClef
//---------------------------------------------------------
void Staff::undoSetClef(int tick, const ClefTypeList& ctl)
2013-09-05 16:37:49 +02:00
{
2014-05-08 17:59:24 +02:00
score()->undo(new SetClefType(this, tick, ctl));
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
// 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;
return (i == timesigs.end()) ? 0 : i->second;
2012-05-26 14:26:10 +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());
}
Measure* m = score()->tick2measure(tick);
2014-05-03 10:10:46 +02:00
return Groups::endings(m ? m->timesig() : Fraction(4,4));
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// addTimeSig
//---------------------------------------------------------
void Staff::addTimeSig(TimeSig* timesig)
{
2013-05-06 14:20:31 +02:00
timesigs[timesig->segment()->tick()] = timesig;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// removeTimeSig
//---------------------------------------------------------
void Staff::removeTimeSig(TimeSig* timesig)
{
2013-09-05 16:37:49 +02:00
timesigs.erase(timesig->segment()->tick());
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// Staff::key
//
// locates the key sig currently in effect at tick
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
Key Staff::key(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-06-20 17:07:22 +02:00
void Staff::setKey(int tick, Key k)
2014-06-04 10:20:14 +02:00
{
_keys.setKey(tick, k);
// printf("setKey %d %d\n", tick, k);
// for (auto k : _keys)
// printf(" %d - %d\n", k.first, k.second);
}
//---------------------------------------------------------
// removeKey
//---------------------------------------------------------
void Staff::removeKey(int tick)
{
/*int n =*/ _keys.erase(tick);
// Q_ASSERT(n == 1); there are scores with empty KeySig's (type 0)
// printf("remove key %d\n", tick);
// for (auto k : _keys)
// printf(" %d - %d\n", k.first, k.second);
}
2014-06-03 15:28:10 +02:00
//---------------------------------------------------------
// prevkey
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
Key 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
}
//---------------------------------------------------------
// 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);
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// write
//---------------------------------------------------------
void Staff::write(Xml& xml) const
{
int idx = score()->staffIdx(this);
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) {
Interval v = part()->instr(0)->transpose();
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-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());
foreach(const BracketItem& i, _brackets)
xml.tagE("bracket type=\"%d\" span=\"%d\"", i._bracket, i._bracketSpan);
// for economy and consistency, only output "from" and "to" attributes if different from default
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
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();
defaultLineTo = (targetStaffLines == 1 ? BARLINE_SPAN_1LINESTAFF_TO : (targetStaffLines-1) * 2);
}
if (_barLineSpan != 1 || _barLineFrom != defaultLineFrom || _barLineTo != defaultLineTo) {
if(_barLineFrom != defaultLineFrom || _barLineTo != defaultLineTo)
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)
xml.tag("distOffset", _userDist / spatium());
if (color() != Qt::black)
xml.tag("color", 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();
qDebug("Staff::read staffTypeIdx %d", staffTypeIdx);
_staffType = *StaffType::preset(StaffTypes(staffTypeIdx));
// 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);
// 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
}
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());
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") {
// WARNING: following statement assumes number of staff lines to be correctly set
// must read <StaffType> before reading the <barLineSpan>
int defaultSpan = (lines() == 1 ? BARLINE_SPAN_1LINESTAFF_FROM : 0);
_barLineFrom = e.attribute("from", QString::number(defaultSpan)).toInt();
// 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);
// ready to read the main value...
_barLineSpan = e.readInt();
//...and to adjust the SpanTo value if the source did not provide an explicit value
// if no bar line or single staff span, set _barLineTo to this staff height
// if span to another staff (yet to be read), leave as unknown
// (Score::read() will retrieve the correct height of the target staff)
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")
2013-01-11 18:10:18 +01:00
_userDist = e.readDouble() * spatium();
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);
if (v >= 0 && v < idx)
2012-05-26 14:26:10 +02:00
linkTo(score()->staff(v));
}
}
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-05-26 15:31:36 +02:00
return _small ? score()->styleD(StyleIdx::smallStaffMag) : 1.0;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// channel
//---------------------------------------------------------
int Staff::channel(int tick, int voice) const
{
if (_channelList[voice].isEmpty())
return 0;
QMap<int, int>::const_iterator i = _channelList[voice].upperBound(tick);
2012-05-26 14:26:10 +02:00
if (i == _channelList[voice].begin())
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
//---------------------------------------------------------
// line distance
//---------------------------------------------------------
qreal Staff::lineDistance() const
{
2014-04-28 18:38:50 +02:00
return _staffType.lineDistance().val();
2012-10-14 00:35:11 +02:00
}
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
}
}
//---------------------------------------------------------
// add
//---------------------------------------------------------
void LinkedStaves::add(Staff* staff)
{
_staves.append(staff);
}
//---------------------------------------------------------
// remove
//---------------------------------------------------------
void LinkedStaves::remove(Staff* staff)
{
_staves.removeOne(staff);
}
//---------------------------------------------------------
// isLinked
/// return true if staff is different and
/// linked to this staff
//---------------------------------------------------------
2014-04-24 15:03:03 +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
/// the one who is played back
//---------------------------------------------------------
bool Staff::primaryStaff() const
{
QList<Staff*> s;
if (!_linkedStaves)
return true;
foreach(Staff* staff, _linkedStaves->staves()) {
if (staff->score() == score())
s.append(staff);
}
return s.front() == this;
}
//---------------------------------------------------------
// 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;
int linesOld = lines();
int linesNew = st->lines();
2014-04-28 18:38:50 +02:00
_staffType = *st;
if (linesNew != linesOld) {
int sIdx = score()->staffIdx(this);
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;
}
}
else // update barLineFrom/To in whole score context
score()->updateBarLineSpans(sIdx, linesOld, linesNew /*, true*/);
}
2012-05-26 14:26:10 +02:00
//
// check for right clef-type and fix
// if necessary
//
ClefType ct = clef(0);
2013-09-05 16:37:49 +02:00
StaffGroup csg = ClefInfo::staffGroup(ct);
2012-05-26 14:26:10 +02:00
2014-04-28 18:38:50 +02:00
if (_staffType.group() != csg) {
switch(_staffType.group()) {
case StaffGroup::TAB: ct = ClefType(score()->styleI(StyleIdx::tabClef)); break;
case StaffGroup::STANDARD: ct = ClefType::G; break; // TODO: use preferred clef for instrument
case StaffGroup::PERCUSSION: ct = ClefType::PERC; break;
2012-05-26 14:26:10 +02:00
}
2013-09-05 16:37:49 +02:00
clefs.setClef(0, ClefTypeList(ct, ct));
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
// init
//---------------------------------------------------------
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);
2013-09-05 16:37:49 +02:00
clefs.setClef(0, t->clefTypes[0]);
2012-05-26 14:26:10 +02:00
}
else {
setSmall(t->smallStaff[cidx]);
2013-09-05 16:37:49 +02:00
clefs.setClef(0, t->clefTypes[cidx]); // initial clef will be fixed to staff-type clef by setStaffType()
2012-05-26 14:26:10 +02:00
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-05-24 17:03:30 +02:00
// if (pst->group() == ArticulationShowIn::PITCHED_STAFF) // if PITCHED (in other staff groups num of lines is determined by style)
// setLines(t->staffLines[cidx]); // use number of lines from instr. template
2012-05-26 14:26:10 +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)
staffType = StaffType::getDefaultPreset(StaffGroup::STANDARD);
// use selected staff type
2014-04-28 18:38:50 +02:00
setStaffType(staffType);
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// spatiumChanged
//---------------------------------------------------------
void Staff::spatiumChanged(qreal oldValue, qreal newValue)
{
_userDist = (_userDist / oldValue) * newValue;
}
//---------------------------------------------------------
// show
//---------------------------------------------------------
bool Staff::show() const
{
return _part->show();
}
2013-07-16 09:03:47 +02:00
//---------------------------------------------------------
// genKeySig
//---------------------------------------------------------
bool Staff::genKeySig()
{
if (_staffType.group() == StaffGroup::TAB)
2014-04-28 18:38:50 +02:00
return false;
else
return _staffType.genKeysig();
}
2013-07-16 09:03:47 +02:00
//---------------------------------------------------------
// showLedgerLines
//---------------------------------------------------------
bool Staff::showLedgerLines()
{
if (_staffType.group() == StaffGroup::TAB)
2014-05-08 17:59:24 +02:00
return false;
2014-04-28 18:38:50 +02:00
else
return _staffType.showLedgerLines();
}
2013-07-16 09:03:47 +02:00
//---------------------------------------------------------
// updateOttava
//---------------------------------------------------------
void Staff::updateOttava(Ottava* o)
{
_pitchOffsets.setPitchOffset(o->tick(), o->pitchShift());
_pitchOffsets.setPitchOffset(o->tick2(), 0);
2013-07-16 09:03:47 +02:00
}
//---------------------------------------------------------
// undoSetColor
//---------------------------------------------------------
2014-01-15 22:05:05 +01:00
void Staff::undoSetColor(const QColor& /*val*/)
{
2014-05-26 18:18:01 +02:00
// score()->undoChangeProperty(this, P_ID::COLOR, val);
}
2014-05-08 17:59:24 +02:00
//---------------------------------------------------------
// insertTime
//---------------------------------------------------------
void Staff::insertTime(int tick, int len)
{
KeyList kl2;
2014-06-03 15:28:10 +02:00
for (auto i = _keys.upper_bound(tick); i != _keys.end();) {
2014-06-20 17:07:22 +02:00
Key kse = i->second;
int k = i->first;
2014-06-03 15:28:10 +02:00
_keys.erase(i++);
2014-06-20 17:07:22 +02:00
kl2[k + 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
ClefList cl2;
for (auto i = clefs.upper_bound(tick); i != clefs.end();) {
ClefTypeList ctl = i->second;
int key = i->first;
clefs.erase(i++);
cl2.setClef(key + len, ctl);
}
clefs.insert(cl2.begin(), cl2.end());
}
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-06-03 15:28:10 +02:00
//---------------------------------------------------------
// updateKeys
// the keys list can be reconstructed from actual keys
//---------------------------------------------------------
void Staff::updateKeys()
{
int track = idx() * VOICES;
_keys.clear();
for (Measure* m = score()->firstMeasure(); m; m = m->nextMeasure()) {
for (Segment* s = m->first(Segment::Type::KeySig); s; s = s->next(Segment::Type::KeySig)) {
2014-06-03 15:28:10 +02:00
KeySig* ks = static_cast<KeySig*>(s->element(track));
if (ks == 0 || ks->generated())
continue;
setKey(s->tick(), ks->key());
}
}
}
2013-05-13 18:49:17 +02:00
}