2012-05-26 14:26:10 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
2012-11-19 09:29:46 +01:00
|
|
|
// Copyright (C) 2002-2012 Werner Schweer
|
2012-05-26 14:26:10 +02:00
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/**
|
|
|
|
\file
|
|
|
|
Implementation of classes Note and ShadowNote.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#include "note.h"
|
|
|
|
#include "score.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "chord.h"
|
|
|
|
#include "sym.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "slur.h"
|
2013-08-22 12:18:14 +02:00
|
|
|
#include "tie.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "text.h"
|
|
|
|
#include "clef.h"
|
|
|
|
#include "staff.h"
|
|
|
|
#include "pitchspelling.h"
|
|
|
|
#include "arpeggio.h"
|
|
|
|
#include "tremolo.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "image.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "tuplet.h"
|
|
|
|
#include "articulation.h"
|
|
|
|
#include "drumset.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "measure.h"
|
|
|
|
#include "undo.h"
|
|
|
|
#include "part.h"
|
|
|
|
#include "stafftype.h"
|
2013-12-05 21:37:28 +01:00
|
|
|
#include "stringdata.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
#include "fret.h"
|
|
|
|
#include "harmony.h"
|
|
|
|
#include "fingering.h"
|
|
|
|
#include "bend.h"
|
|
|
|
#include "accidental.h"
|
|
|
|
#include "page.h"
|
|
|
|
#include "icon.h"
|
|
|
|
#include "notedot.h"
|
2012-09-12 16:19:03 +02:00
|
|
|
#include "spanner.h"
|
2012-12-11 20:37:35 +01:00
|
|
|
#include "glissando.h"
|
2013-08-01 22:24:36 +02:00
|
|
|
#include "bagpembell.h"
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// noteHeads
|
|
|
|
// note head groups
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-11-25 15:42:40 +01:00
|
|
|
static const SymId noteHeads[2][int(NoteHeadGroup::HEAD_GROUPS)][int(NoteHeadType::HEAD_TYPES)] = {
|
2013-11-15 11:18:16 +01:00
|
|
|
// previous non-SMUFL data kept in comments for future reference
|
|
|
|
{ // down stem
|
|
|
|
{ SymId::noteheadWhole, SymId::noteheadHalf, SymId::noteheadBlack, SymId::noteheadDoubleWhole },
|
|
|
|
{ SymId::noteheadXWhole, SymId::noteheadXHalf, SymId::noteheadXBlack, SymId::noteheadXWhole },
|
|
|
|
{ SymId::noteheadDiamondWhole,SymId::noteheadDiamondHalf, SymId::noteheadDiamondBlack, SymId::noteheadDiamondWhole },
|
|
|
|
// { SymId(s0triangleHeadSym), SymId(d1triangleHeadSym), SymId(d2triangleHeadSym), SymId(s0triangleHeadSym) },
|
|
|
|
{ SymId::noteheadTriangleDownWhole, SymId::noteheadTriangleDownHalf, SymId::noteheadTriangleDownBlack, SymId::noteheadTriangleDownDoubleWhole },
|
|
|
|
// { SymId(s0miHeadSym), SymId(s1miHeadSym), SymId(s2miHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeDiamondWhite, SymId::noteShapeDiamondWhite, SymId::noteShapeDiamondBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(wholeslashheadSym), SymId(halfslashheadSym), SymId(quartslashheadSym), SymId(wholeslashheadSym)},
|
2014-04-18 18:55:33 +02:00
|
|
|
{ SymId::noteheadSlashWhiteWhole, SymId::noteheadSlashWhiteHalf, SymId::noteheadSlashHorizontalEnds, SymId::noteheadSlashWhiteWhole},
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(xcircledheadSym), SymId(xcircledheadSym), SymId(xcircledheadSym), SymId(xcircledheadSym) },
|
|
|
|
{ SymId::noteheadCircleXWhole,SymId::noteheadCircleXHalf, SymId::noteheadCircleX, SymId::noteheadCircleXDoubleWhole},
|
|
|
|
// { SymId(s0doHeadSym), SymId(d1doHeadSym), SymId(d2doHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeTriangleUpWhite, SymId::noteShapeTriangleUpWhite, SymId::noteShapeTriangleUpBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0reHeadSym), SymId(d1reHeadSym), SymId(d2reHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeMoonWhite, SymId::noteShapeMoonWhite, SymId::noteShapeMoonBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(d0faHeadSym), SymId(d1faHeadSym), SymId(d2faHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeTriangleRightWhite, SymId::noteShapeTriangleRightWhite, SymId::noteShapeTriangleRightBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0laHeadSym), SymId(s1laHeadSym), SymId(s2laHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeSquareWhite, SymId::noteShapeSquareWhite, SymId::noteShapeSquareBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0tiHeadSym), SymId(d1tiHeadSym), SymId(d2tiHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeTriangleRoundWhite, SymId::noteShapeTriangleRoundWhite, SymId::noteShapeTriangleRoundBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0solHeadSym), SymId(s1solHeadSym), SymId(s2solHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeRoundWhite, SymId::noteShapeRoundWhite, SymId::noteShapeRoundBlack, SymId::noSym },
|
2013-11-29 00:37:48 +01:00
|
|
|
{ SymId::noteheadWhole, SymId::noteheadHalf, SymId::noteheadBlack, SymId::noteheadDoubleWholeSquare },
|
2013-11-15 11:18:16 +01:00
|
|
|
},
|
|
|
|
{ // up stem
|
|
|
|
{ SymId::noteheadWhole, SymId::noteheadHalf, SymId::noteheadBlack, SymId::noteheadDoubleWhole },
|
|
|
|
{ SymId::noteheadXWhole, SymId::noteheadXHalf, SymId::noteheadXBlack, SymId::noteheadXWhole },
|
|
|
|
{ SymId::noteheadDiamondWhole,SymId::noteheadDiamondHalf, SymId::noteheadDiamondBlack, SymId::noteheadDiamondWhole },
|
|
|
|
// { SymId(s0triangleHeadSym), SymId(d1triangleHeadSym), SymId(d2triangleHeadSym), SymId(s0triangleHeadSym) },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteheadTriangleDownWhole, SymId::noteheadTriangleDownHalf, SymId::noteheadTriangleDownBlack, SymId::noteheadTriangleDownDoubleWhole },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0miHeadSym), SymId(s1miHeadSym), SymId(s2miHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeDiamondWhite, SymId::noteShapeDiamondWhite, SymId::noteShapeDiamondBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(wholeslashheadSym), SymId(halfslashheadSym), SymId(quartslashheadSym), SymId(wholeslashheadSym)},
|
2014-04-18 18:55:33 +02:00
|
|
|
{ SymId::noteheadSlashWhiteWhole, SymId::noteheadSlashWhiteHalf, SymId::noteheadSlashHorizontalEnds, SymId::noteheadSlashWhiteWhole},
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(xcircledheadSym), SymId(xcircledheadSym), SymId(xcircledheadSym), SymId(xcircledheadSym) },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteheadCircleXWhole, SymId::noteheadCircleXHalf, SymId::noteheadCircleX, SymId::noteheadCircleXDoubleWhole},
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0doHeadSym), SymId(d1doHeadSym), SymId(d2doHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeTriangleUpWhite, SymId::noteShapeTriangleUpWhite, SymId::noteShapeTriangleUpBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0reHeadSym), SymId(d1reHeadSym), SymId(d2reHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeMoonWhite, SymId::noteShapeMoonWhite, SymId::noteShapeMoonBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(d0faHeadSym), SymId(d1faHeadSym), SymId(d2faHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeTriangleRightWhite, SymId::noteShapeTriangleRightWhite, SymId::noteShapeTriangleRightBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0laHeadSym), SymId(s1laHeadSym), SymId(s2laHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeSquareWhite, SymId::noteShapeSquareWhite, SymId::noteShapeSquareBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0tiHeadSym), SymId(d1tiHeadSym), SymId(d2tiHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeTriangleRoundWhite, SymId::noteShapeTriangleRoundWhite, SymId::noteShapeTriangleRoundBlack, SymId::noSym },
|
2013-11-15 11:18:16 +01:00
|
|
|
// { SymId(s0solHeadSym), SymId(s1solHeadSym), SymId(s2solHeadSym), SymId::noSym },
|
2013-11-15 14:41:00 +01:00
|
|
|
{ SymId::noteShapeRoundWhite, SymId::noteShapeRoundWhite, SymId::noteShapeRoundBlack, SymId::noSym },
|
2013-11-29 00:37:48 +01:00
|
|
|
{ SymId::noteheadWhole, SymId::noteheadHalf, SymId::noteheadBlack, SymId::noteheadDoubleWholeSquare },
|
2013-11-15 11:18:16 +01:00
|
|
|
}
|
|
|
|
};
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2013-11-25 15:42:40 +01:00
|
|
|
// noteHead
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-11-25 15:42:40 +01:00
|
|
|
SymId Note::noteHead(int direction, NoteHeadGroup g, NoteHeadType t)
|
|
|
|
{
|
|
|
|
return noteHeads[direction][int(g)][int(t)];
|
|
|
|
};
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void NoteHead::write(Xml& xml) const
|
|
|
|
{
|
|
|
|
xml.stag("NoteHead");
|
2012-09-08 11:33:46 +02:00
|
|
|
xml.tag("name", Sym::id2name(_sym));
|
2012-05-26 14:26:10 +02:00
|
|
|
Element::writeProperties(xml);
|
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
2013-11-25 15:02:23 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// headGroup
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
NoteHeadGroup NoteHead::headGroup() const
|
|
|
|
{
|
|
|
|
NoteHeadGroup group = NoteHeadGroup::HEAD_INVALID;
|
|
|
|
|
|
|
|
for (int i = 0; i < int(NoteHeadGroup::HEAD_GROUPS); ++i) {
|
|
|
|
if (noteHeads[0][i][1] == _sym || noteHeads[0][i][3] == _sym) {
|
|
|
|
group = (NoteHeadGroup)i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// Note
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Note::Note(Score* s)
|
|
|
|
: Element(s)
|
|
|
|
{
|
2014-05-22 10:10:58 +02:00
|
|
|
setFlags(ElementFlag::MOVABLE | ElementFlag::SELECTABLE);
|
2012-05-26 14:26:10 +02:00
|
|
|
dragMode = false;
|
|
|
|
_pitch = 0;
|
2013-08-23 13:55:54 +02:00
|
|
|
_play = true;
|
2012-05-26 14:26:10 +02:00
|
|
|
_tuning = 0.0;
|
|
|
|
_accidental = 0;
|
|
|
|
_mirror = false;
|
2014-05-07 18:09:01 +02:00
|
|
|
_userMirror = DirectionH::DH_AUTO;
|
2012-05-26 14:26:10 +02:00
|
|
|
_small = false;
|
2014-05-07 18:09:01 +02:00
|
|
|
_userDotPosition = Direction::AUTO;
|
2012-05-26 14:26:10 +02:00
|
|
|
_line = 0;
|
|
|
|
_fret = -1;
|
|
|
|
_string = -1;
|
|
|
|
_fretConflict = false;
|
|
|
|
_ghost = false;
|
|
|
|
_lineOffset = 0;
|
|
|
|
_tieFor = 0;
|
|
|
|
_tieBack = 0;
|
2014-05-30 10:18:20 +02:00
|
|
|
_tpc[0] = Tpc::TPC_INVALID;
|
|
|
|
_tpc[1] = Tpc::TPC_INVALID;
|
2013-11-25 15:02:23 +01:00
|
|
|
_headGroup = NoteHeadGroup::HEAD_NORMAL;
|
|
|
|
_headType = NoteHeadType::HEAD_AUTO;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
_hidden = false;
|
|
|
|
_subchannel = 0;
|
|
|
|
|
2014-05-07 18:09:01 +02:00
|
|
|
_veloType = ValueType::OFFSET_VAL;
|
2012-05-26 14:26:10 +02:00
|
|
|
_veloOffset = 0;
|
|
|
|
|
|
|
|
_dots[0] = 0;
|
|
|
|
_dots[1] = 0;
|
|
|
|
_dots[2] = 0;
|
2012-11-19 09:29:46 +01:00
|
|
|
_playEvents.append(NoteEvent()); // add default play event
|
2013-02-20 17:53:15 +01:00
|
|
|
_mark = 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Note::~Note()
|
|
|
|
{
|
|
|
|
delete _accidental;
|
2012-11-19 09:29:46 +01:00
|
|
|
qDeleteAll(_el);
|
2012-05-26 14:26:10 +02:00
|
|
|
delete _tieFor;
|
|
|
|
delete _dots[0];
|
|
|
|
delete _dots[1];
|
|
|
|
delete _dots[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
Note::Note(const Note& n)
|
|
|
|
: Element(n)
|
|
|
|
{
|
|
|
|
_subchannel = n._subchannel;
|
|
|
|
_line = n._line;
|
|
|
|
_fret = n._fret;
|
|
|
|
_string = n._string;
|
|
|
|
_fretConflict = n._fretConflict;
|
|
|
|
_ghost = n._ghost;
|
|
|
|
dragMode = n.dragMode;
|
|
|
|
_pitch = n._pitch;
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[0] = n._tpc[0];
|
|
|
|
_tpc[1] = n._tpc[1];
|
2012-05-26 14:26:10 +02:00
|
|
|
_hidden = n._hidden;
|
2013-08-23 13:55:54 +02:00
|
|
|
_play = n._play;
|
2012-05-26 14:26:10 +02:00
|
|
|
_tuning = n._tuning;
|
|
|
|
_veloType = n._veloType;
|
|
|
|
_veloOffset = n._veloOffset;
|
|
|
|
_headGroup = n._headGroup;
|
|
|
|
_headType = n._headType;
|
|
|
|
_mirror = n._mirror;
|
|
|
|
_userMirror = n._userMirror;
|
|
|
|
_small = n._small;
|
2014-04-02 20:31:37 +02:00
|
|
|
_userDotPosition = n._userDotPosition;
|
2012-05-26 14:26:10 +02:00
|
|
|
_accidental = 0;
|
2013-01-03 16:56:56 +01:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
if (n._accidental)
|
|
|
|
add(new Accidental(*(n._accidental)));
|
|
|
|
|
2013-03-25 16:27:20 +01:00
|
|
|
for (const Element* e : n._el)
|
|
|
|
add(e->clone());
|
|
|
|
|
2012-11-19 09:29:46 +01:00
|
|
|
_playEvents = n._playEvents;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
if (n._tieFor) {
|
|
|
|
_tieFor = new Tie(*n._tieFor);
|
|
|
|
_tieFor->setStartNote(this);
|
|
|
|
_tieFor->setEndNote(0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
_tieFor = 0;
|
|
|
|
_tieBack = 0;
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
_dots[i] = 0;
|
|
|
|
if (n._dots[i])
|
|
|
|
add(new NoteDot(*n._dots[i]));
|
|
|
|
}
|
|
|
|
_lineOffset = n._lineOffset;
|
2013-02-20 17:53:15 +01:00
|
|
|
_mark = n._mark;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2014-04-09 09:40:25 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// concertPitchIdx
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
inline int Note::concertPitchIdx() const
|
|
|
|
{
|
|
|
|
return concertPitch() ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setPitch
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setPitch(int val)
|
|
|
|
{
|
2014-04-09 16:09:21 +02:00
|
|
|
Q_ASSERT(val >= 0 && val <= 127);
|
|
|
|
if (_pitch != val) {
|
|
|
|
_pitch = val;
|
|
|
|
score()->setPlaylistDirty(true);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-09 09:40:25 +02:00
|
|
|
void Note::setPitch(int pitch, int tpc1, int tpc2)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-04-09 11:11:02 +02:00
|
|
|
Q_ASSERT(tpcIsValid(tpc1));
|
|
|
|
Q_ASSERT(tpcIsValid(tpc2));
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[0] = tpc1;
|
|
|
|
_tpc[1] = tpc2;
|
2014-04-09 11:11:02 +02:00
|
|
|
setPitch(pitch);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-07-16 20:21:31 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetPitch
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetPitch(int p)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(this, P_ID::PITCH, p);
|
2012-07-16 20:21:31 +02:00
|
|
|
}
|
|
|
|
|
2014-04-10 13:13:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// tpc1default
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::tpc1default(int p) const
|
|
|
|
{
|
2014-06-20 17:07:22 +02:00
|
|
|
Key key = Key::C;
|
2014-04-10 13:13:37 +02:00
|
|
|
if (staff() && chord()) {
|
2014-06-03 15:28:10 +02:00
|
|
|
key = staff()->key(chord()->tick());
|
2014-04-10 13:13:37 +02:00
|
|
|
if (!concertPitch()) {
|
|
|
|
Interval interval = staff()->part()->instr()->transpose();
|
|
|
|
if (!interval.isZero()) {
|
|
|
|
interval.flip();
|
|
|
|
key = transposeKey(key, interval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-23 21:14:22 +02:00
|
|
|
return pitch2tpc(p, key, Prefer::NEAREST);
|
2014-04-10 13:13:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// tpc2default
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::tpc2default(int p) const
|
|
|
|
{
|
2014-06-20 17:07:22 +02:00
|
|
|
Key key = Key::C;
|
2014-04-10 13:13:37 +02:00
|
|
|
if (staff() && chord()) {
|
2014-06-03 15:28:10 +02:00
|
|
|
key = staff()->key(chord()->tick());
|
2014-04-10 13:13:37 +02:00
|
|
|
if (concertPitch()) {
|
|
|
|
Interval interval = staff()->part()->instr()->transpose();
|
|
|
|
if (!interval.isZero())
|
|
|
|
key = transposeKey(key, interval);
|
|
|
|
}
|
|
|
|
}
|
2014-05-23 21:14:22 +02:00
|
|
|
return pitch2tpc(p - transposition(), key, Prefer::NEAREST);
|
2014-04-10 13:13:37 +02:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setTpcFromPitch
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setTpcFromPitch()
|
|
|
|
{
|
2014-06-20 17:07:22 +02:00
|
|
|
Key key = (staff() && chord()) ? staff()->key(chord()->tick()) : Key::C;
|
2014-05-23 21:14:22 +02:00
|
|
|
_tpc[0] = pitch2tpc(_pitch, key, Prefer::NEAREST);
|
|
|
|
_tpc[1] = pitch2tpc(_pitch - transposition(), key, Prefer::NEAREST);
|
2014-04-09 11:11:02 +02:00
|
|
|
Q_ASSERT(tpcIsValid(_tpc[0]));
|
|
|
|
Q_ASSERT(tpcIsValid(_tpc[1]));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setTpc
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setTpc(int v)
|
|
|
|
{
|
2014-04-02 18:11:56 +02:00
|
|
|
if (!tpcIsValid(v))
|
2014-06-05 20:58:05 +02:00
|
|
|
qFatal("Note::setTpc: bad tpc %d", v);
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[concertPitchIdx()] = v;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-07-16 20:21:31 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetTpc
|
2014-04-09 09:40:25 +02:00
|
|
|
// change the current tpc
|
2012-07-16 20:21:31 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-04-09 09:40:25 +02:00
|
|
|
void Note::undoSetTpc(int v)
|
2012-07-16 20:21:31 +02:00
|
|
|
{
|
2014-04-09 09:40:25 +02:00
|
|
|
if (concertPitch()) {
|
|
|
|
if (v != tpc1())
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::TPC1, v);
|
2014-04-09 09:40:25 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (v != tpc2())
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::TPC2, v);
|
2014-04-09 09:40:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// tpc
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::tpc() const
|
|
|
|
{
|
|
|
|
return _tpc[concertPitchIdx()];
|
2012-07-16 20:21:31 +02:00
|
|
|
}
|
|
|
|
|
2014-04-23 11:08:51 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// transposeTpc
|
|
|
|
// return transposed tpc
|
|
|
|
// If in concertPitch mode return tpc for transposed view
|
|
|
|
// else return tpc for concert pitch view.
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::transposeTpc(int tpc)
|
|
|
|
{
|
|
|
|
Interval v = staff()->part()->instr()->transpose();
|
|
|
|
if (v.isZero())
|
|
|
|
return tpc;
|
|
|
|
if (concertPitch()) {
|
|
|
|
v.flip();
|
|
|
|
return Ms::transposeTpc(tpc, v, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return Ms::transposeTpc(tpc, v, false);
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// noteHead
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-11-06 15:58:05 +01:00
|
|
|
SymId Note::noteHead() const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-11-25 15:02:23 +01:00
|
|
|
int up;
|
|
|
|
NoteHeadType ht;
|
2012-05-26 14:26:10 +02:00
|
|
|
if (chord()) {
|
2013-11-15 11:18:16 +01:00
|
|
|
up = chord()->up();
|
2012-05-26 14:26:10 +02:00
|
|
|
ht = chord()->durationType().headType();
|
|
|
|
}
|
2013-01-02 20:13:58 +01:00
|
|
|
else {
|
2013-11-15 11:18:16 +01:00
|
|
|
up = 1;
|
2013-11-25 15:02:23 +01:00
|
|
|
ht = NoteHeadType::HEAD_QUARTER;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-11-25 15:02:23 +01:00
|
|
|
if (_headType != NoteHeadType::HEAD_AUTO)
|
2013-01-28 21:45:36 +01:00
|
|
|
ht = _headType;
|
2013-01-02 20:13:58 +01:00
|
|
|
|
2013-11-25 15:42:40 +01:00
|
|
|
SymId t = noteHead(up, _headGroup, ht);
|
2013-11-06 15:58:05 +01:00
|
|
|
if (t == SymId::noSym) {
|
2014-06-17 14:20:24 +02:00
|
|
|
qDebug("invalid note head %hhd/%hhd", _headGroup, ht);
|
2013-11-25 15:42:40 +01:00
|
|
|
t = noteHead(up, NoteHeadGroup::HEAD_NORMAL, ht);
|
2013-01-28 21:45:36 +01:00
|
|
|
}
|
|
|
|
return t;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// headWidth
|
2012-12-26 21:03:00 +01:00
|
|
|
//
|
|
|
|
// returns the width of the note head symbol
|
|
|
|
// or the width of the string representation of the fret mark
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Note::headWidth() const
|
|
|
|
{
|
2013-11-11 15:11:28 +01:00
|
|
|
return symWidth(noteHead());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2014-04-28 18:38:50 +02:00
|
|
|
qreal Note::tabHeadWidth(StaffType* tab) const
|
2012-12-26 21:03:00 +01:00
|
|
|
{
|
|
|
|
qreal val;
|
|
|
|
if (tab && _fret != FRET_NONE && _string != STRING_NONE) {
|
|
|
|
qreal mags = magS();
|
|
|
|
QFont f = tab->fretFont();
|
|
|
|
int size = lrint(tab->fretFontSize() * MScore::DPI / PPI);
|
|
|
|
f.setPixelSize(size);
|
|
|
|
QFontMetricsF fm(f);
|
|
|
|
QString s = tab->fretString(_fret, _ghost);
|
|
|
|
val = fm.width(s) * mags;
|
2013-05-23 16:58:22 +02:00
|
|
|
}
|
2012-12-26 21:03:00 +01:00
|
|
|
else
|
2012-12-28 00:30:46 +01:00
|
|
|
val = headWidth();
|
2012-12-26 21:03:00 +01:00
|
|
|
return val;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// headHeight
|
2012-12-26 21:03:00 +01:00
|
|
|
//
|
|
|
|
// returns the height of the note head symbol
|
|
|
|
// or the height of the string representation of the fret mark
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Note::headHeight() const
|
|
|
|
{
|
2013-11-11 15:11:28 +01:00
|
|
|
return symHeight(noteHead());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2014-04-28 18:38:50 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// tabHeadHeight
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
qreal Note::tabHeadHeight(StaffType* tab) const
|
2012-12-26 21:03:00 +01:00
|
|
|
{
|
|
|
|
if(tab && _fret != FRET_NONE && _string != STRING_NONE)
|
|
|
|
return tab->fretBoxH() * magS();
|
|
|
|
return headHeight();
|
|
|
|
}
|
|
|
|
|
2013-01-02 09:29:17 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// attach
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QPointF Note::attach() const
|
|
|
|
{
|
2013-11-11 15:11:28 +01:00
|
|
|
return symAttach(noteHead());
|
2013-01-02 09:29:17 +01:00
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// playTicks
|
2013-05-12 12:43:22 +02:00
|
|
|
/// Return total tick len of tied notes
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::playTicks() const
|
|
|
|
{
|
|
|
|
const Note* note = this;
|
|
|
|
while (note->tieBack())
|
|
|
|
note = note->tieBack()->startNote();
|
2013-05-12 12:43:22 +02:00
|
|
|
int stick = note->chord()->tick();
|
|
|
|
while (note->tieFor() && note->tieFor()->endNote())
|
2012-05-26 14:26:10 +02:00
|
|
|
note = note->tieFor()->endNote();
|
2013-05-12 12:43:22 +02:00
|
|
|
return note->chord()->tick() + note->chord()->actualTicks() - stick;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-09-12 16:19:03 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// addSpanner
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::addSpanner(Spanner* l)
|
|
|
|
{
|
|
|
|
Element* e = l->endElement();
|
|
|
|
if (e)
|
|
|
|
static_cast<Note*>(e)->addSpannerBack(l);
|
2013-01-03 16:56:56 +01:00
|
|
|
addSpannerFor(l);
|
2012-09-12 16:19:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// removeSpanner
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::removeSpanner(Spanner* l)
|
|
|
|
{
|
|
|
|
if (!static_cast<Note*>(l->endElement())->removeSpannerBack(l)) {
|
2013-01-03 16:56:56 +01:00
|
|
|
qDebug("Note::removeSpanner(%p): cannot remove spannerBack %s %p", this, l->name(), l);
|
2012-09-12 16:19:03 +02:00
|
|
|
// abort();
|
|
|
|
}
|
2013-01-03 16:56:56 +01:00
|
|
|
if (!removeSpannerFor(l)) {
|
|
|
|
qDebug("Note(%p): cannot remove spannerFor %s %p", this, l->name(), l);
|
2012-09-12 16:19:03 +02:00
|
|
|
// abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// add
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::add(Element* e)
|
|
|
|
{
|
2014-02-22 11:19:44 +01:00
|
|
|
e->setParent(this);
|
2012-08-16 11:09:36 +02:00
|
|
|
e->setTrack(track());
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
switch(e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::NOTEDOT:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
NoteDot* dot = static_cast<NoteDot*>(e);
|
|
|
|
_dots[dot->idx()] = dot;
|
|
|
|
}
|
|
|
|
break;
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SYMBOL:
|
|
|
|
case Element::Type::IMAGE:
|
|
|
|
case Element::Type::FINGERING:
|
|
|
|
case Element::Type::TEXT:
|
|
|
|
case Element::Type::BEND:
|
2013-03-25 16:27:20 +01:00
|
|
|
_el.push_back(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TIE:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Tie* tie = static_cast<Tie*>(e);
|
2014-05-30 13:35:44 +02:00
|
|
|
tie->setStartNote(this);
|
2012-05-26 14:26:10 +02:00
|
|
|
tie->setTrack(track());
|
2014-05-30 13:35:44 +02:00
|
|
|
setTieFor(tie);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (tie->endNote())
|
|
|
|
tie->endNote()->setTieBack(tie);
|
2013-01-30 17:50:01 +01:00
|
|
|
int n = tie->spannerSegments().size();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
SpannerSegment* ss = tie->spannerSegments().at(i);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (ss->system())
|
|
|
|
ss->system()->add(ss);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ACCIDENTAL:
|
2012-05-26 14:26:10 +02:00
|
|
|
_accidental = static_cast<Accidental*>(e);
|
|
|
|
break;
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TEXTLINE:
|
2012-09-12 16:19:03 +02:00
|
|
|
addSpanner(static_cast<Spanner*>(e));
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("Note::add() not impl. %s", e->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// remove
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::remove(Element* e)
|
|
|
|
{
|
|
|
|
switch(e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::NOTEDOT:
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
if (_dots[i] == e) {
|
|
|
|
_dots[i] = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TEXT:
|
|
|
|
case Element::Type::SYMBOL:
|
|
|
|
case Element::Type::IMAGE:
|
|
|
|
case Element::Type::FINGERING:
|
|
|
|
case Element::Type::BEND:
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!_el.remove(e))
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("Note::remove(): cannot find %s", e->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TIE:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Tie* tie = static_cast<Tie*>(e);
|
|
|
|
setTieFor(0);
|
2013-11-14 16:20:41 +01:00
|
|
|
if (tie->endNote()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
tie->endNote()->setTieBack(0);
|
2013-11-14 16:20:41 +01:00
|
|
|
// update accidentals for endNote
|
|
|
|
Chord* chord = tie->endNote()->chord();
|
2014-03-26 11:02:23 +01:00
|
|
|
Measure* m = chord->segment()->measure();
|
2014-04-22 17:02:03 +02:00
|
|
|
m->cmdUpdateNotes(chord->staffIdx());
|
2013-11-14 16:20:41 +01:00
|
|
|
}
|
2013-01-30 17:50:01 +01:00
|
|
|
int n = tie->spannerSegments().size();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
SpannerSegment* ss = tie->spannerSegments().at(i);
|
2012-05-26 14:26:10 +02:00
|
|
|
Q_ASSERT(ss->spanner() == tie);
|
|
|
|
if (ss->system())
|
|
|
|
ss->system()->remove(ss);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ACCIDENTAL:
|
2012-05-26 14:26:10 +02:00
|
|
|
_accidental = 0;
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::TEXTLINE:
|
2012-09-12 16:19:03 +02:00
|
|
|
removeSpanner(static_cast<Spanner*>(e));
|
|
|
|
break;
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
default:
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("Note::remove() not impl. %s", e->name());
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// draw
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::draw(QPainter* painter) const
|
|
|
|
{
|
2012-06-09 10:50:51 +02:00
|
|
|
if (_hidden)
|
|
|
|
return;
|
2013-02-20 17:53:15 +01:00
|
|
|
|
2013-03-07 21:00:22 +01:00
|
|
|
QColor c(curColor());
|
2013-02-20 17:53:15 +01:00
|
|
|
painter->setPen(c);
|
2012-08-16 11:09:36 +02:00
|
|
|
bool tablature = staff() && staff()->isTabStaff();
|
2012-08-17 00:33:38 +02:00
|
|
|
|
|
|
|
// tablature
|
|
|
|
|
2012-06-09 10:50:51 +02:00
|
|
|
if (tablature) {
|
2014-04-28 18:38:50 +02:00
|
|
|
StaffType* tab = staff()->staffType();
|
2012-09-21 18:31:31 +02:00
|
|
|
if (tieBack() && tab->slashStyle())
|
|
|
|
return;
|
2012-08-17 00:33:38 +02:00
|
|
|
QString s = tab->fretString(_fret, _ghost);
|
2012-06-09 10:50:51 +02:00
|
|
|
|
|
|
|
// draw background, if required
|
|
|
|
if (!tab->linesThrough() || fretConflict()) {
|
2012-09-21 18:31:31 +02:00
|
|
|
qreal d = spatium() * .1;
|
2013-02-06 21:57:40 +01:00
|
|
|
QRectF bb = QRectF(bbox().x()-d, tab->fretMaskY(), bbox().width() + 2*d, tab->fretMaskH());
|
2012-06-09 10:50:51 +02:00
|
|
|
// we do not know which viewer did this draw() call
|
|
|
|
// so update all:
|
|
|
|
foreach(MuseScoreView* view, score()->getViewer())
|
|
|
|
view->drawBackground(painter, bb);
|
|
|
|
|
|
|
|
if (fretConflict()) { //on fret conflict, draw on red background
|
|
|
|
painter->save();
|
|
|
|
painter->setPen(Qt::red);
|
|
|
|
painter->setBrush(QBrush(QColor(Qt::red)));
|
|
|
|
painter->drawRect(bb);
|
|
|
|
painter->restore();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2013-03-11 13:30:43 +01:00
|
|
|
qreal mag = magS();
|
|
|
|
qreal imag = 1.0 / mag;
|
|
|
|
painter->scale(mag, mag);
|
|
|
|
painter->setFont(tab->fretFont());
|
2013-03-07 21:00:22 +01:00
|
|
|
painter->setPen(c);
|
2012-06-09 10:50:51 +02:00
|
|
|
painter->drawText(QPointF(bbox().x(), tab->fretFontYOffset()), s);
|
|
|
|
painter->scale(imag, imag);
|
|
|
|
}
|
2012-08-17 00:33:38 +02:00
|
|
|
|
|
|
|
// NOT tablature
|
|
|
|
|
|
|
|
else {
|
2013-05-12 12:51:42 +02:00
|
|
|
// skip drawing, if second note of a cross-measure value
|
2014-05-21 15:41:23 +02:00
|
|
|
if (chord()->crossMeasure() == CrossMeasure::SECOND)
|
2013-05-12 12:51:42 +02:00
|
|
|
return;
|
2012-06-09 10:50:51 +02:00
|
|
|
//
|
|
|
|
// warn if pitch extends usable range of instrument
|
|
|
|
// by coloring the note head
|
|
|
|
//
|
|
|
|
if (chord() && chord()->segment() && staff() && !selected()
|
|
|
|
&& !score()->printing() && MScore::warnPitchRange) {
|
|
|
|
const Instrument* in = staff()->part()->instr();
|
|
|
|
int i = ppitch();
|
|
|
|
if (i < in->minPitchP() || i > in->maxPitchP())
|
|
|
|
painter->setPen(Qt::red);
|
|
|
|
else if (i < in->minPitchA() || i > in->maxPitchA())
|
|
|
|
painter->setPen(Qt::darkYellow);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-11-06 15:58:05 +01:00
|
|
|
drawSymbol(noteHead(), painter);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------
|
|
|
|
// Note::write
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::write(Xml& xml) const
|
|
|
|
{
|
|
|
|
xml.stag("Note");
|
|
|
|
Element::writeProperties(xml);
|
|
|
|
|
|
|
|
if (_accidental)
|
|
|
|
_accidental->write(xml);
|
|
|
|
_el.write(xml);
|
2012-09-14 10:09:06 +02:00
|
|
|
int dots = chord() ? chord()->dots() : 0;
|
2012-05-26 14:26:10 +02:00
|
|
|
if (dots) {
|
|
|
|
bool hasUserModifiedDots = false;
|
|
|
|
for (int i = 0; i < dots; ++i) {
|
|
|
|
if (_dots[i] && (!_dots[i]->userOff().isNull() || !_dots[i]->visible()
|
2014-05-22 18:57:48 +02:00
|
|
|
|| _dots[i]->color() != Qt::black || _dots[i]->visible() != visible())) {
|
2012-05-26 14:26:10 +02:00
|
|
|
hasUserModifiedDots = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (hasUserModifiedDots) {
|
|
|
|
for (int i = 0; i < dots; ++i)
|
|
|
|
_dots[i]->write(xml);
|
|
|
|
}
|
|
|
|
}
|
2013-08-21 11:59:41 +02:00
|
|
|
if (_tieFor) {
|
|
|
|
_tieFor->setId(++xml.spannerId);
|
2012-05-26 14:26:10 +02:00
|
|
|
_tieFor->write(xml);
|
2013-08-21 11:59:41 +02:00
|
|
|
}
|
|
|
|
if (_tieBack)
|
|
|
|
xml.tagE(QString("endSpanner id=\"%1\"").arg(_tieBack->id()));
|
2014-03-28 16:29:55 +01:00
|
|
|
if ((chord() == 0 || chord()->playEventType() != PlayEventType::Auto) && !_playEvents.isEmpty()) {
|
|
|
|
xml.stag("Events");
|
|
|
|
foreach(const NoteEvent& e, _playEvents)
|
|
|
|
e.write(xml);
|
|
|
|
xml.etag();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-05-26 18:18:01 +02:00
|
|
|
writeProperty(xml, P_ID::PITCH);
|
2014-05-05 12:41:50 +02:00
|
|
|
// write tpc1 before tpc2 !
|
2014-05-26 18:18:01 +02:00
|
|
|
writeProperty(xml, P_ID::TPC1);
|
2014-05-05 12:41:50 +02:00
|
|
|
if (_tpc[1] != _tpc[0])
|
2014-05-26 18:18:01 +02:00
|
|
|
writeProperty(xml, P_ID::TPC2);
|
|
|
|
writeProperty(xml, P_ID::SMALL);
|
|
|
|
writeProperty(xml, P_ID::MIRROR_HEAD);
|
|
|
|
writeProperty(xml, P_ID::DOT_POSITION);
|
|
|
|
writeProperty(xml, P_ID::HEAD_GROUP);
|
|
|
|
writeProperty(xml, P_ID::VELO_OFFSET);
|
|
|
|
writeProperty(xml, P_ID::PLAY);
|
|
|
|
writeProperty(xml, P_ID::TUNING);
|
|
|
|
writeProperty(xml, P_ID::FRET);
|
|
|
|
writeProperty(xml, P_ID::STRING);
|
|
|
|
writeProperty(xml, P_ID::GHOST);
|
|
|
|
writeProperty(xml, P_ID::HEAD_TYPE);
|
|
|
|
writeProperty(xml, P_ID::VELO_TYPE);
|
2012-08-10 17:01:35 +02:00
|
|
|
|
2013-06-10 11:03:34 +02:00
|
|
|
foreach (Spanner* e, _spannerFor) {
|
2012-09-12 16:19:03 +02:00
|
|
|
e->setId(++xml.spannerId);
|
|
|
|
e->write(xml);
|
|
|
|
}
|
2013-06-10 11:03:34 +02:00
|
|
|
foreach (Spanner* e, _spannerBack)
|
2012-09-12 16:19:03 +02:00
|
|
|
xml.tagE(QString("endSpanner id=\"%1\"").arg(e->id()));
|
2013-01-03 16:56:56 +01:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
xml.etag();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// Note::read
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
void Note::read(XmlReader& e)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
bool hasAccidental = false; // used for userAccidental backward compatibility
|
|
|
|
|
2014-05-30 10:18:20 +02:00
|
|
|
_tpc[0] = Tpc::TPC_INVALID;
|
|
|
|
_tpc[1] = Tpc::TPC_INVALID;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
if (e.hasAttribute("pitch")) // obsolete
|
|
|
|
_pitch = e.intAttribute("pitch");
|
|
|
|
if (e.hasAttribute("tpc")) // obsolete
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[0] = e.intAttribute("tpc");
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
const QStringRef& tag(e.name());
|
2012-08-10 17:01:35 +02:00
|
|
|
if (tag == "pitch")
|
2013-01-11 18:10:18 +01:00
|
|
|
_pitch = e.readInt();
|
2014-05-05 12:41:50 +02:00
|
|
|
else if (tag == "tpc") {
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[0] = e.readInt();
|
2014-05-05 12:41:50 +02:00
|
|
|
_tpc[1] = _tpc[0];
|
|
|
|
}
|
2014-04-09 09:40:25 +02:00
|
|
|
else if (tag == "tpc2")
|
|
|
|
_tpc[1] = e.readInt();
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "small")
|
2013-01-11 18:10:18 +01:00
|
|
|
setSmall(e.readInt());
|
2014-05-07 05:56:46 +02:00
|
|
|
else if (tag == "mirror")
|
2014-05-26 18:18:01 +02:00
|
|
|
setProperty(P_ID::MIRROR_HEAD, Ms::getProperty(P_ID::MIRROR_HEAD, e));
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "dotPosition")
|
2014-05-26 18:18:01 +02:00
|
|
|
setProperty(P_ID::DOT_POSITION, Ms::getProperty(P_ID::DOT_POSITION, e));
|
2014-04-23 15:07:37 +02:00
|
|
|
else if (tag == "onTimeType") { //obsolete
|
|
|
|
if (e.readElementText() == "offset")
|
|
|
|
_onTimeType = 2;
|
|
|
|
else
|
|
|
|
_onTimeType = 1;
|
|
|
|
}
|
|
|
|
else if (tag == "offTimeType") { //obsolete
|
|
|
|
if (e.readElementText() == "offset")
|
|
|
|
_offTimeType = 2;
|
|
|
|
else
|
|
|
|
_offTimeType = 1;
|
|
|
|
}
|
|
|
|
else if (tag == "onTimeOffset") {// obsolete
|
|
|
|
if (_onTimeType == 1)
|
|
|
|
setOnTimeOffset(e.readInt() * 1000 / chord()->actualTicks());
|
|
|
|
else
|
|
|
|
setOnTimeOffset(e.readInt() * 10);
|
|
|
|
}
|
|
|
|
else if (tag == "offTimeOffset") {// obsolete
|
|
|
|
if (_offTimeType == 1)
|
|
|
|
setOffTimeOffset(e.readInt() * 1000 / chord()->actualTicks());
|
|
|
|
else
|
|
|
|
setOffTimeOffset(e.readInt() * 10);
|
|
|
|
}
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "head")
|
2014-05-26 18:18:01 +02:00
|
|
|
setProperty(P_ID::HEAD_GROUP, Ms::getProperty(P_ID::HEAD_GROUP, e));
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "velocity")
|
2013-01-11 18:10:18 +01:00
|
|
|
setVeloOffset(e.readInt());
|
2013-08-23 13:55:54 +02:00
|
|
|
else if (tag == "play")
|
|
|
|
setPlay(e.readInt());
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "tuning")
|
2013-01-11 18:10:18 +01:00
|
|
|
setTuning(e.readDouble());
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "fret")
|
2013-01-11 18:10:18 +01:00
|
|
|
setFret(e.readInt());
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "string")
|
2013-01-11 18:10:18 +01:00
|
|
|
setString(e.readInt());
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "ghost")
|
2013-01-11 18:10:18 +01:00
|
|
|
setGhost(e.readInt());
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "headType")
|
2013-10-08 00:07:26 +02:00
|
|
|
if (score()->mscVersion() <= 114)
|
2014-05-26 18:18:01 +02:00
|
|
|
setProperty(P_ID::HEAD_TYPE, Ms::getProperty(P_ID::HEAD_TYPE, e).toInt() - 1);
|
2013-10-08 00:07:26 +02:00
|
|
|
else
|
2014-05-26 18:18:01 +02:00
|
|
|
setProperty(P_ID::HEAD_TYPE, Ms::getProperty(P_ID::HEAD_TYPE, e).toInt());
|
2012-08-10 17:01:35 +02:00
|
|
|
else if (tag == "veloType")
|
2014-05-26 18:18:01 +02:00
|
|
|
setProperty(P_ID::VELO_TYPE, Ms::getProperty(P_ID::VELO_TYPE, e));
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "line")
|
2013-01-11 18:10:18 +01:00
|
|
|
_line = e.readInt();
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "Tie") {
|
|
|
|
_tieFor = new Tie(score());
|
|
|
|
_tieFor->setTrack(track());
|
|
|
|
_tieFor->read(e);
|
|
|
|
_tieFor->setStartNote(this);
|
2014-06-24 14:45:50 +02:00
|
|
|
e.addSpanner(_tieFor);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Fingering" || tag == "Text") { // Text is obsolete
|
|
|
|
Fingering* f = new Fingering(score());
|
2014-05-30 10:13:29 +02:00
|
|
|
f->setTextStyleType(TextStyleType::FINGERING);
|
2012-05-26 14:26:10 +02:00
|
|
|
f->read(e);
|
|
|
|
add(f);
|
|
|
|
}
|
|
|
|
else if (tag == "Symbol") {
|
|
|
|
Symbol* s = new Symbol(score());
|
|
|
|
s->setTrack(track());
|
|
|
|
s->read(e);
|
|
|
|
add(s);
|
|
|
|
}
|
|
|
|
else if (tag == "Image") {
|
2014-03-04 17:40:23 +01:00
|
|
|
if (MScore::noImages)
|
|
|
|
e.skipCurrentElement();
|
|
|
|
else {
|
|
|
|
Image* image = new Image(score());
|
|
|
|
image->setTrack(track());
|
|
|
|
image->read(e);
|
|
|
|
add(image);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else if (tag == "userAccidental") {
|
2013-01-11 18:10:18 +01:00
|
|
|
QString val(e.readElementText());
|
2012-05-26 14:26:10 +02:00
|
|
|
bool ok;
|
|
|
|
int k = val.toInt(&ok);
|
|
|
|
if (ok) {
|
|
|
|
// on older scores, a note could have both a <userAccidental> tag and an <Accidental> tag
|
|
|
|
// if a userAccidental has some other property set (like for instance offset)
|
2013-07-02 09:41:04 +02:00
|
|
|
// only construct a new accidental, if the other tag has not been read yet
|
2012-05-26 14:26:10 +02:00
|
|
|
// (<userAccidental> tag is only used in older scores: no need to check the score mscVersion)
|
|
|
|
if (!hasAccidental) {
|
2014-06-13 04:13:41 +02:00
|
|
|
Accidental* a = new Accidental(score());
|
|
|
|
add(a);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
// TODO: for backward compatibility
|
|
|
|
bool bracket = k & 0x8000;
|
|
|
|
k &= 0xfff;
|
2014-05-21 17:55:40 +02:00
|
|
|
Accidental::AccidentalType at = Accidental::AccidentalType::NONE;
|
2012-05-26 14:26:10 +02:00
|
|
|
switch(k) {
|
2014-05-21 17:55:40 +02:00
|
|
|
case 0: at = Accidental::AccidentalType::NONE; break;
|
|
|
|
case 1: at = Accidental::AccidentalType::SHARP; break;
|
|
|
|
case 2: at = Accidental::AccidentalType::FLAT; break;
|
|
|
|
case 3: at = Accidental::AccidentalType::SHARP2; break;
|
|
|
|
case 4: at = Accidental::AccidentalType::FLAT2; break;
|
|
|
|
case 5: at = Accidental::AccidentalType::NATURAL; break;
|
|
|
|
|
|
|
|
case 6: at = Accidental::AccidentalType::FLAT_SLASH; break;
|
|
|
|
case 7: at = Accidental::AccidentalType::FLAT_SLASH2; break;
|
|
|
|
case 8: at = Accidental::AccidentalType::MIRRORED_FLAT2; break;
|
|
|
|
case 9: at = Accidental::AccidentalType::MIRRORED_FLAT; break;
|
2014-06-13 04:13:41 +02:00
|
|
|
case 10: at = Accidental::AccidentalType::MIRRORED_FLAT_SLASH; break;
|
2014-05-21 17:55:40 +02:00
|
|
|
case 11: at = Accidental::AccidentalType::FLAT_FLAT_SLASH; break;
|
|
|
|
|
|
|
|
case 12: at = Accidental::AccidentalType::SHARP_SLASH; break;
|
|
|
|
case 13: at = Accidental::AccidentalType::SHARP_SLASH2; break;
|
|
|
|
case 14: at = Accidental::AccidentalType::SHARP_SLASH3; break;
|
|
|
|
case 15: at = Accidental::AccidentalType::SHARP_SLASH4; break;
|
|
|
|
|
|
|
|
case 16: at = Accidental::AccidentalType::SHARP_ARROW_UP; break;
|
|
|
|
case 17: at = Accidental::AccidentalType::SHARP_ARROW_DOWN; break;
|
|
|
|
case 18: at = Accidental::AccidentalType::SHARP_ARROW_BOTH; break;
|
|
|
|
case 19: at = Accidental::AccidentalType::FLAT_ARROW_UP; break;
|
|
|
|
case 20: at = Accidental::AccidentalType::FLAT_ARROW_DOWN; break;
|
|
|
|
case 21: at = Accidental::AccidentalType::FLAT_ARROW_BOTH; break;
|
|
|
|
case 22: at = Accidental::AccidentalType::NATURAL_ARROW_UP; break;
|
|
|
|
case 23: at = Accidental::AccidentalType::NATURAL_ARROW_DOWN; break;
|
|
|
|
case 24: at = Accidental::AccidentalType::NATURAL_ARROW_BOTH; break;
|
|
|
|
case 25: at = Accidental::AccidentalType::SORI; break;
|
|
|
|
case 26: at = Accidental::AccidentalType::KORON; break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-03-05 20:23:59 +01:00
|
|
|
_accidental->setAccidentalType(at);
|
2012-05-26 14:26:10 +02:00
|
|
|
_accidental->setHasBracket(bracket);
|
2014-05-21 15:49:48 +02:00
|
|
|
_accidental->setRole(Accidental::AccidentalRole::USER);
|
2012-05-26 14:26:10 +02:00
|
|
|
hasAccidental = true; // we now have an accidental
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tag == "Accidental") {
|
|
|
|
// on older scores, a note could have both a <userAccidental> tag and an <Accidental> tag
|
|
|
|
// if a userAccidental has some other property set (like for instance offset)
|
|
|
|
Accidental* a;
|
|
|
|
if (hasAccidental) // if the other tag has already been read,
|
|
|
|
a = _accidental; // re-use the accidental it constructed
|
|
|
|
else
|
|
|
|
a = new Accidental(score());
|
|
|
|
// the accidental needs to know the properties of the
|
|
|
|
// track it belongs to (??)
|
|
|
|
a->setTrack(track());
|
|
|
|
a->read(e);
|
|
|
|
if (!hasAccidental) // only the new accidental, if it has been added previously
|
|
|
|
add(a);
|
|
|
|
if (score()->mscVersion() < 117)
|
|
|
|
hasAccidental = true; // we now have an accidental
|
|
|
|
}
|
|
|
|
else if (tag == "move") // obsolete
|
2013-01-11 18:10:18 +01:00
|
|
|
chord()->setStaffMove(e.readInt());
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "Bend") {
|
|
|
|
Bend* b = new Bend(score());
|
|
|
|
b->setTrack(track());
|
|
|
|
b->read(e);
|
|
|
|
add(b);
|
|
|
|
}
|
|
|
|
else if (tag == "NoteDot") {
|
|
|
|
NoteDot* dot = new NoteDot(score());
|
|
|
|
dot->read(e);
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
if (_dots[i] == 0) {
|
|
|
|
dot->setIdx(i);
|
|
|
|
add(dot);
|
|
|
|
dot = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dot) {
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("Note: too many dots");
|
2012-05-26 14:26:10 +02:00
|
|
|
delete dot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tag == "Events") {
|
2014-03-28 16:29:55 +01:00
|
|
|
_playEvents.clear(); // remove default event
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
|
|
|
const QStringRef& tag(e.name());
|
2012-05-26 14:26:10 +02:00
|
|
|
if (tag == "Event") {
|
2012-11-19 09:29:46 +01:00
|
|
|
NoteEvent ne;
|
2013-01-11 18:10:18 +01:00
|
|
|
ne.read(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
_playEvents.append(ne);
|
|
|
|
}
|
|
|
|
else
|
2013-01-11 18:10:18 +01:00
|
|
|
e.unknown();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-11-22 10:47:00 +01:00
|
|
|
if (chord())
|
2014-03-28 16:29:55 +01:00
|
|
|
chord()->setPlayEventType(PlayEventType::User);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-09-12 16:19:03 +02:00
|
|
|
else if (tag == "endSpanner") {
|
2013-01-11 18:10:18 +01:00
|
|
|
int id = e.intAttribute("id");
|
2014-06-24 14:45:50 +02:00
|
|
|
Spanner* sp = e.findSpanner(id);
|
2013-07-04 13:40:25 +02:00
|
|
|
if (sp) {
|
|
|
|
sp->setEndElement(this);
|
2014-06-24 18:36:02 +02:00
|
|
|
if (sp->type() == Element::Type::TIE)
|
2013-08-21 11:59:41 +02:00
|
|
|
_tieBack = static_cast<Tie*>(sp);
|
|
|
|
else
|
|
|
|
addSpannerBack(sp);
|
2014-06-24 14:45:50 +02:00
|
|
|
e.removeSpanner(sp);
|
2012-09-12 16:19:03 +02:00
|
|
|
}
|
|
|
|
else
|
2012-12-10 14:00:17 +01:00
|
|
|
qDebug("Note::read(): cannot find spanner %d", id);
|
2013-07-04 13:40:25 +02:00
|
|
|
e.readNext();
|
2012-09-12 16:19:03 +02:00
|
|
|
}
|
|
|
|
else if (tag == "TextLine") {
|
2013-01-18 10:55:52 +01:00
|
|
|
Spanner* sp = static_cast<Spanner*>(Element::name2Element(tag, score()));
|
2012-09-12 16:19:03 +02:00
|
|
|
sp->setTrack(track());
|
|
|
|
sp->read(e);
|
2014-05-26 20:48:27 +02:00
|
|
|
sp->setAnchor(Spanner::Anchor::NOTE);
|
2012-09-12 16:19:03 +02:00
|
|
|
sp->setStartElement(this);
|
2013-07-04 13:40:25 +02:00
|
|
|
sp->setTick(e.tick());
|
2013-01-03 16:56:56 +01:00
|
|
|
addSpannerFor(sp);
|
2012-09-12 16:19:03 +02:00
|
|
|
sp->setParent(this);
|
2014-06-24 14:45:50 +02:00
|
|
|
e.addSpanner(sp);
|
2012-09-12 16:19:03 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "onTimeType") // obsolete
|
2013-01-22 21:53:45 +01:00
|
|
|
e.skipCurrentElement(); // _onTimeType = readValueType(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "offTimeType") // obsolete
|
2013-01-22 21:53:45 +01:00
|
|
|
e.skipCurrentElement(); // _offTimeType = readValueType(e);
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (tag == "tick") // bad input file
|
2013-01-22 21:53:45 +01:00
|
|
|
e.skipCurrentElement();
|
2014-05-06 04:28:15 +02:00
|
|
|
else if (tag == "offset") {
|
2014-05-06 17:05:27 +02:00
|
|
|
if (score()->mscVersion() > 114) // || voice() >= 2)
|
2014-05-06 04:28:15 +02:00
|
|
|
Element::readProperties(e);
|
|
|
|
else
|
2014-05-06 17:05:27 +02:00
|
|
|
e.skipCurrentElement(); // ignore manual layout in older scores
|
2014-05-06 04:28:15 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
else if (Element::readProperties(e))
|
|
|
|
;
|
|
|
|
else
|
2013-01-11 18:10:18 +01:00
|
|
|
e.unknown();
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
// ensure sane values:
|
2014-05-12 12:52:13 +02:00
|
|
|
_pitch = limit(_pitch, 0, 127);
|
2014-04-09 09:40:25 +02:00
|
|
|
|
2014-04-14 13:16:46 +02:00
|
|
|
if (score()->mscVersion() < 117 && !concertPitch()) {
|
|
|
|
_pitch += transposition();
|
|
|
|
_tpc[1] = _tpc[0];
|
2014-05-30 10:18:20 +02:00
|
|
|
_tpc[0] = Tpc::TPC_INVALID;
|
2014-04-14 13:16:46 +02:00
|
|
|
}
|
|
|
|
if (!tpcIsValid(_tpc[0]) && !tpcIsValid(_tpc[1])) {
|
2014-06-20 17:07:22 +02:00
|
|
|
Key key = (staff() && chord()) ? staff()->key(chord()->tick()) : Key::C;
|
2014-06-05 11:37:21 +02:00
|
|
|
int tpc = pitch2tpc(_pitch, key, Prefer::NEAREST);
|
2014-04-14 13:16:46 +02:00
|
|
|
if (concertPitch())
|
|
|
|
_tpc[0] = tpc;
|
|
|
|
else
|
|
|
|
_tpc[1] = tpc;
|
|
|
|
}
|
|
|
|
if (!(tpcIsValid(_tpc[0]) && tpcIsValid(_tpc[1]))) {
|
|
|
|
Interval v = staff() ? staff()->part()->instr()->transpose() : Interval();
|
|
|
|
if (tpcIsValid(_tpc[0])) {
|
|
|
|
v.flip();
|
|
|
|
if (v.isZero())
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[1] = _tpc[0];
|
|
|
|
else
|
2014-04-14 13:16:46 +02:00
|
|
|
_tpc[1] = Ms::transposeTpc(_tpc[0], v, false);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (v.isZero())
|
|
|
|
_tpc[0] = _tpc[1];
|
|
|
|
else
|
|
|
|
_tpc[0] = Ms::transposeTpc(_tpc[1], v, false);
|
2014-04-09 09:40:25 +02:00
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// drag
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-10-22 12:05:31 +02:00
|
|
|
QRectF Note::drag(EditData* data)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-03-22 18:30:05 +01:00
|
|
|
if (staff()->isDrumStaff())
|
|
|
|
return QRect();
|
2012-05-26 14:26:10 +02:00
|
|
|
dragMode = true;
|
|
|
|
QRectF bb(chord()->bbox());
|
|
|
|
|
|
|
|
qreal _spatium = spatium();
|
2012-08-16 11:09:36 +02:00
|
|
|
bool tab = staff()->isTabStaff();
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal step = _spatium * (tab ? staff()->staffType()->lineDistance().val() : 0.5);
|
2013-10-24 12:09:00 +02:00
|
|
|
_lineOffset = lrint(data->delta.y() / step);
|
2013-06-05 15:47:34 +02:00
|
|
|
score()->setLayoutAll(true);
|
2012-05-26 14:26:10 +02:00
|
|
|
return bb.translated(chord()->pagePos());
|
|
|
|
}
|
|
|
|
|
2014-04-09 09:40:25 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// transposition
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::transposition() const
|
|
|
|
{
|
|
|
|
return staff() ? staff()->part()->instr()->transpose().chromatic : 0;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// endDrag
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::endDrag()
|
|
|
|
{
|
|
|
|
dragMode = false;
|
|
|
|
if (_lineOffset == 0)
|
|
|
|
return;
|
|
|
|
int staffIdx = chord()->staffIdx() + chord()->staffMove();
|
|
|
|
Staff* staff = score()->staff(staffIdx);
|
2012-08-16 11:09:36 +02:00
|
|
|
if (staff->isTabStaff()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
// on TABLATURE staves, dragging a note keeps same pitch on a different string (if possible)
|
|
|
|
// determine new string of dragged note (if tablature is upside down, invert _lineOffset)
|
2014-06-17 14:38:39 +02:00
|
|
|
int nString = _string + (staff->staffType()->upsideDown() ? -_lineOffset : _lineOffset);
|
2012-05-26 14:26:10 +02:00
|
|
|
_lineOffset = 0;
|
|
|
|
// get a fret number for same pitch on new string
|
2014-05-13 17:15:32 +02:00
|
|
|
const StringData* strData = staff->part()->instr()->stringData();
|
2014-04-09 09:40:25 +02:00
|
|
|
int nFret = strData->fret(_pitch, nString);
|
2012-08-06 09:29:11 +02:00
|
|
|
if (nFret < 0) // no fret?
|
2012-05-26 14:26:10 +02:00
|
|
|
return; // no party!
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(this, P_ID::FRET, nFret);
|
|
|
|
score()->undoChangeProperty(this, P_ID::STRING, nString);
|
2013-11-05 00:48:08 +01:00
|
|
|
strData->fretChords(chord());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// on PITCHED / PERCUSSION staves, dragging a note changes the note pitch
|
2014-04-09 09:40:25 +02:00
|
|
|
int nLine = _line + _lineOffset;
|
2012-05-26 14:26:10 +02:00
|
|
|
_lineOffset = 0;
|
|
|
|
// get note context
|
2014-06-20 17:07:22 +02:00
|
|
|
int tick = chord()->tick();
|
|
|
|
ClefType clef = staff->clef(tick);
|
|
|
|
Key key = staff->key(tick);
|
2012-05-26 14:26:10 +02:00
|
|
|
// determine new pitch of dragged note
|
2014-06-20 17:07:22 +02:00
|
|
|
int nPitch = line2pitch(nLine, clef, key);
|
|
|
|
int tpc1 = pitch2tpc(nPitch, key, Prefer::NEAREST);
|
|
|
|
int tpc2 = pitch2tpc(nPitch - transposition(), key, Prefer::NEAREST);
|
2012-05-26 14:26:10 +02:00
|
|
|
// undefined for non-tablature staves
|
2014-04-09 09:40:25 +02:00
|
|
|
Note* n = this;
|
|
|
|
while (n->tieBack())
|
|
|
|
n = n->tieBack()->startNote();
|
|
|
|
for (; n; n = n->tieFor() ? n->tieFor()->endNote() : 0) {
|
|
|
|
if (n->pitch() != nPitch)
|
2014-05-26 18:18:01 +02:00
|
|
|
n->undoChangeProperty(P_ID::PITCH, nPitch);
|
2014-04-09 09:40:25 +02:00
|
|
|
if (n->_tpc[0] != tpc1)
|
2014-05-26 18:18:01 +02:00
|
|
|
n->undoChangeProperty(P_ID::TPC1, tpc1);
|
2014-04-09 09:40:25 +02:00
|
|
|
if (n->_tpc[1] != tpc2)
|
2014-05-26 18:18:01 +02:00
|
|
|
n->undoChangeProperty(P_ID::TPC2, tpc2);
|
2014-04-09 09:40:25 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-05-27 10:34:08 +02:00
|
|
|
score()->select(this, SelectType::SINGLE, 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// acceptDrop
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Note::acceptDrop(MuseScoreView*, const QPointF&, Element* e) const
|
|
|
|
{
|
2014-06-24 18:36:02 +02:00
|
|
|
Element::Type type = e->type();
|
|
|
|
return (type == Element::Type::ARTICULATION
|
|
|
|
|| type == Element::Type::CHORDLINE
|
|
|
|
|| type == Element::Type::TEXT
|
|
|
|
|| type == Element::Type::REHEARSAL_MARK
|
|
|
|
|| type == Element::Type::FINGERING
|
|
|
|
|| type == Element::Type::ACCIDENTAL
|
|
|
|
|| type == Element::Type::BREATH
|
|
|
|
|| type == Element::Type::ARPEGGIO
|
|
|
|
|| type == Element::Type::NOTEHEAD
|
|
|
|
|| type == Element::Type::NOTE
|
|
|
|
|| type == Element::Type::TREMOLO
|
|
|
|
|| type == Element::Type::STAFF_STATE
|
|
|
|
|| type == Element::Type::INSTRUMENT_CHANGE
|
|
|
|
|| type == Element::Type::IMAGE
|
|
|
|
|| type == Element::Type::CHORD
|
|
|
|
|| type == Element::Type::HARMONY
|
|
|
|
|| type == Element::Type::DYNAMIC
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::ACCIACCATURA)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::APPOGGIATURA)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::GRACE4)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::GRACE16)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::GRACE32)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::GRACE8_AFTER)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::GRACE16_AFTER)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::GRACE32_AFTER)
|
|
|
|
|| (noteType() == NoteType::NORMAL && type == Element::Type::BAGPIPE_EMBELLISHMENT)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::SBEAM)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::MBEAM)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::NBEAM)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::BEAM32)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::BEAM64)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::AUTOBEAM)
|
|
|
|
|| (type == Element::Type::ICON && static_cast<Icon*>(e)->iconType() == IconType::BRACKETS)
|
|
|
|
|| (type == Element::Type::SYMBOL)
|
|
|
|
|| (type == Element::Type::CLEF)
|
|
|
|
|| (type == Element::Type::BAR_LINE)
|
|
|
|
|| (type == Element::Type::GLISSANDO)
|
|
|
|
|| (type == Element::Type::SLUR)
|
|
|
|
|| (type == Element::Type::STAFF_TEXT)
|
|
|
|
|| (type == Element::Type::TEMPO_TEXT)
|
|
|
|
|| (type == Element::Type::BEND && (staff()->isTabStaff()))
|
|
|
|
|| (type == Element::Type::FRET_DIAGRAM));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// drop
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
Element* Note::drop(const DropData& data)
|
|
|
|
{
|
|
|
|
Element* e = data.element;
|
|
|
|
|
|
|
|
Chord* ch = chord();
|
|
|
|
switch(e->type()) {
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::REHEARSAL_MARK:
|
2012-05-26 14:26:10 +02:00
|
|
|
return ch->drop(data);
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SYMBOL:
|
|
|
|
case Element::Type::IMAGE:
|
2012-10-25 16:21:07 +02:00
|
|
|
e->setParent(this);
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::FINGERING:
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setParent(this);
|
|
|
|
score()->undoAddElement(e);
|
2012-10-25 16:21:07 +02:00
|
|
|
{
|
|
|
|
// set style
|
|
|
|
Fingering* f = static_cast<Fingering*>(e);
|
|
|
|
int st = f->textStyleType();
|
2014-03-14 11:30:19 +01:00
|
|
|
f->setTextStyleType(st);
|
2012-10-25 16:21:07 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::SLUR:
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
data.view->cmdAddSlur(this, 0);
|
|
|
|
return 0;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::LYRICS:
|
2013-10-05 17:04:41 +02:00
|
|
|
e->setParent(ch);
|
|
|
|
e->setTrack(track());
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoAddElement(e);
|
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ACCIDENTAL:
|
2013-03-05 20:23:59 +01:00
|
|
|
score()->changeAccidental(this, static_cast<Accidental*>(e)->accidentalType());
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::BEND:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Bend* b = static_cast<Bend*>(e);
|
|
|
|
b->setParent(this);
|
|
|
|
b->setTrack(track());
|
|
|
|
score()->undoAddElement(b);
|
|
|
|
}
|
|
|
|
return e;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::NOTEHEAD:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-11-25 15:02:23 +01:00
|
|
|
NoteHead* s = static_cast<NoteHead*>(e);
|
|
|
|
NoteHeadGroup group = s->headGroup();
|
|
|
|
if (group == NoteHeadGroup::HEAD_INVALID) {
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("unknown note head");
|
2013-11-25 15:02:23 +01:00
|
|
|
group = NoteHeadGroup::HEAD_NORMAL;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
delete s;
|
|
|
|
|
|
|
|
if (group != _headGroup) {
|
|
|
|
if (links()) {
|
|
|
|
foreach(Element* e, *links()) {
|
2014-05-26 18:18:01 +02:00
|
|
|
e->score()->undoChangeProperty(e, P_ID::HEAD_GROUP, int(group));
|
2012-05-26 14:26:10 +02:00
|
|
|
Note* note = static_cast<Note*>(e);
|
2012-08-16 11:09:36 +02:00
|
|
|
if (note->staff() && note->staff()->isTabStaff()
|
2013-11-25 15:02:23 +01:00
|
|
|
&& group == NoteHeadGroup::HEAD_CROSS) {
|
2014-05-26 18:18:01 +02:00
|
|
|
e->score()->undoChangeProperty(e, P_ID::GHOST, true);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(this, P_ID::HEAD_GROUP, int(group));
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->select(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::ICON:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-03-05 20:23:59 +01:00
|
|
|
switch(static_cast<Icon*>(e)->iconType()) {
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::ACCIACCATURA:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::ACCIACCATURA, MScore::division/2);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::APPOGGIATURA:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::APPOGGIATURA, MScore::division/2);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::GRACE4:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::GRACE4, MScore::division);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::GRACE16:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::GRACE16, MScore::division/4);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::GRACE32:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::GRACE32, MScore::division/8);
|
2014-04-23 18:07:38 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::GRACE8_AFTER:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::GRACE8_AFTER, MScore::division/2);
|
2014-04-23 18:07:38 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::GRACE16_AFTER:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::GRACE16_AFTER, MScore::division/4);
|
2014-04-23 18:07:38 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::GRACE32_AFTER:
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, pitch(), NoteType::GRACE32_AFTER, MScore::division/8);
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::SBEAM:
|
|
|
|
case IconType::MBEAM:
|
|
|
|
case IconType::NBEAM:
|
|
|
|
case IconType::BEAM32:
|
|
|
|
case IconType::BEAM64:
|
|
|
|
case IconType::AUTOBEAM:
|
2012-05-26 14:26:10 +02:00
|
|
|
return ch->drop(data);
|
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
case IconType::BRACKETS:
|
2013-05-27 11:28:20 +02:00
|
|
|
{
|
2013-11-25 15:02:23 +01:00
|
|
|
Symbol* s = new Symbol(score());
|
|
|
|
s->setSym(SymId::noteheadParenthesisLeft);
|
2013-05-27 11:28:20 +02:00
|
|
|
s->setParent(this);
|
|
|
|
score()->undoAddElement(s);
|
2013-11-25 15:02:23 +01:00
|
|
|
s = new Symbol(score());
|
|
|
|
s->setSym(SymId::noteheadParenthesisRight);
|
2013-05-27 11:28:20 +02:00
|
|
|
s->setParent(this);
|
|
|
|
score()->undoAddElement(s);
|
|
|
|
}
|
|
|
|
break;
|
2014-05-30 10:14:57 +02:00
|
|
|
default:
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
delete e;
|
|
|
|
break;
|
2013-08-21 11:59:41 +02:00
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::BAGPIPE_EMBELLISHMENT:
|
2013-08-01 22:24:36 +02:00
|
|
|
{
|
2013-08-04 10:35:46 +02:00
|
|
|
BagpipeEmbellishment* b = static_cast<BagpipeEmbellishment*>(e);
|
|
|
|
noteList nl = b->getNoteList();
|
|
|
|
// add grace notes in reverse order, as setGraceNote adds a grace note
|
|
|
|
// before the current note
|
|
|
|
for (int i = nl.size() - 1; i >= 0; --i) {
|
|
|
|
int p = BagpipeEmbellishment::BagpipeNoteInfoList[nl.at(i)].pitch;
|
2014-05-27 10:35:28 +02:00
|
|
|
score()->setGraceNote(ch, p, NoteType::GRACE32, MScore::division/8);
|
2013-08-01 22:24:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
delete e;
|
|
|
|
break;
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::NOTE:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Chord* ch = chord();
|
2014-05-27 10:35:28 +02:00
|
|
|
if (ch->noteType() != NoteType::NORMAL) {
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
e->setParent(ch);
|
|
|
|
score()->undoRemoveElement(this);
|
|
|
|
score()->undoAddElement(e);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::GLISSANDO:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Segment* s = ch->segment();
|
|
|
|
s = s->next1();
|
|
|
|
while (s) {
|
2014-06-01 20:24:29 +02:00
|
|
|
if ((s->segmentType() == SegmentType::ChordRest) && s->element(track()))
|
2012-05-26 14:26:10 +02:00
|
|
|
break;
|
|
|
|
s = s->next1();
|
|
|
|
}
|
|
|
|
if (s == 0) {
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("no segment for second note of glissando found");
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ChordRest* cr1 = static_cast<ChordRest*>(s->element(track()));
|
2014-06-24 18:36:02 +02:00
|
|
|
if (cr1 == 0 || cr1->type() != Element::Type::CHORD) {
|
2014-03-25 13:33:47 +01:00
|
|
|
qDebug("no second note for glissando found, track %d", track());
|
2012-05-26 14:26:10 +02:00
|
|
|
delete e;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
e->setTrack(track());
|
|
|
|
e->setParent(cr1);
|
2012-12-11 20:37:35 +01:00
|
|
|
// in TAB, use straight line with no text
|
|
|
|
if (staff()->isTabStaff()) {
|
2013-03-05 20:23:59 +01:00
|
|
|
(static_cast<Glissando*>(e))->setGlissandoType(GlissandoType::STRAIGHT);
|
2012-12-11 20:37:35 +01:00
|
|
|
(static_cast<Glissando*>(e))->setShowText(false);
|
2013-02-28 15:06:54 +01:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->undoAddElement(e);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2014-06-24 18:36:02 +02:00
|
|
|
case Element::Type::CHORD:
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
Chord* c = static_cast<Chord*>(e);
|
|
|
|
Note* n = c->upNote();
|
2014-05-07 18:09:01 +02:00
|
|
|
Direction dir = c->stemDirection();
|
2013-01-02 20:13:58 +01:00
|
|
|
int t = (staff2track(staffIdx()) + n->voice());
|
2014-05-27 10:34:08 +02:00
|
|
|
score()->select(0, SelectType::SINGLE, 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
NoteVal nval;
|
|
|
|
nval.pitch = n->pitch();
|
|
|
|
nval.headGroup = n->headGroup();
|
|
|
|
Segment* seg = score()->setNoteRest(chord()->segment(), t, nval,
|
|
|
|
score()->inputState().duration().fraction(), dir);
|
|
|
|
ChordRest* cr = static_cast<ChordRest*>(seg->element(t));
|
|
|
|
if (cr)
|
|
|
|
score()->nextInputPos(cr, true);
|
|
|
|
delete e;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return ch->drop(data);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-04-02 20:31:37 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setDotPosition
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-05-07 18:09:01 +02:00
|
|
|
void Note::setDotY(Direction pos)
|
2014-04-02 20:31:37 +02:00
|
|
|
{
|
|
|
|
bool onLine = false;
|
|
|
|
qreal y = 0;
|
|
|
|
|
|
|
|
if (staff()->isTabStaff()) {
|
|
|
|
// with TAB's, dotPosX is not set:
|
|
|
|
// get dot X from width of fret text and use TAB default spacing
|
2014-04-28 18:38:50 +02:00
|
|
|
StaffType* tab = staff()->staffType();
|
2014-04-02 20:31:37 +02:00
|
|
|
if (tab->stemThrough() ) {
|
|
|
|
// if fret mark on lines, use standard processing
|
|
|
|
if (tab->onLines())
|
|
|
|
onLine = true;
|
|
|
|
else
|
|
|
|
// if fret marks above lines, raise the dots by half line distance
|
|
|
|
y = -0.5;
|
|
|
|
}
|
|
|
|
// if stems beside staff, do nothing
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
onLine = !(line() & 1);
|
|
|
|
|
|
|
|
bool oddVoice = voice() & 1;
|
|
|
|
if (onLine) {
|
|
|
|
// displace dots by half spatium up or down according to voice
|
2014-05-07 18:09:01 +02:00
|
|
|
if (pos == Direction::AUTO)
|
2014-04-02 20:31:37 +02:00
|
|
|
y = oddVoice ? 0.5 : -0.5;
|
2014-05-07 18:09:01 +02:00
|
|
|
else if (pos == Direction::UP)
|
2014-04-02 20:31:37 +02:00
|
|
|
y = -0.5;
|
|
|
|
else
|
|
|
|
y = 0.5;
|
|
|
|
}
|
|
|
|
else {
|
2014-05-07 18:09:01 +02:00
|
|
|
if (pos == Direction::UP && !oddVoice)
|
2014-04-02 20:31:37 +02:00
|
|
|
y -= 1.0;
|
2014-05-07 18:09:01 +02:00
|
|
|
else if (pos == Direction::DOWN && oddVoice)
|
2014-04-02 20:31:37 +02:00
|
|
|
y += 1.0;
|
|
|
|
}
|
|
|
|
y *= spatium() * staff()->lineDistance();
|
|
|
|
|
|
|
|
// apply to dots
|
|
|
|
|
|
|
|
int dots = chord()->dots();
|
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
if (i < dots) {
|
|
|
|
if (_dots[i] == 0) {
|
|
|
|
NoteDot* dot = new NoteDot(score());
|
|
|
|
dot->setIdx(i);
|
|
|
|
dot->setParent(this);
|
|
|
|
dot->setTrack(track()); // needed to know the staff it belongs to (and detect tablature)
|
2014-05-22 18:57:48 +02:00
|
|
|
dot->setVisible(visible());
|
2014-04-02 20:31:37 +02:00
|
|
|
score()->undoAddElement(dot); // move dot to _dots[i]
|
|
|
|
}
|
|
|
|
_dots[i]->layout();
|
|
|
|
_dots[i]->rypos() = y;
|
|
|
|
}
|
|
|
|
else if (_dots[i])
|
|
|
|
score()->undoRemoveElement(_dots[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// layout
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::layout()
|
|
|
|
{
|
2012-08-16 11:09:36 +02:00
|
|
|
bool useTablature = staff() && staff()->isTabStaff();
|
2012-05-26 14:26:10 +02:00
|
|
|
if (useTablature) {
|
2014-04-28 18:38:50 +02:00
|
|
|
StaffType* tab = staff()->staffType();
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal mags = magS();
|
2012-12-28 00:30:46 +01:00
|
|
|
qreal w = tabHeadWidth(tab);
|
2013-02-04 23:28:24 +01:00
|
|
|
bbox().setRect(0.0, tab->fretBoxY() * mags, w, tab->fretBoxH() * mags);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2012-08-01 18:00:27 +02:00
|
|
|
else {
|
2013-11-11 15:11:28 +01:00
|
|
|
setbbox(symBbox(noteHead()));
|
2012-08-01 18:00:27 +02:00
|
|
|
if (parent() == 0)
|
|
|
|
return;
|
2013-03-09 09:58:43 +01:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// layout2
|
|
|
|
// called after final position of note is set
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::layout2()
|
|
|
|
{
|
2014-05-21 00:43:28 +02:00
|
|
|
// this is now done in Score::layoutChords3()
|
|
|
|
// so that the results are available there
|
|
|
|
// adjustReadPos();
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
int dots = chord()->dots();
|
|
|
|
if (dots) {
|
2014-05-26 15:31:36 +02:00
|
|
|
qreal d = point(score()->styleS(StyleIdx::dotNoteDistance));
|
|
|
|
qreal dd = point(score()->styleS(StyleIdx::dotDotDistance));
|
2012-05-26 14:26:10 +02:00
|
|
|
qreal x = chord()->dotPosX() - pos().x() - chord()->pos().x();
|
2013-03-23 11:36:04 +01:00
|
|
|
|
|
|
|
// if TAB and stems through staff
|
|
|
|
if (staff()->isTabStaff()) {
|
2013-08-31 18:42:24 +02:00
|
|
|
// with TAB's, dotPosX is not set:
|
|
|
|
// get dot X from width of fret text and use TAB default spacing
|
|
|
|
x = width();
|
|
|
|
dd = STAFFTYPE_TAB_DEFAULTDOTDIST_X * spatium();
|
|
|
|
d = dd * 0.5;
|
2014-04-28 18:38:50 +02:00
|
|
|
StaffType* tab = staff()->staffType();
|
2014-04-02 20:31:37 +02:00
|
|
|
if (!tab->stemThrough())
|
2013-08-31 18:42:24 +02:00
|
|
|
return;
|
2013-03-23 11:36:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// apply to dots
|
2012-05-26 14:26:10 +02:00
|
|
|
for (int i = 0; i < dots; ++i) {
|
|
|
|
NoteDot* dot = _dots[i];
|
|
|
|
if (dot) {
|
2014-04-02 20:31:37 +02:00
|
|
|
dot->rxpos() = x + d + dd * i;
|
2012-05-26 14:26:10 +02:00
|
|
|
_dots[i]->adjustReadPos();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-23 11:36:04 +01:00
|
|
|
// layout elements attached to note
|
2013-03-25 16:27:20 +01:00
|
|
|
for (Element* e : _el) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!score()->tagIsValid(e->tag()))
|
|
|
|
continue;
|
|
|
|
e->setMag(mag());
|
|
|
|
e->layout();
|
2014-06-24 18:36:02 +02:00
|
|
|
if (e->type() == Element::Type::SYMBOL && static_cast<Symbol*>(e)->sym() == SymId::noteheadParenthesisRight) {
|
2013-06-03 14:53:50 +02:00
|
|
|
qreal w = headWidth();
|
|
|
|
if (staff()->isTabStaff()) {
|
2014-04-28 18:38:50 +02:00
|
|
|
StaffType* tab = staff()->staffType();
|
2013-06-03 14:53:50 +02:00
|
|
|
w = tabHeadWidth(tab);
|
|
|
|
}
|
|
|
|
e->setPos(w, 0.0);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// dotIsUp
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Note::dotIsUp() const
|
|
|
|
{
|
|
|
|
if (_dots[0] == 0)
|
|
|
|
return true;
|
2014-05-07 18:09:01 +02:00
|
|
|
if (_userDotPosition == Direction::AUTO)
|
2014-04-02 22:37:13 +02:00
|
|
|
return _dots[0]->y() < spatium() * .1;
|
|
|
|
else
|
2014-05-07 18:09:01 +02:00
|
|
|
return (_userDotPosition == Direction::UP);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// layout10
|
|
|
|
// compute actual accidental and line
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::layout10(AccidentalState* as)
|
|
|
|
{
|
2012-08-16 11:09:36 +02:00
|
|
|
if (staff()->isTabStaff()) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (_accidental) {
|
|
|
|
delete _accidental;
|
|
|
|
_accidental = 0;
|
|
|
|
}
|
|
|
|
if (_fret < 0) {
|
|
|
|
int string, fret;
|
2014-05-13 17:15:32 +02:00
|
|
|
const StringData* stringData = staff()->part()->instr()->stringData();
|
2013-09-15 18:43:48 +02:00
|
|
|
if (stringData->convertPitch(_pitch, &string, &fret)) {
|
2012-05-26 14:26:10 +02:00
|
|
|
_fret = fret;
|
|
|
|
_string = string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2014-04-22 17:02:03 +02:00
|
|
|
int relLine = absStep(tpc(), epitch());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
|
|
|
// calculate accidental
|
|
|
|
|
2014-05-21 17:55:40 +02:00
|
|
|
Accidental::AccidentalType acci = Accidental::AccidentalType::NONE;
|
2014-05-21 15:49:48 +02:00
|
|
|
if (_accidental && _accidental->role() == Accidental::AccidentalRole::USER) {
|
2013-03-05 20:23:59 +01:00
|
|
|
acci = _accidental->accidentalType();
|
2014-05-21 17:55:40 +02:00
|
|
|
if (acci == Accidental::AccidentalType::SHARP || acci == Accidental::AccidentalType::FLAT) {
|
2013-02-07 23:52:13 +01:00
|
|
|
// TODO - what about double flat and double sharp?
|
2014-06-20 17:07:22 +02:00
|
|
|
Key key = (staff() && chord()) ? staff()->key(chord()->tick()) : Key::C;
|
2014-06-05 11:37:21 +02:00
|
|
|
int ntpc = pitch2tpc(epitch(), key, acci == Accidental::AccidentalType::SHARP ? Prefer::SHARPS : Prefer::FLATS);
|
2014-04-09 09:40:25 +02:00
|
|
|
if (ntpc != tpc()) {
|
|
|
|
//not true: qDebug("note at %d has wrong tpc: %d, expected %d, acci %d", chord()->tick(), tpc(), ntpc, acci);
|
2012-09-11 21:10:44 +02:00
|
|
|
// setColor(QColor(255, 0, 0));
|
2014-04-09 09:40:25 +02:00
|
|
|
// setTpc(ntpc);
|
2014-04-22 17:02:03 +02:00
|
|
|
relLine = absStep(tpc(), epitch());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-13 04:13:41 +02:00
|
|
|
else if (acci > Accidental::AccidentalType::NATURAL) {
|
|
|
|
// microtonal accidental - see comment in updateAccidental
|
|
|
|
as->setAccidentalVal(relLine, AccidentalVal::NATURAL, _tieBack != 0);
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
2014-04-09 09:40:25 +02:00
|
|
|
AccidentalVal accVal = tpc2alter(tpc());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
if ((accVal != as->accidentalVal(relLine)) || hidden() || as->tieContext(relLine)) {
|
|
|
|
as->setAccidentalVal(relLine, accVal, _tieBack != 0);
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!_tieBack) {
|
|
|
|
acci = Accidental::value2subtype(accVal);
|
2014-05-21 17:55:40 +02:00
|
|
|
if (acci == Accidental::AccidentalType::NONE)
|
|
|
|
acci = Accidental::AccidentalType::NATURAL;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 17:55:40 +02:00
|
|
|
if (acci != Accidental::AccidentalType::NONE && !_tieBack && !_hidden) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (_accidental == 0) {
|
|
|
|
_accidental = new Accidental(score());
|
|
|
|
_accidental->setGenerated(true);
|
2012-08-16 11:09:36 +02:00
|
|
|
add(_accidental);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2013-03-05 20:23:59 +01:00
|
|
|
_accidental->setAccidentalType(acci);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (_accidental) {
|
2014-04-10 13:13:37 +02:00
|
|
|
if (_accidental->selected())
|
2012-05-26 14:26:10 +02:00
|
|
|
score()->deselect(_accidental);
|
|
|
|
delete _accidental;
|
|
|
|
_accidental = 0;
|
|
|
|
}
|
|
|
|
}
|
2014-04-22 17:02:03 +02:00
|
|
|
updateRelLine(relLine, false);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// noteType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
NoteType Note::noteType() const
|
|
|
|
{
|
|
|
|
return chord()->noteType();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// pagePos
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QPointF Note::pagePos() const
|
|
|
|
{
|
|
|
|
if (parent() == 0)
|
|
|
|
return pos();
|
|
|
|
|
|
|
|
return parent()->pagePos() + pos();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// canvasPos
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QPointF Note::canvasPos() const
|
|
|
|
{
|
|
|
|
if (parent() == 0)
|
|
|
|
return pos();
|
|
|
|
return parent()->canvasPos() + pos();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// scanElements
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::scanElements(void* data, void (*func)(void*, Element*), bool all)
|
|
|
|
{
|
|
|
|
func(data, this);
|
|
|
|
// tie segments are collected from System
|
2012-08-16 11:09:36 +02:00
|
|
|
// if (_tieFor && !staff()->isTabStaff()) // no ties in tablature
|
2012-05-26 14:26:10 +02:00
|
|
|
// _tieFor->scanElements(data, func, all);
|
2013-03-25 16:27:20 +01:00
|
|
|
for (Element* e : _el) {
|
2012-05-26 14:26:10 +02:00
|
|
|
if (score()->tagIsValid(e->tag()))
|
|
|
|
e->scanElements(data, func, all);
|
|
|
|
}
|
2013-07-04 13:40:25 +02:00
|
|
|
for (Spanner* sp : _spannerFor)
|
|
|
|
sp->scanElements(data, func, all);
|
2012-09-17 10:43:59 +02:00
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
if (!dragMode && _accidental)
|
|
|
|
func(data, _accidental);
|
|
|
|
if (chord()) {
|
|
|
|
for (int i = 0; i < chord()->dots(); ++i) {
|
|
|
|
if (_dots[i])
|
|
|
|
func(data, _dots[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setTrack
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setTrack(int val)
|
|
|
|
{
|
|
|
|
Element::setTrack(val);
|
|
|
|
if (_tieFor) {
|
|
|
|
_tieFor->setTrack(val);
|
|
|
|
foreach(SpannerSegment* seg, _tieFor->spannerSegments())
|
|
|
|
seg->setTrack(val);
|
|
|
|
}
|
2013-06-16 23:33:37 +02:00
|
|
|
foreach (Element* e, _el)
|
2012-05-26 14:26:10 +02:00
|
|
|
e->setTrack(val);
|
|
|
|
if (_accidental)
|
|
|
|
_accidental->setTrack(val);
|
|
|
|
if (!chord()) // if note is dragged with shift+ctrl
|
|
|
|
return;
|
|
|
|
for (int i = 0; i < chord()->dots(); ++i) {
|
|
|
|
if (_dots[i])
|
|
|
|
_dots[i]->setTrack(val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2012-11-19 10:08:15 +01:00
|
|
|
// reset
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2012-11-19 10:08:15 +01:00
|
|
|
void Note::reset()
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(this, P_ID::USER_OFF, QPointF());
|
|
|
|
score()->undoChangeProperty(chord(), P_ID::USER_OFF, QPointF());
|
|
|
|
score()->undoChangeProperty(chord(), P_ID::STEM_DIRECTION, int(Direction::AUTO));
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2013-05-28 15:42:02 +02:00
|
|
|
// mag
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-05-28 15:42:02 +02:00
|
|
|
qreal Note::mag() const
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
2013-05-28 15:42:02 +02:00
|
|
|
qreal m = chord()->mag();
|
|
|
|
if (_small)
|
2014-05-26 15:31:36 +02:00
|
|
|
m *= score()->styleD(StyleIdx::smallNoteMag);
|
2013-05-28 15:42:02 +02:00
|
|
|
return m;
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2013-01-02 09:29:17 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setSmall
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setSmall(bool val)
|
|
|
|
{
|
|
|
|
_small = val;
|
|
|
|
}
|
|
|
|
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setLine
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setLine(int n)
|
|
|
|
{
|
|
|
|
_line = n;
|
|
|
|
rypos() = _line * spatium() * .5;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setString
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setString(int val)
|
|
|
|
{
|
|
|
|
_string = val;
|
|
|
|
rypos() = _string * spatium() * 1.5;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setHeadGroup
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setHeadGroup(NoteHeadGroup val)
|
|
|
|
{
|
2013-11-25 15:02:23 +01:00
|
|
|
Q_ASSERT(int(val) >= 0 && int(val) < int(NoteHeadGroup::HEAD_GROUPS));
|
2012-05-26 14:26:10 +02:00
|
|
|
_headGroup = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// ppitch
|
|
|
|
// playback pitch
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::ppitch() const
|
|
|
|
{
|
2014-04-09 09:40:25 +02:00
|
|
|
return _pitch + staff()->pitchOffset(chord()->segment()->tick());
|
2014-04-02 18:11:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// epitch
|
|
|
|
// effective pitch
|
|
|
|
// honours transposing instruments
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::epitch() const
|
|
|
|
{
|
2014-04-09 09:40:25 +02:00
|
|
|
return _pitch - (concertPitch() ? 0 : transposition());
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// customizeVelocity
|
|
|
|
// Input is the global velocity determined by dynamic
|
|
|
|
// signs and crescende/decrescendo etc.
|
|
|
|
// Returns the actual play velocity for this note
|
|
|
|
// modified by veloOffset
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
int Note::customizeVelocity(int velo) const
|
|
|
|
{
|
2014-05-07 18:09:01 +02:00
|
|
|
if (veloType() == ValueType::OFFSET_VAL)
|
2012-05-26 14:26:10 +02:00
|
|
|
velo = velo + (velo * veloOffset()) / 100;
|
2014-05-07 18:09:01 +02:00
|
|
|
else if (veloType() == ValueType::USER_VAL)
|
2012-05-26 14:26:10 +02:00
|
|
|
velo = veloOffset();
|
2014-05-12 12:52:13 +02:00
|
|
|
return limit(velo, 1, 127);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// endEdit
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::endEdit()
|
|
|
|
{
|
|
|
|
Chord* ch = chord();
|
|
|
|
if (ch->notes().size() == 1) {
|
2014-05-26 18:18:01 +02:00
|
|
|
score()->undoChangeProperty(ch, P_ID::USER_OFF, ch->userOff() + userOff());
|
2012-05-26 14:26:10 +02:00
|
|
|
setUserOff(QPointF());
|
2012-06-09 10:50:51 +02:00
|
|
|
score()->setLayoutAll(true);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateAccidental
|
2014-04-18 11:28:04 +02:00
|
|
|
// set _accidental and _line depending on tpc
|
2012-05-26 14:26:10 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::updateAccidental(AccidentalState* as)
|
|
|
|
{
|
2014-04-22 17:02:03 +02:00
|
|
|
int relLine = absStep(tpc(), epitch());
|
2012-05-26 14:26:10 +02:00
|
|
|
|
2013-03-10 14:10:09 +01:00
|
|
|
// don't touch accidentals that don't concern tpc such as
|
|
|
|
// quarter tones
|
2014-05-21 17:55:40 +02:00
|
|
|
if (!(_accidental && _accidental->accidentalType() > Accidental::AccidentalType::NATURAL)) {
|
2014-04-09 16:09:21 +02:00
|
|
|
// calculate accidental
|
2014-05-21 17:55:40 +02:00
|
|
|
Accidental::AccidentalType acci = Accidental::AccidentalType::NONE;
|
2013-03-10 14:10:09 +01:00
|
|
|
|
2014-04-09 16:09:21 +02:00
|
|
|
AccidentalVal accVal = tpc2alter(tpc());
|
2014-04-22 17:02:03 +02:00
|
|
|
if ((accVal != as->accidentalVal(relLine)) || hidden() || as->tieContext(relLine)) {
|
|
|
|
as->setAccidentalVal(relLine, accVal, _tieBack != 0);
|
2014-04-09 16:09:21 +02:00
|
|
|
if (_tieBack)
|
2014-05-21 17:55:40 +02:00
|
|
|
acci = Accidental::AccidentalType::NONE;
|
2013-03-10 14:10:09 +01:00
|
|
|
else {
|
|
|
|
acci = Accidental::value2subtype(accVal);
|
2014-05-21 17:55:40 +02:00
|
|
|
if (acci == Accidental::AccidentalType::NONE)
|
|
|
|
acci = Accidental::AccidentalType::NATURAL;
|
2014-04-09 16:09:21 +02:00
|
|
|
}
|
|
|
|
}
|
2014-05-21 17:55:40 +02:00
|
|
|
if (acci != Accidental::AccidentalType::NONE && !_tieBack && !_hidden) {
|
2014-04-09 16:09:21 +02:00
|
|
|
if (_accidental == 0) {
|
|
|
|
Accidental* a = new Accidental(score());
|
|
|
|
a->setParent(this);
|
|
|
|
a->setAccidentalType(acci);
|
|
|
|
score()->undoAddElement(a);
|
|
|
|
}
|
|
|
|
else if (_accidental->accidentalType() != acci) {
|
|
|
|
Accidental* a = _accidental->clone();
|
|
|
|
a->setParent(this);
|
|
|
|
a->setAccidentalType(acci);
|
|
|
|
score()->undoChangeElement(_accidental, a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (_accidental) {
|
2014-05-21 15:49:48 +02:00
|
|
|
// remove this if it was AUTO:
|
|
|
|
if (_accidental->role() == Accidental::AccidentalRole::AUTO)
|
2014-04-09 16:09:21 +02:00
|
|
|
score()->undoRemoveElement(_accidental);
|
|
|
|
else {
|
|
|
|
// keep it, but update type if needed
|
|
|
|
acci = Accidental::value2subtype(accVal);
|
2014-05-21 17:55:40 +02:00
|
|
|
if (acci == Accidental::AccidentalType::NONE)
|
|
|
|
acci = Accidental::AccidentalType::NATURAL;
|
2014-04-09 16:09:21 +02:00
|
|
|
if (_accidental->accidentalType() != acci) {
|
|
|
|
Accidental* a = _accidental->clone();
|
|
|
|
a->setParent(this);
|
|
|
|
a->setAccidentalType(acci);
|
|
|
|
score()->undoChangeElement(_accidental, a);
|
|
|
|
}
|
2013-03-10 14:10:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
2014-06-18 07:17:11 +02:00
|
|
|
|
2014-06-13 04:13:41 +02:00
|
|
|
else {
|
2014-06-18 07:17:11 +02:00
|
|
|
// microtonal accidentals playback as naturals
|
|
|
|
// in 1.X, they had no effect on accidental state of measure
|
2014-06-13 04:13:41 +02:00
|
|
|
// ultimetely, they should probably get their own state
|
2014-06-18 07:17:11 +02:00
|
|
|
// for now, at least change state to natural, so subsequent notes playback as might be expected
|
|
|
|
// this is an incompatible change, but better to break it for 2.0 than wait until later
|
2014-06-13 04:13:41 +02:00
|
|
|
as->setAccidentalVal(relLine, AccidentalVal::NATURAL, _tieBack != 0);
|
|
|
|
}
|
2014-06-18 07:17:11 +02:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
updateRelLine(relLine, true);
|
2014-04-09 16:09:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateRelLine
|
|
|
|
// calculate the real note line depending on clef,
|
|
|
|
// _line is the absolute line
|
|
|
|
//---------------------------------------------------------
|
2013-03-10 14:10:09 +01:00
|
|
|
|
2014-04-22 17:02:03 +02:00
|
|
|
void Note::updateRelLine(int relLine, bool undoable)
|
2014-04-09 16:09:21 +02:00
|
|
|
{
|
2012-05-26 14:26:10 +02:00
|
|
|
Staff* s = score()->staff(staffIdx() + chord()->staffMove());
|
2014-04-09 16:09:21 +02:00
|
|
|
ClefType clef = s->clef(chord()->tick());
|
2014-04-22 17:02:03 +02:00
|
|
|
int line = relStep(relLine, clef);
|
2014-04-09 16:09:21 +02:00
|
|
|
if (line != _line) {
|
2014-04-22 17:02:03 +02:00
|
|
|
if (undoable)
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::LINE, line);
|
2014-04-22 17:02:03 +02:00
|
|
|
else
|
|
|
|
setLine(line);
|
2014-04-09 16:09:21 +02:00
|
|
|
}
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// updateLine
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::updateLine()
|
|
|
|
{
|
2014-04-22 17:02:03 +02:00
|
|
|
int relLine = absStep(tpc(), epitch());
|
|
|
|
updateRelLine(relLine, false);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setNval
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-06-26 11:41:18 +02:00
|
|
|
void Note::setNval(const NoteVal& nval)
|
2012-05-26 14:26:10 +02:00
|
|
|
{
|
|
|
|
setPitch(nval.pitch);
|
2014-06-26 11:41:18 +02:00
|
|
|
_fret = nval.fret;
|
|
|
|
_string = nval.string;
|
2014-05-30 10:18:20 +02:00
|
|
|
if (nval.tpc == Tpc::TPC_INVALID) {
|
2014-06-20 17:07:22 +02:00
|
|
|
Key key = staff()->key(chord()->tick());
|
2014-05-23 21:14:22 +02:00
|
|
|
_tpc[0] = pitch2tpc(nval.pitch, key, Prefer::NEAREST);
|
2014-04-17 12:32:10 +02:00
|
|
|
Interval v = staff()->part()->instr()->transpose();
|
|
|
|
if (v.isZero())
|
|
|
|
_tpc[1] = _tpc[0];
|
|
|
|
else {
|
|
|
|
v.flip();
|
|
|
|
_tpc[1] = Ms::transposeTpc(_tpc[0], v, false);
|
|
|
|
}
|
|
|
|
return;
|
2014-04-11 14:50:53 +02:00
|
|
|
}
|
|
|
|
|
2014-04-14 10:39:27 +02:00
|
|
|
if (concertPitch()) {
|
|
|
|
_tpc[0] = nval.tpc;
|
|
|
|
_tpc[1] = transposeTpc(nval.tpc);
|
2014-04-11 14:50:53 +02:00
|
|
|
}
|
|
|
|
else {
|
2014-04-14 10:39:27 +02:00
|
|
|
_tpc[0] = transposeTpc(nval.tpc);
|
2014-04-11 14:50:53 +02:00
|
|
|
_tpc[1] = nval.tpc;
|
|
|
|
}
|
2012-08-04 15:46:43 +02:00
|
|
|
_headGroup = NoteHeadGroup(nval.headGroup);
|
2012-05-26 14:26:10 +02:00
|
|
|
}
|
|
|
|
|
2012-08-10 17:01:35 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// getProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Note::getProperty(P_ID propertyId) const
|
|
|
|
{
|
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::PITCH:
|
2012-08-10 17:01:35 +02:00
|
|
|
return pitch();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TPC1:
|
2014-04-09 09:40:25 +02:00
|
|
|
return _tpc[0];
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TPC2:
|
2014-04-09 09:40:25 +02:00
|
|
|
return _tpc[1];
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::SMALL:
|
2012-08-10 17:01:35 +02:00
|
|
|
return small();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::MIRROR_HEAD:
|
2014-05-07 18:09:01 +02:00
|
|
|
return int(userMirror());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::DOT_POSITION:
|
2014-05-07 18:09:01 +02:00
|
|
|
return int(userDotPosition());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::HEAD_GROUP:
|
2013-11-25 15:02:23 +01:00
|
|
|
return int(headGroup());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VELO_OFFSET:
|
2012-08-10 17:01:35 +02:00
|
|
|
return veloOffset();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TUNING:
|
2012-08-10 17:01:35 +02:00
|
|
|
return tuning();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::FRET:
|
2012-08-10 17:01:35 +02:00
|
|
|
return fret();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::STRING:
|
2012-08-10 17:01:35 +02:00
|
|
|
return string();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::GHOST:
|
2012-08-10 17:01:35 +02:00
|
|
|
return ghost();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::HEAD_TYPE:
|
2013-11-25 15:02:23 +01:00
|
|
|
return int(headType());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VELO_TYPE:
|
2014-05-07 18:09:01 +02:00
|
|
|
return int(veloType());
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::PLAY:
|
2013-08-23 13:55:54 +02:00
|
|
|
return play();
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::LINE:
|
2014-04-22 17:02:03 +02:00
|
|
|
return _line;
|
2012-08-10 17:01:35 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return Element::getProperty(propertyId);
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setProperty
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
bool Note::setProperty(P_ID propertyId, const QVariant& v)
|
|
|
|
{
|
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::PITCH:
|
2012-08-10 17:01:35 +02:00
|
|
|
setPitch(v.toInt());
|
2014-04-09 09:40:25 +02:00
|
|
|
if (chord()->measure())
|
2014-04-22 17:02:03 +02:00
|
|
|
chord()->measure()->cmdUpdateNotes(chord()->staffIdx());
|
2014-04-02 10:49:54 +02:00
|
|
|
score()->setPlaylistDirty(true);
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TPC1:
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[0] = v.toInt();
|
2014-04-10 13:13:37 +02:00
|
|
|
if (chord()->measure())
|
2014-04-22 17:02:03 +02:00
|
|
|
chord()->measure()->cmdUpdateNotes(chord()->staffIdx());
|
2014-04-09 09:40:25 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TPC2:
|
2014-04-09 09:40:25 +02:00
|
|
|
_tpc[1] = v.toInt();
|
2014-04-10 13:13:37 +02:00
|
|
|
if (chord()->measure())
|
2014-04-22 17:02:03 +02:00
|
|
|
chord()->measure()->cmdUpdateNotes(chord()->staffIdx());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::LINE:
|
2014-04-22 17:02:03 +02:00
|
|
|
_line = v.toInt();
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::SMALL:
|
2012-08-10 17:01:35 +02:00
|
|
|
setSmall(v.toBool());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::MIRROR_HEAD:
|
2014-05-07 18:09:01 +02:00
|
|
|
setUserMirror(DirectionH(v.toInt()));
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::DOT_POSITION:
|
2014-05-07 18:09:01 +02:00
|
|
|
setUserDotPosition(Direction(v.toInt()));
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::HEAD_GROUP:
|
2012-08-10 17:01:35 +02:00
|
|
|
setHeadGroup(NoteHeadGroup(v.toInt()));
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VELO_OFFSET:
|
2012-08-10 17:01:35 +02:00
|
|
|
setVeloOffset(v.toInt());
|
2014-04-02 10:49:54 +02:00
|
|
|
score()->setPlaylistDirty(true);
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TUNING:
|
2012-08-10 17:01:35 +02:00
|
|
|
setTuning(v.toDouble());
|
2014-04-02 10:49:54 +02:00
|
|
|
score()->setPlaylistDirty(true);
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::FRET:
|
2012-08-10 17:01:35 +02:00
|
|
|
setFret(v.toInt());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::STRING:
|
2012-08-10 17:01:35 +02:00
|
|
|
setString(v.toInt());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::GHOST:
|
2012-08-10 17:01:35 +02:00
|
|
|
setGhost(v.toBool());
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::HEAD_TYPE:
|
2012-08-10 17:01:35 +02:00
|
|
|
setHeadType(NoteHeadType(v.toInt()));
|
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VELO_TYPE:
|
2014-05-07 18:09:01 +02:00
|
|
|
setVeloType(ValueType(v.toInt()));
|
2014-04-02 10:49:54 +02:00
|
|
|
score()->setPlaylistDirty(true);
|
2012-08-10 17:01:35 +02:00
|
|
|
break;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VISIBLE: { // P_ID::VISIBLE requires reflecting property on dots
|
2012-12-05 13:44:30 +01:00
|
|
|
setVisible(v.toBool());
|
|
|
|
int dots = chord()->dots();
|
|
|
|
for (int i = 0; i < dots; ++i) {
|
|
|
|
if (_dots[i])
|
|
|
|
_dots[i]->setVisible(visible());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::PLAY:
|
2013-08-23 13:55:54 +02:00
|
|
|
setPlay(v.toBool());
|
2014-04-02 10:49:54 +02:00
|
|
|
score()->setPlaylistDirty(true);
|
2013-08-23 13:55:54 +02:00
|
|
|
break;
|
2012-08-10 17:01:35 +02:00
|
|
|
default:
|
|
|
|
if (!Element::setProperty(propertyId, v))
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
score()->setLayoutAll(true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-12 11:44:36 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetFret
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetFret(int val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::FRET, val);
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetString
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetString(int val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::STRING, val);
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetGhost
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetGhost(bool val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::GHOST, val);
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetSmall
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetSmall(bool val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::SMALL, val);
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
2013-08-23 13:55:54 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetPlay
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetPlay(bool val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::PLAY, val);
|
2013-08-23 13:55:54 +02:00
|
|
|
}
|
|
|
|
|
2012-08-12 11:44:36 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetTuning
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetTuning(qreal val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::TUNING, val);
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetVeloType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-05-07 18:09:01 +02:00
|
|
|
void Note::undoSetVeloType(ValueType val)
|
2012-08-12 11:44:36 +02:00
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::VELO_TYPE, int(val));
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetVeloOffset
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetVeloOffset(int val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::VELO_OFFSET, val);
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetUserMirror
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-05-07 18:09:01 +02:00
|
|
|
void Note::undoSetUserMirror(DirectionH val)
|
2012-08-12 11:44:36 +02:00
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::MIRROR_HEAD, int(val));
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
2014-04-02 20:31:37 +02:00
|
|
|
// undoSetUserDotPosition
|
2012-08-12 11:44:36 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-05-07 18:09:01 +02:00
|
|
|
void Note::undoSetUserDotPosition(Direction val)
|
2012-08-12 11:44:36 +02:00
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::DOT_POSITION, int(val));
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetHeadGroup
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetHeadGroup(NoteHeadGroup val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::HEAD_GROUP, int(val));
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
2013-01-28 21:45:36 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setHeadType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::setHeadType(NoteHeadType t)
|
|
|
|
{
|
|
|
|
_headType = t;
|
|
|
|
}
|
|
|
|
|
2012-08-12 11:44:36 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// undoSetHeadType
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Note::undoSetHeadType(NoteHeadType val)
|
|
|
|
{
|
2014-05-26 18:18:01 +02:00
|
|
|
undoChangeProperty(P_ID::HEAD_TYPE, int(val));
|
2012-08-12 11:44:36 +02:00
|
|
|
}
|
|
|
|
|
2012-08-10 17:01:35 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// propertyDefault
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
QVariant Note::propertyDefault(P_ID propertyId) const
|
|
|
|
{
|
|
|
|
switch(propertyId) {
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::GHOST:
|
|
|
|
case P_ID::SMALL:
|
2012-08-10 17:01:35 +02:00
|
|
|
return false;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::MIRROR_HEAD:
|
2014-05-07 18:09:01 +02:00
|
|
|
return int(DirectionH::DH_AUTO);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::DOT_POSITION:
|
2014-05-07 18:09:01 +02:00
|
|
|
return int(Direction::AUTO);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::HEAD_GROUP:
|
2013-11-25 15:02:23 +01:00
|
|
|
return int(NoteHeadGroup::HEAD_NORMAL);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VELO_OFFSET:
|
2012-08-10 17:01:35 +02:00
|
|
|
return 0;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::TUNING:
|
2012-08-10 17:01:35 +02:00
|
|
|
return 0.0;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::FRET:
|
|
|
|
case P_ID::STRING:
|
2012-08-10 17:01:35 +02:00
|
|
|
return -1;
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::HEAD_TYPE:
|
2013-11-25 15:02:23 +01:00
|
|
|
return int(NoteHeadType::HEAD_AUTO);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::VELO_TYPE:
|
2014-05-07 18:09:01 +02:00
|
|
|
return int (ValueType::OFFSET_VAL);
|
2014-05-26 18:18:01 +02:00
|
|
|
case P_ID::PLAY:
|
2013-08-23 13:55:54 +02:00
|
|
|
return true;
|
2012-08-10 17:01:35 +02:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2012-10-31 14:21:13 +01:00
|
|
|
return Element::propertyDefault(propertyId);
|
2012-08-10 17:01:35 +02:00
|
|
|
}
|
|
|
|
|
2012-11-19 09:29:46 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// setOnTimeOffset
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-04-09 09:40:25 +02:00
|
|
|
void Note::setOnTimeOffset(int val)
|
2012-11-19 09:29:46 +01:00
|
|
|
{
|
2014-04-09 09:40:25 +02:00
|
|
|
_playEvents[0].setOntime(val);
|
2014-04-23 15:07:37 +02:00
|
|
|
chord()->setPlayEventType(PlayEventType::User);
|
2012-11-19 09:29:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// setOffTimeOffset
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2014-04-09 09:40:25 +02:00
|
|
|
void Note::setOffTimeOffset(int val)
|
2012-11-19 09:29:46 +01:00
|
|
|
{
|
2014-04-09 09:40:25 +02:00
|
|
|
_playEvents[0].setLen(val - _playEvents[0].ontime());
|
2014-04-23 15:07:37 +02:00
|
|
|
chord()->setPlayEventType(PlayEventType::User);
|
2012-11-19 09:29:46 +01:00
|
|
|
}
|
2013-01-02 20:13:58 +01:00
|
|
|
|
2013-01-03 16:56:56 +01:00
|
|
|
//---------------------------------------------------------
|
2013-06-10 11:03:34 +02:00
|
|
|
// setScore
|
2013-01-03 16:56:56 +01:00
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-06-10 11:03:34 +02:00
|
|
|
void Note::setScore(Score* s)
|
2013-01-03 16:56:56 +01:00
|
|
|
{
|
2013-06-10 11:03:34 +02:00
|
|
|
Element::setScore(s);
|
|
|
|
if (_tieFor)
|
|
|
|
_tieFor->setScore(s);
|
2013-01-03 16:56:56 +01:00
|
|
|
}
|
2014-06-26 11:41:18 +02:00
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// noteVal
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
NoteVal Note::noteVal() const
|
|
|
|
{
|
|
|
|
NoteVal nval;
|
|
|
|
nval.pitch = pitch();
|
|
|
|
nval.tpc = tpc1();
|
|
|
|
nval.fret = fret();
|
|
|
|
nval.string = string();
|
|
|
|
nval.headGroup = headGroup();
|
|
|
|
return nval;
|
|
|
|
}
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|