MuseScore/libmscore/staff.cpp

1442 lines
45 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"
#include "harmony.h"
2017-03-31 13:03:15 +02:00
#include "bracketItem.h"
2012-05-26 14:26:10 +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
{
2016-09-28 21:13:05 +02:00
return score()->staves().indexOf((Staff*)this, 0);
2012-05-26 14:26:10 +02:00
}
2017-03-31 13:03:15 +02:00
//---------------------------------------------------------
// fillBrackets
// make sure index idx is valid
//---------------------------------------------------------
void Staff::fillBrackets(int idx)
{
for (int i = _brackets.size(); i <= idx; ++i) {
BracketItem* bi = new BracketItem(score());
bi->setStaff(this);
_brackets.append(bi);
}
}
//---------------------------------------------------------
// cleanBrackets
// remove NO_BRACKET entries from the end of list
//---------------------------------------------------------
void Staff::cleanBrackets()
{
while (!_brackets.empty() && (_brackets.last()->bracketType() == BracketType::NO_BRACKET))
delete _brackets.takeLast();
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// bracket
//---------------------------------------------------------
2017-03-31 13:03:15 +02:00
BracketType Staff::bracketType(int idx) const
2012-05-26 14:26:10 +02:00
{
if (idx < _brackets.size())
2017-03-31 13:03:15 +02:00
return _brackets[idx]->bracketType();
return BracketType::NO_BRACKET;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// bracketSpan
//---------------------------------------------------------
int Staff::bracketSpan(int idx) const
{
if (idx < _brackets.size())
2017-03-31 13:03:15 +02:00
return _brackets[idx]->bracketSpan();
2012-05-26 14:26:10 +02:00
return 0;
}
//---------------------------------------------------------
// setBracket
//---------------------------------------------------------
2017-03-31 13:03:15 +02:00
void Staff::setBracketType(int idx, BracketType val)
2012-05-26 14:26:10 +02:00
{
2017-03-31 13:03:15 +02:00
fillBrackets(idx);
_brackets[idx]->setBracketType(val);
cleanBrackets();
2012-05-26 14:26:10 +02:00
}
2016-12-29 19:46:40 +01:00
//---------------------------------------------------------
// swapBracket
//---------------------------------------------------------
2017-01-05 11:23:47 +01:00
void Staff::swapBracket(int oldIdx, int newIdx)
2016-12-29 19:46:40 +01:00
{
2017-03-31 13:03:15 +02:00
int idx = qMax(oldIdx, newIdx);
fillBrackets(idx);
2016-12-29 19:46:40 +01:00
_brackets.swap(oldIdx, newIdx);
2017-03-31 13:03:15 +02:00
cleanBrackets();
2016-12-29 19:46:40 +01:00
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// setBracketSpan
//---------------------------------------------------------
void Staff::setBracketSpan(int idx, int val)
{
2012-10-12 15:36:57 +02:00
Q_ASSERT(idx >= 0);
Q_ASSERT(val >= 0);
2017-03-31 13:03:15 +02:00
fillBrackets(idx);
_brackets[idx]->setBracketSpan(val);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// addBracket
//---------------------------------------------------------
2017-03-31 13:03:15 +02:00
void Staff::addBracket(BracketItem* b)
2012-05-26 14:26:10 +02:00
{
2017-03-31 13:03:15 +02:00
b->setStaff(this);
if (!_brackets.empty() && _brackets[0]->bracketType() == BracketType::NO_BRACKET)
2012-05-26 14:26:10 +02:00
_brackets[0] = b;
else {
//
// create new bracket level
//
2017-03-31 13:03:15 +02:00
for (Staff* s : score()->staves()) {
2012-05-26 14:26:10 +02:00
if (s == this)
s->_brackets.append(b);
2017-03-31 13:03:15 +02:00
else {
BracketItem* bi = new BracketItem(score());
bi->setStaff(this);
s->_brackets.append(bi);
}
2012-05-26 14:26:10 +02:00
}
}
}
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) {
2017-03-31 13:03:15 +02:00
const BracketItem* bi = staff->brackets().at(k);
if (bi->bracketType() != BracketType::NO_BRACKET) {
if (i < staffIdx && ((i + bi->bracketSpan()) > staffIdx) && k < level) {
t = bi->bracketType();
2016-03-02 13:20:19 +01:00
level = k;
break;
}
}
}
}
return t;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// cleanupBrackets
//---------------------------------------------------------
void Staff::cleanupBrackets()
{
int index = idx();
2016-03-10 10:41:31 +01:00
int n = score()->nstaves();
2012-05-26 14:26:10 +02:00
for (int i = 0; i < _brackets.size(); ++i) {
2017-03-31 13:03:15 +02:00
if (_brackets[i]->bracketType() == BracketType::NO_BRACKET)
2013-06-05 15:47:34 +02:00
continue;
2017-03-31 13:03:15 +02:00
int span = _brackets[i]->bracketSpan();
2013-06-05 15:47:34 +02:00
if (span > (n - index)) {
span = n - index;
2017-03-31 13:03:15 +02:00
_brackets[i]->setBracketSpan(span);
2012-05-26 14:26:10 +02:00
}
}
for (int i = 0; i < _brackets.size(); ++i) {
2017-03-31 13:03:15 +02:00
if (_brackets[i]->bracketType() == BracketType::NO_BRACKET)
2013-06-05 15:47:34 +02:00
continue;
2017-03-31 13:03:15 +02:00
int span = _brackets[i]->bracketSpan();
if (span <= 1) {
_brackets[i] = new BracketItem(score());
_brackets[i]->setStaff(this);
}
2013-06-05 15:47:34 +02:00
else {
// delete all other brackets with same span
for (int k = i + 1; k < _brackets.size(); ++k) {
2017-03-31 13:03:15 +02:00
if (span == _brackets[k]->bracketSpan()) {
_brackets[k] = new BracketItem(score());
_brackets[k]->setStaff(this);
}
2012-05-26 14:26:10 +02:00
}
}
}
}
2017-03-31 13:03:15 +02:00
//---------------------------------------------------------
// bracketLevels
//---------------------------------------------------------
int Staff::bracketLevels() const
{
int columns = 0;
for (auto bi : _brackets)
columns = qMax(columns, bi->column());
return columns;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// partName
//---------------------------------------------------------
QString Staff::partName() const
{
return _part->partName();
}
//---------------------------------------------------------
// ~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
{
ClefTypeList ct = clefs.clef(tick);
if (ct._concertClef == ClefType::INVALID) {
2016-12-13 13:16:17 +01:00
switch(staffType(tick)->group()) {
2014-08-16 11:21:56 +02:00
case StaffGroup::TAB:
{
ClefType sct = ClefType(score()->styleI(StyleIdx::tabClef));
2016-12-13 13:16:17 +01:00
ct = staffType(tick)->lines() <= 4 ? ClefTypeList(sct == ClefType::TAB ? ClefType::TAB4 : ClefType::TAB4_SERIF) : ClefTypeList(sct == ClefType::TAB ? ClefType::TAB : ClefType::TAB_SERIF);
}
break;
case StaffGroup::STANDARD:
2014-08-16 11:21:56 +02:00
ct = defaultClefType();
break;
case StaffGroup::PERCUSSION:
2014-08-16 11:21:56 +02:00
ct = ClefTypeList(ClefType::PERC);
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
}
//---------------------------------------------------------
// Staff::nextClefTick
//
// return the tick of next clef after tick
// return last tick of score if not found
//---------------------------------------------------------
int Staff::nextClefTick(int tick) const
{
int t = clefs.nextClefTick(tick);
2017-02-13 17:06:30 +01:00
return t != -1 ? t : score()->endTick();
}
#ifndef NDEBUG
//---------------------------------------------------------
// dumpClef
//---------------------------------------------------------
void Staff::dumpClefs(const char* title) const
{
qDebug("(%zd): %s", clefs.size(), title);
for (auto& i : clefs) {
qDebug(" %d: %d %d", i.first, int(i.second._concertClef), int(i.second._transposingClef));
}
}
//---------------------------------------------------------
// dumpKeys
//---------------------------------------------------------
void Staff::dumpKeys(const char* title) const
{
qDebug("(%zd): %s", _keys.size(), title);
for (auto& i : _keys) {
qDebug(" %d: %d", i.first, int(i.second.key()));
}
}
2015-02-16 12:12:23 +01:00
//---------------------------------------------------------
// dumpTimeSigs
//---------------------------------------------------------
void Staff::dumpTimeSigs(const char* title) const
{
qDebug("size (%zd) staffIdx %d: %s", timesigs.size(), idx(), title);
2015-02-16 12:12:23 +01:00
for (auto& i : timesigs) {
qDebug(" %d: %d/%d", i.first, i.second->sig().numerator(), i.second->sig().denominator());
}
}
#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
{
2016-03-18 09:29:16 +01:00
// qDebug("Staff::setClef generated %d", clef->generated());
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()) {
2017-03-08 13:12:26 +01:00
if (s->segmentType() == SegmentType::Clef && s->element(clef->track())) {
2014-07-25 17:13:27 +02:00
// adding this clef has no effect on the clefs list
return;
}
}
clefs.setClef(clef->segment()->tick(), clef->clefTypeList());
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
{
2016-03-18 09:29:16 +01:00
// qDebug("Staff::removeClef generated %d", clef->generated());
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()) {
2017-03-08 13:12:26 +01:00
if (s->segmentType() == SegmentType::Clef && s->element(clef->track())) {
2014-07-25 17:13:27 +02:00
// 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()) {
2017-03-08 13:12:26 +01:00
if (s->segmentType() == SegmentType::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
2017-12-20 16:49:30 +01:00
clefs.setClef(tick, toClef(s->element(clef->track()))->clefTypeList());
2014-07-25 17:13:27 +02:00
break;
}
}
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 ? timesig->stretch() : Fraction(1,1);
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;
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
}
//---------------------------------------------------------
// nextTimeSig
// lookup time signature at tick or after
//---------------------------------------------------------
TimeSig* Staff::nextTimeSig(int tick) const
{
auto i = timesigs.lower_bound(tick);
return (i == timesigs.end()) ? 0 : i->second;
}
//---------------------------------------------------------
// 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)
{
2017-03-08 13:12:26 +01:00
if (timesig->segment()->segmentType() == SegmentType::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)
{
2017-03-08 13:12:26 +01:00
if (timesig->segment()->segmentType() == SegmentType::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
//
// locates the key sig currently in effect at tick
2012-05-26 14:26:10 +02: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
//---------------------------------------------------------
void Staff::setKey(int tick, KeySigEvent k)
2014-06-04 10:20:14 +02:00
{
_keys.setKey(tick, k);
// 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);
// dumpKeys("removeKey");
2014-06-04 10:20:14 +02:00
}
2014-06-03 15:28:10 +02:00
//---------------------------------------------------------
// prevkey
//---------------------------------------------------------
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
}
//---------------------------------------------------------
// 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
{
2017-02-13 17:06:30 +01:00
int t = _keys.nextKeyTick(tick);
return t != -1 ? t : score()->endTick();
2014-06-03 15:28:10 +02:00
}
//---------------------------------------------------------
// 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
//---------------------------------------------------------
2016-11-19 11:51:21 +01:00
void Staff::write(XmlWriter& xml) const
2012-05-26 14:26:10 +02:00
{
2016-09-28 21:13:05 +02:00
int idx = this->idx();
xml.stag(QString("Staff id=\"%1\"").arg(idx + 1));
2012-05-26 14:26:10 +02:00
if (linkedStaves()) {
2016-03-10 10:41:31 +01:00
Score* s = masterScore();
2016-12-18 14:31:13 +01:00
for (Staff* staff : linkedStaves()->staves()) {
2012-05-26 14:26:10 +02:00
if ((staff->score() == s) && (staff != this))
2016-09-28 21:13:05 +02:00
xml.tag("linkedTo", staff->idx() + 1);
2012-05-26 14:26:10 +02:00
}
}
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
2016-11-19 10:31:14 +01:00
if (xml.clipboardmode()) {
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);
}
2016-12-18 14:31:13 +01:00
staffType(0)->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 (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());
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
2017-03-31 13:03:15 +02:00
for (const BracketItem* i : _brackets) {
BracketType a = i->bracketType();
int b = i->bracketSpan();
int c = i->column();
if (a != BracketType::NO_BRACKET || b > 0)
xml.tagE(QString("bracket type=\"%1\" span=\"%2\" col=\"%3\"").arg((int)(a)).arg(b).arg(c));
}
2016-12-28 16:23:10 +01:00
writeProperty(xml, P_ID::STAFF_BARLINE_SPAN);
writeProperty(xml, P_ID::STAFF_BARLINE_SPAN_FROM);
writeProperty(xml, P_ID::STAFF_BARLINE_SPAN_TO);
2016-12-23 12:05:18 +01:00
writeProperty(xml, P_ID::STAFF_USERDIST);
writeProperty(xml, P_ID::COLOR);
2016-09-16 12:07:37 +02:00
writeProperty(xml, P_ID::PLAYBACK_VOICE1);
writeProperty(xml, P_ID::PLAYBACK_VOICE2);
writeProperty(xml, P_ID::PLAYBACK_VOICE3);
writeProperty(xml, P_ID::PLAYBACK_VOICE4);
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()) {
2016-12-23 12:05:18 +01:00
if (!readProperties(e))
e.unknown();
}
}
//---------------------------------------------------------
// readProperties
//---------------------------------------------------------
bool Staff::readProperties(XmlReader& e)
{
const QStringRef& tag(e.name());
if (tag == "StaffType") {
StaffType st;
st.read(e);
_staffTypeList.setStaffType(0, &st);
}
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)));
}
2017-02-13 18:21:12 +01:00
else if (tag == "small") // obsolete
setSmall(0, e.readInt());
2016-12-23 12:05:18 +01:00
else if (tag == "invisible")
setInvisible(e.readInt());
else if (tag == "hideWhenEmpty")
setHideWhenEmpty(HideMode(e.readInt()));
else if (tag == "cutaway")
setCutaway(e.readInt());
else if (tag == "showIfSystemEmpty")
setShowIfEmpty(e.readInt());
else if (tag == "hideSystemBarLine")
_hideSystemBarLine = e.readInt();
else if (tag == "keylist")
_keys.read(e, score());
else if (tag == "bracket") {
2017-03-31 13:03:15 +02:00
BracketItem* b = new BracketItem(score());
b->setStaff(this);
b->setBracketType(BracketType(e.intAttribute("type", -1)));
b->setBracketSpan(e.intAttribute("span", 0));
int col = e.intAttribute("col", -1);
if (col == -1)
col = _brackets.size();
b->setColumn(col);
2016-12-23 12:05:18 +01:00
_brackets.append(b);
e.readNext();
}
else if (tag == "barLineSpan")
2017-05-29 14:59:10 +02:00
_barLineSpan = e.readInt();
2016-12-23 12:05:18 +01:00
else if (tag == "barLineSpanFrom")
_barLineFrom = e.readInt();
else if (tag == "barLineSpanTo")
_barLineTo = e.readInt();
else if (tag == "distOffset")
_userDist = e.readDouble() * score()->spatium();
else if (tag == "mag")
/*_userMag =*/ e.readDouble(0.1, 10.0);
else if (tag == "linkedTo") {
int v = e.readInt() - 1;
//
// if this is an excerpt, link staff to masterScore()
//
if (!score()->isMaster()) {
Staff* st = masterScore()->staff(v);
if (st)
linkTo(st);
2012-05-26 14:26:10 +02:00
else {
2016-12-23 12:05:18 +01:00
qDebug("staff %d not found in parent", v);
2012-05-26 14:26:10 +02:00
}
}
2016-12-23 12:05:18 +01:00
else {
if (v >= 0 && v < idx())
linkTo(score()->staff(v));
}
2012-05-26 14:26:10 +02:00
}
2016-12-23 12:05:18 +01:00
else if (tag == "color")
_color = e.readColor();
else if (tag == "transposeDiatonic")
e.setTransposeDiatonic(e.readInt());
else if (tag == "transposeChromatic")
e.setTransposeChromatic(e.readInt());
else if (tag == "playbackVoice1")
setPlaybackVoice(0, e.readInt());
else if (tag == "playbackVoice2")
setPlaybackVoice(1, e.readInt());
else if (tag == "playbackVoice3")
setPlaybackVoice(2, e.readInt());
else if (tag == "playbackVoice4")
setPlaybackVoice(3, e.readInt());
else
return false;
return true;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// height
//---------------------------------------------------------
qreal Staff::height() const
{
2016-12-13 13:16:17 +01:00
int tick = 0; // TODO
2016-12-23 12:05:18 +01:00
return (lines(tick) == 1 ? 2 : lines(tick)-1) * spatium(tick) * staffType(tick)->lineDistance().val();
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// spatium
//---------------------------------------------------------
2016-12-23 12:05:18 +01:00
qreal Staff::spatium(int tick) const
2012-05-26 14:26:10 +02:00
{
2016-12-23 12:05:18 +01:00
return score()->spatium() * mag(tick);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// mag
//---------------------------------------------------------
2016-12-23 12:05:18 +01:00
qreal Staff::mag(int tick) const
{
return (small(tick) ? score()->styleD(StyleIdx::smallStaffMag) : 1.0) * userMag(tick);
}
//---------------------------------------------------------
// userMag
//---------------------------------------------------------
qreal Staff::userMag(int tick) const
{
return staffType(tick)->userMag();
}
//---------------------------------------------------------
// setUserMag
//---------------------------------------------------------
void Staff::setUserMag(int tick, qreal m)
{
return staffType(tick)->setUserMag(m);
}
//---------------------------------------------------------
// small
//---------------------------------------------------------
bool Staff::small(int tick) const
{
return staffType(tick)->small();
}
//---------------------------------------------------------
// setSmall
//---------------------------------------------------------
void Staff::setSmall(int tick, bool val)
2012-05-26 14:26:10 +02:00
{
2016-12-23 12:05:18 +01:00
staffType(tick)->setSmall(val);
2012-05-26 14:26:10 +02:00
}
Implementation of text swing (step1) added swing tab swing settings tab in staff text properties Implemented step 2 of swing implementation using staff texts Added call for updateSwing in stafftextproperties Initial page for dialog changed System flag enabled for swing parameters saving and loading with text specified swing implemented removed extra print statement fixed formatting Added groupbox to make the default behavior to no change in swing fixed indentation in stafftextproperties fixing conflicts in staff.h Removed writing of setSwing to file Removed SwingParameter member from staff and fixed layout of swing tab in dialog fixed the issue with disabled controls Added tests for staff text implementation of swing playback cleaned up the code Swing playback using staff texts implemented, facilitating local control over swing parameters and tests for the same added Cleaned up code Cleaned up code further Swing Playback using staff texts implemented Cleaned up code further Cleaning up code further Using MScore::division in place of 480 as ticks Modified test files according to new usage of MScore::division Removed unwanted printf statements Using strings to write to xml rather than doubles for swingUnit Replaced 240 and 120 in terms of MScore::division in stafftext:write Using TDuration to write to xml Replaced string literals by TDuration for style parameters Replaced "off" with "" in style.cpp Set defaults for unit and ratio in constructors Removed usage of two structs for SwingParameters Changed order of assignments in setSwingParameters Swing playback using staff-texts implemented and tests added
2014-07-24 20:09:49 +02:00
//---------------------------------------------------------
// swing
//---------------------------------------------------------
SwingParameters Staff::swing(int tick) const
{
SwingParameters sp;
int swingUnit = 0;
Implementation of text swing (step1) added swing tab swing settings tab in staff text properties Implemented step 2 of swing implementation using staff texts Added call for updateSwing in stafftextproperties Initial page for dialog changed System flag enabled for swing parameters saving and loading with text specified swing implemented removed extra print statement fixed formatting Added groupbox to make the default behavior to no change in swing fixed indentation in stafftextproperties fixing conflicts in staff.h Removed writing of setSwing to file Removed SwingParameter member from staff and fixed layout of swing tab in dialog fixed the issue with disabled controls Added tests for staff text implementation of swing playback cleaned up the code Swing playback using staff texts implemented, facilitating local control over swing parameters and tests for the same added Cleaned up code Cleaned up code further Swing Playback using staff texts implemented Cleaned up code further Cleaning up code further Using MScore::division in place of 480 as ticks Modified test files according to new usage of MScore::division Removed unwanted printf statements Using strings to write to xml rather than doubles for swingUnit Replaced 240 and 120 in terms of MScore::division in stafftext:write Using TDuration to write to xml Replaced string literals by TDuration for style parameters Replaced "off" with "" in style.cpp Set defaults for unit and ratio in constructors Removed usage of two structs for SwingParameters Changed order of assignments in setSwingParameters Swing playback using staff-texts implemented and tests added
2014-07-24 20:09:49 +02:00
QString unit = score()->styleSt(StyleIdx::swingUnit);
int swingRatio = score()->styleI(StyleIdx::swingRatio);
if (unit == TDuration(TDuration::DurationType::V_EIGHTH).name()) {
Implementation of text swing (step1) added swing tab swing settings tab in staff text properties Implemented step 2 of swing implementation using staff texts Added call for updateSwing in stafftextproperties Initial page for dialog changed System flag enabled for swing parameters saving and loading with text specified swing implemented removed extra print statement fixed formatting Added groupbox to make the default behavior to no change in swing fixed indentation in stafftextproperties fixing conflicts in staff.h Removed writing of setSwing to file Removed SwingParameter member from staff and fixed layout of swing tab in dialog fixed the issue with disabled controls Added tests for staff text implementation of swing playback cleaned up the code Swing playback using staff texts implemented, facilitating local control over swing parameters and tests for the same added Cleaned up code Cleaned up code further Swing Playback using staff texts implemented Cleaned up code further Cleaning up code further Using MScore::division in place of 480 as ticks Modified test files according to new usage of MScore::division Removed unwanted printf statements Using strings to write to xml rather than doubles for swingUnit Replaced 240 and 120 in terms of MScore::division in stafftext:write Using TDuration to write to xml Replaced string literals by TDuration for style parameters Replaced "off" with "" in style.cpp Set defaults for unit and ratio in constructors Removed usage of two structs for SwingParameters Changed order of assignments in setSwingParameters Swing playback using staff-texts implemented and tests added
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())
Implementation of text swing (step1) added swing tab swing settings tab in staff text properties Implemented step 2 of swing implementation using staff texts Added call for updateSwing in stafftextproperties Initial page for dialog changed System flag enabled for swing parameters saving and loading with text specified swing implemented removed extra print statement fixed formatting Added groupbox to make the default behavior to no change in swing fixed indentation in stafftextproperties fixing conflicts in staff.h Removed writing of setSwing to file Removed SwingParameter member from staff and fixed layout of swing tab in dialog fixed the issue with disabled controls Added tests for staff text implementation of swing playback cleaned up the code Swing playback using staff texts implemented, facilitating local control over swing parameters and tests for the same added Cleaned up code Cleaned up code further Swing Playback using staff texts implemented Cleaned up code further Cleaning up code further Using MScore::division in place of 480 as ticks Modified test files according to new usage of MScore::division Removed unwanted printf statements Using strings to write to xml rather than doubles for swingUnit Replaced 240 and 120 in terms of MScore::division in stafftext:write Using TDuration to write to xml Replaced string literals by TDuration for style parameters Replaced "off" with "" in style.cpp Set defaults for unit and ratio in constructors Removed usage of two structs for SwingParameters Changed order of assignments in setSwingParameters Swing playback using staff-texts implemented and tests added
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;
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();
}
//---------------------------------------------------------
// middleLine
// returns logical line number of middle staff line
//---------------------------------------------------------
2016-12-13 13:16:17 +01:00
int Staff::middleLine(int tick) const
{
2016-12-23 12:05:18 +01:00
return lines(tick) - 1;
}
//---------------------------------------------------------
// bottomLine
// returns logical line number of bottom staff line
//---------------------------------------------------------
2016-12-13 13:16:17 +01:00
int Staff::bottomLine(int tick) const
{
2016-12-23 12:05:18 +01:00
return (lines(tick) - 1) * 2;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// slashStyle
//---------------------------------------------------------
2016-12-13 13:16:17 +01:00
bool Staff::slashStyle(int tick) const
2012-05-26 14:26:10 +02:00
{
2016-12-13 13:16:17 +01:00
return staffType(tick)->slashStyle();
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// setSlashStyle
//---------------------------------------------------------
2016-12-13 13:16:17 +01:00
void Staff::setSlashStyle(int tick, bool val)
2012-05-26 14:26:10 +02:00
{
2016-12-13 13:16:17 +01:00
staffType(tick)->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;
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)
{
if (!_staves.contains(staff))
_staves.append(staff);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// 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
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);
2016-12-13 13:16:17 +01:00
if (!staff->isTabStaff(0))
2015-06-22 18:19:05 +02:00
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
}
2016-12-13 13:16:17 +01:00
//---------------------------------------------------------
// staffType
//---------------------------------------------------------
const StaffType* Staff::staffType(int tick) const
{
return &_staffTypeList.staffType(tick);
}
StaffType* Staff::staffType(int tick)
{
return &_staffTypeList.staffType(tick);
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2016-12-18 14:31:13 +01:00
// staffTypeListChanged
// Signal that the staffTypeList has changed at
// position tick. Update layout range.
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2016-12-18 14:31:13 +01:00
void Staff::staffTypeListChanged(int tick)
2012-05-26 14:26:10 +02:00
{
2016-12-18 14:31:13 +01:00
score()->setLayout(tick);
auto i = _staffTypeList.find(tick);
++i;
if (i != _staffTypeList.end())
score()->setLayout(i->first);
else
score()->setLayout(score()->lastMeasure()->endTick());
2016-12-18 14:31:13 +01:00
}
2016-12-14 09:56:16 +01:00
2016-12-18 14:31:13 +01:00
//---------------------------------------------------------
// setStaffType
//---------------------------------------------------------
StaffType* Staff::setStaffType(int tick, const StaffType* nst)
{
auto i = _staffTypeList.find(tick);
if (i != _staffTypeList.end()) {
qDebug("there is alread a type at %d", tick);
}
2016-12-18 14:31:13 +01:00
return _staffTypeList.setStaffType(tick, nst);
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) {
2016-12-23 12:05:18 +01:00
setSmall(0, false);
2012-05-26 14:26:10 +02:00
}
else {
setSmall(0, t->smallStaff[cidx]);
2017-03-31 13:03:15 +02:00
setBracketType(0, t->bracket[cidx]);
2012-05-26 14:26:10 +02:00
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
2016-12-13 13:16:17 +01:00
setStaffType(0, pst);
2014-08-16 11:21:56 +02:00
setDefaultClefType(t->clefType(cidx));
}
//---------------------------------------------------------
// init
//---------------------------------------------------------
void Staff::init(const Staff* s)
{
2016-12-13 13:16:17 +01:00
_staffTypeList = s->_staffTypeList;
setDefaultClefType(s->defaultClefType());
for (BracketItem* i : s->_brackets){
BracketItem* ni = new BracketItem(*i);
ni->setScore(score());
_brackets.push_back(ni);
}
_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;
_showIfEmpty = s->_showIfEmpty;
_hideSystemBarLine = s->_hideSystemBarLine;
_color = s->_color;
_userDist = s->_userDist;
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
2016-12-13 13:16:17 +01:00
setStaffType(0, 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()
{
2016-12-13 13:16:17 +01:00
if (staffType(0)->group() == StaffGroup::TAB)
2014-04-28 18:38:50 +02:00
return false;
else
2016-12-13 13:16:17 +01:00
return staffType(0)->genKeysig();
}
2013-07-16 09:03:47 +02:00
//---------------------------------------------------------
// showLedgerLines
//---------------------------------------------------------
2016-12-13 13:16:17 +01:00
bool Staff::showLedgerLines(int tick)
{
2016-12-13 13:16:17 +01:00
return staffType(tick)->showLedgerLines();
}
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;
2017-01-18 14:16:33 +01:00
if (s->type() == ElementType::OTTAVA && s->staffIdx() == staffIdx) {
2014-07-15 12:49:51 +02:00
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
}
//---------------------------------------------------------
// undoSetColor
//---------------------------------------------------------
2014-01-15 22:05:05 +01:00
void Staff::undoSetColor(const QColor& /*val*/)
{
2016-06-09 09:26:13 +02:00
// undoChangeProperty(P_ID::COLOR, val);
}
2014-05-08 17:59:24 +02:00
//---------------------------------------------------------
// insertTime
//---------------------------------------------------------
void Staff::insertTime(int tick, int len)
{
if (len == 0)
return;
// 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-05-08 17:59:24 +02:00
KeyList kl2;
for (auto i = _keys.lower_bound(tick); i != _keys.end();) {
KeySigEvent kse = i->second;
int tick = i->first;
2014-06-03 15:28:10 +02:00
_keys.erase(i++);
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
// check if there is a clef at the end of measure
// before tick
Clef* clef = 0;
2016-03-10 10:41:31 +01:00
Measure* m = score()->tick2measure(tick);
if (m && (m->tick() == tick) && (m->prevMeasure())) {
m = m->prevMeasure();
2017-03-08 13:12:26 +01:00
Segment* s = m->findSegment(SegmentType::Clef, tick);
if (s) {
int track = idx() * VOICES;
2017-12-20 16:49:30 +01:00
clef = toClef(s->element(track));
}
}
2014-05-08 17:59:24 +02:00
ClefList cl2;
for (auto i = clefs.lower_bound(tick); i != clefs.end();) {
2014-05-08 17:59:24 +02:00
ClefTypeList ctl = i->second;
int t = i->first;
if (clef && tick == t) {
++i;
continue;
}
2014-05-08 17:59:24 +02:00
clefs.erase(i++);
cl2.setClef(t + len, ctl);
2014-05-08 17:59:24 +02:00
}
clefs.insert(cl2.begin(), cl2.end());
// check if there is a clef at the end of measure
// before tick: do not remove from clefs list
if (clef)
setClef(clef);
updateOttava();
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-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;
}
//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
QVariant Staff::getProperty(P_ID id) const
{
switch (id) {
2017-02-13 18:21:12 +01:00
case P_ID::SMALL:
return small(0);
case P_ID::MAG:
return userMag(0);
case P_ID::COLOR:
return color();
2016-09-16 12:07:37 +02:00
case P_ID::PLAYBACK_VOICE1:
return playbackVoice(0);
case P_ID::PLAYBACK_VOICE2:
return playbackVoice(1);
case P_ID::PLAYBACK_VOICE3:
return playbackVoice(2);
case P_ID::PLAYBACK_VOICE4:
return playbackVoice(3);
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN:
return barLineSpan();
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN_FROM:
return barLineFrom();
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN_TO:
return barLineTo();
2016-12-23 12:05:18 +01:00
case P_ID::STAFF_USERDIST:
return userDist();
default:
2016-12-29 13:42:55 +01:00
qDebug("unhandled id %s", propertyName(id));
return QVariant();
}
}
//---------------------------------------------------------
// setProperty
//---------------------------------------------------------
bool Staff::setProperty(P_ID id, const QVariant& v)
{
switch (id) {
2017-02-13 18:21:12 +01:00
case P_ID::SMALL:
setSmall(0, v.toBool());
break;
case P_ID::MAG: {
qreal _spatium = spatium(0);
setUserMag(0, v.toReal());
score()->spatiumChanged(_spatium, spatium(0));
}
break;
case P_ID::COLOR:
setColor(v.value<QColor>());
break;
2016-09-16 12:07:37 +02:00
case P_ID::PLAYBACK_VOICE1:
setPlaybackVoice(0, v.toBool());
break;
case P_ID::PLAYBACK_VOICE2:
setPlaybackVoice(1, v.toBool());
break;
case P_ID::PLAYBACK_VOICE3:
setPlaybackVoice(2, v.toBool());
break;
case P_ID::PLAYBACK_VOICE4:
setPlaybackVoice(3, v.toBool());
break;
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN:
setBarLineSpan(v.toInt());
break;
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN_FROM:
setBarLineFrom(v.toInt());
break;
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN_TO:
setBarLineTo(v.toInt());
break;
2016-12-23 12:05:18 +01:00
case P_ID::STAFF_USERDIST:
setUserDist(v.toReal());
break;
default:
2016-12-29 13:42:55 +01:00
qDebug("unhandled id %s", propertyName(id));
break;
}
2016-03-02 13:20:19 +01:00
score()->setLayoutAll();
return true;
}
//---------------------------------------------------------
// propertyDefault
//---------------------------------------------------------
QVariant Staff::propertyDefault(P_ID id) const
{
switch (id) {
2017-02-13 18:21:12 +01:00
case P_ID::SMALL:
return false;
case P_ID::MAG:
return 1.0;
case P_ID::COLOR:
return QColor(Qt::black);
2016-09-16 12:07:37 +02:00
case P_ID::PLAYBACK_VOICE1:
case P_ID::PLAYBACK_VOICE2:
case P_ID::PLAYBACK_VOICE3:
case P_ID::PLAYBACK_VOICE4:
return true;
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN:
2016-12-23 12:05:18 +01:00
return false;
2016-12-28 16:23:10 +01:00
case P_ID::STAFF_BARLINE_SPAN_FROM:
case P_ID::STAFF_BARLINE_SPAN_TO:
2016-12-23 12:05:18 +01:00
return 0;
case P_ID::STAFF_USERDIST:
return qreal(0.0);
default:
2016-12-29 13:42:55 +01:00
qDebug("unhandled id %s", propertyName(id));
return QVariant();
}
}
//---------------------------------------------------------
// scaleChanged
//---------------------------------------------------------
void Staff::scaleChanged(double oldVal, double newVal)
{
int staffIdx = idx();
int startTrack = staffIdx * VOICES;
int endTrack = startTrack + VOICES;
2017-03-08 13:12:26 +01:00
for (Segment* s = score()->firstSegment(SegmentType::All); 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);
}
}
}
2016-12-13 13:16:17 +01:00
2016-12-23 12:05:18 +01:00
//---------------------------------------------------------
// isPitchedStaff
//---------------------------------------------------------
bool Staff::isPitchedStaff(int tick) const
{
return staffType(tick)->group() == StaffGroup::STANDARD;
}
//---------------------------------------------------------
// isTabStaff
//---------------------------------------------------------
bool Staff::isTabStaff(int tick) const
{
return staffType(tick)->group() == StaffGroup::TAB;
}
//---------------------------------------------------------
// isDrumStaff
//---------------------------------------------------------
bool Staff::isDrumStaff(int tick) const
{
return staffType(tick)->group() == StaffGroup::PERCUSSION;
}
2016-12-13 13:16:17 +01:00
//---------------------------------------------------------
// lines
//---------------------------------------------------------
int Staff::lines(int tick) const
{
return staffType(tick)->lines();
}
//---------------------------------------------------------
// setLines
//---------------------------------------------------------
void Staff::setLines(int tick, int val)
{
staffType(tick)->setLines(val); // TODO: make undoable
}
//---------------------------------------------------------
// lineDistance
// distance between staff lines
//---------------------------------------------------------
qreal Staff::lineDistance(int tick) const
{
return staffType(tick)->lineDistance().val();
}
2013-05-13 18:49:17 +02:00
}