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 "barline.h"
|
|
|
|
#include "score.h"
|
|
|
|
#include "sym.h"
|
|
|
|
#include "staff.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "measure.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "articulation.h"
|
|
|
|
#include "stafftype.h"
|
2014-04-09 16:09:21 +02:00
|
|
|
#include "xml.h"
|
2014-07-10 14:13:37 +02:00
|
|
|
#include "marker.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-10-14 00:35:11 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// static members init
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal BarLine::yoff1 = 0.0;
|
|
|
|
qreal BarLine::yoff2 = 0.0;
|
|
|
|
|
|
|
|
bool BarLine::ctrlDrag = false;
|
2014-04-08 10:42:25 +02:00
|
|
|
bool BarLine::shiftDrag = false;
|
2012-10-14 19:48:36 +02:00
|
|
|
int BarLine::_origSpan, BarLine::_origSpanFrom, BarLine::_origSpanTo;
|
2012-10-14 00:35:11 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// barLineNames
|
|
|
|
// must be synchronized with enum BarLineType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
static const char* barLineNames[] = {
|
2014-03-24 11:50:26 +01:00
|
|
|
QT_TRANSLATE_NOOP("barline", "normal"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "double"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "start-repeat"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "end-repeat"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "dashed"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "end"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "end-start-repeat"),
|
|
|
|
QT_TRANSLATE_NOOP("barline", "dotted")
|
2012-05-26 14:26:10 +02:00
|
|
|
};
|
|
|
|
|
2014-07-10 14:13:37 +02:00
|
|
|
const barLineTableItem barLineTable[] = {
|
2014-08-22 22:19:49 +02:00
|
|
|
{ BarLineType::NORMAL, QT_TRANSLATE_NOOP("Palette", "Normal") },
|
|
|
|
{ BarLineType::BROKEN, QT_TRANSLATE_NOOP("Palette", "Dashed style") },
|
|
|
|
{ BarLineType::DOTTED, QT_TRANSLATE_NOOP("Palette", "Dotted style") },
|
|
|
|
{ BarLineType::END, QT_TRANSLATE_NOOP("Palette", "End Bar style") },
|
|
|
|
{ BarLineType::DOUBLE, QT_TRANSLATE_NOOP("Palette", "Double Bar style") },
|
2014-07-10 14:13:37 +02:00
|
|
|
{ BarLineType::START_REPEAT, QT_TRANSLATE_NOOP("Palette", "Start Repeat") },
|
|
|
|
{ BarLineType::END_REPEAT, QT_TRANSLATE_NOOP("Palette", "End Repeat") },
|
|
|
|
{ BarLineType::END_START_REPEAT, QT_TRANSLATE_NOOP("Palette", "End-Start Repeat") },
|
|
|
|
};
|
|
|
|
|
|
|
|
unsigned int barLineTableSize()
|
|
|
|
{
|
|
|
|
return sizeof(barLineTable)/sizeof(*barLineTable);
|
|
|
|
}
|
|
|
|
|
2014-03-24 11:50:26 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// userTypeName
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QString BarLine::userTypeName(BarLineType t)
|
|
|
|
{
|
|
|
|
return qApp->translate("barline", barLineNames[int(t)]);
|
|
|
|
}
|
|
|
|
|
2014-07-10 14:13:37 +02:00
|
|
|
QString BarLine::userTypeName2(BarLineType t)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < sizeof(barLineTable)/sizeof(*barLineTable); ++i) {
|
|
|
|
if(barLineTable[i].type == t)
|
2014-08-22 22:19:49 +02:00
|
|
|
return qApp->translate("Palette", barLineTable[i].name);
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// BarLine
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
BarLine::BarLine(Score* s)
|
|
|
|
: Element(s)
|
|
|
|
{
|
Bar lines: fixing custom type and generated management
There are some inconsistencies in the current management of bar line `_generated` flag and user-modified type:
- Bar lines created by the New Score Wizard are flagged as non-generated, as well as bar lines of measures manually **appended** by the user, while bar lines of measures **inserted** are flagged as generated.
- If a generated bar line is individually changed of typed, it remains flagged as generated, it is not saved and the change is lost upon saving and re-loading.
- The management of the internal flag `BarLine::_customSubtype` is not always consistent.
- The `Measure::_endBarLineGenerated` flag was not always restored properly by undo.
This PR introduces the following fixes:
- The `_generated` flag is consistently used for bar lines whose type can be reconstructed from the context and then do not need to be saved to the output file.
- Normal bar lines are **always** created as generated: initially created by the Wizard, manually appended or inserted.
- Bar lines with custom type (i.e. different from the type which can be expected according to the bar line context) are always flagged as non-generated, ensuring the custom type is written to the output file.
- The `Measure::_endBarLineGenerated` flag is stored by `ChangeEndBarLineType()` and restore upon undo.
- Some test reference scores, based on the inconsistent bar line `_generated` flag, have been uniformed.
Notes:
- Tests about measure (and then bar line) appending, inserting and relative undo's are already included in the `tst_parts` test suite.
- Some inconsistencies remain in the management of custom bar line span and of system-initial bar lines: for the sake of simplicity, they will be dealt with in separate PR's.
2014-09-06 10:36:35 +02:00
|
|
|
_barLineType = BarLineType::NORMAL;
|
2012-10-14 00:35:11 +02:00
|
|
|
_span = 1;
|
|
|
|
_spanFrom = 0;
|
|
|
|
_spanTo = DEFAULT_BARLINE_TO;
|
2012-10-14 13:46:04 +02:00
|
|
|
_customSpan = false;
|
2012-11-06 14:57:04 +01:00
|
|
|
_customSubtype = false;
|
2012-10-14 18:36:08 +02:00
|
|
|
setHeight(DEFAULT_BARLINE_TO/2 * spatium()); // for use in palettes
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-08-06 14:45:03 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// mag
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal BarLine::mag() const
|
|
|
|
{
|
|
|
|
qreal m = staff() ? staff()->mag() : 1.0;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// pagePos
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QPointF BarLine::pagePos() const
|
|
|
|
{
|
|
|
|
if (parent() == 0)
|
|
|
|
return pos();
|
2012-11-08 11:32:31 +01:00
|
|
|
System* system;
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent()->type() != Element::Type::SEGMENT)
|
2012-11-08 11:32:31 +01:00
|
|
|
system = static_cast<System*>(parent());
|
|
|
|
else
|
|
|
|
system = static_cast<Segment*>(parent())->measure()->system();
|
2012-10-11 11:14:45 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal yp = y();
|
2014-02-23 11:06:03 +01:00
|
|
|
if (system) {
|
|
|
|
// get first not hidden staff
|
|
|
|
int staffIdx1 = staffIdx();
|
|
|
|
Staff* staff1 = score()->staff(staffIdx1);
|
|
|
|
SysStaff* sysStaff1 = system->staff(staffIdx1);
|
2014-02-28 13:11:00 +01:00
|
|
|
while ( staff1 && sysStaff1 && !(sysStaff1->show() && staff1->show()) ) {
|
2014-02-23 11:06:03 +01:00
|
|
|
staffIdx1++;
|
|
|
|
staff1 = score()->staff(staffIdx1);
|
|
|
|
sysStaff1 = system->staff(staffIdx1);
|
|
|
|
}
|
|
|
|
yp += system->staffYpage(staffIdx1);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
return QPointF(pageX(), yp);
|
|
|
|
}
|
|
|
|
|
2013-07-23 19:08:24 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// canvasPos
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QPointF BarLine::canvasPos() const
|
|
|
|
{
|
|
|
|
QPointF p(pagePos());
|
|
|
|
Element* e = parent();
|
|
|
|
while (e) {
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() == Element::Type::PAGE) {
|
2013-07-23 19:08:24 +02:00
|
|
|
p += e->pos();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
e = e->parent();
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// getY
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::getY(qreal* y1, qreal* y2) const
|
|
|
|
{
|
2012-10-14 00:35:11 +02:00
|
|
|
qreal _spatium = spatium();
|
2012-10-11 11:14:45 +02:00
|
|
|
if (parent()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
int staffIdx1 = staffIdx();
|
|
|
|
int staffIdx2 = staffIdx1 + _span - 1;
|
|
|
|
if (staffIdx2 >= score()->nstaves()) {
|
2012-12-08 00:16:38 +01:00
|
|
|
qDebug("BarLine: bad _span %d", _span);
|
2012-05-26 14:26:10 +02:00
|
|
|
staffIdx2 = score()->nstaves() - 1;
|
|
|
|
}
|
2012-10-11 11:14:45 +02:00
|
|
|
Measure* measure;
|
|
|
|
System* system;
|
2013-03-27 12:32:23 +01:00
|
|
|
qreal yp = 0.0;
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent()->type() == Element::Type::SEGMENT) {
|
2012-10-11 11:14:45 +02:00
|
|
|
Segment* segment = static_cast<Segment*>(parent());
|
|
|
|
measure = segment->measure();
|
2013-03-27 12:32:23 +01:00
|
|
|
system = measure->system();
|
2012-10-11 11:14:45 +02:00
|
|
|
}
|
|
|
|
else {
|
2013-03-27 12:32:23 +01:00
|
|
|
system = static_cast<System*>(parent());
|
2012-10-11 11:14:45 +02:00
|
|
|
measure = system->firstMeasure();
|
|
|
|
}
|
2013-01-25 21:17:04 +01:00
|
|
|
if (measure) {
|
2013-12-28 01:11:51 +01:00
|
|
|
// test start and end staff visibility
|
2013-12-30 09:52:54 +01:00
|
|
|
int nstaves = score()->nstaves();
|
2013-12-28 01:11:51 +01:00
|
|
|
int span = _span;
|
|
|
|
Staff* staff1 = score()->staff(staffIdx1);
|
|
|
|
Staff* staff2 = score()->staff(staffIdx2);
|
|
|
|
SysStaff* sysStaff1 = system->staff(staffIdx1);
|
|
|
|
SysStaff* sysStaff2 = system->staff(staffIdx2);
|
|
|
|
while (span > 0) {
|
|
|
|
// if start staff not shown, reduce span and move one staff down
|
|
|
|
if ( !(sysStaff1->show() && staff1->show()) ) {
|
|
|
|
span--;
|
2013-12-30 09:52:54 +01:00
|
|
|
if (staffIdx1 >= nstaves-1) // running out of staves?
|
|
|
|
break;
|
2013-12-28 01:11:51 +01:00
|
|
|
sysStaff1 = system->staff(++staffIdx1);
|
|
|
|
staff1 = score()->staff(staffIdx1);
|
|
|
|
}
|
|
|
|
// if end staff not shown, reduce span and move one staff up
|
|
|
|
else if ( !(sysStaff2->show() && staff2->show()) ) {
|
|
|
|
span--;
|
2013-12-30 09:52:54 +01:00
|
|
|
if (staffIdx2 == 0)
|
|
|
|
break;
|
2013-12-28 01:11:51 +01:00
|
|
|
sysStaff2 = system->staff(--staffIdx2);
|
|
|
|
staff2 = score()->staff(staffIdx2);
|
|
|
|
}
|
|
|
|
// if both staves shown, exit loop
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// if no longer any span, set 0 length and exit
|
|
|
|
if (span <= 0) {
|
|
|
|
*y1 = *y2 = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// both staffIdx1 and staffIdx2 are shown: compute corresponding line length
|
2013-01-25 21:17:04 +01:00
|
|
|
StaffLines* l1 = measure->staffLines(staffIdx1);
|
|
|
|
StaffLines* l2 = measure->staffLines(staffIdx2);
|
|
|
|
|
2013-03-27 12:32:23 +01:00
|
|
|
if (system)
|
2013-12-28 01:11:51 +01:00
|
|
|
yp += sysStaff1->y();
|
2013-01-25 21:17:04 +01:00
|
|
|
*y1 = l1->y1() - yp;
|
2013-05-28 15:42:02 +02:00
|
|
|
*y1 += (_spanFrom * staff1->lineDistance() * staff1->spatium()) / 2;
|
2013-01-25 21:17:04 +01:00
|
|
|
*y2 = l2->y1() - yp;
|
2013-05-28 15:42:02 +02:00
|
|
|
*y2 += (_spanTo * staff2->lineDistance() * staff2->spatium()) / 2;
|
2013-01-25 21:17:04 +01:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// for use in palette
|
2012-11-06 14:57:04 +01:00
|
|
|
*y1 = _spanFrom * _spatium / 2;
|
|
|
|
*y2 = _spanTo * _spatium / 2;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-11-08 11:32:31 +01:00
|
|
|
if (selected()) {
|
2012-10-18 23:34:03 +02:00
|
|
|
*y1 += yoff1;
|
|
|
|
*y2 += yoff2;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// drawDots
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::drawDots(QPainter* painter, qreal x) const
|
|
|
|
{
|
|
|
|
qreal _spatium = spatium();
|
|
|
|
|
|
|
|
if (parent() == 0) { // for use in palette
|
2014-01-07 13:17:03 +01:00
|
|
|
drawSymbol(SymId::repeatDot, painter, QPointF(x, 2.0 * _spatium));
|
|
|
|
drawSymbol(SymId::repeatDot, painter, QPointF(x, 3.0 * _spatium));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (parent()->type() == Element::Type::SEGMENT) {
|
2012-10-11 11:14:45 +02:00
|
|
|
System* s = static_cast<Segment*>(parent())->measure()->system();
|
2012-12-08 00:16:38 +01:00
|
|
|
int staffIdx1 = staffIdx();
|
|
|
|
int staffIdx2 = staffIdx1 + _span - 1;
|
|
|
|
int sp = _span;
|
|
|
|
if (staffIdx2 >= score()->nstaves()) {
|
|
|
|
qDebug("BarLine: bad _span %d", _span);
|
|
|
|
staffIdx2 = score()->nstaves() - 1;
|
|
|
|
sp = staffIdx2 - staffIdx1 + 1;
|
|
|
|
}
|
|
|
|
qreal dy = s->staff(staffIdx1)->y();
|
|
|
|
for (int i = 0; i < sp; ++i) {
|
|
|
|
Staff* staff = score()->staff(staffIdx1 + i);
|
2012-05-26 14:26:10 +02:00
|
|
|
StaffType* st = staff->staffType();
|
2014-01-07 13:17:03 +01:00
|
|
|
qreal doty1 = (st->doty1() + .5) * _spatium;
|
|
|
|
qreal doty2 = (st->doty2() + .5) * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2012-12-08 00:16:38 +01:00
|
|
|
qreal staffy = s->staff(staffIdx1 + i)->y() - dy;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-12-04 00:08:31 +01:00
|
|
|
drawSymbol(SymId::repeatDot, painter, QPointF(x, staffy + doty1));
|
|
|
|
drawSymbol(SymId::repeatDot, painter, QPointF(x, staffy + doty2));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// draw
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::draw(QPainter* painter) const
|
|
|
|
{
|
2013-12-28 01:11:51 +01:00
|
|
|
// get line length and do nothing if 0 (or near enough)
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal y1, y2;
|
|
|
|
getY(&y1, &y2);
|
2013-12-28 01:11:51 +01:00
|
|
|
if (y2-y1 < 0.1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
qreal _spatium = score()->spatium();
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw = score()->styleS(StyleIdx::barWidth).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
QPen pen(curColor(), lw, Qt::SolidLine, Qt::FlatCap);
|
|
|
|
painter->setPen(pen);
|
|
|
|
|
2013-03-05 20:23:59 +01:00
|
|
|
switch(barLineType()) {
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::BROKEN:
|
2012-05-26 14:26:10 +02:00
|
|
|
pen.setStyle(Qt::DashLine);
|
|
|
|
painter->setPen(pen);
|
2012-11-06 00:19:54 +01:00
|
|
|
painter->drawLine(QLineF(lw * .5, y1, lw * .5, y2));
|
|
|
|
break;
|
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::DOTTED:
|
2012-11-06 00:19:54 +01:00
|
|
|
pen.setStyle(Qt::DotLine);
|
|
|
|
painter->setPen(pen);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::NORMAL:
|
2012-05-26 14:26:10 +02:00
|
|
|
painter->drawLine(QLineF(lw * .5, y1, lw * .5, y2));
|
|
|
|
break;
|
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw2 = score()->styleS(StyleIdx::endBarWidth).val() * _spatium;
|
|
|
|
qreal d = score()->styleS(StyleIdx::endBarDistance).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
painter->drawLine(QLineF(lw * .5, y1, lw * .5, y2));
|
|
|
|
pen.setWidthF(lw2);
|
|
|
|
painter->setPen(pen);
|
|
|
|
qreal x = d + lw2 * .5 + lw;
|
|
|
|
painter->drawLine(QLineF(x, y1, x, y2));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::DOUBLE:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-26 15:31:36 +02:00
|
|
|
lw = point(score()->styleS(StyleIdx::doubleBarWidth));
|
|
|
|
qreal d = point(score()->styleS(StyleIdx::doubleBarDistance));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
pen.setWidthF(lw);
|
|
|
|
painter->setPen(pen);
|
|
|
|
qreal x = lw * .5;
|
|
|
|
painter->drawLine(QLineF(x, y1, x, y2));
|
|
|
|
x += d + lw;
|
|
|
|
painter->drawLine(QLineF(x, y1, x, y2));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::START_REPEAT:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw2 = point(score()->styleS(StyleIdx::endBarWidth));
|
|
|
|
qreal d1 = point(score()->styleS(StyleIdx::endBarDistance));
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
qreal x2 = lw2 * .5; // thick line (lw2)
|
|
|
|
qreal x1 = lw2 + d1 + lw * .5; // thin line (lw)
|
|
|
|
qreal x0 = lw2 + d1 + lw + d1; // dot position
|
|
|
|
|
|
|
|
drawDots(painter, x0);
|
|
|
|
|
|
|
|
painter->drawLine(QLineF(x1, y1, x1, y2));
|
|
|
|
|
|
|
|
pen.setWidthF(lw2);
|
|
|
|
painter->setPen(pen);
|
|
|
|
painter->drawLine(QLineF(x2, y1, x2, y2));
|
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
if (score()->styleB(StyleIdx::repeatBarTips)) {
|
2013-11-07 16:05:00 +01:00
|
|
|
drawSymbol(SymId::bracketTop, painter, QPointF(0.0, y1));
|
|
|
|
drawSymbol(SymId::bracketBottom, painter, QPointF(0.0, y2));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END_REPEAT:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw2 = point(score()->styleS(StyleIdx::endBarWidth));
|
|
|
|
qreal d1 = point(score()->styleS(StyleIdx::endBarDistance));
|
2013-12-04 00:08:31 +01:00
|
|
|
qreal dotw = symWidth(SymId::repeatDot);
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal x1 = dotw + d1 + lw * .5;
|
|
|
|
qreal x2 = dotw + d1 + lw + d1 + lw2 * .5;
|
|
|
|
|
|
|
|
drawDots(painter, 0.0);
|
|
|
|
painter->drawLine(QLineF(x1, y1, x1, y2));
|
|
|
|
pen.setWidthF(lw2);
|
|
|
|
painter->setPen(pen);
|
|
|
|
painter->drawLine(QLineF(x2, y1, x2, y2));
|
2012-09-19 19:32:15 +02:00
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
if (score()->styleB(StyleIdx::repeatBarTips)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal x = x2 + lw2 * .5;
|
2014-02-19 19:13:21 +01:00
|
|
|
qreal w1 = symBbox(SymId::reversedBracketTop).width();
|
|
|
|
drawSymbol(SymId::reversedBracketTop, painter, QPointF(x - w1, y1));
|
|
|
|
drawSymbol(SymId::reversedBracketBottom, painter, QPointF(x - w1, y2));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END_START_REPEAT:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw2 = point(score()->styleS(StyleIdx::endBarWidth));
|
|
|
|
qreal d1 = point(score()->styleS(StyleIdx::endBarDistance));
|
2013-12-04 00:08:31 +01:00
|
|
|
qreal dotw = symWidth(SymId::repeatDot);
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
qreal x1 = dotw + d1 + lw * .5; // thin bar
|
|
|
|
qreal x2 = dotw + d1 + lw + d1 + lw2 * .5; // thick bar
|
|
|
|
qreal x3 = dotw + d1 + lw + d1 + lw2 + d1 + lw * .5; // thin bar
|
|
|
|
qreal x4 = dotw + d1 + lw + d1 + lw2 + d1 + lw + d1; // dot position
|
|
|
|
|
|
|
|
drawDots(painter, .0);
|
|
|
|
drawDots(painter, x4);
|
|
|
|
painter->drawLine(QLineF(x1, y1, x1, y2));
|
|
|
|
|
|
|
|
pen.setWidthF(lw2);
|
|
|
|
painter->setPen(pen);
|
|
|
|
painter->drawLine(QLineF(x2, y1, x2, y2));
|
|
|
|
|
|
|
|
pen.setWidthF(lw);
|
|
|
|
painter->setPen(pen);
|
|
|
|
painter->drawLine(QLineF(x3, y1, x3, y2));
|
2012-09-19 19:32:15 +02:00
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
if (score()->styleB(StyleIdx::repeatBarTips)) {
|
2012-09-19 19:32:15 +02:00
|
|
|
qreal x = x2;
|
2014-02-19 19:13:21 +01:00
|
|
|
qreal w1 = symBbox(SymId::reversedBracketTop).width();
|
2013-11-07 16:05:00 +01:00
|
|
|
drawSymbol(SymId::bracketTop, painter, QPointF(x, y1));
|
|
|
|
drawSymbol(SymId::bracketBottom, painter, QPointF(x, y2));
|
2014-02-19 19:13:21 +01:00
|
|
|
drawSymbol(SymId::reversedBracketTop, painter, QPointF(x - w1, y1));
|
|
|
|
drawSymbol(SymId::reversedBracketBottom, painter, QPointF(x - w1, y2));
|
2012-09-19 19:32:15 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::write(Xml& xml) const
|
|
|
|
{
|
|
|
|
xml.stag("BarLine");
|
2013-03-05 20:23:59 +01:00
|
|
|
xml.tag("subtype", barLineTypeName());
|
2013-03-08 12:55:12 +01:00
|
|
|
if (_customSubtype)
|
2012-11-06 14:57:04 +01:00
|
|
|
xml.tag("customSubtype", _customSubtype);
|
2012-10-20 20:32:40 +02:00
|
|
|
// if any span value is different from staff's, output all values
|
2012-11-06 14:57:04 +01:00
|
|
|
if ( (staff() && ( _span != staff()->barLineSpan()
|
|
|
|
|| _spanFrom != staff()->barLineFrom()
|
|
|
|
|| _spanTo != staff()->barLineTo()
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|| !staff()) // (palette bar lines have no staff: output all values)
|
2012-10-14 00:35:11 +02:00
|
|
|
xml.tag(QString("span from=\"%1\" to=\"%2\"").arg(_spanFrom).arg(_spanTo), _span);
|
2012-10-20 20:32:40 +02:00
|
|
|
// if no custom value, output _span only (as in previous code)
|
|
|
|
else
|
|
|
|
xml.tag("span", _span);
|
2012-05-26 14:26:10 +02:00
|
|
|
foreach(const Element* e, _el)
|
|
|
|
e->write(xml);
|
|
|
|
Element::writeProperties(xml);
|
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// read
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
void BarLine::read(XmlReader& e)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2012-10-14 00:35:11 +02:00
|
|
|
// if bar line belongs to a staff, span values default to staff values
|
2013-01-11 18:10:18 +01:00
|
|
|
if (staff()) {
|
|
|
|
_span = staff()->barLineSpan();
|
|
|
|
_spanFrom = staff()->barLineFrom();
|
|
|
|
_spanTo = staff()->barLineTo();
|
|
|
|
}
|
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
const QStringRef& tag(e.name());
|
2012-05-26 14:26:10 +02:00
|
|
|
if (tag == "subtype") {
|
|
|
|
bool ok;
|
2013-01-11 18:10:18 +01:00
|
|
|
const QString& val(e.readElementText());
|
2012-05-26 14:26:10 +02:00
|
|
|
int i = val.toInt(&ok);
|
|
|
|
if (!ok)
|
2013-03-05 20:23:59 +01:00
|
|
|
setBarLineType(val);
|
2012-05-26 14:26:10 +02:00
|
|
|
else {
|
2014-05-30 10:14:09 +02:00
|
|
|
BarLineType ct = BarLineType::NORMAL;
|
2012-05-26 14:26:10 +02:00
|
|
|
switch (i) {
|
|
|
|
default:
|
2014-05-30 10:14:09 +02:00
|
|
|
case 0: ct = BarLineType::NORMAL; break;
|
|
|
|
case 1: ct = BarLineType::DOUBLE; break;
|
|
|
|
case 2: ct = BarLineType::START_REPEAT; break;
|
|
|
|
case 3: ct = BarLineType::END_REPEAT; break;
|
|
|
|
case 4: ct = BarLineType::BROKEN; break;
|
|
|
|
case 5: ct = BarLineType::END; break;
|
|
|
|
case 6: ct = BarLineType::END_START_REPEAT; break;
|
|
|
|
case 7: ct = BarLineType::DOTTED; break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
Bar lines: fixing custom type and generated management
There are some inconsistencies in the current management of bar line `_generated` flag and user-modified type:
- Bar lines created by the New Score Wizard are flagged as non-generated, as well as bar lines of measures manually **appended** by the user, while bar lines of measures **inserted** are flagged as generated.
- If a generated bar line is individually changed of typed, it remains flagged as generated, it is not saved and the change is lost upon saving and re-loading.
- The management of the internal flag `BarLine::_customSubtype` is not always consistent.
- The `Measure::_endBarLineGenerated` flag was not always restored properly by undo.
This PR introduces the following fixes:
- The `_generated` flag is consistently used for bar lines whose type can be reconstructed from the context and then do not need to be saved to the output file.
- Normal bar lines are **always** created as generated: initially created by the Wizard, manually appended or inserted.
- Bar lines with custom type (i.e. different from the type which can be expected according to the bar line context) are always flagged as non-generated, ensuring the custom type is written to the output file.
- The `Measure::_endBarLineGenerated` flag is stored by `ChangeEndBarLineType()` and restore upon undo.
- Some test reference scores, based on the inconsistent bar line `_generated` flag, have been uniformed.
Notes:
- Tests about measure (and then bar line) appending, inserting and relative undo's are already included in the `tst_parts` test suite.
- Some inconsistencies remain in the management of custom bar line span and of system-initial bar lines: for the sake of simplicity, they will be dealt with in separate PR's.
2014-09-06 10:36:35 +02:00
|
|
|
_barLineType = ct; // set type directly, without triggering setBarLineType() checks
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent() && parent()->type() == Element::Type::SEGMENT) {
|
2014-03-24 13:23:54 +01:00
|
|
|
Measure* m = static_cast<Segment*>(parent())->measure();
|
|
|
|
if (barLineType() != m->endBarLineType())
|
|
|
|
_customSubtype = true;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-11-06 14:57:04 +01:00
|
|
|
else if (tag == "customSubtype")
|
2013-03-08 12:55:12 +01:00
|
|
|
_customSubtype = e.readInt();
|
2012-10-14 00:35:11 +02:00
|
|
|
else if (tag == "span") {
|
2013-01-11 18:10:18 +01:00
|
|
|
_spanFrom = e.intAttribute("from", _spanFrom);
|
|
|
|
_spanTo = e.intAttribute("to", _spanTo);
|
2013-03-14 19:34:51 +01:00
|
|
|
_span = e.readInt();
|
2012-10-14 13:46:04 +02:00
|
|
|
// WARNING: following statements assume staff and staff bar line spans are correctly set
|
2013-01-11 18:10:18 +01:00
|
|
|
if (staff() && (_span != staff()->barLineSpan()
|
|
|
|
|| _spanFrom != staff()->barLineFrom() || _spanTo != staff()->barLineTo()))
|
2012-10-14 13:46:04 +02:00
|
|
|
_customSpan = true;
|
2012-10-14 00:35:11 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "Articulation") {
|
|
|
|
Articulation* a = new Articulation(score());
|
|
|
|
a->read(e);
|
|
|
|
add(a);
|
|
|
|
}
|
|
|
|
else if (!Element::readProperties(e))
|
2013-01-11 18:10:18 +01:00
|
|
|
e.unknown();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// space
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Space BarLine::space() const
|
|
|
|
{
|
|
|
|
return Space(0.0, width());
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// acceptDrop
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-08-13 21:01:21 +02:00
|
|
|
bool BarLine::acceptDrop(const DropData& data) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-08-13 21:01:21 +02:00
|
|
|
Element::Type type = data.element->type();
|
2014-06-24 18:36:02 +02:00
|
|
|
if (type == Element::Type::BAR_LINE) {
|
|
|
|
if (parent() && parent()->type() == Element::Type::SEGMENT)
|
2013-03-05 20:23:59 +01:00
|
|
|
return true;
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent() && parent()->type() == Element::Type::SYSTEM) {
|
2014-08-13 21:01:21 +02:00
|
|
|
BarLine* b = static_cast<BarLine*>(data.element);
|
2014-05-30 10:14:09 +02:00
|
|
|
return (b->barLineType() == BarLineType::BROKEN || b->barLineType() == BarLineType::DOTTED
|
|
|
|
|| b->barLineType() == BarLineType::NORMAL || b->barLineType() == BarLineType::DOUBLE
|
2013-03-05 20:23:59 +01:00
|
|
|
|| b->spanFrom() != 0 || b->spanTo() != DEFAULT_BARLINE_TO);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2014-06-24 18:36:02 +02:00
|
|
|
return (type == Element::Type::ARTICULATION
|
2013-03-05 20:23:59 +01:00
|
|
|
&& parent()
|
2014-06-24 18:36:02 +02:00
|
|
|
&& parent()->type() == Element::Type::SEGMENT
|
2014-06-25 11:46:10 +02:00
|
|
|
&& static_cast<Segment*>(parent())->segmentType() == Segment::Type::EndBarLine);
|
2012-10-22 14:46:35 +02:00
|
|
|
}
|
|
|
|
return false;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// drop
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* BarLine::drop(const DropData& data)
|
|
|
|
{
|
|
|
|
Element* e = data.element;
|
2014-06-24 18:36:02 +02:00
|
|
|
Element::Type type = e->type();
|
|
|
|
if (type == Element::Type::BAR_LINE) {
|
2012-05-26 14:26:10 +02:00
|
|
|
BarLine* bl = static_cast<BarLine*>(e);
|
2013-03-05 20:23:59 +01:00
|
|
|
BarLineType st = bl->barLineType();
|
2012-11-06 14:57:04 +01:00
|
|
|
// if no change in subtype or no change in span, do nothing
|
2013-03-05 20:23:59 +01:00
|
|
|
if (st == barLineType() && bl->spanFrom() == 0 && bl->spanTo() == DEFAULT_BARLINE_TO) {
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
2012-11-11 01:50:57 +01:00
|
|
|
// system left-side bar line
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent()->type() == Element::Type::SYSTEM) {
|
2012-10-17 20:22:24 +02:00
|
|
|
BarLine* b = static_cast<System*>(parent())->barLine();
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(b, P_ID::SUBTYPE, int(bl->barLineType()));
|
2012-10-17 20:22:24 +02:00
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
2012-11-06 14:57:04 +01:00
|
|
|
|
2013-03-19 16:01:43 +01:00
|
|
|
//parent is a segment
|
|
|
|
Measure* m = static_cast<Segment*>(parent())->measure();
|
|
|
|
|
2012-11-06 14:57:04 +01:00
|
|
|
// check if the new property can apply to this single bar line
|
2014-05-30 10:14:09 +02:00
|
|
|
bool oldRepeat = (barLineType() == BarLineType::START_REPEAT || barLineType() == BarLineType::END_REPEAT
|
|
|
|
|| barLineType() == BarLineType::END_START_REPEAT);
|
|
|
|
bool newRepeat = (bl->barLineType() == BarLineType::START_REPEAT || bl->barLineType() == BarLineType::END_REPEAT
|
|
|
|
|| bl->barLineType() == BarLineType::END_START_REPEAT);
|
2012-11-06 14:57:04 +01:00
|
|
|
// if repeats are not involved or drop refers to span rather than subtype =>
|
|
|
|
// single bar line drop
|
|
|
|
if( (!oldRepeat && !newRepeat) || (bl->spanFrom() != 0 || bl->spanTo() != DEFAULT_BARLINE_TO) ) {
|
|
|
|
// if drop refers to span, update this bar line span
|
|
|
|
if(bl->spanFrom() != 0 || bl->spanTo() != DEFAULT_BARLINE_TO) {
|
|
|
|
// if dropped spanFrom or spanTo are below the middle of standard staff (5 lines)
|
2012-11-11 01:50:57 +01:00
|
|
|
// adjust to the number of syaff lines
|
2012-11-06 14:57:04 +01:00
|
|
|
int bottomSpan = (staff()->lines()-1) * 2;
|
|
|
|
int spanFrom = bl->spanFrom() > 4 ? bottomSpan - (8 - bl->spanFrom()) : bl->spanFrom();
|
|
|
|
int spanTo = bl->spanTo() > 4 ? bottomSpan - (8 - bl->spanTo()) : bl->spanTo();
|
|
|
|
score()->undoChangeSingleBarLineSpan(this, 1, spanFrom, spanTo);
|
|
|
|
}
|
|
|
|
// if drop refer to subtype, update this bar line subtype
|
|
|
|
else {
|
2013-03-23 00:57:37 +01:00
|
|
|
// score()->undoChangeBarLine(m, bl->barLineType());
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(this, P_ID::SUBTYPE, int(bl->barLineType()));
|
2012-11-06 14:57:04 +01:00
|
|
|
}
|
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// drop applies to all bar lines of the measure
|
2014-05-30 10:14:09 +02:00
|
|
|
if (st == BarLineType::START_REPEAT) {
|
2012-05-26 14:26:10 +02:00
|
|
|
m = m->nextMeasure();
|
|
|
|
if (m == 0) {
|
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m->drop(data);
|
|
|
|
}
|
2014-06-24 18:36:02 +02:00
|
|
|
else if (type == Element::Type::ARTICULATION) {
|
2012-05-26 14:26:10 +02:00
|
|
|
Articulation* atr = static_cast<Articulation*>(e);
|
|
|
|
atr->setParent(this);
|
|
|
|
atr->setTrack(track());
|
|
|
|
score()->undoAddElement(atr);
|
|
|
|
return atr;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateGrips
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-03-16 14:57:32 +01:00
|
|
|
void BarLine::updateGrips(int* grips, int* defaultGrip, QRectF* grip) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2012-10-14 00:35:11 +02:00
|
|
|
*grips = 2;
|
2014-03-16 14:57:32 +01:00
|
|
|
*defaultGrip = 1;
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw = point(score()->styleS(StyleIdx::barWidth));
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal y1, y2;
|
|
|
|
getY(&y1, &y2);
|
2012-10-14 00:35:11 +02:00
|
|
|
grip[0].translate(QPointF(lw * .5, y1) + pagePos());
|
|
|
|
grip[1].translate(QPointF(lw * .5, y2) + pagePos());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-10-14 19:48:36 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// startEdit
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::startEdit(MuseScoreView*, const QPointF&)
|
|
|
|
{
|
|
|
|
// keep a copy of original span values
|
|
|
|
_origSpan = _span;
|
|
|
|
_origSpanFrom = _spanFrom;
|
|
|
|
_origSpanTo = _spanTo;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// endEdit
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::endEdit()
|
|
|
|
{
|
2014-04-14 19:42:12 +02:00
|
|
|
shiftDrag = false;
|
|
|
|
|
2013-03-08 12:55:12 +01:00
|
|
|
if (ctrlDrag) { // if single bar line edit
|
2012-10-14 13:46:04 +02:00
|
|
|
ctrlDrag = false;
|
2012-10-14 19:48:36 +02:00
|
|
|
_customSpan = true; // mark bar line as custom spanning
|
|
|
|
int newSpan = _span; // copy edited span values
|
|
|
|
int newSpanFrom = _spanFrom;
|
|
|
|
int newSpanTo = _spanTo;
|
|
|
|
_span = _origSpan; // restore original span values
|
|
|
|
_spanFrom = _origSpanFrom;
|
|
|
|
_spanTo = _origSpanTo;
|
|
|
|
score()->undoChangeSingleBarLineSpan(this, newSpan, newSpanFrom, newSpanTo);
|
2012-10-14 13:46:04 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-11 01:50:57 +01:00
|
|
|
// if same as staff settings, do nothing
|
2012-10-14 00:35:11 +02:00
|
|
|
if (staff()->barLineSpan() == _span && staff()->barLineFrom() == _spanFrom && staff()->barLineTo() == _spanTo)
|
2012-05-26 14:26:10 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
int idx1 = staffIdx();
|
|
|
|
|
2012-10-14 00:35:11 +02:00
|
|
|
if(_span != staff()->barLineSpan()) {
|
|
|
|
// if now bar lines span more staves
|
|
|
|
if (_span > staff()->barLineSpan()) {
|
|
|
|
int idx2 = idx1 + _span;
|
|
|
|
// set span 0 to all additional staves
|
|
|
|
for (int idx = idx1 + 1; idx < idx2; ++idx)
|
2012-11-02 10:03:07 +01:00
|
|
|
// mensurstrich special case:
|
|
|
|
// if line spans to top line of a stave AND current staff is
|
|
|
|
// the last spanned staff BUT NOT the last score staff
|
|
|
|
// keep its bar lines
|
|
|
|
// otherwise remove them
|
|
|
|
if(_spanTo > 0 || !(idx == idx2-1 && idx != score()->nstaves()-1) )
|
|
|
|
score()->undoChangeBarLineSpan(score()->staff(idx), 0, 0,
|
|
|
|
(score()->staff(idx)->lines()-1)*2);
|
2012-10-14 00:35:11 +02:00
|
|
|
}
|
|
|
|
// if now bar lines span fewer staves
|
|
|
|
else {
|
|
|
|
int idx1 = staffIdx() + _span;
|
|
|
|
int idx2 = staffIdx() + staff()->barLineSpan();
|
2012-11-11 01:50:57 +01:00
|
|
|
// set standard span for each no-longer-spanned staff
|
2012-10-14 00:35:11 +02:00
|
|
|
for (int idx = idx1; idx < idx2; ++idx)
|
2012-10-14 18:36:08 +02:00
|
|
|
score()->undoChangeBarLineSpan(score()->staff(idx), 1, 0, (score()->staff(idx)->lines()-1)*2);
|
2012-10-14 00:35:11 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-10-14 13:46:04 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
// update span for the staff the edited bar line belongs to
|
2012-10-14 00:35:11 +02:00
|
|
|
score()->undoChangeBarLineSpan(staff(), _span, _spanFrom, _spanTo);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// editDrag
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::editDrag(const EditData& ed)
|
|
|
|
{
|
2012-10-14 00:35:11 +02:00
|
|
|
qreal lineDist = staff()->lineDistance() * spatium();
|
|
|
|
qreal min, max, lastmax, y1, y2;
|
|
|
|
getY(&y1, &y2);
|
|
|
|
y1 -= yoff1; // current positions of barline ends, ignoring any in-process dragging
|
|
|
|
y2 -= yoff2;
|
|
|
|
if(ed.curGrip == 0) {
|
|
|
|
// min offset for top grip is line -1
|
|
|
|
// max offset is 1 line above bottom grip or 1 below last staff line, whichever comes first
|
|
|
|
min = -y1 - lineDist;
|
|
|
|
max = y2 - y1 - lineDist; // 1 line above bottom grip
|
2012-10-14 18:36:08 +02:00
|
|
|
lastmax = (staff()->lines() - _spanFrom/2) * lineDist; // 1 line below last staff line
|
2012-10-14 00:35:11 +02:00
|
|
|
if(lastmax < max)
|
|
|
|
max = lastmax;
|
|
|
|
// update yoff1 and bring it within limits
|
|
|
|
yoff1 += ed.delta.y();
|
|
|
|
if(yoff1 < min)
|
|
|
|
yoff1 = min;
|
|
|
|
if(yoff1 > max)
|
|
|
|
yoff1 = max;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// min for bottom grip is 1 line below top grip
|
|
|
|
// no max
|
|
|
|
min = y1 - y2 + lineDist;
|
|
|
|
// update yoff2 and bring it within limit
|
|
|
|
yoff2 += ed.delta.y();
|
|
|
|
if(yoff2 < min)
|
|
|
|
yoff2 = min;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// endEditDrag
|
2012-10-14 00:35:11 +02:00
|
|
|
// snap to nearest staff / staff line
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::endEditDrag()
|
|
|
|
{
|
2014-04-14 19:42:12 +02:00
|
|
|
if (yoff1 == 0.0 && yoff2 == 0.0) // if no drag, do nothing
|
|
|
|
return;
|
|
|
|
|
2012-10-14 00:35:11 +02:00
|
|
|
qreal y1, y2;
|
|
|
|
getY(&y1, &y2);
|
|
|
|
qreal ay0 = pagePos().y();
|
|
|
|
qreal ay2 = ay0 + y2; // absolute (page-relative) bar line bottom coord
|
2012-05-26 14:26:10 +02:00
|
|
|
int staffIdx1 = staffIdx();
|
|
|
|
int staffIdx2;
|
2012-10-22 14:46:35 +02:00
|
|
|
System* syst;
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent()->type() == Element::Type::SYSTEM) {
|
2012-10-22 14:46:35 +02:00
|
|
|
syst = static_cast<System*>(parent());
|
2012-11-08 11:32:31 +01:00
|
|
|
}
|
2012-10-22 14:46:35 +02:00
|
|
|
else {
|
|
|
|
syst = static_cast<Segment*>(parent())->measure()->system();
|
2012-11-08 11:32:31 +01:00
|
|
|
}
|
2012-10-22 14:46:35 +02:00
|
|
|
qreal systTopY = syst->pagePos().y();
|
2012-10-14 00:35:11 +02:00
|
|
|
|
|
|
|
// determine new span value
|
|
|
|
int numOfStaves = syst->staves()->size();
|
|
|
|
if (staffIdx1 + 1 >= numOfStaves)
|
|
|
|
// if initial staff is last staff, ending staff must be the same
|
2012-05-26 14:26:10 +02:00
|
|
|
staffIdx2 = staffIdx1;
|
2012-10-14 00:35:11 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
else {
|
2012-10-14 00:35:11 +02:00
|
|
|
// if there are other staves after it, look for staff nearest to bar line bottom coord
|
|
|
|
qreal staff1TopY = syst->staff(staffIdx1)->y() + systTopY;
|
|
|
|
|
|
|
|
for (staffIdx2 = staffIdx1 + 1; staffIdx2 < numOfStaves; ++staffIdx2) {
|
|
|
|
// compute 1st staff height, absolute top Y of 2nd staff and height of blank between the staves
|
|
|
|
Staff * staff1 = score()->staff(staffIdx2-1);
|
|
|
|
qreal staff1Hght = (staff1->lines()-1) * staff1->lineDistance() * spatium();
|
|
|
|
qreal staff2TopY = systTopY + syst->staff(staffIdx2)->y();
|
|
|
|
qreal blnkBtwnStaff = staff2TopY - staff1TopY - staff1Hght;
|
|
|
|
// if bar line bottom coord is above than mid-way of blank between staves...
|
|
|
|
if (ay2 < (staff1TopY + staff1Hght + blnkBtwnStaff * .5))
|
|
|
|
break; // ...staff 1 is ending staff
|
|
|
|
// if bar line is below, advance to next staff
|
|
|
|
staff1TopY = staff2TopY;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
staffIdx2 -= 1;
|
|
|
|
}
|
|
|
|
int newSpan = staffIdx2 - staffIdx1 + 1;
|
2012-10-14 00:35:11 +02:00
|
|
|
|
2014-04-14 19:42:12 +02:00
|
|
|
// determine new spanFrom and spanTo values
|
|
|
|
int newSpanFrom, newSpanTo;
|
|
|
|
Staff * staff2 = score()->staff(staffIdx2);
|
|
|
|
int Staff1lines = staff()->lines();
|
|
|
|
int Staff2lines = staff2->lines();
|
|
|
|
|
|
|
|
if (shiftDrag) { // if precision dragging
|
|
|
|
newSpanFrom = _spanFrom;
|
|
|
|
if(yoff1 != 0.0) {
|
|
|
|
// round bar line top coord to nearest line of 1st staff (in half line dist units)
|
|
|
|
newSpanFrom = ((int)floor(y1 / (staff()->lineDistance() * spatium()) + 0.5 )) * 2;
|
|
|
|
// min = 1 line dist above 1st staff line | max = 1 line dist below last staff line
|
|
|
|
if(newSpanFrom < MIN_BARLINE_SPAN_FROMTO)
|
|
|
|
newSpanFrom = MIN_BARLINE_SPAN_FROMTO;
|
|
|
|
if(newSpanFrom > Staff1lines*2)
|
|
|
|
newSpanFrom = Staff1lines*2;
|
|
|
|
}
|
2012-10-14 00:35:11 +02:00
|
|
|
|
2014-04-14 19:42:12 +02:00
|
|
|
newSpanTo = _spanTo;
|
|
|
|
if(yoff2 != 0.0) {
|
|
|
|
// round bar line bottom coord to nearest line of 2nd staff (in half line dist units)
|
|
|
|
qreal staff2TopY = systTopY + syst->staff(staffIdx2)->y();
|
|
|
|
newSpanTo = ((int)floor( (ay2 - staff2TopY) / (staff2->lineDistance() * spatium()) + 0.5 )) * 2;
|
|
|
|
// min = 1 line dist above 1st staff line | max = 1 line dist below last staff line
|
|
|
|
if(newSpanTo < MIN_BARLINE_SPAN_FROMTO)
|
|
|
|
newSpanTo = MIN_BARLINE_SPAN_FROMTO;
|
|
|
|
if(newSpanTo > Staff2lines*2)
|
|
|
|
newSpanTo = Staff2lines*2;
|
|
|
|
}
|
|
|
|
// shiftDrag = false; // NO: a last call to this function is made when exiting editing:
|
|
|
|
} // it would find shiftDrag = false and reset extrema to coarse resolution
|
|
|
|
|
|
|
|
else { // if coarse dragging
|
2014-04-08 10:42:25 +02:00
|
|
|
newSpanFrom = 0;
|
2014-04-14 19:42:12 +02:00
|
|
|
newSpanTo = (Staff2lines - 1) * 2;
|
|
|
|
}
|
2014-04-09 16:09:21 +02:00
|
|
|
|
2012-10-14 13:46:04 +02:00
|
|
|
// if any value changed, update
|
|
|
|
if(newSpan != _span || newSpanFrom != _spanFrom || newSpanTo != _spanTo) {
|
2012-10-14 00:35:11 +02:00
|
|
|
_span = newSpan;
|
|
|
|
_spanFrom = newSpanFrom;
|
|
|
|
_spanTo = newSpanTo;
|
|
|
|
}
|
2012-10-14 13:46:04 +02:00
|
|
|
|
|
|
|
yoff1 = yoff2 = 0.0;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-08-02 18:33:43 +02:00
|
|
|
// layoutWidth
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-02 18:33:43 +02:00
|
|
|
qreal BarLine::layoutWidth(Score* score, BarLineType type, qreal mag)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2012-08-02 18:33:43 +02:00
|
|
|
qreal _spatium = score->spatium();
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal dw = score->styleS(StyleIdx::barWidth).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-12-04 00:08:31 +01:00
|
|
|
qreal dotwidth = score->scoreFont()->width(SymId::repeatDot, mag);
|
2012-08-02 18:33:43 +02:00
|
|
|
switch(type) {
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::DOUBLE:
|
2014-05-26 15:31:36 +02:00
|
|
|
dw = (score->styleS(StyleIdx::doubleBarWidth) * 2
|
|
|
|
+ score->styleS(StyleIdx::doubleBarDistance)).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::START_REPEAT:
|
2014-05-26 15:31:36 +02:00
|
|
|
dw += dotwidth + (score->styleS(StyleIdx::endBarWidth)
|
|
|
|
+ 2 * score->styleS(StyleIdx::endBarDistance)).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END_REPEAT:
|
2014-05-26 15:31:36 +02:00
|
|
|
dw += dotwidth + (score->styleS(StyleIdx::endBarWidth)
|
|
|
|
+ 2 * score->styleS(StyleIdx::endBarDistance)).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END:
|
2014-05-26 15:31:36 +02:00
|
|
|
dw += (score->styleS(StyleIdx::endBarWidth)
|
|
|
|
+ score->styleS(StyleIdx::endBarDistance)).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END_START_REPEAT:
|
2014-05-26 15:31:36 +02:00
|
|
|
dw += 2 * dotwidth + (score->styleS(StyleIdx::barWidth)
|
|
|
|
+ score->styleS(StyleIdx::endBarWidth)
|
|
|
|
+ 4 * score->styleS(StyleIdx::endBarDistance)).val() * _spatium;
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::BROKEN:
|
|
|
|
case BarLineType::NORMAL:
|
|
|
|
case BarLineType::DOTTED:
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
default:
|
2012-12-08 00:16:38 +01:00
|
|
|
qDebug("illegal bar line type");
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-08-02 18:33:43 +02:00
|
|
|
return dw;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// layout
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::layout()
|
|
|
|
{
|
|
|
|
qreal y1, y2;
|
|
|
|
getY(&y1, &y2);
|
|
|
|
|
2013-03-17 00:54:17 +01:00
|
|
|
// if bar line does not belong to a system, has a staff and staff is set to hide bar lines, set null bbox
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent() && parent()->type() != Element::Type::SYSTEM && staff() && !staff()->staffType()->showBarlines())
|
2013-03-17 00:54:17 +01:00
|
|
|
setbbox(QRectF());
|
2012-09-19 19:32:15 +02:00
|
|
|
|
2013-03-17 00:54:17 +01:00
|
|
|
// bar lines not hidden
|
|
|
|
else {
|
|
|
|
qreal dw = layoutWidth(score(), barLineType(), magS());
|
|
|
|
QRectF r(0.0, y1, dw, y2-y1);
|
|
|
|
|
2014-05-26 15:31:36 +02:00
|
|
|
if (score()->styleB(StyleIdx::repeatBarTips)) {
|
2013-03-17 00:54:17 +01:00
|
|
|
switch (barLineType()) {
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::START_REPEAT:
|
2013-11-11 15:11:28 +01:00
|
|
|
r |= symBbox(SymId::bracketTop).translated(0, y1);
|
|
|
|
r |= symBbox(SymId::bracketBottom).translated(0, y2);
|
2013-03-17 00:54:17 +01:00
|
|
|
break;
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END_REPEAT:
|
2014-02-19 19:13:21 +01:00
|
|
|
{
|
|
|
|
qreal w1 = symBbox(SymId::reversedBracketTop).width();
|
|
|
|
r |= symBbox(SymId::reversedBracketTop).translated(dw - w1, y1);
|
|
|
|
r |= symBbox(SymId::reversedBracketBottom).translated(dw - w1, y2);
|
2013-03-17 00:54:17 +01:00
|
|
|
break;
|
2014-02-19 19:13:21 +01:00
|
|
|
}
|
2013-03-17 00:54:17 +01:00
|
|
|
|
2014-05-30 10:14:09 +02:00
|
|
|
case BarLineType::END_START_REPEAT:
|
2013-03-17 00:54:17 +01:00
|
|
|
{
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal lw = point(score()->styleS(StyleIdx::barWidth));
|
|
|
|
qreal lw2 = point(score()->styleS(StyleIdx::endBarWidth));
|
|
|
|
qreal d1 = point(score()->styleS(StyleIdx::endBarDistance));
|
2013-12-04 00:08:31 +01:00
|
|
|
qreal dotw = symWidth(SymId::repeatDot);
|
2013-03-17 00:54:17 +01:00
|
|
|
qreal x = dotw + 2 * d1 + lw + lw2 * .5; // thick bar
|
2014-02-19 19:13:21 +01:00
|
|
|
qreal w1 = symBbox(SymId::reversedBracketTop).width();
|
2013-11-11 15:11:28 +01:00
|
|
|
r |= symBbox(SymId::bracketTop).translated(x, y1);
|
|
|
|
r |= symBbox(SymId::bracketBottom).translated(x, y2);
|
2014-02-19 19:13:21 +01:00
|
|
|
r |= symBbox(SymId::reversedBracketTop).translated(x - w1 , y1);
|
|
|
|
r |= symBbox(SymId::reversedBracketBottom).translated(x - w1, y2);
|
2013-03-17 00:54:17 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-03-17 00:54:17 +01:00
|
|
|
setbbox(r);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-03-17 00:54:17 +01:00
|
|
|
|
|
|
|
// in any case, lay out attached elements
|
2012-05-26 14:26:10 +02:00
|
|
|
foreach(Element* e, _el) {
|
|
|
|
e->layout();
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() == Element::Type::ARTICULATION) {
|
2014-06-26 10:53:57 +02:00
|
|
|
Articulation* a = static_cast<Articulation*>(e);
|
|
|
|
MScore::Direction dir = a->direction();
|
|
|
|
qreal distance = 0.5 * spatium();
|
|
|
|
qreal x = width() * .5;
|
|
|
|
if (dir == MScore::Direction::DOWN) {
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal botY = y2 + distance;
|
|
|
|
a->setPos(QPointF(x, botY));
|
|
|
|
}
|
2012-10-23 16:09:45 +02:00
|
|
|
else {
|
|
|
|
qreal topY = y1 - distance;
|
|
|
|
a->setPos(QPointF(x, topY));
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// shape
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QPainterPath BarLine::shape() const
|
|
|
|
{
|
|
|
|
QPainterPath p;
|
|
|
|
qreal d = spatium() * .3;
|
|
|
|
p.addRect(bbox().adjusted(-d, .0, d, .0));
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// tick
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int BarLine::tick() const
|
|
|
|
{
|
2014-06-24 18:36:02 +02:00
|
|
|
return (parent() && parent()->type() == Element::Type::SEGMENT)
|
2012-10-11 11:14:45 +02:00
|
|
|
? static_cast<Segment*>(parent())->tick() : 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2013-03-05 20:23:59 +01:00
|
|
|
// barLineTypeName
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-03-05 20:23:59 +01:00
|
|
|
QString BarLine::barLineTypeName() const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-30 10:14:09 +02:00
|
|
|
return QString(barLineNames[int(barLineType())]);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2013-03-05 20:23:59 +01:00
|
|
|
// setBarLineType
|
Bar lines: fixing custom type and generated management
There are some inconsistencies in the current management of bar line `_generated` flag and user-modified type:
- Bar lines created by the New Score Wizard are flagged as non-generated, as well as bar lines of measures manually **appended** by the user, while bar lines of measures **inserted** are flagged as generated.
- If a generated bar line is individually changed of typed, it remains flagged as generated, it is not saved and the change is lost upon saving and re-loading.
- The management of the internal flag `BarLine::_customSubtype` is not always consistent.
- The `Measure::_endBarLineGenerated` flag was not always restored properly by undo.
This PR introduces the following fixes:
- The `_generated` flag is consistently used for bar lines whose type can be reconstructed from the context and then do not need to be saved to the output file.
- Normal bar lines are **always** created as generated: initially created by the Wizard, manually appended or inserted.
- Bar lines with custom type (i.e. different from the type which can be expected according to the bar line context) are always flagged as non-generated, ensuring the custom type is written to the output file.
- The `Measure::_endBarLineGenerated` flag is stored by `ChangeEndBarLineType()` and restore upon undo.
- Some test reference scores, based on the inconsistent bar line `_generated` flag, have been uniformed.
Notes:
- Tests about measure (and then bar line) appending, inserting and relative undo's are already included in the `tst_parts` test suite.
- Some inconsistencies remain in the management of custom bar line span and of system-initial bar lines: for the sake of simplicity, they will be dealt with in separate PR's.
2014-09-06 10:36:35 +02:00
|
|
|
//
|
|
|
|
// Set the bar line type from the type name string.
|
|
|
|
// Does not update _customSubtype or _generated flags: to be used when reading from a score file
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-03-05 20:23:59 +01:00
|
|
|
void BarLine::setBarLineType(const QString& s)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < sizeof(barLineNames)/sizeof(*barLineNames); ++i) {
|
|
|
|
if (barLineNames[i] == s) {
|
2013-03-05 20:23:59 +01:00
|
|
|
_barLineType = BarLineType(i);
|
2012-05-26 14:26:10 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2014-05-30 10:14:09 +02:00
|
|
|
_barLineType = BarLineType::NORMAL;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// scanElements
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::scanElements(void* data, void (*func)(void*, Element*), bool all)
|
|
|
|
{
|
2013-03-25 23:35:36 +01:00
|
|
|
// if no width (staff has bar lines turned off) and not all requested, do nothing
|
|
|
|
if (width() == 0.0 && !all)
|
|
|
|
return;
|
2012-05-26 14:26:10 +02:00
|
|
|
func(data, this);
|
|
|
|
foreach(Element* e, _el)
|
|
|
|
e->scanElements(data, func, all);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// add
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::add(Element* e)
|
|
|
|
{
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent() && parent()->type() != Element::Type::SEGMENT) {
|
2012-10-11 11:14:45 +02:00
|
|
|
delete e;
|
|
|
|
return;
|
|
|
|
}
|
2014-05-30 13:35:44 +02:00
|
|
|
e->setParent(this);
|
2012-05-26 14:26:10 +02:00
|
|
|
switch(e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ARTICULATION:
|
2013-03-25 16:27:20 +01:00
|
|
|
_el.push_back(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
setGenerated(false);
|
2012-10-11 11:14:45 +02:00
|
|
|
if (parent() && parent()->parent())
|
|
|
|
static_cast<Measure*>(parent()->parent())->setEndBarLineGenerated(false);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
default:
|
2012-12-08 00:16:38 +01:00
|
|
|
qDebug("BarLine::add() not impl. %s", e->name());
|
2012-10-11 11:14:45 +02:00
|
|
|
delete e;
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::remove(Element* e)
|
|
|
|
{
|
|
|
|
switch(e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ARTICULATION:
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!_el.remove(e))
|
2012-12-08 00:16:38 +01:00
|
|
|
qDebug("BarLine::remove(): cannot find %s", e->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
default:
|
2012-12-08 00:16:38 +01:00
|
|
|
qDebug("BarLine::remove() not impl. %s", e->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-18 13:01:50 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateCustomSpan
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::updateCustomSpan()
|
|
|
|
{
|
|
|
|
// if barline belongs to a staff and any of the staff span params is different from barline's...
|
|
|
|
if (staff())
|
|
|
|
if (staff()->barLineSpan() != _span || staff()->barLineFrom() != _spanFrom || staff()->barLineTo() != _spanTo) {
|
|
|
|
_customSpan = true; // ...span is custom
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// if no staff or same span params as staff, span is not custom
|
|
|
|
_customSpan = false;
|
|
|
|
}
|
|
|
|
|
Bar lines: fixing custom type and generated management
There are some inconsistencies in the current management of bar line `_generated` flag and user-modified type:
- Bar lines created by the New Score Wizard are flagged as non-generated, as well as bar lines of measures manually **appended** by the user, while bar lines of measures **inserted** are flagged as generated.
- If a generated bar line is individually changed of typed, it remains flagged as generated, it is not saved and the change is lost upon saving and re-loading.
- The management of the internal flag `BarLine::_customSubtype` is not always consistent.
- The `Measure::_endBarLineGenerated` flag was not always restored properly by undo.
This PR introduces the following fixes:
- The `_generated` flag is consistently used for bar lines whose type can be reconstructed from the context and then do not need to be saved to the output file.
- Normal bar lines are **always** created as generated: initially created by the Wizard, manually appended or inserted.
- Bar lines with custom type (i.e. different from the type which can be expected according to the bar line context) are always flagged as non-generated, ensuring the custom type is written to the output file.
- The `Measure::_endBarLineGenerated` flag is stored by `ChangeEndBarLineType()` and restore upon undo.
- Some test reference scores, based on the inconsistent bar line `_generated` flag, have been uniformed.
Notes:
- Tests about measure (and then bar line) appending, inserting and relative undo's are already included in the `tst_parts` test suite.
- Some inconsistencies remain in the management of custom bar line span and of system-initial bar lines: for the sake of simplicity, they will be dealt with in separate PR's.
2014-09-06 10:36:35 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateCustomType
|
|
|
|
//
|
|
|
|
// Turns off _customSubtype flag if bar line type is the same of the context it is in
|
|
|
|
// (usually the endBarLineType of the measure); turns it on otherwise.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::updateCustomType()
|
|
|
|
{
|
|
|
|
BarLineType refType = BarLineType::NORMAL;
|
|
|
|
if (parent()) {
|
|
|
|
if (parent()->type() == Element::Type::SEGMENT) {
|
|
|
|
Segment* seg = static_cast<Segment*>(parent());
|
|
|
|
switch (seg->segmentType()) {
|
|
|
|
case Segment::Type::StartRepeatBarLine:
|
|
|
|
// if a start-repeat segment, ref. type is START_REPEAT
|
|
|
|
// if measure has relevant repeat flag or none if measure hasn't
|
|
|
|
refType = (seg->measure()->repeatFlags() & Repeat::START) != 0
|
|
|
|
? BarLineType::START_REPEAT : BarLineType(-1);
|
|
|
|
break;
|
|
|
|
case Segment::Type::BarLine:
|
|
|
|
// if a non-end-measure bar line, type is always custom
|
|
|
|
refType = BarLineType(-1); // use an invalid type
|
|
|
|
break;
|
|
|
|
case Segment::Type::EndBarLine:
|
|
|
|
// if end-measure bar line, reference type is the measure endBarLinetype
|
|
|
|
refType = seg->measure()->endBarLineType();
|
|
|
|
break;
|
|
|
|
default: // keep lint happy!
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if parent is not a segment, it can only be a system and NORMAL can be used as ref. type
|
|
|
|
}
|
|
|
|
_customSubtype = (_barLineType != refType);
|
|
|
|
updateGenerated(!_customSubtype); // if _customSubType, _genereated is surely false
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateGenerated
|
|
|
|
//
|
|
|
|
// Sets the _generated status flag by checking all the bar line properties are at default values.
|
|
|
|
//
|
|
|
|
// canBeTrue: optional parameter; if set to false, the _generated flag is unconditionally set to false
|
|
|
|
// without checking the individual properties; to be used when a non-default condition is already known
|
|
|
|
// to speed up the function.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void BarLine::updateGenerated(bool canBeTrue)
|
|
|
|
{
|
|
|
|
if (!canBeTrue)
|
|
|
|
setGenerated(false);
|
|
|
|
else {
|
|
|
|
bool generatedType = !_customSubtype; // if customSubType, assume not generated
|
|
|
|
if (parent()) {
|
|
|
|
if (parent()->type() == Element::Type::SEGMENT) {
|
|
|
|
// if bar line belongs to an EndBarLine segment,
|
|
|
|
// combine with measure endBarLineGenerated flag
|
|
|
|
if (static_cast<Segment*>(parent())->segmentType() == Segment::Type::EndBarLine)
|
|
|
|
generatedType &= static_cast<Segment*>(parent())->measure()->endBarLineGenerated();
|
|
|
|
// if any other segment (namely, StartBarLine and BarLine), bar line is not generated
|
|
|
|
else
|
|
|
|
generatedType = false;
|
|
|
|
}
|
|
|
|
// if bar line does not belongs to a segment, it belongs to a system and is generated only if NORMAL
|
|
|
|
else
|
|
|
|
generatedType = (_barLineType == BarLineType::NORMAL);
|
|
|
|
}
|
|
|
|
// set to generated only if all properties are non-customized
|
|
|
|
setGenerated(
|
|
|
|
color() == MScore::defaultColor
|
|
|
|
&& _visible == true
|
|
|
|
&& generatedType == true
|
|
|
|
&& _customSpan == false
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// getProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-10 17:01:35 +02:00
|
|
|
QVariant BarLine::getProperty(P_ID id) const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-03-07 20:01:22 +01:00
|
|
|
switch (id) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::SUBTYPE:
|
2013-03-07 20:01:22 +01:00
|
|
|
return int(_barLineType);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN:
|
2013-03-07 20:01:22 +01:00
|
|
|
return span();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN_FROM:
|
2013-03-08 12:55:12 +01:00
|
|
|
return spanFrom();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN_TO:
|
2013-03-08 12:55:12 +01:00
|
|
|
return spanTo();
|
2013-03-07 20:01:22 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2012-08-10 17:01:35 +02:00
|
|
|
return Element::getProperty(id);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-08-10 17:01:35 +02:00
|
|
|
bool BarLine::setProperty(P_ID id, const QVariant& v)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-03-07 20:01:22 +01:00
|
|
|
switch(id) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::SUBTYPE:
|
Bar lines: fixing custom type and generated management
There are some inconsistencies in the current management of bar line `_generated` flag and user-modified type:
- Bar lines created by the New Score Wizard are flagged as non-generated, as well as bar lines of measures manually **appended** by the user, while bar lines of measures **inserted** are flagged as generated.
- If a generated bar line is individually changed of typed, it remains flagged as generated, it is not saved and the change is lost upon saving and re-loading.
- The management of the internal flag `BarLine::_customSubtype` is not always consistent.
- The `Measure::_endBarLineGenerated` flag was not always restored properly by undo.
This PR introduces the following fixes:
- The `_generated` flag is consistently used for bar lines whose type can be reconstructed from the context and then do not need to be saved to the output file.
- Normal bar lines are **always** created as generated: initially created by the Wizard, manually appended or inserted.
- Bar lines with custom type (i.e. different from the type which can be expected according to the bar line context) are always flagged as non-generated, ensuring the custom type is written to the output file.
- The `Measure::_endBarLineGenerated` flag is stored by `ChangeEndBarLineType()` and restore upon undo.
- Some test reference scores, based on the inconsistent bar line `_generated` flag, have been uniformed.
Notes:
- Tests about measure (and then bar line) appending, inserting and relative undo's are already included in the `tst_parts` test suite.
- Some inconsistencies remain in the management of custom bar line span and of system-initial bar lines: for the sake of simplicity, they will be dealt with in separate PR's.
2014-09-06 10:36:35 +02:00
|
|
|
setBarLineType(BarLineType(v.toInt()));
|
2013-03-07 20:01:22 +01:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN:
|
2013-03-07 20:01:22 +01:00
|
|
|
setSpan(v.toInt());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN_FROM:
|
2013-03-08 12:55:12 +01:00
|
|
|
setSpanFrom(v.toInt());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN_TO:
|
2013-03-08 12:55:12 +01:00
|
|
|
setSpanTo(v.toInt());
|
|
|
|
break;
|
2013-03-07 20:01:22 +01:00
|
|
|
default:
|
|
|
|
return Element::setProperty(id, v);
|
2012-11-18 00:28:38 +01:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->setLayoutAll(true);
|
2012-08-10 17:01:35 +02:00
|
|
|
return true;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-10-17 20:22:24 +02:00
|
|
|
|
2013-03-07 20:01:22 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// propertyDefault
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant BarLine::propertyDefault(P_ID propertyId) const
|
|
|
|
{
|
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::SUBTYPE:
|
2013-03-18 13:01:50 +01:00
|
|
|
// default subtype is the subtype of the measure, if any
|
2014-06-24 18:36:02 +02:00
|
|
|
if (parent() && parent()->type() == Element::Type::SEGMENT && static_cast<Segment*>(parent())->measure() )
|
2014-05-30 10:14:09 +02:00
|
|
|
return int(static_cast<Segment*>(parent())->measure()->endBarLineType());
|
|
|
|
return int(BarLineType::NORMAL);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN:
|
2013-03-18 13:01:50 +01:00
|
|
|
// if there is a staff, default span is staff span
|
|
|
|
if (staff())
|
|
|
|
return staff()->barLineSpan();
|
|
|
|
// if no staff, default span is 1
|
2013-03-07 20:01:22 +01:00
|
|
|
return 1;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN_FROM:
|
2013-03-18 13:01:50 +01:00
|
|
|
// if there is a staff, default From span is staff From span
|
|
|
|
if (staff())
|
|
|
|
return staff()->barLineFrom();
|
|
|
|
// if no staff, default From is from top
|
2013-03-08 12:55:12 +01:00
|
|
|
return 0;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::BARLINE_SPAN_TO:
|
2013-03-18 13:01:50 +01:00
|
|
|
// if there is a staff, default To span is staff To span
|
|
|
|
if (staff())
|
|
|
|
return staff()->barLineTo();
|
|
|
|
// if no staff, assume a standard 5-line setup
|
2013-03-08 12:55:12 +01:00
|
|
|
return DEFAULT_BARLINE_TO;
|
2013-03-07 20:01:22 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return Element::propertyDefault(propertyId);
|
|
|
|
}
|
2013-05-13 18:49:17 +02:00
|
|
|
|
2014-06-20 22:48:34 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// nextElement
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* BarLine::nextElement()
|
|
|
|
{
|
|
|
|
if (parent()->type() == Element::Type::SEGMENT)
|
|
|
|
return static_cast<Segment*>(parent())->firstInNextSegments(score()->inputState().prevTrack() / VOICES);
|
|
|
|
|
|
|
|
return parent()->nextElement();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// prevElement
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* BarLine::prevElement()
|
|
|
|
{
|
|
|
|
if (parent()->type() == Element::Type::SEGMENT)
|
|
|
|
return static_cast<Segment*>(parent())->lastInPrevSegments(score()->inputState().prevTrack() / VOICES);
|
|
|
|
|
|
|
|
return parent()->prevElement();
|
|
|
|
}
|
|
|
|
|
2014-07-10 14:13:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// accessibleInfo
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QString BarLine::accessibleInfo()
|
|
|
|
{
|
2014-08-21 18:32:52 +02:00
|
|
|
return QString("%1: %2").arg(Element::accessibleInfo()).arg(BarLine::userTypeName2(this->barLineType()));
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// accessibleExtraInfo
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QString BarLine::accessibleExtraInfo()
|
|
|
|
{
|
|
|
|
if (parent()->type() == Element::Type::SEGMENT) {
|
|
|
|
Segment* seg = static_cast<Segment*>(parent());
|
|
|
|
QString rez = "";
|
|
|
|
|
|
|
|
foreach(Element* e, *el())
|
2014-08-21 18:32:52 +02:00
|
|
|
rez = QString("%1 %2").arg(rez).arg(e->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
|
|
|
|
foreach (Element* e, seg->annotations()) {
|
|
|
|
if (e->track() == track())
|
2014-08-21 18:32:52 +02:00
|
|
|
rez = QString("%1 %2").arg(rez).arg(e->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
Measure* m = seg->measure();
|
|
|
|
|
|
|
|
if (m) {
|
|
|
|
//jumps
|
|
|
|
foreach (Element* e, *m->el()) {
|
|
|
|
if(e->type() == Element::Type::JUMP)
|
2014-08-21 18:32:52 +02:00
|
|
|
rez= QString("%1 %2").arg(rez).arg(e->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
if(e->type() == Element::Type::MARKER) {
|
|
|
|
Marker* m = static_cast<Marker*>(e);
|
|
|
|
if (m->markerType() == Marker::Type::FINE)
|
2014-08-21 18:32:52 +02:00
|
|
|
rez = QString("%1 %2").arg(rez).arg(e->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
//markers
|
|
|
|
Measure* nextM = m->nextMeasureMM();
|
|
|
|
if (nextM) {
|
|
|
|
foreach (Element* e, *nextM->el()) {
|
|
|
|
if(e->type() == Element::Type::MARKER)
|
|
|
|
if(static_cast<Marker*>(e)->markerType() == Marker::Type::FINE)
|
|
|
|
continue; //added above^
|
2014-08-21 18:32:52 +02:00
|
|
|
rez = QString("%1 %2").arg(rez).arg(e->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int tick = seg->tick();
|
2014-08-19 14:35:27 +02:00
|
|
|
|
|
|
|
std::vector< ::Interval<Spanner*> > spanners = score()->spannerMap().findOverlapping(tick, tick);
|
2014-07-10 14:13:37 +02:00
|
|
|
for (std::vector< ::Interval<Spanner*> >::iterator i = spanners.begin(); i < spanners.end(); i++) {
|
|
|
|
::Interval<Spanner*> interval = *i;
|
|
|
|
Spanner* s = interval.value;
|
|
|
|
if (s->type() == Element::Type::VOLTA) {
|
|
|
|
if(s->tick() == tick)
|
2014-08-21 18:32:52 +02:00
|
|
|
rez = tr("%1 Start of %2").arg(rez).arg(s->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
if(s->tick2() == tick)
|
2014-08-21 18:32:52 +02:00
|
|
|
rez = tr("%1 End of %2").arg(rez).arg(s->screenReaderInfo());
|
2014-07-10 14:13:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return rez;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Element::accessibleExtraInfo();
|
|
|
|
}
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|