MuseScore/libmscore/spanner.cpp

561 lines
16 KiB
C++
Raw Normal View History

2012-05-26 14:26:10 +02:00
//=============================================================================
// MuseScore
// Music Composition & Notation
//
// Copyright (C) 2010-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
//=============================================================================
2013-06-10 11:03:34 +02:00
#include "score.h"
2012-05-26 14:26:10 +02:00
#include "spanner.h"
#include "system.h"
#include "chordrest.h"
2013-06-16 23:33:37 +02:00
#include "chord.h"
2012-05-26 14:26:10 +02:00
#include "segment.h"
2013-06-10 11:03:34 +02:00
#include "measure.h"
2014-07-10 14:32:04 +02:00
#include "undo.h"
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2013-06-10 11:03:34 +02:00
int Spanner::editTick;
int Spanner::editTick2;
2013-09-27 11:18:30 +02:00
int Spanner::editTrack2;
2013-06-10 11:03:34 +02:00
QList<QPointF> Spanner::userOffsets2;
QList<QPointF> Spanner::userOffsets;
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// SpannerSegment
//---------------------------------------------------------
SpannerSegment::SpannerSegment(Score* s)
: Element(s)
{
2014-07-09 18:05:58 +02:00
setFlags(ElementFlag::MOVABLE | ElementFlag::SELECTABLE | ElementFlag::SEGMENT | ElementFlag::ON_STAFF);
setSpannerSegmentType(SpannerSegmentType::SINGLE);
2012-05-26 14:26:10 +02:00
_spanner = 0;
}
SpannerSegment::SpannerSegment(const SpannerSegment& s)
: Element(s)
{
_spanner = s._spanner;
_spannerSegmentType = s._spannerSegmentType;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// startEdit
//---------------------------------------------------------
void SpannerSegment::startEdit(MuseScoreView*s , const QPointF& p)
{
spanner()->startEdit(s, p);
}
//---------------------------------------------------------
// endEdit
//---------------------------------------------------------
void SpannerSegment::endEdit()
{
spanner()->endEdit();
}
//---------------------------------------------------------
// setSystem
//---------------------------------------------------------
void SpannerSegment::setSystem(System* s)
{
if (system() != s) {
if (system())
system()->remove(this);
2013-06-10 11:03:34 +02:00
if (s)
s->add(this);
else
setParent(0);
2012-05-26 14:26:10 +02:00
}
}
2013-05-02 16:12:17 +02:00
//---------------------------------------------------------
// getProperty
//---------------------------------------------------------
QVariant SpannerSegment::getProperty(P_ID id) const
{
switch (id) {
2014-05-26 18:18:01 +02:00
case P_ID::COLOR:
case P_ID::VISIBLE:
2013-05-02 16:12:17 +02:00
return spanner()->getProperty(id);
2014-05-26 18:18:01 +02:00
case P_ID::USER_OFF2:
2013-06-10 11:03:34 +02:00
return _userOff2;
2013-05-02 16:12:17 +02:00
default:
return Element::getProperty(id);
}
}
//---------------------------------------------------------
// setProperty
//---------------------------------------------------------
bool SpannerSegment::setProperty(P_ID id, const QVariant& v)
{
switch (id) {
2014-05-26 18:18:01 +02:00
case P_ID::COLOR:
case P_ID::VISIBLE:
2013-05-02 16:12:17 +02:00
return spanner()->setProperty(id, v);
2014-05-26 18:18:01 +02:00
case P_ID::USER_OFF2:
2013-06-10 11:03:34 +02:00
_userOff2 = v.toPointF();
score()->setLayoutAll(true);
break;
2013-05-02 16:12:17 +02:00
default:
return Element::setProperty(id, v);
}
2013-06-10 11:03:34 +02:00
return true;
2013-05-02 16:12:17 +02:00
}
//---------------------------------------------------------
// propertyDefault
//---------------------------------------------------------
QVariant SpannerSegment::propertyDefault(P_ID id) const
{
switch (id) {
2014-05-26 18:18:01 +02:00
case P_ID::COLOR:
case P_ID::VISIBLE:
2013-05-02 16:12:17 +02:00
return spanner()->propertyDefault(id);
2014-05-26 18:18:01 +02:00
case P_ID::USER_OFF2:
2013-06-10 11:03:34 +02:00
return QVariant();
2013-05-02 16:12:17 +02:00
default:
return Element::propertyDefault(id);
}
}
2013-08-26 10:39:16 +02:00
//---------------------------------------------------------
// reset
//---------------------------------------------------------
void SpannerSegment::reset()
{
2014-05-26 18:18:01 +02:00
score()->undoChangeProperty(this, P_ID::USER_OFF2, QPointF());
2013-08-26 10:39:16 +02:00
Element::reset();
spanner()->reset();
}
2014-05-07 12:10:28 +02:00
//---------------------------------------------------------
// setSelected
//---------------------------------------------------------
void SpannerSegment::setSelected(bool f)
{
for (SpannerSegment* ss : _spanner->spannerSegments())
ss->_selected = f;
_spanner->_selected = f;
}
//---------------------------------------------------------
// setVisible
//---------------------------------------------------------
void SpannerSegment::setVisible(bool f)
{
if (_spanner) {
for (SpannerSegment* ss : _spanner->spannerSegments())
ss->_visible = f;
_spanner->_visible = f;
}
else
_visible = f;
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// Spanner
//---------------------------------------------------------
Spanner::Spanner(Score* s)
: Element(s)
{
}
Spanner::Spanner(const Spanner& s)
: Element(s)
{
2013-06-16 23:33:37 +02:00
_anchor = s._anchor;
_startElement = s._startElement;
_endElement = s._endElement;
_tick = s._tick;
2014-08-13 15:42:40 +02:00
_ticks = s._ticks;
2013-10-14 11:56:54 +02:00
_track2 = s._track2;
2012-05-26 14:26:10 +02:00
}
Spanner::~Spanner()
{
2013-06-16 23:33:37 +02:00
foreach (SpannerSegment* ss, spannerSegments())
2012-05-26 14:26:10 +02:00
delete ss;
}
//---------------------------------------------------------
// add
//---------------------------------------------------------
void Spanner::add(Element* e)
{
SpannerSegment* ls = static_cast<SpannerSegment*>(e);
ls->setSpanner(this);
2014-05-07 12:10:28 +02:00
ls->setSelected(selected());
ls->setTrack(ls->spanner()->track());
2012-05-26 14:26:10 +02:00
segments.append(ls);
}
//---------------------------------------------------------
// remove
//---------------------------------------------------------
void Spanner::remove(Element* e)
{
SpannerSegment* ss = static_cast<SpannerSegment*>(e);
if (ss->system())
ss->system()->remove(ss);
segments.removeOne(ss);
}
//---------------------------------------------------------
// scanElements
2014-05-07 12:10:28 +02:00
// used in palettes
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
void Spanner::scanElements(void* data, void (*func)(void*, Element*), bool all)
{
Q_UNUSED(all)
2014-05-07 12:10:28 +02:00
for (SpannerSegment* seg : segments)
2012-05-26 14:26:10 +02:00
seg->scanElements(data, func, true);
}
//---------------------------------------------------------
// setScore
//---------------------------------------------------------
void Spanner::setScore(Score* s)
{
Element::setScore(s);
foreach(SpannerSegment* seg, segments)
seg->setScore(s);
}
//---------------------------------------------------------
// startEdit
//---------------------------------------------------------
void Spanner::startEdit(MuseScoreView*, const QPointF&)
{
2014-07-10 14:32:04 +02:00
editTick = _tick;
2014-08-13 15:42:40 +02:00
editTick2 = tick2();
2013-09-27 11:18:30 +02:00
editTrack2 = _track2;
2013-06-10 11:03:34 +02:00
userOffsets.clear();
userOffsets2.clear();
foreach (SpannerSegment* ss, spannerSegments()) {
userOffsets.push_back(ss->userOff());
userOffsets2.push_back(ss->userOff2());
}
}
//---------------------------------------------------------
// endEdit
//---------------------------------------------------------
void Spanner::endEdit()
{
bool rebuild = false;
if (editTick != tick()) {
2014-05-26 18:18:01 +02:00
score()->undoPropertyChanged(this, P_ID::SPANNER_TICK, editTick);
rebuild = true;
}
if (editTick2 != tick2()) {
2014-08-13 15:42:40 +02:00
score()->undoPropertyChanged(this, P_ID::SPANNER_TICKS, editTick2 - editTick);
rebuild = true;
}
if (editTrack2 != track2()) {
2014-05-26 18:18:01 +02:00
score()->undoPropertyChanged(this, P_ID::SPANNER_TRACK2, editTrack2);
rebuild = true;
2013-08-13 14:26:40 +02:00
}
2013-06-10 11:03:34 +02:00
if (rebuild)
score()->rebuildBspTree();
2013-06-10 11:03:34 +02:00
if (spannerSegments().size() != userOffsets2.size()) {
2014-07-31 16:30:04 +02:00
qDebug("Spanner::endEdit(): segment size changed");
2013-06-10 11:03:34 +02:00
return;
}
2014-07-31 16:30:04 +02:00
2013-06-10 11:03:34 +02:00
for (int i = 0; i < userOffsets2.size(); ++i) {
SpannerSegment* ss = segments[i];
2014-05-26 18:18:01 +02:00
score()->undoPropertyChanged(ss, P_ID::USER_OFF, userOffsets[i]);
score()->undoPropertyChanged(ss, P_ID::USER_OFF2, userOffsets2[i]);
2013-06-10 11:03:34 +02:00
}
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
2013-06-10 11:03:34 +02:00
// getProperty
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2013-06-10 11:03:34 +02:00
QVariant Spanner::getProperty(P_ID propertyId) const
2012-05-26 14:26:10 +02:00
{
2013-06-10 11:03:34 +02:00
switch (propertyId) {
2014-05-26 18:18:01 +02:00
case P_ID::SPANNER_TICK:
2013-06-10 11:03:34 +02:00
return tick();
2014-08-13 15:42:40 +02:00
case P_ID::SPANNER_TICKS:
return ticks();
2014-05-26 18:18:01 +02:00
case P_ID::SPANNER_TRACK2:
2013-09-27 11:18:30 +02:00
return track2();
2014-06-18 20:57:45 +02:00
case P_ID::ANCHOR:
return int(anchor());
2013-06-10 11:03:34 +02:00
default:
break;
}
return Element::getProperty(propertyId);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
2013-06-10 11:03:34 +02:00
// setProperty
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2013-06-10 11:03:34 +02:00
bool Spanner::setProperty(P_ID propertyId, const QVariant& v)
2012-05-26 14:26:10 +02:00
{
2013-06-10 11:03:34 +02:00
switch(propertyId) {
2014-05-26 18:18:01 +02:00
case P_ID::SPANNER_TICK:
2013-06-10 11:03:34 +02:00
setTick(v.toInt());
break;
2014-08-13 15:42:40 +02:00
case P_ID::SPANNER_TICKS:
setTicks(v.toInt());
2013-06-10 11:03:34 +02:00
break;
2014-05-26 18:18:01 +02:00
case P_ID::SPANNER_TRACK2:
2013-09-27 11:18:30 +02:00
setTrack2(v.toInt());
break;
2014-06-18 20:57:45 +02:00
case P_ID::ANCHOR:
setAnchor(Anchor(v.toInt()));
break;
2013-06-10 11:03:34 +02:00
default:
if (!Element::setProperty(propertyId, v))
return false;
break;
}
score()->setLayoutAll(true);
return true;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
2013-06-10 11:03:34 +02:00
// propertyDefault
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2013-06-10 11:03:34 +02:00
QVariant Spanner::propertyDefault(P_ID propertyId) const
2012-05-26 14:26:10 +02:00
{
2013-06-10 11:03:34 +02:00
switch(propertyId) {
2014-06-18 20:57:45 +02:00
case P_ID::ANCHOR:
return int(Anchor::SEGMENT);
2013-06-10 11:03:34 +02:00
default:
break;
}
return Element::propertyDefault(propertyId);
2012-05-26 14:26:10 +02:00
}
2013-06-10 11:03:34 +02:00
//---------------------------------------------------------
2013-06-16 23:33:37 +02:00
// computeStartElement
2013-06-10 11:03:34 +02:00
//---------------------------------------------------------
2013-06-16 23:33:37 +02:00
void Spanner::computeStartElement()
2013-06-10 11:03:34 +02:00
{
switch (_anchor) {
2014-05-26 20:48:27 +02:00
case Anchor::SEGMENT:
_startElement = score()->findCR(tick(), track());
2013-06-16 23:33:37 +02:00
break;
2014-05-26 20:48:27 +02:00
case Anchor::MEASURE:
_startElement = score()->tick2measure(tick());
2013-06-16 23:33:37 +02:00
break;
2013-06-12 14:23:57 +02:00
2014-05-26 20:48:27 +02:00
case Anchor::CHORD:
case Anchor::NOTE:
2013-06-16 23:33:37 +02:00
return;
2013-06-10 11:03:34 +02:00
}
}
//---------------------------------------------------------
2013-06-16 23:33:37 +02:00
// computeEndElement
2013-06-10 11:03:34 +02:00
//---------------------------------------------------------
2013-06-16 23:33:37 +02:00
void Spanner::computeEndElement()
2013-06-10 11:03:34 +02:00
{
switch (_anchor) {
2014-05-26 20:48:27 +02:00
case Anchor::SEGMENT:
if (type() == Element::Type::SLUR) {
Segment* s = score()->tick2segmentMM(tick2(), false, Segment::Type::ChordRest);
2014-05-05 12:25:17 +02:00
_endElement = s ? static_cast<ChordRest*>(s->element(track2())) : nullptr;
}
else
_endElement = score()->findCR(tick2() - 1, track2());
2013-06-16 23:33:37 +02:00
break;
2014-05-26 20:48:27 +02:00
case Anchor::MEASURE:
_endElement = score()->tick2measure(tick2() - 1);
2014-08-13 15:42:40 +02:00
if (!_endElement) {
qDebug("Spanner::computeEndElement(), measure not found for tick %d\n", tick2()-1);
2013-07-29 18:06:11 +02:00
_endElement = score()->lastMeasure();
2014-08-13 15:42:40 +02:00
}
2013-06-16 23:33:37 +02:00
break;
2014-05-26 20:48:27 +02:00
case Anchor::CHORD:
case Anchor::NOTE:
2013-06-10 11:03:34 +02:00
break;
}
2013-06-16 23:33:37 +02:00
}
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// setStartChord
//---------------------------------------------------------
2013-06-16 23:33:37 +02:00
void Spanner::setStartChord(Chord* c)
{
2014-05-26 20:48:27 +02:00
_anchor = Anchor::CHORD;
2013-06-16 23:33:37 +02:00
_startElement = c;
}
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// startChord
//---------------------------------------------------------
Chord* Spanner::startChord()
2013-06-16 23:33:37 +02:00
{
2014-05-26 20:48:27 +02:00
Q_ASSERT(_anchor == Anchor::CHORD);
if (!_startElement)
_startElement = score()->findCR(tick(), track());
2014-07-08 11:16:21 +02:00
Q_ASSERT(_startElement->type() == Element::Type::CHORD);
2013-06-16 23:33:37 +02:00
return static_cast<Chord*>(_startElement);
}
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// setEndChord
//---------------------------------------------------------
2013-06-16 23:33:37 +02:00
void Spanner::setEndChord(Chord* c)
{
_endElement = c;
}
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// endChord
//---------------------------------------------------------
Chord* Spanner::endChord()
2013-06-16 23:33:37 +02:00
{
2014-05-26 20:48:27 +02:00
Q_ASSERT(_anchor == Anchor::CHORD);
if (!_endElement && type() == Element::Type::SLUR) {
Segment* s = score()->tick2segmentMM(tick2(), false, Segment::Type::ChordRest);
_endElement = s ? static_cast<ChordRest*>(s->element(track2())) : nullptr;
if (_endElement->type() != Element::Type::CHORD)
_endElement = nullptr;
}
2014-07-08 11:16:21 +02:00
Q_ASSERT(_endElement->type() == Element::Type::CHORD);
2013-06-16 23:33:37 +02:00
return static_cast<Chord*>(_endElement);
2013-06-10 11:03:34 +02:00
}
2013-06-16 23:33:37 +02:00
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// startCR
//---------------------------------------------------------
ChordRest* Spanner::startCR()
2013-06-16 23:33:37 +02:00
{
2014-05-26 20:48:27 +02:00
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
if (!_startElement)
_startElement = score()->findCR(tick(), track());
2013-06-16 23:33:37 +02:00
return static_cast<ChordRest*>(_startElement);
}
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// endCR
//---------------------------------------------------------
ChordRest* Spanner::endCR()
2013-06-16 23:33:37 +02:00
{
2014-05-26 20:48:27 +02:00
Q_ASSERT(_anchor == Anchor::SEGMENT || _anchor == Anchor::CHORD);
if (!_endElement && type() == Element::Type::SLUR) {
Segment* s = score()->tick2segmentMM(tick2(), false, Segment::Type::ChordRest);
_endElement = s ? static_cast<ChordRest*>(s->element(track2())) : nullptr;
}
2013-06-16 23:33:37 +02:00
return static_cast<ChordRest*>(_endElement);
}
2013-06-19 16:25:29 +02:00
//---------------------------------------------------------
// startSegment
//---------------------------------------------------------
Segment* Spanner::startSegment() const
{
return score()->tick2rightSegment(tick());
2013-06-19 16:25:29 +02:00
}
//---------------------------------------------------------
// endSegment
//---------------------------------------------------------
Segment* Spanner::endSegment() const
{
return score()->tick2leftSegment(tick2());
2013-06-19 16:25:29 +02:00
}
2014-05-07 12:10:28 +02:00
//---------------------------------------------------------
// setSelected
//---------------------------------------------------------
void Spanner::setSelected(bool f)
{
for (SpannerSegment* ss : spannerSegments())
ss->setSelected(f);
_selected = f;
}
//---------------------------------------------------------
// setVisible
//---------------------------------------------------------
void Spanner::setVisible(bool f)
{
for (SpannerSegment* ss : spannerSegments())
ss->setVisible(f);
_visible = f;
}
2014-08-07 10:18:50 +02:00
//---------------------------------------------------------
// setStartElement
//---------------------------------------------------------
void Spanner::setStartElement(Element* e)
{
#ifndef NDEBUG
if (_anchor == Anchor::NOTE)
2014-08-07 11:44:52 +02:00
Q_ASSERT(!e || e->type() == Element::Type::NOTE);
2014-08-07 10:18:50 +02:00
#endif
_startElement = e;
}
//---------------------------------------------------------
// setEndElement
//---------------------------------------------------------
void Spanner::setEndElement(Element* e)
{
#ifndef NDEBUG
if (_anchor == Anchor::NOTE)
2014-08-07 11:44:52 +02:00
Q_ASSERT(!e || e->type() == Element::Type::NOTE);
2014-08-07 10:18:50 +02:00
#endif
_endElement = e;
}
2013-05-13 18:49:17 +02:00
}